Skip to content

StreamableHTTPClientTransport doesn't handle 404 per spec (no session clear + re-init) #1708

@mbochneak

Description

@mbochneak

The MCP spec (2025-03-26), Session Management point 4 says:

When a client receives HTTP 404 in response to a request containing an Mcp-Session-Id, it MUST start a new session by sending a new InitializeRequest without a session ID attached.

Neither send() (POST) nor _startOrAuthSse() (GET) handle 404. Both paths just throw StreamableHTTPError. There's no session ID clearing and no re-initialization.

send() has retry logic for 401 (auth) and 403 (insufficient_scope), but 404 falls through to:

throw new StreamableHTTPError(response.status, `Error POSTing to endpoint: ${text}`);

Since _sessionId isn't cleared before the throw, subsequent send() calls keep sending the stale session ID and keep getting 404. It's not a transient failure - the client is stuck until it's destroyed and recreated.

This means servers that correctly return 404 for expired/unknown session IDs (as #389 asks them to) permanently break SDK-based clients instead of triggering a graceful reconnect.

Expected behavior: On 404, clear _sessionId and either re-initialize the session automatically or surface an event that lets the Client layer handle re-initialization (since InitializeRequest involves capability negotiation that the transport doesn't own).

Ref: #389 tracks the server-side of this (examples returning 400 instead of 404). This is the client-side counterpart. Affects v1.26.0 and v1.27.1.

Metadata

Metadata

Assignees

No one assigned

    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