diff --git a/litellm/proxy/_experimental/mcp_server/server.py b/litellm/proxy/_experimental/mcp_server/server.py index ba107a9dd10..31836a27509 100644 --- a/litellm/proxy/_experimental/mcp_server/server.py +++ b/litellm/proxy/_experimental/mcp_server/server.py @@ -149,7 +149,7 @@ class ListMCPToolsRestAPIResponseObject(MCPTool): app=server, event_store=None, json_response=False, # enables SSE streaming - stateless=False, # enables session state + stateless=True, ) # Create SSE session manager diff --git a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_server.py b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_server.py index 8996ef1b7e7..0513650e1ff 100644 --- a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_server.py +++ b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_server.py @@ -779,6 +779,30 @@ async def init_task(): mcp_server._sse_session_manager_cm = original_sse_session_cm +@pytest.mark.asyncio +async def test_streamable_http_session_manager_is_stateless(): + """ + Test that the StreamableHTTPSessionManager is initialized with stateless=True. + + Regression test for GitHub issue #20242 / PR #19809. + When stateless=False, the mcp library rejects non-initialize requests + that lack an mcp-session-id header, breaking clients like MCP Inspector, + curl, and any HTTP client without automatic session management. + """ + try: + from litellm.proxy._experimental.mcp_server.server import session_manager + except ImportError: + pytest.skip("MCP server not available") + + # The session manager must be stateless to avoid requiring mcp-session-id + # on every request. This was regressed by PR #19809 (stateless=True -> False). + assert session_manager.stateless is True, ( + "StreamableHTTPSessionManager must be initialized with stateless=True. " + "stateless=False breaks MCP clients that don't manage session IDs. " + "See: https://github.com/BerriAI/litellm/issues/20242" + ) + + @pytest.mark.asyncio @pytest.mark.no_parallel async def test_mcp_routing_with_conflicting_alias_and_group_name():