You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
During OAuth discovery, when a GET to the MCP endpoint returns 404 or 405, AuthorizationManager falls back to POSTing a synthetic JSON-RPC initialize request to the endpoint in order to elicit a 401 response with a WWW-Authenticate header. If the server actually accepts that initialize instead of rejecting it (e.g. authorization is optional, or initialize is served before authentication), the server may allocate a session and return an Mcp-Session-Id. The client discards any non-401 probe response without ever sending an HTTP DELETE for that session, so the session is orphaned on the server.
Separately, the MCP spec does not clearly indicate that clients should send initialize as part of OAuth discovery at all. The probe exists as a pragmatic workaround for streamable HTTP servers that reject a session-less GET, but it means discovery — which callers reasonably expect to be a read-only operation — can have server-side side effects.
Current behavior
At 6839cfd, resource metadata discovery works like this:
Any response other than 401 is logged and discarded. If the server processed the initialize and returned an Mcp-Session-Id, no DELETE is ever sent for it.
The probe was introduced in #960 to pass the client conformance suite against servers that reject session-less GETs.
Why this is a problem
Servers where authorization is optional (or where initialize is allowed pre-auth) accumulate orphaned sessions: one per discovery attempt, never cleaned up.
The spec describes discovery via 401 + WWW-Authenticate (RFC 9728) and well-known metadata paths; it does not sanction initialize as a discovery mechanism, so servers have no reason to expect or special-case this probe.
Possible fixes
Best-effort cleanup: when the probe response is not 401 and carries an Mcp-Session-Id header, send an HTTP DELETE for that session before discarding the response.
Make the probe a last resort: try the well-known oauth-protected-resource paths before falling back to the POST probe (today the probe runs before the well-known lookup), so most servers never receive a synthetic initialize.
Upstream spec clarification: raise with the spec repo whether clients are intended to send initialize as part of OAuth discovery at all, and what server-side session semantics apply to unauthenticated probe requests.
Options 1 and 2 are complementary and could both be implemented in the SDK regardless of the spec discussion.
Summary
During OAuth discovery, when a
GETto the MCP endpoint returns404or405,AuthorizationManagerfalls back to POSTing a synthetic JSON-RPCinitializerequest to the endpoint in order to elicit a401response with aWWW-Authenticateheader. If the server actually accepts thatinitializeinstead of rejecting it (e.g. authorization is optional, orinitializeis served before authentication), the server may allocate a session and return anMcp-Session-Id. The client discards any non-401probe response without ever sending an HTTPDELETEfor that session, so the session is orphaned on the server.Separately, the MCP spec does not clearly indicate that clients should send
initializeas part of OAuth discovery at all. The probe exists as a pragmatic workaround for streamable HTTP servers that reject a session-lessGET, but it means discovery — which callers reasonably expect to be a read-only operation — can have server-side side effects.Current behavior
At
6839cfd, resource metadata discovery works like this:discover_resource_metadata_url()first issues aGETagainst the base URL viafetch_resource_metadata_url(), hoping for a401+WWW-Authenticate.GETwith404/405, in which casefetch_resource_metadata_url_with_post_probe()POSTsRESOURCE_METADATA_POST_PROBE_BODY— a syntheticinitializerequest withprotocolVersion: 2024-11-05.401is logged and discarded. If the server processed theinitializeand returned anMcp-Session-Id, noDELETEis ever sent for it.The probe was introduced in #960 to pass the client conformance suite against servers that reject session-less
GETs.Why this is a problem
initializeis allowed pre-auth) accumulate orphaned sessions: one per discovery attempt, never cleaned up.401+WWW-Authenticate(RFC 9728) and well-known metadata paths; it does not sanctioninitializeas a discovery mechanism, so servers have no reason to expect or special-case this probe.Possible fixes
401and carries anMcp-Session-Idheader, send an HTTPDELETEfor that session before discarding the response.oauth-protected-resourcepaths before falling back to the POST probe (today the probe runs before the well-known lookup), so most servers never receive a syntheticinitialize.initializeas part of OAuth discovery at all, and what server-side session semantics apply to unauthenticated probe requests.Options 1 and 2 are complementary and could both be implemented in the SDK regardless of the spec discussion.
Related