All posts
mcpfastapi

MCP With FastAPI: A Practical Guide for Full-Stack Developers

A practical guide to mounting a Model Context Protocol server alongside an existing FastAPI application, sharing dependencies and auth.

SR

Suhail Roushan

August 6, 2026

·
5 min read
·
0 views

FastAPI and MCP share more DNA than they first appear to — both lean on Python type hints and Pydantic for schema generation, which makes mounting an MCP server inside an existing FastAPI application feel natural rather than bolted-on.

Integrating MCP with FastAPI means mounting an MCP server (via FastMCP's ASGI integration) as a sub-application within your existing FastAPI app, letting it share the same dependency injection system, database connections, and authentication middleware your REST endpoints already use, rather than standing up separate infrastructure.

Why MCP With FastAPI Matters (and When to Skip It)

For teams with an existing FastAPI backend, mounting MCP as a sub-application reuses your existing dependency injection (database sessions, auth dependencies), Pydantic models, and deployment setup — meaning tool handlers can share the exact same validated data models and service functions your REST routes already use, with less duplication than building a standalone MCP server would require.

Skip a dedicated MCP mount if there's no concrete use case for AI-assistant access to your FastAPI application's data or actions — as with any MCP integration, it's added surface area that should be justified by an actual workflow, not added speculatively.

Getting Started with MCP and FastAPI

Mounting an MCP server as an ASGI sub-application:

from fastapi import FastAPI, Depends
from mcp.server.fastmcp import FastMCP

app = FastAPI()
mcp = FastMCP("my-app")

@mcp.tool()
async def get_user_orders(user_id: str) -> list[dict]:
    """Return all orders for a given user ID."""
    async with get_db_session() as session:
        orders = await order_service.get_by_user(session, user_id)
        return [order.model_dump() for order in orders]

app.mount("/mcp", mcp.streamable_http_app())

Sharing FastAPI's dependency injection within a tool handler, for consistent auth and DB session handling:

@mcp.tool()
async def get_current_user_profile(ctx) -> dict:
    """Return the profile of the currently authenticated user."""
    user = await get_authenticated_user(ctx.request)
    return user.model_dump()

Core MCP With FastAPI Concepts Every Developer Should Know

Mounting as a sub-application preserves middleware from the parent app, meaning authentication, CORS, and logging middleware configured on your main FastAPI app apply to the mounted MCP endpoint too — this is a real convenience, letting you avoid reconfiguring cross-cutting concerns separately for the MCP surface.

Pydantic models used in your FastAPI routes can be reused directly for MCP tool parameters and return types, since both FastAPI and FastMCP build on the same Pydantic-based schema generation — a model already defining your API's request/response shape doesn't need to be redefined for the MCP-facing tool.

Database session and dependency lifecycle need explicit handling in tool handlers, since FastAPI's Depends() injection system is route-scoped and doesn't automatically apply the same way inside an MCP tool function — you typically need to explicitly acquire a session (via a context manager or a shared helper) rather than relying on FastAPI's automatic dependency resolution within the tool handler itself.

Authentication context needs to flow from the request into the tool handler explicitly, similar to the Express integration pattern — the calling user's identity needs to be available to the tool so it can enforce the same authorization rules your REST endpoints apply.

Common Mistakes Integrating MCP With FastAPI and How to Fix Them

Mistake 1: assuming Depends() injection works automatically inside MCP tool handlers the same way it does in FastAPI routes. Fix: explicitly acquire dependencies (database sessions, auth context) within tool handlers using the same underlying helper functions your dependencies wrap, rather than relying on automatic injection that doesn't apply in this context.

Mistake 2: not reusing existing Pydantic models, redefining data shapes separately for MCP tools instead of importing the models already defined for your REST API. Fix: import and reuse existing Pydantic models for tool parameters and return types wherever the shape matches.

Mistake 3: skipping authorization checks in tool handlers, assuming the mounted sub-application inherits security automatically in every respect. Fix: verify explicitly that authentication middleware actually applies to the mounted path as expected, and add explicit authorization checks within tool handlers for user-scoped data.

When Should You Mount MCP as a FastAPI Sub-Application Instead of a Standalone Server?

Mount as a sub-application when you want to share dependency injection, Pydantic models, and middleware with an existing FastAPI application, minimizing duplication. Run a standalone MCP server when the tools it exposes are logically independent from your FastAPI application's domain, or need an entirely separate deployment and scaling profile.

MCP With FastAPI in Production

Verify that authentication and authorization actually apply correctly to the mounted MCP path, since sub-application mounting handles some middleware concerns automatically but tool-level authorization still needs explicit implementation. Also reuse existing Pydantic models and service functions from your REST API wherever possible, keeping a single source of truth for both data shapes and business logic.

If you're running FastAPI already and want to expose it to AI clients, mounting FastMCP as a sub-application is a natural fit that reuses more of your existing infrastructure than most other integration approaches.

Related posts

Written by Suhail Roushan — Full-stack developer. More posts on AI, Next.js, and building products at suhailroushan.com/blog.

Get in touch