mcp: Implement server-side support for discover method (SEP-2575) (#987)
## Summary
Part 3 of the SEP-2575 ("Make MCP Stateless") implementation. Builds on
PR #975 which landed the client-side discover/fallback flow and the
per-request `_meta` plumbing. This PR adds the **server-side**
counterparts:
- `server/discover` handler (replaces the
stub),ProtocolVersionSupporter`
- transport hook for per-transport version filtering,
- transport-agnostic version validation and method-removal enforcement
in `ServerSession.handle`,
- HTTP-level wire compliance for SEP-2575 error codes/status codes,
- bug fix in `internal/jsonrpc2`,`processResult` with an `MCPGODEBUG`
opt-out for backward compatibility.
This commit is contained in:
parent
00d3642840
commit
dd978160ab
3 changed files with 702 additions and 187 deletions
|
|
@ -38,6 +38,17 @@ Options listed below were added and will be removed in the 1.9.0 version of the
|
|||
restoring the previous behavior. The default behavior was changed so that
|
||||
stateless servers ignore session IDs entirely and reject `DELETE` with 405.
|
||||
|
||||
- `nomethodnotfoundcodeinerror` added. If set to `1`, the jsonrpc2 layer will not
|
||||
include the MethodNotFound Error (`-32601`) in the error response when the
|
||||
requested method in STDIO transport is not found. The default behavior was
|
||||
changed to include the MethodNotFound Error in the error response when the
|
||||
requested method in STDIO transport is not found.
|
||||
|
||||
- `noprotocolerrorbody` added. If set to `1`, the streamable HTTP client will
|
||||
not attempt to decode the JSON-RPC error body of a non-2xx HTTP response,
|
||||
restoring the previous behavior. The default behavior was changed so that
|
||||
the client always attempts to surface the underlying JSON-RPC error.
|
||||
|
||||
### 1.6.0
|
||||
|
||||
Options listed below were added and will be removed in the 1.8.0 version of the SDK.
|
||||
|
|
|
|||
|
|
@ -14,8 +14,25 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/modelcontextprotocol/go-sdk/internal/json"
|
||||
"github.com/modelcontextprotocol/go-sdk/internal/mcpgodebug"
|
||||
)
|
||||
|
||||
// nomethodnotfoundcodeinerror is a compatibility parameter that restores the
|
||||
// pre-fix behavior of [processResult], where wrapped [ErrNotHandled] or
|
||||
// [ErrMethodNotFound] errors returned by request handlers were not
|
||||
// recognized as "method not found" signals. The original switch statement
|
||||
// compared sentinel errors with ==, which never matched errors returned via
|
||||
// fmt.Errorf("%w: ...", ErrNotHandled, ...) — including the ones produced
|
||||
// by checkRequest. As a result the wire error response carried code 0
|
||||
// instead of code -32601. The fix uses errors.Is to recognize wrapped
|
||||
// sentinels and append the method name to the message.
|
||||
//
|
||||
// To restore the previous behavior, set MCPGODEBUG=nomethodnotfoundcodeinerror=1.
|
||||
// This option will be removed in a future SDK version.
|
||||
// See the documentation for the mcpgodebug package for instructions on how
|
||||
// to use it.
|
||||
var nomethodnotfoundcodeinerror = mcpgodebug.Value("nomethodnotfoundcodeinerror")
|
||||
|
||||
// Connection manages the jsonrpc2 protocol, connecting responses back to their
|
||||
// calls. Connection is bidirectional; it does not have a designated server or
|
||||
// client end.
|
||||
|
|
@ -648,9 +665,7 @@ func (c *Connection) handleAsync() {
|
|||
|
||||
// processResult processes the result of a request and, if appropriate, sends a response.
|
||||
func (c *Connection) processResult(from any, req *incomingRequest, result any, err error) error {
|
||||
switch err {
|
||||
case ErrNotHandled, ErrMethodNotFound:
|
||||
// Add detail describing the unhandled method.
|
||||
if nomethodnotfoundcodeinerror != "1" && (errors.Is(err, ErrNotHandled) || errors.Is(err, ErrMethodNotFound)) {
|
||||
err = fmt.Errorf("%w: %q", ErrMethodNotFound, req.Method)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ var (
|
|||
// ErrServerClosing is returned for calls that arrive while the server is closing.
|
||||
ErrServerClosing = NewError(-32006, "server is closing")
|
||||
// ErrClientClosing is a dummy error returned for calls initiated while the client is closing.
|
||||
ErrClientClosing = NewError(-32003, "client is closing")
|
||||
ErrClientClosing = NewError(-32007, "client is closing")
|
||||
|
||||
// The following errors have special semantics for MCP transports
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue