@@ -1261,27 +1261,35 @@ Basic example showing how to mount StreamableHTTP server in Starlette.
12611261Run from the repository root:
12621262 uvicorn examples.snippets.servers.streamable_http_basic_mounting:app --reload
12631263"""
1264+ import contextlib
12641265
12651266from starlette.applications import Starlette
12661267from starlette.routing import Mount
12671268
12681269from mcp.server.fastmcp import FastMCP
12691270
12701271# Create MCP server
1271- mcp = FastMCP(" My App" )
1272+ mcp = FastMCP(" My App" , stateless_http = True )
12721273
12731274
12741275@mcp.tool ()
12751276def hello () -> str :
12761277 """ A simple hello tool"""
12771278 return " Hello from MCP!"
12781279
1280+ # Create lifespan context manager to initialize the session manager
1281+ @contextlib.asynccontextmanager
1282+ async def lifespan (app : Starlette):
1283+ """ Context manager for managing MCP session manager lifecycle."""
1284+ async with mcp.session_manager.run():
1285+ yield
12791286
12801287# Mount the StreamableHTTP server to the existing ASGI server
12811288app = Starlette(
12821289 routes = [
12831290 Mount(" /" , app = mcp.streamable_http_app()),
1284- ]
1291+ ],
1292+ lifespan = lifespan,
12851293)
12861294```
12871295
@@ -1298,27 +1306,35 @@ Example showing how to mount StreamableHTTP server using Host-based routing.
12981306Run from the repository root:
12991307 uvicorn examples.snippets.servers.streamable_http_host_mounting:app --reload
13001308"""
1309+ import contextlib
13011310
13021311from starlette.applications import Starlette
13031312from starlette.routing import Host
13041313
13051314from mcp.server.fastmcp import FastMCP
13061315
13071316# Create MCP server
1308- mcp = FastMCP(" MCP Host App" )
1317+ mcp = FastMCP(" MCP Host App" , stateless_http = True )
13091318
13101319
13111320@mcp.tool ()
13121321def domain_info () -> str :
13131322 """ Get domain-specific information"""
13141323 return " This is served from mcp.acme.corp"
13151324
1325+ # Create lifespan context manager to initialize the session manager
1326+ @contextlib.asynccontextmanager
1327+ async def lifespan (app : Starlette):
1328+ """ Context manager for managing MCP session manager lifecycle."""
1329+ async with mcp.session_manager.run():
1330+ yield
13161331
13171332# Mount using Host-based routing
13181333app = Starlette(
13191334 routes = [
13201335 Host(" mcp.acme.corp" , app = mcp.streamable_http_app()),
1321- ]
1336+ ],
1337+ lifespan = lifespan,
13221338)
13231339```
13241340
@@ -1335,15 +1351,16 @@ Example showing how to mount multiple StreamableHTTP servers with path configura
13351351Run from the repository root:
13361352 uvicorn examples.snippets.servers.streamable_http_multiple_servers:app --reload
13371353"""
1354+ import contextlib
13381355
13391356from starlette.applications import Starlette
13401357from starlette.routing import Mount
13411358
13421359from mcp.server.fastmcp import FastMCP
13431360
13441361# Create multiple MCP servers
1345- api_mcp = FastMCP(" API Server" )
1346- chat_mcp = FastMCP(" Chat Server" )
1362+ api_mcp = FastMCP(" API Server" , stateless_http = True )
1363+ chat_mcp = FastMCP(" Chat Server" , stateless_http = True )
13471364
13481365
13491366@api_mcp.tool ()
@@ -1363,12 +1380,22 @@ def send_message(message: str) -> str:
13631380api_mcp.settings.streamable_http_path = " /"
13641381chat_mcp.settings.streamable_http_path = " /"
13651382
1383+ # Create lifespan context manager to initialize both session managers
1384+ @contextlib.asynccontextmanager
1385+ async def lifespan (app : Starlette):
1386+ """ Context manager for managing multiple MCP session managers."""
1387+ async with contextlib.AsyncExitStack() as stack:
1388+ await stack.enter_async_context(api_mcp.session_manager.run())
1389+ await stack.enter_async_context(chat_mcp.session_manager.run())
1390+ yield
1391+
13661392# Mount the servers
13671393app = Starlette(
13681394 routes = [
13691395 Mount(" /api" , app = api_mcp.streamable_http_app()),
13701396 Mount(" /chat" , app = chat_mcp.streamable_http_app()),
1371- ]
1397+ ],
1398+ lifespan = lifespan,
13721399)
13731400```
13741401
@@ -1385,6 +1412,7 @@ Example showing path configuration during FastMCP initialization.
13851412Run from the repository root:
13861413 uvicorn examples.snippets.servers.streamable_http_path_config:app --reload
13871414"""
1415+ import contextlib
13881416
13891417from starlette.applications import Starlette
13901418from starlette.routing import Mount
@@ -1393,7 +1421,7 @@ from mcp.server.fastmcp import FastMCP
13931421
13941422# Configure streamable_http_path during initialization
13951423# This server will mount at the root of wherever it's mounted
1396- mcp_at_root = FastMCP(" My Server" , streamable_http_path = " /" )
1424+ mcp_at_root = FastMCP(" My Server" , streamable_http_path = " /" , stateless_http = True )
13971425
13981426
13991427@mcp_at_root.tool ()
@@ -1402,11 +1430,19 @@ def process_data(data: str) -> str:
14021430 return f " Processed: { data} "
14031431
14041432
1433+ # Create lifespan context manager to initialize the session manager
1434+ @contextlib.asynccontextmanager
1435+ async def lifespan (app : Starlette):
1436+ """ Context manager for managing MCP session manager lifecycle."""
1437+ async with mcp_at_root.session_manager.run():
1438+ yield
1439+
14051440# Mount at /process - endpoints will be at /process instead of /process/mcp
14061441app = Starlette(
14071442 routes = [
14081443 Mount(" /process" , app = mcp_at_root.streamable_http_app()),
1409- ]
1444+ ],
1445+ lifespan = lifespan,
14101446)
14111447```
14121448
0 commit comments