Skip to content

History: server→client requests (roots/list, sampling, elicitation) stuck Pending with no response body #1440

@cliffhall

Description

@cliffhall

Problem

In the History screen, a server→client request — e.g. roots/list (also sampling/createMessage, elicitation/create) — is shown:

  • a) with no response body (what the client sent back to the server), and
  • b) with a permanent PENDING status.

The client did answer the request; it just isn't recorded.

Cause

MessageTrackingTransport tracks traffic on the way through the transport. Its onmessage (incoming) classifies all three message types, but send (outgoing) only tracked outgoing requests:

// core/mcp/messageTrackingTransport.ts (before)
async send(message, options) {
  if ("method" in message && "id" in message) {
    this.callbacks.trackRequest?.(message as JSONRPCRequest);
  }
  return this.baseTransport.send(message, options);
}

When the server sends a request to the client (roots/list), the inbound request is tracked via onmessage and stored as a pending entry by id. The client then sends its response (a result/error with the matching id, no method) — but send ignored it, so messageLogState never folded it into the request entry (core/mcp/state/messageLogState.ts:77-95). Result: the request sits Pending forever with no response body.

Fix

Make send symmetric with onmessage — track outgoing responses (and keep tracking outgoing requests):

if ("id" in message && message.id != null) {
  if ("result" in message || "error" in message) {
    this.callbacks.trackResponse?.(message as ...);   // outgoing response
  } else if ("method" in message) {
    this.callbacks.trackRequest?.(message as JSONRPCRequest);
  }
}

The response now correlates to its request entry by id → the entry shows OK/Error with the response body. Verified the integration suite's "no orphan responses" assertion still holds (the response folds, it isn't pushed as a standalone entry).

Acceptance criteria

  • A roots/list (and sampling/elicitation) server→client request shows the client's response body and resolves to OK/Error, not permanent Pending.
  • Outgoing client→server requests are still tracked (unchanged).
  • The response folds into its request entry (no orphan response entries).
  • Tests cover outgoing-response tracking in MessageTrackingTransport.

Metadata

Metadata

Assignees

No one assigned

    Labels

    v2Issues and PRs for v2

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions