Skip to content

Commit 3486f6b

Browse files
mco: update JSON-RPC error codes to align with updated MCP specification (#1016)
This PR updates the error codes to align with the updated specifications in modelcontextprotocol/modelcontextprotocol#2907 ErrServerClosing and ErrClientClosing are reverted to their 1.6.0 version codes, as they do not overlap anymore with the newly introduced error codes.
1 parent 1702948 commit 3486f6b

5 files changed

Lines changed: 18 additions & 16 deletions

File tree

internal/jsonrpc2/wire.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ var (
3131
// ErrUnknown should be used for all non coded errors.
3232
ErrUnknown = NewError(-32001, "unknown error")
3333
// ErrServerClosing is returned for calls that arrive while the server is closing.
34-
ErrServerClosing = NewError(-32006, "server is closing")
34+
ErrServerClosing = NewError(-32004, "server is closing")
3535
// ErrClientClosing is a dummy error returned for calls initiated while the client is closing.
36-
ErrClientClosing = NewError(-32007, "client is closing")
36+
ErrClientClosing = NewError(-32003, "client is closing")
3737

3838
// The following errors have special semantics for MCP transports
3939

@@ -45,8 +45,6 @@ var (
4545
// should be returned to the caller to indicate that the specific request is
4646
// invalid in the current context.
4747
ErrRejected = NewError(-32005, "rejected by transport")
48-
// ErrUnsupportedProtocolVersion is returned when a server does not support the protocol version.
49-
ErrUnsupportedProtocolVersion = NewError(-32004, "unsupported protocol version")
5048
)
5149

5250
const wireVersion = "2.0"

mcp/client.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ func (c *Client) Connect(ctx context.Context, t Transport, opts *ClientSessionOp
306306
// Try to negotiate a mutually supported version if the server
307307
// reports an UnsupportedProtocolVersionError with a supported version.
308308
var werr *jsonrpc.Error
309-
if errors.As(err, &werr) && werr.Code == CodeUnsupportedProtocolVersion && werr.Data != nil {
309+
if errors.As(err, &werr) && werr.Code == CodeUnsupportedProtocolVersion && len(werr.Data) > 0 {
310310
var data UnsupportedProtocolVersionData
311311
if err := json.Unmarshal(werr.Data, &data); err == nil {
312312
if negotiatedVersion := negotiateMutuallySupportedVersion(data.Supported); negotiatedVersion != "" && negotiatedVersion >= protocolVersion20260728 {
@@ -384,7 +384,10 @@ func (c *Client) discover(ctx context.Context, cs *ClientSession) (*InitializeRe
384384
if negotiated == "" || negotiated < protocolVersion20260728 {
385385
// If there is no overlap, fall back to initialize so version
386386
// negotiation can happen via the legacy path.
387-
return nil, jsonrpc2.ErrUnsupportedProtocolVersion
387+
return nil, &jsonrpc2.WireError{
388+
Code: CodeUnsupportedProtocolVersion,
389+
Message: "unsupported protocol version",
390+
}
388391
}
389392

390393
return &InitializeResult{

mcp/shared.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -355,15 +355,15 @@ func clientSessionMethod[P Params, R Result](f func(*ClientSession, context.Cont
355355

356356
// MCP-specific error codes.
357357
const (
358+
// CodeHeaderMismatch indicates that HTTP headers do not match the corresponding values
359+
// in the request body, or that required headers are missing or malformed.
360+
CodeHeaderMismatch = -32020
358361
// CodeMissingRequiredClientCapabilities is the JSON-RPC error code defined by
359362
// SEP-2575 for MissingRequiredClientCapabilitiesError.
360-
CodeMissingRequiredClientCapabilities = -32003
363+
CodeMissingRequiredClientCapabilities = -32021
361364
// CodeUnsupportedProtocolVersion is the JSON-RPC error code defined by
362365
// SEP-2575 for UnsupportedProtocolVersionError.
363-
CodeUnsupportedProtocolVersion = -32004
364-
// CodeHeaderMismatch indicates that HTTP headers do not match the corresponding values
365-
// in the request body, or that required headers are missing or malformed.
366-
CodeHeaderMismatch = -32001
366+
CodeUnsupportedProtocolVersion = -32022
367367
// CodeURLElicitationRequired indicates that the server requires URL elicitation
368368
// before processing the request. The client should execute the elicitation handler
369369
// with the elicitations provided in the error data.

mcp/streamable.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -955,7 +955,8 @@ func (s *stream) release() {
955955
//
956956
// Per SEP-2575:
957957
// - MethodNotFound (-32601) MUST return HTTP 404.
958-
// - InvalidParams (-32602) and UnsupportedProtocolVersion (-32004) MUST
958+
// - InvalidParams (-32602), UnsupportedProtocolVersion (-32022) and
959+
// CodeMissingRequiredClientCapabilities (-32021) MUST
959960
// return HTTP 400.
960961
func extractErrorStatus(ctx context.Context, msg jsonrpc.Message) int {
961962
if protocolVersionFromContext(ctx) < protocolVersion20260728 {

mcp/streamable_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2050,7 +2050,7 @@ func TestStreamableMcpHeaderValidation(t *testing.T) {
20502050
}
20512051

20522052
// TestStreamableMcpHeaderValidationErrorFormat verifies that header
2053-
// validation errors return a JSON-RPC error with code -32001 and
2053+
// validation errors return a JSON-RPC error with code -32020 and
20542054
// Content-Type application/json, per SEP-2243.
20552055
func TestStreamableMcpHeaderValidationErrorFormat(t *testing.T) {
20562056
orig := supportedProtocolVersions
@@ -2125,7 +2125,7 @@ func TestStreamableMcpHeaderValidationErrorFormat(t *testing.T) {
21252125
t.Errorf("Content-Type = %q, want %q", baseMediaType(toolCallResp.Header.Get("Content-Type")), "application/json")
21262126
}
21272127

2128-
// Verify JSON-RPC error body contains error code -32001.
2128+
// Verify JSON-RPC error body contains error code -32020.
21292129
msg, err := jsonrpc2.DecodeMessage(toolCallRespBody)
21302130
if err != nil {
21312131
t.Fatalf("failed to decode message: %v", err)
@@ -2138,8 +2138,8 @@ func TestStreamableMcpHeaderValidationErrorFormat(t *testing.T) {
21382138
if !errors.As(resp.Error, &wireErr) {
21392139
t.Fatalf("expected *jsonrpc2.WireError, got %T", resp.Error)
21402140
}
2141-
if wireErr.Code != -32001 {
2142-
t.Errorf("wireErr.Code = %d, want -32001", wireErr.Code)
2141+
if wireErr.Code != CodeHeaderMismatch {
2142+
t.Errorf("wireErr.Code = %d, want %d", wireErr.Code, CodeHeaderMismatch)
21432143
}
21442144
if !strings.Contains(wireErr.Message, "Mcp-Method header value") {
21452145
t.Errorf("wireErr.Message = %q, want it to contain %q", wireErr.Message, "Mcp-Method header value")

0 commit comments

Comments
 (0)