Skip to content

OAuth discovery initialize POST probe can create server sessions that are never DELETEd #1048

Description

@DaleSeo

Summary

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:

  1. discover_resource_metadata_url() first issues a GET against the base URL via fetch_resource_metadata_url(), hoping for a 401 + WWW-Authenticate.
  2. Many streamable HTTP servers answer a session-less GET with 404/405, in which case fetch_resource_metadata_url_with_post_probe() POSTs RESOURCE_METADATA_POST_PROBE_BODY — a synthetic initialize request with protocolVersion: 2024-11-05.
  3. 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.
  • Callers that use discovery to check whether a server supports OAuth (the same usage pattern described in OAuth discovery should distinguish discovered authorization metadata from synthesized legacy endpoints #1037) trigger this side effect on servers that don't require auth at all — exactly the servers that will process the probe.
  • 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

  1. 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.
  2. 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.
  3. 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.

Related

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions