# app/main.py

app = FastAPI(
    title="Django Documentation RAG API",
    description="Semantic search over Django 5.2.8 documentation using RAG (Retrieval-Augmented Generation)",
    version="1.0.0",
    openapi_tags=[
        {
            "name": "search",
            "description": "Semantic search operations over Django documentation",
        },
    ],
)
rag_service = RAGService()

@app.post(
    "/search",
    response_model=SearchResponse,
    tags=["search"],
    summary="Search Django documentation",
    operation_id="search_documentation",
    description="""
    Perform semantic search over Django 5.2.8 documentation chunks.
    Returns relevant documentation sections with similarity scores and token estimates.
    """,
    responses={
        200: {"description": "Successful search with results"},
        422: {"description": "Validation error"},
    },
)
async def search_documentation(request: SearchRequest):
    """Search Django documentation using semantic similarity"""
    results, total_found, tokens_estimate = rag_service.search(
        query=request.query,
        max_results=request.max_results or DEFAULT_MAX_RESULTS,
        min_score=request.min_score or DEFAULT_MIN_SCORE
    )

    return SearchResponse(
        results=results,
        total_found=total_found,
        tokens_estimate=tokens_estimate
    )
```

The `operation_id="search_documentation"` becomes the MCP tool name that Claude will call. The description tells the LLM what this tool does and when to use it. FastAPI handles validation and serialization automatically.

### Customize the OpenAPI document

The MCP server uses an OpenAPI document that we'll host on Gram. Gram provides an OpenAPI [extension](/docs/gram/build-mcp/advanced-tool-curation#provide-rich-context) `x-gram` that helps LLMs better understand the tools they call.

To customize the OpenAPI document, create a function to rewrite the attributes you want:

```python