When a client sends a request without params (or with params: null) for methods flagged with missingParamsOK (e.g. notifications/initialized, ping, tools/list), the middleware receives a Params interface that passes a standard != nil check but panics on any method call.
Root cause:
In newServerMethodInfo, when unmarshalParams returns a nil interface (because params are missing and missingParamsOK allows it), newRequest leaves r.Params at its zero value — a typed nil pointer (e.g. (*InitializedParams)(nil)):
mi.newRequest = func(s Session, p Params, re *RequestExtra) Request {
r := &ServerRequest[P]{Session: s.(*ServerSession), Extra: re}
if p != nil { // p is nil-interface here → skipped
r.Params = p.(P)
}
return r // r.Params is (*InitializedParams)(nil)
}
When GetParams() returns this typed nil pointer as a Params interface, the interface is non-nil (it carries type information), but calling any method on it (e.g. GetMeta()) dereferences a nil pointer and panics.
Our use case:
We have middleware that extracts _meta from every incoming request:
func metaFromRequest(req mcpsdk.Request) map[string]any {
if params := req.GetParams(); params != nil { // passes! interface is non-nil
return params.GetMeta() // PANIC: nil pointer dereference
}
return nil
}
This crashes on notifications/initialized when the client sends no params.
Expected behavior:
GetParams() should return a nil Params interface (not a typed nil pointer) when params are absent, so that standard nil checks work correctly in middleware. Alternatively, GetParams() could use the existing orZero helper to unwrap typed nil pointers before returning.
Stack trace (v1.6.1):
github.com/modelcontextprotocol/go-sdk/mcp.(*InitializedParams).GetMeta(0x0?)
:1
Workaround:
Guard metaFromRequest with a method allowlist (only call for methods without missingParamsOK), or use reflect.ValueOf(params).IsNil() instead of params != nil.
When a client sends a request without params (or with params: null) for methods flagged with missingParamsOK (e.g. notifications/initialized, ping, tools/list), the middleware receives a Params interface that passes a standard != nil check but panics on any method call.
Root cause:
In newServerMethodInfo, when unmarshalParams returns a nil interface (because params are missing and missingParamsOK allows it), newRequest leaves r.Params at its zero value — a typed nil pointer (e.g. (*InitializedParams)(nil)):
When GetParams() returns this typed nil pointer as a Params interface, the interface is non-nil (it carries type information), but calling any method on it (e.g. GetMeta()) dereferences a nil pointer and panics.
Our use case:
We have middleware that extracts _meta from every incoming request:
This crashes on notifications/initialized when the client sends no params.
Expected behavior:
GetParams() should return a nil Params interface (not a typed nil pointer) when params are absent, so that standard nil checks work correctly in middleware. Alternatively, GetParams() could use the existing orZero helper to unwrap typed nil pointers before returning.
Stack trace (v1.6.1):
github.com/modelcontextprotocol/go-sdk/mcp.(*InitializedParams).GetMeta(0x0?)
:1
Workaround:
Guard metaFromRequest with a method allowlist (only call for methods without missingParamsOK), or use reflect.ValueOf(params).IsNil() instead of params != nil.