Skip to content

Commit 52828cd

Browse files
committed
refactor: remove redundant meta field from validatedMeta and simplify protocol version validation logic
1 parent 67233a6 commit 52828cd

4 files changed

Lines changed: 27 additions & 60 deletions

File tree

mcp/shared.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,6 @@ func extractRequestMeta(rawParams json.RawMessage) Meta {
482482

483483
type validatedMeta struct {
484484
usesNewProtocol bool
485-
meta Meta
486485
}
487486

488487
// validateRequestMeta inspects a JSON-RPC request to detect whether it follows
@@ -501,7 +500,7 @@ func validateRequestMeta(req *jsonrpc.Request) (*validatedMeta, error) {
501500
}
502501
// Notifications do not carry full client identity
503502
if !req.IsCall() {
504-
return &validatedMeta{usesNewProtocol: true, meta: meta}, nil
503+
return &validatedMeta{usesNewProtocol: true}, nil
505504
}
506505
if _, ok := meta[MetaKeyClientInfo]; !ok {
507506
return nil, &jsonrpc.Error{
@@ -515,7 +514,7 @@ func validateRequestMeta(req *jsonrpc.Request) (*validatedMeta, error) {
515514
Message: fmt.Sprintf("missing required _meta field %q", MetaKeyClientCapabilities),
516515
}
517516
}
518-
return &validatedMeta{usesNewProtocol: true, meta: meta}, nil
517+
return &validatedMeta{usesNewProtocol: true}, nil
519518
}
520519

521520
// A Request is a method request with parameters and additional information, such as the session.

mcp/shared_test.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,10 +136,6 @@ func TestValidateRequestMeta(t *testing.T) {
136136

137137
vmeta, err := validateRequestMeta(req)
138138
usesNew := vmeta != nil && vmeta.usesNewProtocol
139-
if err != nil {
140-
meta := extractRequestMeta(req.Params)
141-
usesNew = meta != nil && meta[MetaKeyProtocolVersion] != nil
142-
}
143139
if usesNew != tc.wantUsesNew {
144140
t.Errorf("usesNewProtocol = %v, want %v", usesNew, tc.wantUsesNew)
145141
}

mcp/streamable.go

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -390,17 +390,16 @@ func (h *StreamableHTTPHandler) serveStatelessLegacyDELETE(w http.ResponseWriter
390390
}
391391

392392
// ephemeralConnectOpts peeks at the request body to determine whether it
393-
// contains an initialize or initialized message, or whether any of its
394-
// messages carry the per-request `_meta.protocolVersion` field that signals
395-
// the >= 2026-06-30 sessionless protocol (SEP-2575).
393+
// contains an initialize or initialized message or whether the protocol version
394+
// header indicates a protocol version >= 2026-06-30 (SEP-2575).
396395
//
397396
// For old-protocol requests, default session state is synthesized so that
398397
// the session's init gate doesn't reject the request.
399398
//
400399
// It is used for both stateless servers and stateful servers with no session ID.
401400
//
402-
// The returned usesNewProtocol bool reports whether any request in the body
403-
// carried `_meta.protocolVersion`.
401+
// The returned usesNewProtocol bool reports whether the protocol version
402+
// header indicates a protocol version >= 2026-06-30 (SEP-2575).
404403
func (h *StreamableHTTPHandler) ephemeralConnectOpts(req *http.Request) (opts *ServerSessionOptions, usesNewProtocol bool, err error) {
405404
protocolVersion := protocolVersionFromContext(req.Context())
406405
if protocolVersion == "" {
@@ -1325,25 +1324,25 @@ func (c *streamableServerConn) servePOST(w http.ResponseWriter, req *http.Reques
13251324
http.Error(w, fmt.Sprintf(
13261325
"Bad Request: protocol version %q is only supported on stateless HTTP servers (set StreamableHTTPOptions.Stateless = true)",
13271326
protocolVersion),
1328-
http.StatusBadRequest)
1329-
return
1330-
}
1331-
if headerVersion == "" {
1332-
http.Error(w, fmt.Sprintf(
1333-
"Bad Request: %s header is required for requests carrying %q",
1334-
protocolVersionHeader, MetaKeyProtocolVersion),
1335-
http.StatusBadRequest)
1336-
return
1337-
}
1338-
if headerVersion != metaVersion {
1339-
http.Error(w, fmt.Sprintf(
1340-
"Bad Request: %s header %q does not match request %s %q",
1341-
protocolVersionHeader, headerVersion,
1342-
MetaKeyProtocolVersion, metaVersion),
1343-
http.StatusBadRequest)
1344-
return
1345-
}
1327+
http.StatusBadRequest)
1328+
return
1329+
}
1330+
if headerVersion == "" {
1331+
http.Error(w, fmt.Sprintf(
1332+
"Bad Request: %s header is required for requests carrying %q",
1333+
protocolVersionHeader, MetaKeyProtocolVersion),
1334+
http.StatusBadRequest)
1335+
return
1336+
}
1337+
if headerVersion != metaVersion {
1338+
http.Error(w, fmt.Sprintf(
1339+
"Bad Request: %s header %q does not match request %s %q",
1340+
protocolVersionHeader, headerVersion,
1341+
MetaKeyProtocolVersion, metaVersion),
1342+
http.StatusBadRequest)
1343+
return
13461344
}
1345+
}
13471346
// Include metadata for all requests (including notifications).
13481347
jreq.Extra = &RequestExtra{
13491348
TokenInfo: tokenInfo,

mcp/streamable_test.go

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1926,39 +1926,12 @@ func TestStreamableMcpHeaderValidation(t *testing.T) {
19261926
return &CallToolResult{}, nil
19271927
})
19281928

1929-
handler := NewStreamableHTTPHandler(func(req *http.Request) *Server { return server }, nil)
1929+
handler := NewStreamableHTTPHandler(func(req *http.Request) *Server { return server }, &StreamableHTTPOptions{
1930+
Stateless: true,
1931+
})
19301932
defer handler.closeAll()
19311933

1932-
initReq := req(1, methodInitialize, &InitializeParams{ProtocolVersion: minVersionForStandardHeaders})
1933-
initResp := resp(1, &InitializeResult{
1934-
Capabilities: &ServerCapabilities{
1935-
Logging: &LoggingCapabilities{},
1936-
Tools: &ToolCapabilities{ListChanged: true},
1937-
},
1938-
ProtocolVersion: minVersionForStandardHeaders,
1939-
ServerInfo: &Implementation{Name: "testServer", Version: "v1.0.0"},
1940-
}, nil)
1941-
1942-
initialize := streamableRequest{
1943-
method: "POST",
1944-
messages: []jsonrpc.Message{initReq},
1945-
wantStatusCode: http.StatusOK,
1946-
wantMessages: []jsonrpc.Message{initResp},
1947-
wantSessionID: true,
1948-
}
1949-
initialized := streamableRequest{
1950-
method: "POST",
1951-
headers: http.Header{
1952-
protocolVersionHeader: {minVersionForStandardHeaders},
1953-
methodHeader: {notificationInitialized},
1954-
},
1955-
messages: []jsonrpc.Message{req(0, notificationInitialized, &InitializedParams{})},
1956-
wantStatusCode: http.StatusAccepted,
1957-
}
1958-
19591934
testStreamableHandler(t, handler, []streamableRequest{
1960-
initialize,
1961-
initialized,
19621935
{
19631936
method: "POST",
19641937
headers: http.Header{

0 commit comments

Comments
 (0)