fix: address Copilot review round 2 on #2318

- fetchTracking: media types and HTTP methods compare case-insensitively;
  a `Request` input's own method is honoured; the SSE line scanner
  accepts LF, CRLF and a bare CR, holding a trailing CR until the next
  chunk decides whether it is half of a CRLF.
- MessageTrackingTransport does not report a send failure for a request
  the caller aborted through `requestSignal`, and InspectorClient keeps a
  request whose send failed with a request timeout — both are sent,
  unanswered requests, which is the state to keep reporting.
- createTransportNode builds a fetch tracker when any tracking callback
  is supplied, not only `onFetchRequest`.
- RemoteClientTransport's relay wait expires with the SDK's own timeout
  shape, so the web client's relay timeout is annotated like every other.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01APKSYHGxXBUpnR7ErFiLJn
Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
cliffhall 2026-09-13 22:27:54 -04:00
commit c565b56fcd

View file

@ -11,6 +11,7 @@ import type {
JSONRPCMessage,
MessageExtraInfo,
} from "@modelcontextprotocol/client";
import { SdkError, SdkErrorCode } from "@modelcontextprotocol/client";
import type { InspectorServerSettings, StderrLogEntry } from "../types.js";
import type { FetchRequestEntryBase, FetchStreamState } from "../types.js";
import type {
@ -689,10 +690,17 @@ export class RemoteClientTransport implements Transport {
return new Promise((resolve, reject) => {
const timer = setTimeout(() => {
this.sseResponseWaits.delete(requestId);
// The SDK's own per-request timeout shape, not a plain `Error`: this
// wait can expire before the SDK's timer does (its budget is the
// relay's, not the request's), and the rejection travels up through
// `Client.request`, where `InspectorClient` annotates a timeout of
// exactly this shape with the connection's state (#2318). A plain
// error would pass that decorator untouched and reach the user as a
// bare timeout on the web client alone.
reject(
new Error(
`Timed out waiting for MCP response on SSE (${this.sseResponseTimeoutMs}ms)`,
),
new SdkError(SdkErrorCode.RequestTimeout, "Request timed out", {
timeout: this.sseResponseTimeoutMs,
}),
);
}, this.sseResponseTimeoutMs);
this.sseResponseWaits.set(requestId, {