Skip to content

[Client] Invalidate expired HTTP sessions - #560

Open
ineersa wants to merge 1 commit into
modelcontextprotocol:mainfrom
ineersa:task/fix-http-session-expiry
Open

ineersa wants to merge 1 commit into
modelcontextprotocol:mainfrom
ineersa:task/fix-http-session-expiry

Conversation

@ineersa

@ineersa ineersa commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #559.

Problem

A request carrying Mcp-Session-Id can receive HTTP 404 when its session expires. Empty or plain-text responses currently leave the request waiting until timeout, while the client still reports itself connected.

Session expiry during a legacy notifications/cancelled POST has the same problem. Protocol::notifyCancellation() logs notification failures and preserves the original interruption, so throwing a connection exception alone does not invalidate the client.

Changes

On HTTP 404 for a request carrying Mcp-Session-Id, HttpTransport::send() now:

  • Closes the response body.
  • Clears the tracked session ID and marks the client uninitialized.
  • Throws the existing ConnectionException with code 404.

An ordinary request fails promptly. During cancellation, the original interruption still reaches the caller, but Client::isConnected() remains false even when the notification failure is logged. Callers can evict the client and reconnect without the expired session ID. This does not replay the failed tool call.

Requests without a session header and other HTTP status codes are unchanged. This is narrower than #425 and addresses the session-expiry behavior required by the 2025-11-25 session management rules.

Validation

  • Unit regressions cover empty and plain-text 404 bodies, body closure, session clearing, and connection invalidation when the cancellation notification failure is logged. Cancellation retains RequestCancelledException.
  • make ci passed: 1,971 tests, 5,353 assertions, 8 existing skips; formatting and PHPStan level 8 passed.
  • make conformance-tests: server 80/80; client 12/54 matches the expected-failure baseline.
  • Host integration regressions cover ordinary session expiry and cancellation/deadline notification expiry. The stateful HTTP fixture rejects missing session headers with 400; subsequent independent calls must initialize a fresh session and succeed. Healthy STDIO connections remain reusable.

P.S. I'm really thinking now that I might just need to upgrade my MCP client version, but it was working just fine all this time!

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Client] Expired HTTP sessions remain marked connected, including during cancellation

1 participant