44
55# Ussing the experimental parser as FASTMCP_EXPERIMENTAL_ENABLE_NEW_OPENAPI_PARSER=true is set in env
66from fastmcp .experimental .server .openapi import RouteMap , MCPType
7- from fastmcp .server .http import create_streamable_http_app , StarletteWithLifespan , EventStore
7+ from fastmcp .server .http import create_streamable_http_app , StarletteWithLifespan
8+
9+ from mcp .server .streamable_http import EventStore
810
911from app .mcp .redis_event_store import RedisEventStore
1012from app .utils .logging_config import get_logger
@@ -65,25 +67,31 @@ def create_mcp_app(
6567 sticky routing by Mcp-Session-Id, or you will see 400 “No valid session ID”.
6668 - `EVENT_STORE`:
6769 * True stateful sessions shared across workers via a central event store (e.g., Redis).
68- * Optional: still add sticky routing to reduce cross-worker chatter.
70+ * Experimental: still add sticky routing to reduce cross-worker chatter.
71+ * sticky routing should be keyed on the Mcp-Session-Id from header;
72+ MCP Streamable HTTP uses this header to keep sessions.
73+
74+ Docs:
75+ - [MCP Transports](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports)
6976 """
70- # Important: expose sub-app at "/" and MOUNT it at "/mcp" later to avoid double-prefixing.
71- # path is "/" here; we'll mount under " /mcp" in the main app.
77+ # Sine we are using the Route-merge pattern it expects the MCP app itself to be mounted at /mcp
78+ # (i.e., the sub-app's internal path is /mcp)
7279 logger .info (f"Creating MCP App with { mode } " )
7380 match mode :
7481 case McpAppModes .STATELESS :
7582 return mcp_server .http_app (
76- path = "/" ,
83+ path = "/mcp " ,
7784 json_response = True ,
7885 stateless_http = True , # multi-worker friendly
79- transport = "http" , # or "streamable- http" (both hit the same factory)
86+ transport = "streamable- http" , # or "http" (both hit the same factory)
8087 )
8188
8289 case McpAppModes .STATEFUL :
8390 return mcp_server .http_app (
84- path = "/" ,
91+ path = "/mcp " ,
8592 json_response = True ,
8693 # stateless_http defaults to False => stateful per-process
94+ transport = "streamable-http" ,
8795 )
8896
8997 case McpAppModes .EVENT_STORE :
@@ -94,7 +102,7 @@ def create_mcp_app(
94102
95103 return create_streamable_http_app (
96104 server = mcp_server ,
97- streamable_http_path = "/" ,
105+ streamable_http_path = "/mcp " ,
98106 event_store = redis_store , # enable cross-worker resumability
99107 json_response = True ,
100108 # stateless_http=False # default (stateful)
0 commit comments