Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

mcp: a property with an array "type" (any pointer field from jsonschema.For) disables x-mcp-header handling for the whole tool

Aperta
#1,406 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@jay23606 ci sta già lavorando.

Dal 16/10/2026.

  • #1408 di @jay23606 — aperta
  • #1410 di @RafalOfficial — aperta

Valutazione

Difficoltà
3/5
Tempo stimato
1-2 giorni
Idoneità per principianti
50/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
go
Ambito
api

Direzione di ricerca

Start in mcp/streamable_headers.go: headerSchemaProperty decodes type as a string, so an array or boolean subschema makes unmarshalSchemaProperties return nil for the whole tool. Read validateParamHeaderAnnotations and the two tests named in the issue, TestExtractToolParamHeaders and TestValidateToolParamHeaders. Done when a property with an array or boolean schema no longer disables annotations on other properties, and an annotated nullable property is rejected with the existing primitive-types error, as the issue proposes. The maintainers still need to decide the nullable case.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Describe the bug

headerSchemaProperty (mcp/streamable_headers.go) decodes type into a string. JSON Schema also allows an array there, and jsonschema.For emits one for every pointer field ("type": ["null", "string"]). When any property in a tool's inputSchema has an array type, the remarshal in unmarshalSchemaProperties fails and returns nil. The client and server then treat the tool as having no x-mcp-header annotations at all, even on other properties:

  • The client sends no Mcp-Param-* headers for the tool. A server that validates them, as the 2026-07-28 spec requires, answers with HeaderMismatch.
  • The server skips validateParamHeaders, so a request whose Mcp-Param-* header contradicts the body is accepted.
  • validateParamHeaderAnnotations returns nil without checking anything, so AddTool and the client's tools/list filter also accept an invalid annotation, such as one on a number property.

A boolean subschema ("properties": {"extra": true}) fails the same way.

To Reproduce

A typed tool with an annotated region and an optional *string field, served over Streamable HTTP and called by the go-sdk client on 2026-07-28 (go run . with a replace to the checkout):

type withOptionalIn struct {
	Region string  `json:"region"`
	Query  string  `json:"query"`
	Note   *string `json:"note,omitempty"` // inferred as "type": ["null", "string"]
}

s, _ := jsonschema.For[withOptionalIn](nil)
s.Properties["region"].Extra = map[string]any{"x-mcp-header": "Region"}
mcp.AddTool(server, &mcp.Tool{Name: "with_optional", InputSchema: s}, handler)

The full program registers this tool next to an identical plain tool without Note. The program serves both tools with NewStreamableHTTPHandler (stateless, TTLMs set so the client caches tools/list). It calls each tool with {"region": "eu", "query": "q"} and records the outgoing headers in a RoundTripper. Then it calls each tool again with Mcp-Param-Region overwritten to forged:

plain          client sent Mcp-Param-Region="eu", call err=<nil>
with_optional  client sent Mcp-Param-Region="", call err=<nil>
plain          header forged to "forged" (body region=eu): call err=... header mismatch: Mcp-Param-Region header value 'forged' does not match body value: rejected by transport: Bad Request
with_optional  header forged to "forged" (body region=eu): call err=<nil>

The only difference between the two tools is the extra optional field.

Expected behavior

with_optional behaves like plain: the client sends Mcp-Param-Region: eu, and the server rejects the forged header.

Proposed fix

In headerSchemaProperty, keep type as a json.RawMessage. Give the struct an UnmarshalJSON that turns true/false into an empty property, so each property decodes independently. An annotated property must still have a single primitive type. A nullable annotated property (["null", "string"]) is rejected with the existing "primitive types" error, like the TypeScript SDK's check (typeof schema.type === 'string'). The change is about 20 lines, plus table cases in TestExtractToolParamHeaders and TestValidateToolParamHeaders. If you'd rather accept ["null", <primitive>] on annotated properties (both header paths already skip null arguments), that is a small change.

Patch: https://github.com/modelcontextprotocol/go-sdk/compare/main...RafalOfficial:go-sdk:fix/param-header-type-arrays

The new cases fail on main and pass with the patch. With the patch, the repro output matches for both tools. go test ./..., go vet ./..., gofmt -l . and staticcheck 2026.2.2 are clean. I couldn't run v0.6.1, the CI version, because it can't read Go 1.27 export data. This is separate from #1250 / #1341, which covers annotations in positions that are not reachable through properties.

If you're happy with this direction, I can open the PR.

Additional context

  • Go MCP SDK: main at 9012a21
  • go version go1.27.0 windows/amd64

This report and the patch were written with Claude Code (AI-assisted). I ran the repro and the tests above on my machine.

Lingua principale
Go
Stelle
5.2k
Fork
583
Merge medio
2g 1h
PR unite (30g)
55

Preparare l'ambiente

Apri in Codespaces

Avvia il container di sviluppo del progetto nel browser, con il tuo account GitHub.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di modelcontextprotocol/go-sdk

Tutte le issue di modelcontextprotocol/go-sdk

Issue simili

Altre issue su Go

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.