mcp: preserve single-request batch responses (#1214)
## What does this PR do? Preserve JSON-RPC batch response arrays when a batch contains a single request. ## Why is this needed? A single-request legacy batch must be returned as a one-element JSON array, but the JSON response path currently unwraps it into a single JSON object. ## Changes - Preserve the original batch state on the logical stream - Keep single-request batch responses as arrays - Add a regression test for legacy initialization batches ## Testing - `go test ./mcp -count=1` - `go test ./... -count=1` - `git diff --check` Fixes #1211
This commit is contained in:
parent
21c18c6229
commit
d19bfebab9
1 changed files with 52 additions and 1 deletions
|
|
@ -988,6 +988,10 @@ type stream struct {
|
|||
// Note: if we remove support for batching, this could just be a bool.
|
||||
pendingJSONMessages []json.RawMessage
|
||||
|
||||
// isBatch reports whether the request that opened the stream was a JSON-RPC
|
||||
// batch. Batch responses must remain arrays even when they contain one item.
|
||||
isBatch bool
|
||||
|
||||
// w is the HTTP response writer for this stream. A non-nil w indicates
|
||||
// that the stream is claimed by an HTTP request (the hanging POST or GET);
|
||||
// it is set to nil when the request completes.
|
||||
|
|
@ -1138,7 +1142,7 @@ func (s *stream) deliverLocked(data []byte, eventID string, responseTo jsonrpc.I
|
|||
if done {
|
||||
// Flush all pending messages as JSON response.
|
||||
var toWrite []byte
|
||||
if len(s.pendingJSONMessages) == 1 {
|
||||
if len(s.pendingJSONMessages) == 1 && !s.isBatch {
|
||||
toWrite = s.pendingJSONMessages[0]
|
||||
} else {
|
||||
toWrite, err = json.Marshal(s.pendingJSONMessages)
|
||||
|
|
@ -1691,6 +1695,7 @@ func (c *streamableServerConn) servePOST(w http.ResponseWriter, req *http.Reques
|
|||
return
|
||||
}
|
||||
stream.isListen = isSubscriptionsListen
|
||||
stream.isBatch = isBatch
|
||||
|
||||
// subscriptions/listen is inherently a long-lived SSE endpoint (SEP-2575):
|
||||
// it has no synchronous result, the response stream stays open until the
|
||||
|
|
|
|||
Loading…
Reference in a new issue