mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-17 02:59:11 +02:00
214 lines
No EOL
6.7 KiB
Text
214 lines
No EOL
6.7 KiB
Text
---
|
|
title: Integrating FastMCP in ASGI Applications
|
|
sidebarTitle: ASGI Integration
|
|
description: Integrate FastMCP servers into existing Starlette, FastAPI, or other ASGI applications
|
|
icon: plug
|
|
---
|
|
|
|
import { VersionBadge } from '/snippets/version-badge.mdx'
|
|
|
|
|
|
While FastMCP provides standalone server capabilities, you can also integrate your FastMCP server into existing web applications. This approach 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
|
|
|
|
Please note that all FastMCP servers have a `run()` method that can be used to start the server. This guide focuses on integration with broader ASGI frameworks.
|
|
|
|
## ASGI Server
|
|
|
|
FastMCP servers can be created as [Starlette](https://www.starlette.io/) ASGI apps for straightforward hosting or integration into existing applications.
|
|
|
|
The first step is to obtain a Starlette application instance from your FastMCP server using the `http_app()` method:
|
|
|
|
<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")
|
|
```
|
|
|
|
Both approaches return a Starlette application that can be integrated with other ASGI-compatible web frameworks.
|
|
|
|
The returned app stores the `FastMCP` instance on `app.state.fastmcp_server`, so you
|
|
can access it from custom middleware or routes via `request.app.state.fastmcp_server`.
|
|
|
|
The MCP server's endpoint is mounted at the root path `/mcp` for Streamable HTTP transport, and `/sse` for SSE transport, though you can change these paths by passing a `path` argument to the `http_app()` method:
|
|
|
|
```python
|
|
# For Streamable HTTP transport
|
|
http_app = mcp.http_app(path="/custom-mcp-path")
|
|
|
|
# For SSE transport (deprecated)
|
|
sse_app = mcp.http_app(path="/custom-sse-path", transport="sse")
|
|
```
|
|
|
|
### Running the Server
|
|
|
|
To run the FastMCP server, you can use the `uvicorn` ASGI server:
|
|
|
|
```python
|
|
from fastmcp import FastMCP
|
|
import uvicorn
|
|
|
|
mcp = FastMCP("MyServer")
|
|
|
|
http_app = mcp.http_app()
|
|
|
|
if __name__ == "__main__":
|
|
uvicorn.run(http_app, host="0.0.0.0", port=8000)
|
|
```
|
|
|
|
Or, from the command line:
|
|
|
|
```bash
|
|
uvicorn path.to.your.app:http_app --host 0.0.0.0 --port 8000
|
|
```
|
|
|
|
### Custom Middleware
|
|
|
|
<VersionBadge version="2.3.2" />
|
|
|
|
You can add custom Starlette middleware to your FastMCP ASGI apps by passing a list of middleware instances to the app creation methods:
|
|
|
|
```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=["*"]),
|
|
]
|
|
|
|
# Create ASGI app with custom middleware
|
|
http_app = mcp.http_app(middleware=custom_middleware)
|
|
```
|
|
|
|
|
|
## Starlette Integration
|
|
|
|
<VersionBadge version="2.3.1" />
|
|
|
|
You can 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 as well as any tools, resources, etc.
|
|
mcp = FastMCP("MyServer")
|
|
|
|
# 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 as well as any tools, resources, etc.
|
|
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 of the resulting Starlette app.
|
|
|
|
<Warning>
|
|
For Streamable HTTP transport, you **must** pass the lifespan context from the FastMCP app to the *outer* Starlette app, as nested lifespans are not recognized. Otherwise, the FastMCP server's session manager will not be properly initialized.
|
|
</Warning>
|
|
## FastAPI Integration
|
|
|
|
<VersionBadge version="2.3.1" />
|
|
|
|
FastAPI is built on Starlette, so you can mount your FastMCP server in a similar way:
|
|
|
|
```python
|
|
from fastmcp import FastMCP
|
|
from fastapi import FastAPI
|
|
from starlette.routing import Mount
|
|
|
|
# Create your FastMCP server as well as any tools, resources, etc.
|
|
mcp = FastMCP("MyServer")
|
|
|
|
# Create the ASGI app
|
|
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)
|
|
```
|
|
|
|
The MCP endpoint will be available at `/mcp-server/mcp` of the resulting FastAPI app.
|
|
|
|
<Warning>
|
|
For Streamable HTTP transport, you **must** pass the lifespan context from the FastMCP app to the resulting FastAPI app, as nested lifespans are not recognized. Otherwise, the FastMCP server's session manager will not be properly initialized.
|
|
</Warning>
|
|
|
|
|
|
## Custom Routes
|
|
|
|
In addition to adding your FastMCP server to an existing ASGI app, you can also add custom web routes to your FastMCP server, which will be exposed alongside the MCP endpoint. To do so, use the `@custom_route` decorator. Note that this is less flexible than using a full ASGI framework, but can be useful for adding simple endpoints like health checks to your standalone server.
|
|
|
|
```python
|
|
from fastmcp import FastMCP
|
|
from starlette.requests import Request
|
|
from starlette.responses import PlainTextResponse
|
|
|
|
mcp = FastMCP("MyServer")
|
|
|
|
@mcp.custom_route("/health", methods=["GET"])
|
|
async def health_check(request: Request) -> PlainTextResponse:
|
|
return PlainTextResponse("OK")
|
|
```
|
|
|
|
These routes will be included in the FastMCP app when mounted in your web application. |