Skip to content

[Server] Clean up timed-out client requests and drop responses nobody waits for #561

Description

@chr-hertel

Follow-up to #556, raised by @jarrettdustinqq in #544 (comment)

Currently Protocol::checkResponse() is the only path that removes an entry from _mcp.pending_requests - so two things pile up in the session:

  • a timed-out request: the timeout branches in StreamableHttpTransport and StdioTransport resume the fiber with an error, but leave the pending entry behind
  • a response to an ID that isn't pending: handleResponse() stores it without checking, so late answers (or IDs that were never sent) stay in _mcp.responses until the session ends

With #556 none of that reaches the wrong fiber anymore, and request IDs are never reused within a session - so it's stale state, not misdelivery.

Rough direction:

  • move the timeout check into Protocol::checkResponse(): an expired request returns the timeout Error and drops its pending entry, like an answer does - also removes the duplicated timeout logic in both transports, checkForResponse() keeps its signature
  • handleResponse() logs and discards responses whose ID isn't pending
  • both together, since the second only works once expired entries are gone

The whole-session read-modify-write race stays with #275.

Activity

  1. added
    bugSomething isn't working
    ServerIssues & PRs related to the Server component
    on Oct 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    ServerIssues & PRs related to the Server componentbugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions