Repository navigation
mcp: keep x-mcp-header handling working next to type arrays - #1410
RafalOfficial wants to merge 1 commit into
Conversation
headerSchemaProperty decoded "type" into a string, so one property whose type is an array, such as the ["null", "string"] that jsonschema.For infers for a pointer field, failed decoding of the whole inputSchema. A boolean subschema did the same. The client then sent no Mcp-Param-* headers for the tool, the server skipped validating them, and validateParamHeaderAnnotations returned nil without checking any annotation. Keep "type" raw and accept boolean subschemas, so each property is decoded on its own. An annotated property must still have a single primitive type. Fixes modelcontextprotocol#1406 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Heads-up for reviewers: #1408 fixes the same issue (#1406). Pick whichever you prefer; if it's #1408, I'll close this one. One difference I checked: #1408's (Checked with a throwaway test, written with Claude Code.) |
chrikrah
left a comment
There was a problem hiding this comment.
@RafalOfficial nothing in this diff blocks. At 2807cef the client sends Mcp-Param-Region: eu for the issue's with_optional tool again, and the five new cases fail with streamable_headers.go from the merge base 3e9d812.
$ go test -count=1 -run TestProbe1410 -v ./mcp/ # probe annotates "note" (*string) with x-mcp-header
# 3e9d812
ptr annotated err=<nil> bindings=0
# 2807cef
ptr annotated err=property "note": x-mcp-header can only be applied to primitive types (integer, string, boolean), got ["null","string"] bindings=1
$ go test -count=1 ./... # 2807cef
ok github.com/modelcontextprotocol/go-sdk/mcp 33.052s
$ go test -count=1 ./mcp/ -run 'TestExtractToolParamHeaders|TestValidateToolParamHeaders' # tests kept, streamable_headers.go from 3e9d812
5 subtests FAIL
# not run: Windows, and the issue's HTTP program (I called generateParamHeaders on its schema)
Go 1.27.1, vet and gofmt clean. Also probed: ["string"] and ["string","null"] are rejected too, a false subschema is skipped, and a nested ["null","integer"] no longer hides its sibling.
non-blocking: rejecting ["null","string"] is the design you proposed in #1406, and docs/protocol.md says annotated properties must be string, integer or boolean. Neither text says where that lands. jsonschema.For types every *string that way, so an annotated pointer field now panics in AddTool. #1408 rejects the same union, so this applies to both pull requests.
Allowing ["null", <primitive>] in the doc and the check is the option #1406 offered, and it fits: a pointer is how Go marks an optional argument, and both header paths already skip a null one. @guglielmo-san, does that go in here, or is the panic the intended result?
|
@chrikrah thanks for the probe. I reproduced it with a The spec's constraint only lists @guglielmo-san if you want that, I'll add it to this PR. Otherwise the strict check stays as is. The same choice applies to #1408. |
|
See comment #1406 (comment) |
headerSchemaPropertydecodedtypeinto astring. One property with an arraytype(such as the["null", "string"]thatjsonschema.Forinfers for a pointer field) or a boolean subschema made decoding of the wholeinputSchemafail. The client then sent noMcp-Param-*headers for that tool, the server skipped validating them, andvalidateParamHeaderAnnotationsaccepted invalid annotations. Details and an end-to-end repro are in #1406.This change keeps
typeas raw JSON and treats boolean subschemas as empty properties, so each property decodes on its own. An annotated property must still have a single primitivetype; a nullable one (["null", "string"]) gets the existing "primitive types" error.Tests: 5 new table cases in
TestExtractToolParamHeadersandTestValidateToolParamHeaders, including one built withjsonschema.Forand a pointer field. They fail onmainand pass with this change. On Windows with Go 1.27, rebased on 3e9d812:All pass and are clean.
Fixes #1406
This PR was written with Claude Code (AI-assisted).
🤖 Generated with Claude Code