Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

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

Đã đóng
#1,406 1 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

@jay23606 đang làm issue này rồi.

Từ ngày 16/10/2026.

  • #1408 của @jay23606 — đang mở
  • #1410 của @RafalOfficial — đang mở

Đánh giá

Độ khó
3/5
Thời gian dự kiến
1-2 ngày
Mức phù hợp với người mới
50/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
go
Lĩnh vực
api

Hướng nghiên cứu

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.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

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.

Ngôn ngữ chính
Go
Star
5.3k
Fork
606
Merge trung bình
1 ngày 16 giờ
Pull request đã merge (30 ngày)
72

Chuẩn bị môi trường

Mở trong Codespaces

Khởi chạy dev container của dự án ngay trên trình duyệt, bằng tài khoản GitHub của bạn.

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của modelcontextprotocol/go-sdk

Tất cả issue của modelcontextprotocol/go-sdk

Issue tương tự

Thêm issue về Go

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.