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
Problem
In the History screen, a server→client request — e.g.
roots/list(also sampling/createMessage,elicitation/create) — is shown:The client did answer the request; it just isn't recorded.
Cause
MessageTrackingTransporttracks traffic on the way through the transport. Itsonmessage(incoming) classifies all three message types, butsend(outgoing) only tracked outgoing requests:When the server sends a request to the client (
roots/list), the inbound request is tracked viaonmessageand stored as a pending entry by id. The client then sends its response (aresult/errorwith the matching id, nomethod) — butsendignored it, somessageLogStatenever 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
sendsymmetric withonmessage— track outgoing responses (and keep tracking outgoing requests):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
roots/list(and sampling/elicitation) server→client request shows the client's response body and resolves to OK/Error, not permanent Pending.MessageTrackingTransport.