---
title: Starlette / ASGI 🤝 FastMCP
sidebarTitle: Starlette / ASGI
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

