tools/call with "arguments": null panics the server when the tool schema has a default
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 86/100
Hướng nghiên cứu
Bắt đầu trong mcp/tool.go tại applySchema và so sánh cách xử lý null của nó với nhánh output được đề cập trong issue. Thêm một regression test cho request tools/call có các đối số null và một schema default; hoàn tất khi request không còn gây panic và либо áp dụng các giá trị mặc định hoặc trả về lỗi JSON-RPC hay lỗi tool.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Describe the bug
A tools/call request with "arguments": null panics the whole server process when the tool's input schema declares a default.
applySchema in mcp/tool.go unmarshals the arguments into v := make(map[string]any). Unmarshalling JSON null sets v to a nil map, which still passes the unmarshaled.(map[string]any) check, so resolved.ApplyDefaults runs and jsonschema-go writes the default into the nil map:
panic: assignment to entry in nil map
The panic happens in the goroutine handling the request and nothing recovers it, so a single request takes the process down for every client. Omitting arguments or sending {} works and applies the default.
This is the same root cause as #1062, fixed for elicitation in #1068 ("jsonschema-go can panic when applying defaults into a nil map"). The tool-call path through applySchema is not covered by that fix.
To Reproduce
Versions: go-sdk v1.8.0 and main at 25a53e3, github.com/google/jsonschema-go v0.4.3, Go 1.27.1.
package main
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/http/httptest"
"strings"
"github.com/google/jsonschema-go/jsonschema"
"github.com/modelcontextprotocol/go-sdk/mcp"
)
type input struct {
Limit int `json:"limit,omitempty"`
}
func main() {
schema, err := jsonschema.For[input](nil)
if err != nil {
panic(err)
}
schema.Properties["limit"].Default = json.RawMessage("20")
server := mcp.NewServer(&mcp.Implementation{Name: "repro", Version: "v0.0.1"}, nil)
mcp.AddTool(server, &mcp.Tool{Name: "list", InputSchema: schema},
func(_ context.Context, _ *mcp.CallToolRequest, in input) (*mcp.CallToolResult, any, error) {
return nil, map[string]int{"limit": in.Limit}, nil
})
handler := mcp.NewStreamableHTTPHandler(func(*http.Request) *mcp.Server { return server },
&mcp.StreamableHTTPOptions{Stateless: true, JSONResponse: true})
ts := httptest.NewServer(handler)
defer ts.Close()
body := `{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"list","arguments":null}}`
req, _ := http.NewRequest(http.MethodPost, ts.URL, strings.NewReader(body))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "application/json, text/event-stream")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
out, _ := io.ReadAll(resp.Body)
fmt.Println(resp.StatusCode, string(out))
}
-
go run . -
The process exits with the panic shown under Logs.
-
Replace
"arguments":nullwith"arguments":{}, or drop the field: the program prints200 {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"{\"limit\":20}"}],"structuredContent":{"limit":20}}}
Expected behavior
"arguments": null is treated like omitted or empty arguments: defaults are applied and the call proceeds. Rejecting it with a JSON-RPC or tool error would also be acceptable. Either way, the process should not crash.
Logs
panic: assignment to entry in nil map
goroutine 37 [running]:
reflect.mapassign_faststr0(...)
reflect.Value.SetMapIndex(...)
github.com/google/jsonschema-go/jsonschema.(*state).applyDefaults(...)
github.com/google/[email protected]/jsonschema/validate.go:741
github.com/google/jsonschema-go/jsonschema.(*Resolved).ApplyDefaults(...)
github.com/google/[email protected]/jsonschema/validate.go:701
github.com/modelcontextprotocol/go-sdk/mcp.applySchema(...)
github.com/modelcontextprotocol/[email protected]/mcp/tool.go:117
github.com/modelcontextprotocol/go-sdk/mcp.toolForErr[...].func1(...)
github.com/modelcontextprotocol/[email protected]/mcp/server.go:402
github.com/modelcontextprotocol/go-sdk/mcp.(*Server).callTool(...)
github.com/modelcontextprotocol/[email protected]/mcp/server.go:1013
Additional context
Possible fixes:
-
In
applySchema, fall back to an empty map when the unmarshalled input is nil, mirroring what the output branch already does fornull:if v == nil { v = map[string]any{} } -
Or make
ApplyDefaultsin jsonschema-go tolerate a nil map, which would also cover the elicitation paths patched in #1068.
Workaround until a fix lands: a receiving middleware that drops null arguments before the tool handler runs.
server.AddReceivingMiddleware(func(next mcp.MethodHandler) mcp.MethodHandler {
return func(ctx context.Context, method string, req mcp.Request) (mcp.Result, error) {
if params, ok := req.GetParams().(*mcp.CallToolParamsRaw); ok &&
bytes.Equal(bytes.TrimSpace(params.Arguments), []byte("null")) {
params.Arguments = nil
}
return next(ctx, method, req)
}
})
- Ngôn ngữ chính
- Go
- Star
- 5.3k
- Fork
- 606
- Merge trung bình
- 1 ngày 7 giờ
- Pull request đã merge (30 ngày)
- 77
Chuẩn bị môi trường
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.
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- 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.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của modelcontextprotocol/go-sdk
-
Expose generic `SendNotification` on `ServerSession` for custom protocol extensionsCó thể đã có người làm @ajuijas đã nhận 228 ngày trước. Đang mởneeds investigation
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
modelcontextprotocol/go-sdk#745 · 13 bình luận · 1 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 75/100
modelcontextprotocol/go-sdk#1476 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
mcp: a client DELETE waits for a pending keepalive pingCó thể đã có người làm @vshalpnjabi đã nhận hôm nay. Đang mở
modelcontextprotocol/go-sdk#1470 · 2 bình luận · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
-
mcp: LoggingHandler drops records logged at custom slog levelsCó thể đã có người làm @kaankucukx đã nhận 5 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 45/100
modelcontextprotocol/go-sdk#1445 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
mcp: Client.Connect falls back to initialize after a 401 on server/discover, running the authorization flow twiceCó thể đã có người làm @kerthans đã nhận 8 ngày trước. Đang mở
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 35/100
modelcontextprotocol/go-sdk#1423 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của modelcontextprotocol/go-sdk
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
google/go-containerregistry#2491 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
aiac enhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Maintainer thường phản hồi trong vòng 1 ngày
-
phase:v1 type:harness
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
scttfrdmn/burroughs#1181 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
compiler-explorer/ce-ci#28 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
Maintainer thường phản hồi trong vòng 1 ngày