modelcontextprotocol / modelcontextprotocol/go-sdk

Streamable HTTP: an x-mcp-header in a non-reachable schema position (items, oneOf, $ref, ...) is silently accepted instead of rejected

Open
#1,250 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

P3
Dominant language
Go
Stars
5.1k
Forks
543
Avg merge
1d 17h
Merged PRs (30d)
37

Description

Describe the bug

validateParamHeaderAnnotations (run from Server.AddTool, mcp/server.go:354) only inspects properties. Its schema struct headerSchemaProperty (mcp/streamable_headers.go:57) parses only type, x-mcp-header, and properties, so an x-mcp-header annotation placed under items, oneOf, anyOf, allOf, not, if/then/else, or $ref is never seen. AddTool accepts the tool with no error and the annotation is silently dropped: no Mcp-Param-* header is ever generated for it.

The SDK already rejects the other invalid x-mcp-header cases at registration (non-primitive type, invalid token syntax, duplicate token), so the non-reachable placement is the remaining gap.

Per the 2026-07-28 Streamable HTTP spec (Standard Request Headers, Schema Extension), an x-mcp-header MUST only be applied to a property that is statically reachable from the schema root via a chain consisting solely of properties keys; the chain MUST NOT pass through items, composition keywords (oneOf, anyOf, allOf, not), conditional keywords (if/then/else), or $ref. An annotation anywhere else makes the annotation, and thus the tool definition, invalid. So such a tool should be rejected, not served with the annotation silently ignored.

To Reproduce

package main

import (
	"context"
	"fmt"

	"github.com/modelcontextprotocol/go-sdk/mcp"
)

func main() {
	s := mcp.NewServer(&mcp.Implementation{Name: "s", Version: "0"}, nil)
	h := func(context.Context, *mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		return &mcp.CallToolResult{}, nil
	}
	// x-mcp-header under array `items`: not statically reachable via `properties`.
	s.AddTool(&mcp.Tool{
		Name: "tag",
		InputSchema: map[string]any{
			"type": "object",
			"properties": map[string]any{
				"tags": map[string]any{
					"type":  "array",
					"items": map[string]any{"type": "string", "x-mcp-header": "Tag"},
				},
			},
		},
	}, h)
	fmt.Println("AddTool returned without rejecting the invalid annotation")
}

AddTool returns normally. The same holds for oneOf/anyOf/allOf/$ref placements. A valid top-level or nested-properties annotation is still handled correctly, so only the non-reachable placements are silently swallowed.

Expected behavior

AddTool rejects the tool, as it already does for the other invalid x-mcp-header cases, so the author gets a signal instead of shipping a tool whose annotation every conforming client drops.

Additional context

headerSchemaProperty would need to also parse items/oneOf/anyOf/allOf/not/if/then/else/$ref so the validator can detect an annotation in a non-reachable position and reject it.

Related (separate, happy to file if useful): the client has no tools/list filter that excludes a tool carrying an invalid x-mcp-header, which the spec lists as a client MUST.

If the direction is welcome I can put up a PR with the validation extension and a regression test.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at validateParamHeaderAnnotations in mcp/server.go:354 and inspect headerSchemaProperty in mcp/streamable_headers.go:57. Reproduce the issue with the provided items schema, then cover the listed non-reachable schema positions while preserving valid properties-based annotations. Done means AddTool rejects each invalid placement instead of silently accepting it.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
api, backend-api-design
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.