mcp: Implement support for SEP-2575 on client side#975
Conversation
…lidation and accessors
…est rejections and update associated tests
…ed regression tests
…t stateless protocol to stateless HTTP servers
…n the new protocol session
…t initialization and version negotiation
…protocol version checking in server and tests
… protocol version validation logic
…ata into requests
…/SEP-2575_Stateless_MCP_part2
… test metadata injection logic
…y in server request handling
…per for InitializeParams
…ready initialized
…rt headers and conditional SSE stream initialization
…ization, and correct session metadata mapping
…k triggers in MCP client
…acks and clarify KeepAlive constraints
…version propagation in client and transport layers
…discover implementation
…/SEP-2575_Stateless_MCP_part2
…tateless_MCP_part2
…njectMeta to injectRequestMeta
…atching version from descending order list
…stub documentation
…n transport connection closure handling
… automatic nil-params collapsing
methodDiscover on client side| if errors.As(err, &werr) && (werr.Code == jsonrpc.CodeMethodNotFound || werr.Code == CodeUnsupportedProtocolVersion) { | ||
| return nil, true, nil | ||
| } | ||
| if strings.Contains(err.Error(), "Bad Request") { |
There was a problem hiding this comment.
this is quite unreliable.
maybe we can use other jsonrpc codes like 32600 invalid request. maybe introduce internal error errNotFound and add http-transport logic for %w-ing it into the error when status code is 404, add a check here
…400 for server/discover
…by handling unsupported version errors during discovery
| ErrUnknown = NewError(-32001, "unknown error") | ||
| // ErrServerClosing is returned for calls that arrive while the server is closing. | ||
| ErrServerClosing = NewError(-32004, "server is closing") | ||
| ErrServerClosing = NewError(-32006, "server is closing") |
There was a problem hiding this comment.
oh, that's not nice . SDK claimed error codes which are now also used in the spec.
ErrClientClosing = NewError(-32003, "client is closing")will now mean MISSING_REQUIRED_CLIENT_CAPABILITY.
for the server side we can do mcgdebug for returning -32004 when server is closing for a session with and old protocol version.
I guess we need to handle it in internal/jsonrpc2/wire.go is-check looking not just at the code but at the message as well 😞
There was a problem hiding this comment.
I am not sure this is needed. The ErrClientClosing and ErrServerClosing are never sent over the wire and the error code is never returned to the calling function. Are only used internally in the client / server implementation.
| // For cancelled or rejected requests, we don't set the writeErr (which would | ||
| // break the connection). They can just be returned to the caller. | ||
| if err != nil && ctx.Err() == nil && !errors.Is(err, ErrRejected) { | ||
| if err != nil && ctx.Err() == nil && !errors.Is(err, ErrRejected) && !errors.Is(err, ErrUnsupportedProtocolVersion) && !errors.Is(err, ErrMethodNotFound) { |
There was a problem hiding this comment.
I wonder if any server implementation close a connection on their side in case of an unknown method request
There was a problem hiding this comment.
In this case it will not pass through this path. The server will send a request from the SSE stream, and the client will respond with a new response that will eventually contain the error. But that will be a new POST Response
…s nil parameter initialization
… discover negotiation
Implements the client half of the SEP-2575 /
2026-06-30protocol. This CL is client-only; server-sideserver/discoveris still aMethodNotFoundstub.Changes
server/discoverprobe inClient.Connect()(client.go). When the caller opts intoprotocolVersion >= 2026-06-30, the client probes the server withserver/discoverbefore falling back to the legacyinitializehandshake.
_metainjection (shared.go,injectRequestMeta). For>= 2026-06-30sessions every outgoing request gets the SEP-2575 triple (protocolVersion,clientInfo,clientCapabilities).ServerSession.handleno longer pre-populatesstate.InitializeParamsfrom aserver/discoverrequest's_meta, so a subsequent fallbackinitializeis not rejected as a duplicate.Fallback rules
Client falls back to the legacy
initializehandshake when discover returns:MethodNotFound(-32601),UnsupportedProtocolVersionError(-32004),Bad Request(substring-matched on the error message, to interopwith pre-2026-06-30 servers).
Fixes #966