Skip to main content
Glama

FastAPI-MCP โšก๐Ÿค–


๐ŸŒŸ Key Highlights

  • ๐Ÿค True Protocol Coexistence: Serve your REST API (OpenAPI/Swagger docs), MCP Server-Sent Events (SSE), and Streamable HTTP endpoints from a single Uvicorn process and single port.

  • ๐Ÿ› ๏ธ Dual @app.api_tool Decorator: Define an endpoint once โ€” it instantly becomes both an HTTP REST endpoint for web clients and an MCP tool for AI agents (Claude, Cursor, Antigravity).

  • ๐Ÿ”„ 2-Line Existing App Conversion: Point to any existing FastAPI application and automatically expose its endpoints as MCP tools with zero changes to your existing code.

  • ๐Ÿ“– Built-in MCP Swagger Explorer (/mcp/docs): An interactive visual playground for testing MCP tools right alongside FastAPI's /docs. Inspect parameters and execute tools live with "Try it out" in your browser.

  • โšก Zero-Network In-Memory Dispatch: In-memory ASGI transport executes tool calls directly without TCP socket loopbacks, preserving FastAPI Depends() injections, auth, and Pydantic validation.


Related MCP server: FastAPI-MCP

๐Ÿ’ก Why a Single Server Architecture? (Resource & Performance Benefits)

Running separate microservices or independent processes for REST and MCP introduces unnecessary infrastructure complexity and resource waste:

1. Zero Process Multiplication & Low Memory Footprint

A typical Python web server process uses 60โ€“150 MB of RAM at boot. Running a separate server process for MCP doubles baseline memory consumption and CPU thread contention. With fastapi-mcp, everything runs in a single shared event loop, conserving memory on budget VMs and cloud containers.

2. Zero-Network In-Memory Execution

When an AI agent triggers an MCP tool that maps to a FastAPI route, fastapi-mcp dispatches the request through an in-memory ASGI pipeline (httpx.ASGITransport):

  • No TCP socket handshakes

  • No loopback network latency

  • Sub-millisecond execution speeds

3. Shared Database Pools & Dependencies

Instead of maintaining two independent database connection pools (one for your REST API and one for your MCP server), your MCP tools directly reuse the existing FastAPI Depends(get_db) connection pool and caching layers.

4. Single Source of Truth for Schemas

You define your Pydantic v2 data models once. Both your OpenAPI specification (/docs) and your MCP tool definitions (/mcp/docs) are generated from the exact same model definitions without drift.


