@@ -51,6 +51,9 @@ class StreamableHTTPSessionManager:
5151 json_response: Whether to use JSON responses instead of SSE streams
5252 stateless: If True, creates a completely fresh transport for each request
5353 with no session tracking or state persistence between requests.
54+ single_tenant: If True, only one transport will be created to process the entire
55+ every request, regardless of the MCP session id. This is useful for
56+ hosting platforms where the MCP server is launched in a single-tenant box.
5457 """
5558
5659 def __init__ (
@@ -59,12 +62,18 @@ def __init__(
5962 event_store : EventStore | None = None ,
6063 json_response : bool = False ,
6164 stateless : bool = False ,
65+ single_tenant : bool = False ,
6266 security_settings : TransportSecuritySettings | None = None ,
6367 ):
6468 self .app = app
6569 self .event_store = event_store
6670 self .json_response = json_response
6771 self .stateless = stateless
72+ self .single_tenant = single_tenant
73+ if self .stateless and self .single_tenant :
74+ # A single-tenant server must be stateful, but stateful server does not
75+ # have to be single tenant.
76+ raise ValueError ("A single-tenant server must stateful." )
6877 self .security_settings = security_settings
6978
7079 # Session tracking (only used if not stateless)
@@ -209,6 +218,19 @@ async def _handle_stateful_request(
209218 request = Request (scope , receive )
210219 request_mcp_session_id = request .headers .get (MCP_SESSION_ID_HEADER )
211220
221+ if self .single_tenant and self ._server_instances :
222+ # being single_tenant means that there is only one ASGI server for the entire application.
223+ # that server is used to process all the mcp requests because the hosting platform
224+ # is already distributing the request to the box where the single-tenant mcp server runs.
225+ assert len (self ._server_instances ) == 1
226+ # hosting platforms might exposes a different mcp session ID hence
227+ # we take the first key of server instances as the mcp session id
228+ request_mcp_session_id = next (iter (self ._server_instances .keys ()))
229+ headers = dict (scope ["headers" ])
230+ # Also need to reset the incoming request mcp session id to this existing session id
231+ headers [MCP_SESSION_ID_HEADER .encode ("latin-1" )] = request_mcp_session_id .encode ("latin-1" )
232+ scope ["headers" ] = list (headers .items ())
233+
212234 # Existing session case
213235 if request_mcp_session_id is not None and request_mcp_session_id in self ._server_instances :
214236 transport = self ._server_instances [request_mcp_session_id ]
0 commit comments