How to manage lifespan for multiple FastMCP streamable HTTP servers mounted in one FastAPI app?
Using MCP Python SDK 1.8.1 with FastAPI and uvicorn on macOS, the reporter mounted two FastMCP streamable HTTP servers at /echo and /math. The FastAPI lifespan was set to only one server's session_manager.run(), so /echo worked but POST /math/mcp returned a 500 error after a 307 redirect. The question is how to start the lifespan for multiple streamable HTTP servers.
Originally asked on GitHub: https://github.com/modelcontextprotocol/python-sdk/issues/713
4 answers
Status: closed as completed. The maintainer replied that the example in the README was updated, but the thread does not paste the corrected code, and no commenter confirms a working multi-server setup.
The reporter's FastAPI app used a lifespan that only called
echo_mcp.session_manager.run(), while a second FastMCP app withstateless_http=Truewas mounted at/math. The request to/math/mcpwas redirected with a 307 to/math/mcp/, then returned a 500 error.Other commenters reported the same symptom with their own attempts:
- Using
mcp_app.lifespanfrom a single FastMCPhttp_app()as the FastAPI lifespan still produced the same problem for one commenter. That commenter used the fastmcp package, not the official SDK. - A combined lifespan helper that enters each mounted app's
lifespaninside anAsyncExitStackraisedRuntimeError: ... task group was not initializedfor another commenter.
General advice, not from the thread: each mounted streamable HTTP app's session manager needs to be started by the parent app's lifespan. Check the current README example and mirror its exact pattern. Call the trailing-slash URL directly to avoid the 307 redirect.
Did this work for you?- Using
What a GitHub user tried on GitHub (Didn't work)
Mounted /echo and /math in one FastAPI app with FastAPI(lifespan=lambda app: echo_mcp.session_manager.run()). Requests to /math/mcp returned a 307 redirect and then a 500 error. The reporter used mcp 1.8.1 with streamablehttp_client.
Source: https://github.com/modelcontextprotocol/python-sdk/issues/713 (opens external site)
Did this work for you?What @bygzyz tried on GitHub (Didn't work)
Used FastAPI(lifespan=mcp_app.lifespan, routes=[Mount('/mcp_http_kn', app=mcp_app)]) with a FastMCP http_app() from the fastmcp package. The commenter reported getting the same problem.
Did this work for you?What @ZhangHaoWeb tried on GitHub (Didn't work)
Built a Starlette app with a combined_lifespan(proxy_apps) helper that enters each proxy app's asgi_app.lifespan(app) in an AsyncExitStack. The commenter reported a RuntimeError saying the FastMCP task group was not initialized.
Did this work for you?
Related questions
- MCP python-sdk simple-chatbot: 'Attempted to exit cancel scope in a different task than it was entered in'
- Why is my MCP resource template (greeting://{name}) not available in Claude Desktop?
- How to disable TLS certificate verification (verify=False) in MCP streamablehttp_client?
- anyio.ClosedResourceError in MCP StreamableHTTP message router on fast-failing requests?
- Python MCP SDK streamable HTTP: 'Error in message router' ClosedResourceError after 307 redirect