FastMCP provides two powerful ways to integrate with FastAPI applications, both of which are documented below.

  1. You can generate an MCP server FROM your FastAPI app by converting existing API endpoints into MCP tools. This is useful for bootstrapping and quickly attaching LLMs to your API.
  2. You can mount an MCP server INTO your FastAPI app by adding MCP functionality to your web application. This is useful for exposing your MCP tools alongside regular API endpoints.

You can even combine both approaches to create a single FastAPI app that serves both regular API endpoints and MCP tools!

Generating MCP servers from FastAPI apps is a great way to get started with FastMCP, but in practice LLMs achieve significantly better performance with well-designed and curated MCP servers than with auto-converted FastAPI servers. This is especially true for complex APIs with many endpoints and parameters.

FastMCP does not include FastAPI as a dependency; you must install it separately to use this integration.

Generating an MCP Server

New in version: 2.0.0

FastMCP can directly convert your existing FastAPI applications into MCP servers, allowing AI models to interact with your API endpoints through the MCP protocol.

Under the hood, the FastAPI integration is built on top of FastMCP’s OpenAPI integration. See the OpenAPI docs for more details.

Create a Server

The simplest way to convert a FastAPI app is using the FastMCP.from_fastapi() method:

server.py
from fastapi import FastAPI
from fastmcp import FastMCP

# Your existing FastAPI app
app = FastAPI(title="My API", version="1.0.0")

@app.get("/items", tags=["items"], operation_id="list_items")
def list_items():
    return [{"id": 1, "name": "Item 1"}, {"id": 2, "name": "Item 2"}]

@app.get("/items/{item_id}", tags=["items", "detail"], operation_id="get_item")
def get_item(item_id: int):
    return {"id": item_id, "name": f"Item {item_id}"}

@app.post("/items", tags=["items", "create"], operation_id="create_item")
def create_item(name: str):
    return {"id": 3, "name": name}

# Convert FastAPI app to MCP server
mcp = FastMCP.from_fastapi(app=app)

if __name__ == "__main__":
    mcp.run()  # Run as MCP server

Component Mapping

By default, FastMCP converts every endpoint in your FastAPI app into an MCP Tool. This provides maximum compatibility with LLM clients that primarily support MCP tools.

You can customize this behavior using route maps to control which endpoints become tools, resources, or resource templates:

from fastmcp.server.openapi import RouteMap, MCPType

# Custom route mapping
mcp = FastMCP.from_fastapi(
    app=app,
    route_maps=[
        # GET requests with path parameters become ResourceTemplates
        RouteMap(methods=["GET"], pattern=r".*\{.*\}.*", mcp_type=MCPType.RESOURCE_TEMPLATE),
        # All other GET requests become Resources
        RouteMap(methods=["GET"], pattern=r".*", mcp_type=MCPType.RESOURCE),
        # POST/PUT/DELETE become Tools (handled by default rule)
    ],
)

The FastMCP.from_fastapi() method accepts all the same configuration options as FastMCP.from_openapi(), including route maps, custom tags, component naming, timeouts, and component customization functions. For comprehensive configuration details, see the OpenAPI Integration guide.

Key Considerations

Operation IDs

FastMCP uses your FastAPI operation IDs to name MCP components. Ensure your endpoints have meaningful operation IDs:

@app.get("/users/{user_id}", operation_id="get_user_detail")  # ✅ Good
@app.get("/users/{user_id}")  # ❌ Auto-generated name might be unclear

Pydantic Models

Your Pydantic models are automatically converted to JSON schema for MCP tool parameters:

from pydantic import BaseModel

class CreateItemRequest(BaseModel):
    name: str
    description: str | None = None
    price: float

@app.post("/items")
def create_item(item: CreateItemRequest):
    return {"id": 123, **item.dict()}

The MCP tool will have properly typed parameters matching your Pydantic model.

Error Handling

FastAPI error handling carries over to the MCP server. HTTPExceptions are automatically converted to appropriate MCP errors.

Since FastAPI integration is built on OpenAPI, all the same configuration options are available including authentication setup, timeout configuration, and request parameter handling. For detailed information on these features, see the OpenAPI Integration guide.

Mounting an MCP Server

New in version: 2.3.1

You can also mount an existing FastMCP server into your FastAPI application, adding MCP functionality to your web application. This is useful for exposing your MCP tools alongside regular API endpoints.

Basic Integration

from fastmcp import FastMCP
from fastapi import FastAPI
from starlette.routing import Mount

# Create your FastMCP server
mcp = FastMCP("MyServer")

@mcp.tool
def analyze_data(query: str) -> dict:
    """Analyze data based on the query."""
    return {"result": f"Analysis for: {query}"}

# Create the ASGI app from your MCP server
mcp_app = mcp.http_app(path='/mcp')

# Create a FastAPI app and mount the MCP server
app = FastAPI(lifespan=mcp_app.lifespan)
app.mount("/mcp-server", mcp_app)

# Add regular FastAPI routes
@app.get("/health")
def health_check():
    return {"status": "healthy"}

The MCP endpoint will be available at /mcp-server/mcp/ of your FastAPI application.

For Streamable HTTP transport, you must pass the lifespan context from the FastMCP app to the FastAPI app. Otherwise, the FastMCP server’s session manager will not be properly initialized.

Advanced Integration

You can combine both approaches - generate an MCP server from your FastAPI app AND mount additional MCP servers:

from fastmcp import FastMCP
from fastapi import FastAPI

# Your existing FastAPI app
app = FastAPI()

@app.get("/items")
def list_items():
    return [{"id": 1, "name": "Item 1"}]

# Generate MCP server from FastAPI app
api_mcp = FastMCP.from_fastapi(app=app, name="API Server")

# Create additional purpose-built MCP server
tools_mcp = FastMCP("Tools Server")

@tools_mcp.tool
def advanced_analysis(data: dict) -> dict:
    """Perform advanced analysis not available via API."""
    return {"analysis": "complex results"}

# Mount the tools server into the same FastAPI app
tools_app = tools_mcp.http_app(path='/mcp')
app.mount("/tools", tools_app, lifespan=tools_app.lifespan)

Now you have:

  • API endpoints converted to MCP tools (via api_mcp)
  • Additional MCP tools available at /tools/mcp/
  • Regular FastAPI endpoints at their original paths

Authentication and Middleware

When mounting MCP servers into FastAPI, you can leverage FastAPI’s authentication and middleware:

from fastapi import FastAPI, Depends, HTTPException
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials

security = HTTPBearer()

def verify_token(credentials: HTTPAuthorizationCredentials = Depends(security)):
    if credentials.credentials != "secret-token":
        raise HTTPException(status_code=401, detail="Invalid token")
    return credentials

app = FastAPI()

# Mount MCP server with authentication
@app.get("/secure")
def secure_endpoint(auth=Depends(verify_token)):
    return {"message": "Authenticated"}

# The mounted MCP server inherits the app's security
mcp_app = mcp.http_app()
app.mount("/mcp", mcp_app, lifespan=mcp_app.lifespan)

For more advanced ASGI integration patterns, see the ASGI Integration guide.