mcp: Enable legacy initialize fallback on any error (#1014)

To guarantee a better compatibility with legacy server, enable the
fallback to the legacy initialize rpc in case of any error returned by
the server, in case of `server/discover` request.
This commit is contained in:
Guglielmo Colombo 2026-06-18 15:52:11 +02:00 • committed by GitHub
commit b85574f685
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -657,7 +657,6 @@ func TestClientConnectDiscover(t *testing.T) {
// Returning (nil, nil) means "let the default stub handle it" (which
// returns ErrMethodNotFound).
discoverHandler func() (Result, error)
wantConnectErr bool
// wantInitialize is true if the legacy initialize handshake should
// have run (i.e. discover signaled "not supported").
wantInitialize bool
@ -710,16 +709,6 @@ func TestClientConnectDiscover(t *testing.T) {
wantInitialize: true,
wantVersion: latestProtocolVersion,
},
{
name: "unexpected error propagates and aborts Connect",
discoverHandler: func() (Result, error) {
return nil, &jsonrpc.Error{
Code: jsonrpc.CodeInternalError,
Message: "boom",
}
},
wantConnectErr: true,
},
}
for _, tc := range tests {
@ -754,19 +743,6 @@ func TestClientConnectDiscover(t *testing.T) {
c := NewClient(testImpl, nil)
cs, err := c.Connect(ctx, ct, &ClientSessionOptions{protocolVersion: protocolVersion20260630})
if tc.wantConnectErr {
if err == nil {
_ = cs.Close()
t.Fatal("Connect succeeded, want error")
}
if !gotDiscover.Load() {
t.Error("server did not receive server/discover")
}
if gotInitialize.Load() {
t.Error("server received initialize but discover should have aborted Connect")
}
return
}
if err != nil {
t.Fatalf("Connect: %v", err)
}
@ -1061,51 +1037,6 @@ func TestInMemory_E2E_DiscoverFallback_UnsupportedProtocolVersion(t *testing.T)
}
}
// TestInMemory_E2E_DiscoverPropagatesOtherErrors verifies that an unrelated
// error from the discover handler aborts Connect and does NOT silently
// fall back.
func TestInMemory_E2E_DiscoverPropagatesOtherErrors(t *testing.T) {
ctx := context.Background()
orig := supportedProtocolVersions
supportedProtocolVersions = append([]string{protocolVersion20260630}, slices.Clone(orig)...)
t.Cleanup(func() { supportedProtocolVersions = orig })
var sawInitialize atomic.Bool
server := NewServer(&Implementation{Name: "broken-server", Version: "v1"}, nil)
server.AddReceivingMiddleware(func(next MethodHandler) MethodHandler {
return func(ctx context.Context, method string, req Request) (Result, error) {
switch method {
case methodDiscover:
return nil, &jsonrpc.Error{
Code: jsonrpc.CodeInternalError,
Message: "boom",
}
case methodInitialize:
sawInitialize.Store(true)
}
return next(ctx, method, req)
}
})
ct, st := NewInMemoryTransports()
ss, err := server.Connect(ctx, st, nil)
if err != nil {
t.Fatalf("server.Connect: %v", err)
}
defer ss.Close()
client := NewClient(&Implementation{Name: "new-client", Version: "v1"}, nil)
cs, err := client.Connect(ctx, ct, &ClientSessionOptions{protocolVersion: protocolVersion20260630})
if err == nil {
_ = cs.Close()
t.Fatal("Connect succeeded; want propagated discover error")
}
if sawInitialize.Load() {
t.Error("server received initialize; Connect should have aborted on the discover error")
}
}
// TestClientConnectDiscover_UnsupportedVersionNegotiation verifies the
// per SEP-2575 Version Negotiation Flow: when the client probes server/discover
// with a protocol version the server doesn't implement, the server's