Bug Description
All 4 MCP e2e tests in tests/mcp_tests/test_proxy_mcp_e2e.py fail on main with auth errors:
AssertionError: assert 'Error: User not allowed to call this tool.' == '30'
Failing Tests
TestProxyMcpSimpleConnections::test_proxy_mcp_stdio_roundtrip
TestProxyMcpSimpleConnections::test_proxy_mcp_streamable_http_roundtrip
TestProxyMcpSimpleConnections::test_proxy_mcp_lists_all_servers_without_header
TestProxyMcpStatelessBehavior::test_independent_clients_no_shared_session
Root Cause
set_auth_context() at server.py:2063 stores auth info (user_api_key_auth, mcp_servers, etc.) in a ContextVar during the HTTP request handler. However, the MCP StreamableHTTPSessionManager spawns new anyio.TaskGroup tasks for handling protocol messages like call_tool and list_tools.
ContextVar values don't reliably propagate into these spawned tasks, so when get_auth_context() is called inside mcp_server_tool_call (line 302), it returns empty/stale data. This causes get_allowed_mcp_servers() to return an empty list → _get_allowed_mcp_servers_from_mcp_server_names returns empty → 403 "User not allowed to call this tool."
Relevant Code
set_auth_context() — server.py:2197
get_auth_context() — server.py:2227
mcp_server_tool_call reads context — server.py:302
handle_streamable_http_mcp sets context — server.py:2063
Suggested Fixes
- Store auth on the MCP session object — persist auth across protocol messages within a session
- Pass auth explicitly through the MCP handler chain instead of relying on ContextVars
- Use
copy_context().run() when spawning tasks in the session manager to inherit parent context
Environment
- All tests fail locally on main (macOS, Python 3.12+)
- Also fails in GitHub Actions CI
Related
Bug Description
All 4 MCP e2e tests in
tests/mcp_tests/test_proxy_mcp_e2e.pyfail on main with auth errors:Failing Tests
TestProxyMcpSimpleConnections::test_proxy_mcp_stdio_roundtripTestProxyMcpSimpleConnections::test_proxy_mcp_streamable_http_roundtripTestProxyMcpSimpleConnections::test_proxy_mcp_lists_all_servers_without_headerTestProxyMcpStatelessBehavior::test_independent_clients_no_shared_sessionRoot Cause
set_auth_context()atserver.py:2063stores auth info (user_api_key_auth, mcp_servers, etc.) in aContextVarduring the HTTP request handler. However, the MCPStreamableHTTPSessionManagerspawns newanyio.TaskGrouptasks for handling protocol messages likecall_toolandlist_tools.ContextVarvalues don't reliably propagate into these spawned tasks, so whenget_auth_context()is called insidemcp_server_tool_call(line 302), it returns empty/stale data. This causesget_allowed_mcp_servers()to return an empty list →_get_allowed_mcp_servers_from_mcp_server_namesreturns empty → 403 "User not allowed to call this tool."Relevant Code
set_auth_context()—server.py:2197get_auth_context()—server.py:2227mcp_server_tool_callreads context —server.py:302handle_streamable_http_mcpsets context —server.py:2063Suggested Fixes
copy_context().run()when spawning tasks in the session manager to inherit parent contextEnvironment
Related