- progressTokenOf now delegates to the SDK's ProgressTokenSchema instead of a bare typeof check, so fractional and past-MAX_SAFE_INTEGER numbers are rejected (matching isProgressToken in inspectorClient.ts); tests cover both. - Browser relay timeout tests use fake timers with advanceTimersByTimeAsync and flush the SSE consumer between pushes, replacing real-sleep windows that a loaded runner could race (#1596). - The log-only timeout test holds and awaits its rejection rather than swallowing it in an empty catch. - progressToken.test.ts gains a file header; the remote-session malformed-token fixture uses a single-cast helper instead of `as unknown as`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PsmUAZ6aLUAFqenjJKSSRp Signed-off-by: cliffhall <cliff@futurescale.com>
40 lines
1.5 KiB
TypeScript
40 lines
1.5 KiB
TypeScript
/**
|
|
* Shared helper for the remote relay's progress-aware request-response waits
|
|
* (#2028). Pure and browser-safe, so both the browser `RemoteClientTransport`
|
|
* and the Node `RemoteSession` import it rather than each carrying a copy.
|
|
*/
|
|
|
|
import { ProgressTokenSchema } from "@modelcontextprotocol/core";
|
|
import type { JSONRPCMessage } from "@modelcontextprotocol/client";
|
|
|
|
/**
|
|
* The token identifying the request a `notifications/progress` belongs to, or
|
|
* `undefined` for any other message. The SDK stamps `progressToken: messageId`
|
|
* on the outbound request, so a progress notification's `progressToken` is the
|
|
* id of the request whose wait should be re-armed.
|
|
*
|
|
* Validation is delegated to the SDK's own `ProgressTokenSchema` rather than a
|
|
* hand-rolled `typeof` check — the protocol allows only a string or a *safe*
|
|
* integer, and zod's `.int()` rejects a fractional or past-`MAX_SAFE_INTEGER`
|
|
* value that a bare `typeof token === "number"` would wave through (the same
|
|
* drift `isProgressToken` in `core/mcp/inspectorClient.ts` exists to avoid).
|
|
*/
|
|
export function progressTokenOf(
|
|
message: JSONRPCMessage,
|
|
): string | number | undefined {
|
|
if (
|
|
"method" in message &&
|
|
message.method === "notifications/progress" &&
|
|
"params" in message &&
|
|
typeof message.params === "object" &&
|
|
message.params !== null
|
|
) {
|
|
const parsed = ProgressTokenSchema.safeParse(
|
|
(message.params as { progressToken?: unknown }).progressToken,
|
|
);
|
|
if (parsed.success) {
|
|
return parsed.data;
|
|
}
|
|
}
|
|
return undefined;
|
|
}
|