From 129a435fd4a87d89d27ac6f49bd21b1b0c3fcc76 Mon Sep 17 00:00:00 2001 From: cliffhall Date: Sun, 23 Aug 2026 19:31:50 -0400 Subject: [PATCH] docs: say "safe integer" for progressToken, matching what the code enforces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The copy said `progressToken` may be "an integer" while the implementation validates with `ProgressTokenSchema` — zod's `.int()`, which rejects anything past `Number.MAX_SAFE_INTEGER`. This repo's own tests assert that `MAX_SAFE_INTEGER + 1` is dropped, so the documentation was promising a value the client discards. Corrected in all three places, so the code comment, the docs callout and the UI hint agree: `dropInvalidReservedMeta`'s doc block (which review did not flag), the `metadata` reserved-keys callout, and the Request Metadata hint. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_0177mPHAdECD18nLLCTwR5rh Signed-off-by: cliffhall --- .../groups/ServerSettingsForm/ServerSettingsForm.tsx | 3 ++- core/mcp/inspectorClient.ts | 3 ++- docs/mcp-server-configuration.md | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/clients/web/src/components/groups/ServerSettingsForm/ServerSettingsForm.tsx b/clients/web/src/components/groups/ServerSettingsForm/ServerSettingsForm.tsx index 2e03a93b..2de2e314 100644 --- a/clients/web/src/components/groups/ServerSettingsForm/ServerSettingsForm.tsx +++ b/clients/web/src/components/groups/ServerSettingsForm/ServerSettingsForm.tsx @@ -734,7 +734,8 @@ export function ServerSettingsForm({ objects, arrays, numbers, booleans, null — not just strings. Leave it as {"{}"} to send none. The keys the protocol reserves keep their own shape:{" "} - progressToken must be a string or an integer, and{" "} + progressToken must be a string or a safe integer (one + JavaScript can represent exactly), and{" "} io.modelcontextprotocol/related-task an object with a string taskId. A reserved key that does not match is dropped from the request rather than sent. diff --git a/core/mcp/inspectorClient.ts b/core/mcp/inspectorClient.ts index 09c8fa89..542ac8ae 100644 --- a/core/mcp/inspectorClient.ts +++ b/core/mcp/inspectorClient.ts @@ -401,7 +401,8 @@ function isProgressToken(value: unknown): value is ProgressToken { * Drop the reserved `_meta` members whose value the protocol will not accept. * * Most of `_meta` is arbitrary JSON (#1910), but a few keys are **reserved** - * and carry their own schema — `progressToken` (`string | integer`) and + * and carry their own schema — `progressToken` (a string or a safe integer; + * zod's `.int()` rejects anything past `Number.MAX_SAFE_INTEGER`) and * `io.modelcontextprotocol/related-task` (`{ taskId: string }`) in the pinned * SDK. Before the widening every value was a string, so only `progressToken` * could even be wrong; now any of them can, and one bad reserved member makes a diff --git a/docs/mcp-server-configuration.md b/docs/mcp-server-configuration.md index 9005411d..b394862a 100644 --- a/docs/mcp-server-configuration.md +++ b/docs/mcp-server-configuration.md @@ -187,7 +187,7 @@ These have no analog in the broader `mcp.json` ecosystem. Each is **omitted on w } ``` -> **A few keys are reserved and keep their own shape.** "Any JSON" holds for keys you invent, not for the ones the protocol defines. In the current SDK those are `progressToken` (a string or an integer) and `io.modelcontextprotocol/related-task` (`{ "taskId": "" }`). A reserved key whose value does not match is **dropped from the outgoing request**, with a warning naming the key — because a conforming server rejects the _entire_ request over one bad reserved member, rather than ignoring that key. Everything else in the payload is sent unchanged. +> **A few keys are reserved and keep their own shape.** "Any JSON" holds for keys you invent, not for the ones the protocol defines. In the current SDK those are `progressToken` (a string or a **safe** integer — one JavaScript represents exactly, so nothing past `Number.MAX_SAFE_INTEGER`) and `io.modelcontextprotocol/related-task` (`{ "taskId": "" }`). A reserved key whose value does not match is **dropped from the outgoing request**, with a warning naming the key — because a conforming server rejects the _entire_ request over one bad reserved member, rather than ignoring that key. Everything else in the payload is sent unchanged. > **Not yet applied by the CLI.** The web client and the TUI both send this payload on every request. The CLI does not — it never passes the persisted value to its client, so a `metadata` entry is currently inert for `--cli` runs ([#2093](https://github.com/modelcontextprotocol/inspector/issues/2093)). Use the per-invocation `--metadata` flag there in the meantime.