fastmcp/docs/integrations/asgi.mdx
2025-08-20 16:22:03 -04:00

213 lines
5.6 KiB
Text

---
title: ASGI / Starlette 🤝 FastMCP
sidebarTitle: ASGI / Starlette
description: Integrate FastMCP servers into ASGI applications
icon: server
---
import { VersionBadge } from '/snippets/version-badge.mdx'
<VersionBadge version="2.3.1" />
FastMCP servers can be integrated into existing ASGI applications, allowing you to add MCP functionality to your web applications. This is useful for:
- Adding MCP functionality to an existing website or API
- Mounting MCP servers under specific URL paths
- Combining multiple services in a single application
- Leveraging existing authentication and middleware
## Basic Usage
To integrate a FastMCP server into an ASGI application, use the `http_app()` method to obtain a Starlette application instance:
<Tip>
The `http_app()` method is new in FastMCP 2.3.2. In older versions, use `sse_app()` for SSE transport or `streamable_http_app()` for Streamable HTTP transport.
</Tip>
```python
from fastmcp import FastMCP
mcp = FastMCP("MyServer")
@mcp.tool
def hello(name: str) -> str:
return f"Hello, {name}!"
# Get a Starlette app instance for Streamable HTTP transport (recommended)
http_app = mcp.http_app()
# For legacy SSE transport (deprecated)
sse_app = mcp.http_app(transport="sse")
```
The returned Starlette application can be integrated with other ASGI-compatible web frameworks. The MCP server's endpoint is mounted at `/mcp/` for Streamable HTTP transport and `/sse/` for SSE transport.
### Configuration Options
You can customize the endpoint path and access the FastMCP server instance:
```python
# Custom endpoint path
http_app = mcp.http_app(path="/custom-mcp-path")
# Access the FastMCP server from middleware/routes
# The server is available at: request.app.state.fastmcp_server
```
### Adding Custom Routes
You can add custom web routes directly to your FastMCP server using the `@custom_route` decorator:
```python
from fastmcp import FastMCP
from starlette.requests import Request
from starlette.responses import JSONResponse
mcp = FastMCP("MyServer")
@mcp.custom_route("/api/status", methods=["GET"])
async def get_status(request: Request):
return JSONResponse({"server": "running"})
http_app = mcp.http_app()
```
#### Health Check Endpoints
Health checks are commonly needed for monitoring and load balancing:
```python
from fastmcp import FastMCP
from starlette.requests import Request
from starlette.responses import JSONResponse
mcp = FastMCP("MyServer")
@mcp.custom_route("/health", methods=["GET"])
async def health_check(request: Request):
return JSONResponse({"status": "healthy"})
http_app = mcp.http_app()
```
The health endpoint will be available at `/health` alongside your MCP endpoint at `/mcp/`.
## Starlette Integration
Mount your FastMCP server in another Starlette application:
```python
from fastmcp import FastMCP
from starlette.applications import Starlette
from starlette.routing import Mount
# Create your FastMCP server
mcp = FastMCP("MyServer")
@mcp.tool
def analyze(data: str) -> dict:
return {"result": f"Analyzed: {data}"}
# Create the ASGI app
mcp_app = mcp.http_app(path='/mcp')
# Create a Starlette app and mount the MCP server
app = Starlette(
routes=[
Mount("/mcp-server", app=mcp_app),
# Add other routes as needed
],
lifespan=mcp_app.lifespan,
)
```
The MCP endpoint will be available at `/mcp-server/mcp/` of the resulting Starlette app.
<Warning>
For Streamable HTTP transport, you **must** pass the lifespan context from the FastMCP app to the resulting Starlette app, as nested lifespans are not recognized. Otherwise, the FastMCP server's session manager will not be properly initialized.
</Warning>
### Nested Mounts
You can create complex routing structures by nesting mounts:
```python
from fastmcp import FastMCP
from starlette.applications import Starlette
from starlette.routing import Mount
# Create your FastMCP server
mcp = FastMCP("MyServer")
# Create the ASGI app
mcp_app = mcp.http_app(path='/mcp')
# Create nested application structure
inner_app = Starlette(routes=[Mount("/inner", app=mcp_app)])
app = Starlette(
routes=[Mount("/outer", app=inner_app)],
lifespan=mcp_app.lifespan,
)
```
In this setup, the MCP server is accessible at the `/outer/inner/mcp/` path.
## Custom Middleware
<VersionBadge version="2.3.2" />
Add custom Starlette middleware to your FastMCP ASGI apps by passing a list of middleware instances:
```python
from fastmcp import FastMCP
from starlette.middleware import Middleware
from starlette.middleware.cors import CORSMiddleware
# Create your FastMCP server
mcp = FastMCP("MyServer")
# Define custom middleware
custom_middleware = [
Middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
]
# Create ASGI app with middleware
http_app = mcp.http_app(custom_middleware=custom_middleware)
```
## Running the Server
To run your ASGI application, use an ASGI server like `uvicorn`:
```python
import uvicorn
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
```
Or from the command line:
```bash
uvicorn path.to.your.app:app --host 0.0.0.0 --port 8000
```
## Framework-Specific Integration
### FastAPI
For FastAPI-specific integration patterns including both mounting MCP servers into FastAPI apps and generating MCP servers from FastAPI apps, see the [FastAPI Integration guide](/integrations/fastapi).
### Other ASGI Frameworks
The patterns shown here work with any ASGI-compatible framework. The key requirements are:
1. Mount the FastMCP ASGI app at your desired path
2. Pass the lifespan context to your root application
3. Configure any necessary middleware or authentication