URL: https://gofastmcp.com/integrations/fastapi
Title: FastAPI 🤝 FastMCP - FastMCP

Documentation Index
Fetch the complete documentation index at:
/llms.txt
Use this file to discover all available pages before exploring further.
Skip to main content
Meet
Prefect Horizon
, the enterprise MCP gateway built by the team behind FastMCP
FastMCP
home page
v3
Prefect Horizon
PrefectHQ/fastmcp
25,596
PrefectHQ/fastmcp
25,596
Search...
Navigation
Web Frameworks
FastAPI 🤝 FastMCP
Search the docs...
Ctrl
K
Documentation
Get Started
Welcome!
Installation
Quickstart
Servers
Overview
Core Components
Working with Tools
MCP Providers
Interactivity
Extensibility
Auth
Deployment
Apps
Overview
Quickstart
NEW
FastMCPApp
NEW
Interactive Tools
NEW
Generative UI
NEW
Custom HTML
Reference
Clients
Overview
Client-Only Package
Transports
fastmcp-remote
Operations
UPDATED
Authentication
UPDATED
Integrations
Auth
Web Frameworks
FastAPI
OpenAPI
AI Assistants
AI SDKs
MCP.json
More
Settings
CLI
Upgrading
Development
What's New
FAQ
On this page
Example FastAPI Application
Generating an MCP Server
Basic Conversion
Adding Components
Interacting with the MCP Server
Custom Route Mapping
Authentication and Headers
Mounting an MCP Server
Basic Mounting
Offering an LLM-Friendly API
Key Considerations
Operation IDs
Lifespan Management
CORS Middleware
Combining Lifespans
Performance Tips
Web Frameworks
FastAPI 🤝 FastMCP
Copy page
Integrate FastMCP with FastAPI applications
Copy page
FastMCP provides two powerful ways to integrate with FastAPI applications:
Generate an MCP server FROM your FastAPI app
- Convert existing API endpoints into MCP tools
Mount an MCP server INTO your FastAPI app
- Add MCP functionality to your web application
When generating an MCP server from FastAPI, FastMCP uses OpenAPIProvider (v3.0.0+) under the hood to source tools from your FastAPI app’s OpenAPI spec. See
Providers
to understand how FastMCP sources components.
Generating MCP servers from OpenAPI 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 OpenAPI servers. This is especially true for complex APIs with many endpoints and parameters.
We recommend using the FastAPI integration for bootstrapping and prototyping, not for mirroring your API to LLM clients. See the post
Stop Converting Your REST APIs to MCP
for more details.
FastMCP does
not
include FastAPI as a dependency; you must install it separately to use this integration.
​
Example FastAPI Application
Throughout this guide, we’ll use this e-commerce API as our example (click the
Copy
button to copy it for use with other code blocks):
# Copy this FastAPI server into other code blocks in this guide
from
fastapi
import
FastAPI
,
HTTPException
from
pydantic
import
BaseModel
# Models
class
Product
(
BaseModel
):
name
:
str
price
:
float
category
:
str
description
:
str
|
None
=
None
class
ProductResponse
(
BaseModel
):
id
:
int
name
:
str
price
:
float
category
:
str
description
:
str
|
None
=
None
# Create FastAPI app
app
=
FastAPI
(
title
=
"
E-commerce API
"
,
version
=
"
1.0.0
"
)
# In-memory database
products_db
=
{
1
:
ProductResponse
(
id
=
1
,
name
=
"
Laptop
"
,
price
=
999.99
,
category
=
"
Electronics
"
),
2
:
ProductResponse
(
id
=
2
,
name
=
"
Mouse
"
,
price
=
29.99
,
category
=
"
Electronics
"
),
3
:
ProductResponse
(
id
=
3
,
name
=
"
Desk Chair
"
,
price
=
299.99
,
category
=
"
Furniture
"
),
}
next_id
=
4
@
app
.
get
(
"
/products
"
,
response_model
=
list
[
ProductResponse
])
def
list_products
(
category
:
str
|
None
=
None
,
max_price
:
float
|
None
=
None
,
)
->
list
[
ProductResponse
]:
"""
List all products with optional filtering.
"""
products
=
list
(
products_db
.
values
())
if
category
:
products
=
[
p
for
p
in
products
if
p
.
category
==
category
]
if
max_price
:
products
=
[
p
for
p
in
products
if
p
.
price
<=
max_price
]
return
products
@
app
.
get
(
"
/products/
{product_id}
"
,
response_model
=
ProductResponse
)
def
get_product
(
product_id
:
int
):
"""
Get a specific product by ID.
"""
if
product_id
not
in
products_db
:
raise
HTTPException
(
status_code
=
404
,
detail
=
"
Product not found
"
)
return
products_db
[
product_id
]
@
app
.
post
(
"
/products
"
,
response_model
=
ProductResponse
)
def
create_product
(
product
:
Product
):
"""
Create a new product.
"""
global
next_id
product_response
=
ProductResponse
(
id
=
next_id
,
**
product
.
model_dump
())
products_db
[
next_id
]
=
product_response
next_id
+=
1
return
product_response
@
app
.
put
(
"
/products/
{product_id}
"
,
response_model
=
ProductResponse
)
def
update_product
(
product_id
:
int
,
product
:
Product
):
"""
Update an existing product.
"""
if
product_id
not
in
products_db
:
raise
HTTPException
(
status_code
=
404
,
detail
=
"
Product not found
"
)
products_db
[
product_id
]
=
ProductResponse
(
id
=
product_id
,
**
product
.
model_dump
(),
)
return
products_db
[
product_id
]
@
app
.
delete
(
"
/products/
{product_id}
"
)
def
delete_product
(
product_id
:
int
):
"""
Delete a product.
"""
if
product_id
not
in
products_db
:
raise
HTTPException
(
status_code
=
404
,
detail
=
"
Product not found
"
)
del
products_db
[
product_id
]
return
{
"
message
"
:
"
Product deleted
"
}
See all 83 lines
All subsequent code examples in this guide assume you have the above FastAPI application code already defined. Each example builds upon this base application,
app
.
​
Generating an MCP Server
New in version
2.0.0
One of the most common ways to bootstrap an MCP server is to generate it from an existing FastAPI application. FastMCP will expose your FastAPI endpoints as MCP components (tools, by default) in order to expose your API to LLM clients.
​
Basic Conversion
Convert the FastAPI app to an MCP server with a single line:
# Assumes the FastAPI app from above is already defined
from
fastmcp
import
FastMCP
# Convert to MCP server
mcp
=
FastMCP
.
from_fastapi
(
app
=
app
)
if
__name__
==
"
__main__
"
:
mcp
.
run
()
​
Adding Components
Your converted MCP server is a full FastMCP instance, meaning you can add new tools, resources, and other components to it just like you would with any other FastMCP instance.
# Assumes the FastAPI app from above is already defined
from
fastmcp
import
FastMCP
# Convert to MCP server
mcp
=
FastMCP
.
from_fastapi
(
app
=
app
)
# Add a new tool
@
mcp
.
tool
def
get_product
(
product_id
:
int
)
->
ProductResponse
:
"""
Get a product by ID.
"""
return
products_db
[
product_id
]
# Run the MCP server
if
__name__
==
"
__main__
"
:
mcp
.
run
()
​
Interacting with the MCP Server
Once you’ve converted your FastAPI app to an MCP server, you can interact with it using the FastMCP client to test functionality before deploying it to an LLM-based application.
# Assumes the FastAPI app from above is already defined
from
fastmcp
import
FastMCP
from
fastmcp
.
client
import
Client
import
asyncio
# Convert to MCP server
mcp
=
FastMCP
.
from_fastapi
(
app
=
app
)
async
def
demo
():
async
with
Client
(
mcp
)
as
client
:
# List available tools
tools
=
await
client
.
list_tools
()
print
(
f
"Available tools:
{
[
t
.
name
for
t
in
tools
]
}
"
)
# Create a product
result
=
await
client
.
call_tool
(
"
create_product_products_post
"
,
{
"
name
"
:
"
Wireless Keyboard
"
,
"
price
"
:
79.99
,
"
category
"
:
"
Electronics
"
,
"
description
"
:
"
Bluetooth mechanical keyboard
"
}
)
print
(
f
"Created product:
{
result
.
data
}
"
)
# List electronics under $100
result
=
await
client
.
call_tool
(
"
list_products_products_get
"
,
{
"
category
"
:
"
Electronics
"
,
"
max_price
"
:
100
}
)
print
(
f
"Affordable electronics:
{
result
.
data
}
"
)
if
__name__
==
"
__main__
"
:
asyncio
.
run
(
demo
())
​
Custom Route Mapping
Because FastMCP’s FastAPI integration is based on its
OpenAPI integration
, you can customize how endpoints are converted to MCP components in exactly the same way. For example, here we use a
RouteMap
to map all GET requests to MCP resources, and all POST/PUT/DELETE requests to MCP tools:
# Assumes the FastAPI app from above is already defined
from
fastmcp
import
FastMCP
from
fastmcp
.
server
.
providers
.
openapi
import
RouteMap
,
MCPType
# Custom mapping rules
mcp
=
FastMCP
.
from_fastapi
(
app
=
app
,
route_maps
=[
# GET with path params → ResourceTemplates
RouteMap
(
methods
=[
"
GET
"
],
pattern
=
r
"
.
*
\{
.
*
\}
.
*
"
,
mcp_type
=
MCPType
.
RESOURCE_TEMPLATE
),
# Other GETs → Resources
RouteMap
(
methods
=[
"
GET
"
],
pattern
=
r
"
.
*
"
,
mcp_type
=
MCPType
.
RESOURCE
),
# POST/PUT/DELETE → Tools (default)
],
)
# Now:
# - GET /products → Resource
# - GET /products/{id} → ResourceTemplate
# - POST/PUT/DELETE → Tools
To learn more about customizing the conversion process, see the
OpenAPI Integration guide
.
​
Authentication and Headers
You can configure headers and other client options via the
httpx_client_kwargs
parameter. For example, to add authentication to your FastAPI app, you can pass a
headers
dictionary to the
httpx_client_kwargs
parameter:
# Assumes the FastAPI app from above is already defined
from
fastmcp
import
FastMCP
# Add authentication to your FastAPI app
from
fastapi
import
Depends
,
Header
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 authentication
"
)
return
credentials
.
credentials
# Add a protected endpoint
@
app
.
get
(
"
/admin/stats
"
,
dependencies
=[
Depends
(
verify_token
)])
def
get_admin_stats
():
return
{
"
total_products
"
:
len
(
products_db
),
"
categories
"
:
list
(
set
(
p
.
category
for
p
in
products_db
.
values
()))
}
# Create MCP server with authentication headers
mcp
=
FastMCP
.
from_fastapi
(
app
=
app
,
httpx_client_kwargs
={
"
headers
"
:
{
"
Authorization
"
:
"
Bearer secret-token
"
,
}
}
)
​
Mounting an MCP Server
New in version
2.3.1
In addition to generating servers, FastMCP can facilitate adding MCP servers to your existing FastAPI application. You can do this by mounting the MCP ASGI application.
​
Basic Mounting
To mount an MCP server, you can use the
http_app
method on your FastMCP instance. This will return an ASGI application that can be mounted to your FastAPI application.
from
fastmcp
import
FastMCP
from
fastapi
import
FastAPI
# Create MCP server
mcp
=
FastMCP
(
"
Analytics Tools
"
)
@
mcp
.
tool
def
analyze_pricing
(
category
:
str
)
->
dict
:
"""
Analyze pricing for a category.
"""
products
=
[
p
for
p
in
products_db
.
values
()
if
p
.
category
==
category
]
if
not
products
:
return
{
"
error
"
:
f
"No products in
{
category
}
"
}
prices
=
[
p
.
price
for
p
in
products
]
return
{
"
category
"
:
category
,
"
avg_price
"
:
round
(
sum
(
prices
)
/
len
(
prices
),
2
),
"
min
"
:
min
(
prices
),
"
max
"
:
max
(
prices
),
}
# Create ASGI app from MCP server
mcp_app
=
mcp
.
http_app
(
path
=
'
/mcp
'
)
# Key: Pass lifespan to FastAPI
app
=
FastAPI
(
title
=
"
E-commerce API
"
,
lifespan
=
mcp_app
.
lifespan
)
# Mount the MCP server
app
.
mount
(
"
/analytics
"
,
mcp_app
)
# Now: API at /products/*, MCP at /analytics/mcp/
​
Offering an LLM-Friendly API
A common pattern is to generate an MCP server from your FastAPI app and serve both interfaces from the same application. This provides an LLM-optimized interface alongside your regular API:
# Assumes the FastAPI app from above is already defined
from
fastmcp
import
FastMCP
from
fastapi
import
FastAPI
# 1. Generate MCP server from your API
mcp
=
FastMCP
.
from_fastapi
(
app
=
app
,
name
=
"
E-commerce MCP
"
)
# 2. Create the MCP's ASGI app
mcp_app
=
mcp
.
http_app
(
path
=
'
/mcp
'
)
# 3. Create a new FastAPI app that combines both sets of routes
combined_app
=
FastAPI
(
title
=
"
E-commerce API with MCP
"
,
routes
=[
*
mcp_app
.
routes
,
# MCP routes
*
app
.
routes
,
# Original API routes
],
lifespan
=
mcp_app
.
lifespan
,
)
# Now you have:
# - Regular API: http://localhost:8000/products
# - LLM-friendly MCP: http://localhost:8000/mcp
# Both served from the same FastAPI application!
This approach lets you maintain a single codebase while offering both traditional REST endpoints and MCP-compatible endpoints for LLM clients.
​
Key Considerations
​
Operation IDs
FastAPI operation IDs become MCP component names. Always specify meaningful operation IDs:
# Good - explicit operation_id
@
app
.
get
(
"
/users/
{user_id}
"
,
operation_id
=
"
get_user_by_id
"
)
def
get_user
(
user_id
:
int
):
return
{
"
id
"
:
user_id
}
# Less ideal - auto-generated name
@
app
.
get
(
"
/users/
{user_id}
"
)
def
get_user
(
user_id
:
int
):
return
{
"
id
"
:
user_id
}
​
Lifespan Management
When mounting MCP servers, always pass the lifespan context:
# Correct - lifespan passed, path="/" since we mount at /mcp
mcp_app
=
mcp
.
http_app
(
path
=
"
/
"
)
app
=
FastAPI
(
lifespan
=
mcp_app
.
lifespan
)
app
.
mount
(
"
/mcp
"
,
mcp_app
)
# MCP endpoint at /mcp
# Incorrect - missing lifespan
app
=
FastAPI
()
app
.
mount
(
"
/mcp
"
,
mcp
.
http_app
(
path
=
"
/
"
))
# Session manager won't initialize
If you’re mounting an authenticated MCP server under a path prefix, see
Mounting Authenticated Servers
for important OAuth routing considerations.
​
CORS Middleware
If your FastAPI app uses
CORSMiddleware
and you’re mounting an OAuth-protected FastMCP server, avoid adding application-wide CORS middleware. FastMCP and the MCP SDK already handle CORS for OAuth routes, and layering CORS middleware can cause conflicts (such as 404 errors on
.well-known
routes or OPTIONS requests).
If you need CORS on your own FastAPI routes, use the sub-app pattern: mount your API and FastMCP as separate apps, each with their own middleware, rather than adding top-level
CORSMiddleware
to the combined application.
​
Combining Lifespans
If your FastAPI app already has a lifespan (for database connections, startup tasks, etc.), you can’t simply replace it with the MCP lifespan. Use
combine_lifespans
to run both:
from
fastapi
import
FastAPI
from
fastmcp
import
FastMCP
from
fastmcp
.
utilities
.
lifespan
import
combine_lifespans
from
contextlib
import
asynccontextmanager
# Your existing lifespan
@
asynccontextmanager
async
def
app_lifespan
(
app
:
FastAPI
):
print
(
"
Starting up the app...
"
)
yield
print
(
"
Shutting down the app...
"
)
# Create MCP server
mcp
=
FastMCP
(
"
Tools
"
)
mcp_app
=
mcp
.
http_app
(
path
=
"
/
"
)
# Combine both lifespans
app
=
FastAPI
(
lifespan
=
combine_lifespans
(
app_lifespan
,
mcp_app
.
lifespan
))
app
.
mount
(
"
/mcp
"
,
mcp_app
)
# MCP endpoint at /mcp
combine_lifespans
enters lifespans in order and exits in reverse order.
​
Performance Tips
Use in-memory transport for testing
- Pass MCP servers directly to clients
Design purpose-built MCP tools
- Better than auto-converting complex APIs
Keep tool parameters simple
- LLMs perform better with focused interfaces
For more details on configuration options, see the
OpenAPI Integration guide
.
WorkOS 🤝 FastMCP
Previous
OpenAPI 🤝 FastMCP
Next
Ctrl
+I
discord
github
website
x
Powered by
This documentation is built and hosted on Mintlify, a developer documentation platform
Assistant
Responses are generated using AI and may contain mistakes.
\n\n
\n
\n \n
\n
