The requirement
Released 2026-07-28 server/tools.mdx, in the x-mcp-header constraint list:
Integer values MUST be within the safe range for integers represented using IEEE754 double-precision floating point numbers (−253+1 to 253−1)
Nothing in the harness covers it: no row in src/seps/sep-2243.yaml (the primitive-only text stops at "not permitted"), no check ID emitted, and grep -iE 'safe range|MAX_SAFE_INTEGER|9007199254740991|2\*\*53' over src/ returns zero matches. An SDK that mirrors 9007199254740993 into a header passes the suite today.
It binds at call time, on argument values
Settled by the discussion on PR #2772, which introduced the sentence (@mikekistler, merged 2026-05-29):
As discussed in the Transports WG, I think we aligned on something like: only integer arguments from -2^53 to 2^53 (inclusive) can be mirrored to a header. Any other numeric values produce an error.
— @pja-ant
and the WG meeting notes @mikekistler pasted into the review:
Consensus: Custom numeric headers are strictly restricted to integers. Clients must reject tool inputs containing non-integer numbers in custom headers.
So this is a runtime constraint on arguments, not a schema-shape constraint.
The actual gap: SDKs disagree on the consequence
The spec states the constraint but never says what the client does when an argument violates it. Two SDKs read it two ways:
| SDK |
Behavior on an out-of-range integer |
| csharp-sdk |
throws McpException — the call fails (McpHeaderExtractor.cs#L116-L121) |
| typescript-sdk |
mcpParamPrimitiveToString returns undefined, and buildMcpParamHeaders does continue — the header is silently omitted and the call proceeds (mcpParamHeaders.ts#L211, L311) |
typescript-sdk is internally consistent — its server-side validateMcpParamHeaders skips the comparison for exactly the same values — so nothing errors end to end. But that silence is the failure mode the WG was trying to prevent: an intermediary routing on Mcp-Param-UserId simply doesn't receive the header, with no signal to anyone. Against the consensus quoted above, the C# behavior looks like the intended one.
Worth confirming which is normative before writing a check, since whichever we assert will make the other SDK fail.
Shape of the check
Belongs in the existing http-custom-headers positive scenario rather than a new one, per the fewer-scenarios-more-checks rule:
- add an integer param carrying
x-mcp-header to a tool the scenario already exercises
- have the scenario ask the client to call it with an out-of-range value (e.g.
2**53)
- emit
sep-2243-x-mcp-header-integer-safe-range asserting the agreed behavior
- add the matching
sep-2243.yaml row and a negative fixture proving the check can fail
Note for whoever writes it: C# accepts 42.0 and 4.2e1 as canonical 42, and TS compares integer-typed declarations numerically, so the fixture should use a genuinely out-of-range value rather than a differently-spelled in-range one.
Aside: the released spec contradicts itself here
Same bound, two different justifications, both shipped in 2026-07-28:
server/tools.mdx — "safe range for integers represented using IEEE754 double-precision floating point numbers"
basic/transports/streamable-http.mdx (line 386) — "safe range for JavaScript"
@pja-ant flagged the JavaScript phrasing as imprecise ("Even in languages that have native integers, sometimes JSON parsing libraries will parse to double by default"), @mikekistler replied "Fair point. I will revise." — but the revision only landed in tools.mdx. Probably a one-line upstream fix.
Filed while verifying spec wording for #344 / #444; unrelated to those changes.
The requirement
Released
2026-07-28server/tools.mdx, in thex-mcp-headerconstraint list:Nothing in the harness covers it: no row in
src/seps/sep-2243.yaml(theprimitive-onlytext stops at "not permitted"), no check ID emitted, andgrep -iE 'safe range|MAX_SAFE_INTEGER|9007199254740991|2\*\*53'oversrc/returns zero matches. An SDK that mirrors9007199254740993into a header passes the suite today.It binds at call time, on argument values
Settled by the discussion on PR #2772, which introduced the sentence (@mikekistler, merged 2026-05-29):
and the WG meeting notes @mikekistler pasted into the review:
So this is a runtime constraint on arguments, not a schema-shape constraint.
The actual gap: SDKs disagree on the consequence
The spec states the constraint but never says what the client does when an argument violates it. Two SDKs read it two ways:
McpException— the call fails (McpHeaderExtractor.cs#L116-L121)mcpParamPrimitiveToStringreturnsundefined, andbuildMcpParamHeadersdoescontinue— the header is silently omitted and the call proceeds (mcpParamHeaders.ts#L211, L311)typescript-sdk is internally consistent — its server-side
validateMcpParamHeadersskips the comparison for exactly the same values — so nothing errors end to end. But that silence is the failure mode the WG was trying to prevent: an intermediary routing onMcp-Param-UserIdsimply doesn't receive the header, with no signal to anyone. Against the consensus quoted above, the C# behavior looks like the intended one.Worth confirming which is normative before writing a check, since whichever we assert will make the other SDK fail.
Shape of the check
Belongs in the existing
http-custom-headerspositive scenario rather than a new one, per the fewer-scenarios-more-checks rule:x-mcp-headerto a tool the scenario already exercises2**53)sep-2243-x-mcp-header-integer-safe-rangeasserting the agreed behaviorsep-2243.yamlrow and a negative fixture proving the check can failNote for whoever writes it: C# accepts
42.0and4.2e1as canonical42, and TS compares integer-typed declarations numerically, so the fixture should use a genuinely out-of-range value rather than a differently-spelled in-range one.Aside: the released spec contradicts itself here
Same bound, two different justifications, both shipped in
2026-07-28:server/tools.mdx— "safe range for integers represented using IEEE754 double-precision floating point numbers"basic/transports/streamable-http.mdx(line 386) — "safe range for JavaScript"@pja-ant flagged the JavaScript phrasing as imprecise ("Even in languages that have native integers, sometimes JSON parsing libraries will parse to
doubleby default"), @mikekistler replied "Fair point. I will revise." — but the revision only landed intools.mdx. Probably a one-line upstream fix.Filed while verifying spec wording for #344 / #444; unrelated to those changes.