Skip to content

Commit 64ee2a9

Browse files
committed
Add lifespan example with ASGI interaction explanations
1 parent c44e68f commit 64ee2a9

File tree

1 file changed

+55
-0
lines changed

1 file changed

+55
-0
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
"""
2+
Example showing ASGI route mounting with lifespan context management.
3+
4+
From the repository root:
5+
cd examples/snippets/servers
6+
uv run streamable_uvicorn_lifespan.py
7+
"""
8+
9+
import contextlib
10+
11+
from starlette.applications import Starlette
12+
from starlette.routing import Mount
13+
14+
from mcp.server.fastmcp import FastMCP
15+
16+
# Create MCP server
17+
mcp = FastMCP(name="My App", stateless_http=True)
18+
19+
20+
@mcp.tool()
21+
def ping() -> str:
22+
"""A simple ping tool"""
23+
return "pong"
24+
25+
26+
# lifespan for managing the session manager
27+
@contextlib.asynccontextmanager
28+
async def lifespan(app: Starlette):
29+
"""Gather any session managers for startup/shutdown.
30+
See streamable_starlette_mount.py for example of multiple mcp managers.
31+
"""
32+
async with mcp.session_manager.run():
33+
yield
34+
35+
36+
"""Create the Starlette app and mount the MCP server.
37+
lifespan ensures the session manager is started/stopped with the app.
38+
session_manager references must only be made after streamable_http_app()
39+
"""
40+
app = Starlette(
41+
routes=[
42+
# Mounted at /mcp
43+
Mount("/", app=mcp.streamable_http_app()),
44+
],
45+
lifespan=lifespan,
46+
)
47+
48+
if __name__ == "__main__":
49+
import uvicorn
50+
51+
"""Attach to another ASGI server LIFO
52+
ASGI chain: Uvicorn -> Starlette -> FastMCP
53+
Route: http://0.0.0.0:8000/mcp
54+
"""
55+
uvicorn.run(app, host="0.0.0.0", port=8000)

0 commit comments

Comments
 (0)