๐Ÿ—๏ธ Architecture Overview

                                  +-----------------------+
                                  |   AI Agent / Client   |
                                  | (Claude Desktop, Cursor|
                                  +-----------+-----------+
                                              |
                     +------------------------+-----------------------+
                     | (HTTP / SSE)                                   | (stdio)
                     v                                                v
+--------------------+---------------------+        +-----------------+---------------------+
|        FastAPI ASGI Server (Uvicorn)     |        |      fastapi-mcp CLI (stdio)          |
|  - Swagger UI: /docs                     |        |  (Direct pipe for desktop LLM agents) |
|  - REST Endpoints: /items, /users        |        +-----------------+---------------------+
|  - MCP Streamable: /mcp                  |                          |
|  - MCP SSE Stream: /sse                  |                          |
|  - MCP Swagger Explorer: /mcp/docs       |                          |
+--------------------+---------------------+                          |
                     |                                                |
                     +------------------------+-----------------------+
                                              |
                                              v
                              +---------------+---------------+
                              |    FastAPIMCP Unified Hub     |
                              +---------------+---------------+
                                              |
                    +-------------------------+-------------------------+
                    |                                                   |
                    v                                                   v
+-------------------+--------------------+            +-----------------+-------------------+
|      Route Scanner & Dynamic Tools     |            |         Native MCP Tools            |
| - Inspects Path, Query, Body, Headers  |            | - @app.tool()                       |
| - Filters out Depends(db), Request     |            | - @app.resource()                   |
| - Preserves Pydantic Schema & Docstrings|           | - @app.prompt()                     |
+-------------------+--------------------+            +-----------------+-------------------+
                    |                                                   |
                    v                                                   v
+-------------------+---------------------------------------------------+-------------------+
|                           In-Memory ASGITransport Dispatcher                              |
|   Resolves Depends() -> Validates Schema -> Invokes Route -> Returns Structured Result    |
+-------------------------------------------------------------------------------------------+

๐Ÿ“ฆ Installation

pip install fastapi-fastmcp

(Works with the latest releases of fastapi, mcp, pydantic, httpx, and uvicorn)


๐Ÿš€ Quickstart Guides

Pattern 1: Convert an Existing FastAPI App (2 Lines)

Take any existing FastAPI application with routes, database sessions, and dependencies, and expose it to AI agents:

from fastapi import FastAPI, Depends, Query, Path
from pydantic import BaseModel, Field
from fastapi_mcp import FastAPIMCP

app = FastAPI(title="Store API")

class Item(BaseModel):
    name: str = Field(..., description="Product title")
    price: float = Field(..., description="Product price")

def get_db():
    return {"status": "connected"}

@app.get("/items/{item_id}", summary="Get item details")
async def get_item(
    item_id: int = Path(..., description="Unique product ID"),
    verbose: bool = Query(False, description="Include detailed specs"),
    db: dict = Depends(get_db)  # Auto-resolved in-memory, hidden from LLM schema!
):
    """Retrieve item details by ID."""
    return {"id": item_id, "verbose": verbose, "db": db["status"]}

@app.post("/items", summary="Create item")
async def create_item(item: Item, db: dict = Depends(get_db)):
    """Create a new item in the catalog."""
    return {"status": "created", "item": item.model_dump()}

# -------------------------------------------------------------
# ๐ŸŒŸ CONVERT & MOUNT IN 2 LINES:
# -------------------------------------------------------------
mcp = FastAPIMCP.bind(app, name="StoreMCP")
mcp.mount_to(app, path="/mcp", sse_path="/sse")

Pattern 2: Hybrid Dual API (@app.api_tool)

Build new services where functions are simultaneously REST endpoints and MCP tools:

from fastapi_mcp import FastAPIMCP
from pydantic import BaseModel, Field

# FastAPIMCP is a drop-in replacement for FastAPI
app = FastAPIMCP(title="Hybrid Service", mcp_name="UnifiedServer")

class CalculateRequest(BaseModel):
    x: float = Field(..., description="First operand")
    y: float = Field(..., description="Second operand")
    op: str = Field("add", description="Operation: 'add', 'sub', 'mul', 'div'")

# 1. ๐Ÿ› ๏ธ DUAL ENDPOINT: Accessible via REST POST /math/calc AND as MCP Tool 'calculate'
@app.api_tool("/math/calc", methods=["POST"], tool_name="calculate")
async def calculate(data: CalculateRequest) -> dict:
    """Perform mathematical calculations."""
    if data.op == "add":
        res = data.x + data.y
    elif data.op == "mul":
        res = data.x * data.y
    else:
        res = data.x - data.y
    return {"result": res, "op": data.op}

# 2. ๐Ÿงฉ PURE MCP TOOL: Agent-only tool (hidden from public REST routes)
@app.tool(name="internal_rag_search")
async def internal_search(query: str) -> list[str]:
    """Search internal documentation."""
    return [f"Article match for '{query}'"]

# 3. ๐ŸŒ PURE REST ROUTE: Standard FastAPI route
@app.get("/health")
async def health():
    return {"status": "ok"}

# Mount MCP endpoints onto the server
app.mount_mcp(path="/mcp", sse_path="/sse")

๐ŸŒ Deployment Options

Serve both your REST API and MCP transports from the same port:

uvicorn main:app --host 0.0.0.0 --port 8000

Available endpoints on port 8000:

  • FastAPI Swagger UI: http://localhost:8000/docs

  • MCP Swagger Explorer: http://localhost:8000/mcp/docs

  • MCP Streamable HTTP: http://localhost:8000/mcp

  • MCP Server-Sent Events (SSE): http://localhost:8000/sse


Option B: Split Port Deployment (Network Segmentation)

If your infrastructure requires keeping internal AI traffic on an isolated private port while serving public REST traffic externally:

import uvicorn
import threading

# Serve REST on public port 8000, and MCP on internal port 9000
def run_rest():
    uvicorn.run(app, host="0.0.0.0", port=8000)

def run_mcp():
    # Run standalone MCP SSE or streamable app on isolated port
    mcp_app = mcp.mcp_server.streamable_http_app()
    uvicorn.run(mcp_app, host="127.0.0.1", port=9000)

if __name__ == "__main__":
    threading.Thread(target=run_mcp, daemon=True).start()
    run_rest()

๐Ÿ“– Interactive MCP Swagger Explorer (/mcp/docs)

FastAPI-MCP includes a visual explorer for your MCP tools, served right at /mcp/docs.

Features:

  • Interactive Tool Catalog: Inspect all tools, schemas, and parameter requirements.

  • Live "Try It Out": Input fields for numbers, strings, booleans, and JSON objects.

  • Instant Live Execution: Trigger tool calls directly in the browser and see structured responses in real time.


๐Ÿ’ป Claude Desktop & Cursor Integration

Run your FastAPI application directly over stdio without needing an active HTTP server:

Add this to your claude_desktop_config.json:

{
  "mcpServers": {
    "my-fastapi-app": {
      "command": "python",
      "args": ["-m", "fastapi_mcp.cli", "run", "main:app", "--transport", "stdio"]
    }
  }
}

๐Ÿ›ก๏ธ Enterprise Hardening: Solving Production Bottlenecks

In large enterprise microservices with dozens or hundreds of routes, simply dumping every endpoint as an individual MCP tool creates serious production hurdles. fastapi-mcp ships with built-in primitives to solve them:

1. Librarian Discovery Pattern (Preventing Context Window Bloat)

Exposing 80+ tools dumps 15,000โ€“25,000 tokens into the LLM system prompt on every single turn, degrading reasoning and exploding API bills.

Activate Librarian Mode to condense all catalog tools into 3 lightweight meta-tools:

mcp = FastAPIMCP.bind(app, librarian=True)

The LLM now only sees:

  • list_api_categories(): Browse high-level domains (e.g. billing, inventory, users) with tool summaries.

  • search_api_tools(query, category): Fetch detailed schemas for matching tools on demand.

  • execute_api_tool(tool_name, arguments): Dynamically invoke the requested underlying endpoint.

2. Dry-Run Simulation Mode (enable_dry_run=True)

Allow AI agents to validate parameters and simulate state mutations (POST, PUT, DELETE, PATCH) safely:

mcp = FastAPIMCP.bind(app, enable_dry_run=True)
  • Injects a dry_run: bool = False argument into mutation tools.

  • Dispatches in-memory with X-Dry-Run: true header and ?dry_run=true query parameter.

  • Wraps responses with {"dry_run": True, "simulated": True, "result": ...} so agents can test changes before committing them.

3. Dynamic Session Context Provider (Multi-Tenant Stdio & SSE Auth)

Desktop agents connecting via stdio (like Claude Desktop or Cursor) do not send standard HTTP Authorization: Bearer <token> headers. Without caller context, endpoints with Depends(get_current_user) fail with 401 Unauthorized.

Inject authentication claims dynamically per session:

def resolve_tenant_context(tool_args: dict) -> dict:
    # Resolve active tenant / user from session or environment
    return {"Authorization": "Bearer session-token-xyz", "X-Tenant-ID": "acme-corp"}

mcp = FastAPIMCP.bind(
    app,
    session_context_provider=resolve_tenant_context,
)

# Or update dynamically during runtime
mcp.set_session_context_provider(lambda kwargs: {"Authorization": "Bearer rotated-token"})

๐Ÿ› ๏ธ CLI Utilities

1. Inspect Tools and Schemas

Inspect which tools and schemas are generated from your FastAPI application:

fastapi-mcp inspect main:app

Output:

=== FastAPI-MCP Server: UnifiedServer ===
Found 2 tools:

* Tool: calculate
  Description: [POST /math/calc] Perform mathematical calculations.
  Arguments (1):
    - data: CalculateRequest (required) - Calculation input data

* Tool: internal_rag_search
  Description: Search internal documentation.
  Arguments (1):
    - query: string (required)

Export schema as JSON:

fastapi-mcp inspect main:app --json

2. Run Directly from CLI

fastapi-mcp run main:app --transport stdio
fastapi-mcp run main:app --transport sse

โš™๏ธ Route Filtering & Custom Headers

mcp = FastAPIMCP.bind(
    app,
    # Exclude internal routes
    exclude_paths=["/admin/*", "/metrics"],
    # Only expose routes with specific OpenAPI tags
    include_tags={"mcp", "public"},
    # Filter methods
    include_methods={"GET", "POST"},
    # Static auth headers for protected routes
    default_headers={"Authorization": "Bearer internal-service-token"},
    # Or dynamic headers callback
    headers_factory=lambda: {"X-Request-Source": "mcp-agent"}
)

๐Ÿงช Running Tests

The test suite covers route auto-scanning, in-memory ASGI dispatch, dual-mode decorators, single-port co-hosting, and the MCP Swagger UI:

pytest tests/ -v

๐Ÿ“„ License

MIT License. See LICENSE for details.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Exposes FastAPI endpoints as Model Context Protocol (MCP) tools while preserving existing authentication, schemas, and documentation. It enables seamless integration of FastAPI services into MCP ecosystems using a native ASGI transport layer.
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Converts any REST API endpoints into MCP tools, enabling AI clients like Cursor and Claude Desktop to call internal services directly.
    -
  • F
    license
    Not graded
    quality
    D
    maintenance
    Exposes any REST API as MCP tools, enabling AI agents to discover and call existing HTTP endpoints without modifying the original API.
    -