tools/call with "arguments": null panics the server when the tool schema has a default
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 86/100
Línea de trabajo
Empieza en mcp/tool.go, en applySchema, y compara cómo se gestiona null con la rama de salida mencionada en el issue. Añade una prueba de regresión para una solicitud tools/call con argumentos null y un valor predeterminado del esquema; se considera terminado cuando la solicitud ya no provoca un panic y aplica los valores predeterminados o devuelve un error JSON-RPC o de herramienta.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
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)
}
})
- Lenguaje dominante
- Go
- Estrellas
- 5.3k
- Forks
- 606
- Merge medio
- 1 d 16 h
- PR fusionados (30 d)
- 72
Preparar el entorno
Inicia el contenedor de desarrollo del proyecto en tu navegador, con tu propia cuenta de GitHub.
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de modelcontextprotocol/go-sdk
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
modelcontextprotocol/go-sdk#1444 · 3 comentarios ·
Los mantenedores suelen responder en 1 día
-
Session-lifecycle bookkeeping logs at info, spamming multiple log lines per request on stateless streamable HTTPPosiblemente ocupada @anneheartrecord la tomó hace 60 días. AbiertoP3
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
modelcontextprotocol/go-sdk#1204 · 1 reacción ·
Los mantenedores suelen responder en 1 día
-
Expose generic `SendNotification` on `ServerSession` for custom protocol extensionsPosiblemente ocupada @ajuijas la tomó hace 226 días. Abiertoneeds investigation
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
modelcontextprotocol/go-sdk#745 · 13 comentarios · 1 reacción ·
Los mantenedores suelen responder en 1 día
-
internal/json: Unmarshal allocates a 32 KiB stream buffer on every callPosiblemente ocupada @raveesh-me la tomó hace 1 día. Abierto
Dificultad 4/5 3-5 días Aptitud para principiantes 25/100
modelcontextprotocol/go-sdk#1453 ·
Los mantenedores suelen responder en 1 día
-
auth/extauth: ClientCredentialsHandler does not send the resource parameterPosiblemente ocupada @shlee1223 la tomó hace 2 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 25/100
modelcontextprotocol/go-sdk#1450 ·
Los mantenedores suelen responder en 1 día
Todos los issues de modelcontextprotocol/go-sdk
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
kubernetes-sigs/kubebuilder#6131 ·
Los mantenedores suelen responder en 2 días
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
aquasecurity/libbpfgo#560 ·
-
[BUG]Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
kagent-dev/kagent#3385 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
hashicorp/nomad-autoscaler#1364 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
theagentrouter/agent-router#2926 ·
Los mantenedores suelen responder en 1 día