Skip to content

[BUG] MCP Streamable-HTTP returns stale/fabricated JSON-RPC response for notifications #6834

Description

@Aias00

Description

processWithExistingSession unconditionally chains .then(waitForTransportResponse(transport, sessionId, messageId)) for every incoming message, with no detection of JSONRPCNotification (messages with no id). waitForTransportResponse either returns transport.getLastSentMessage() (the previous request's response still held, since resetCapturedMessage is never called on the existing-session path) when isResponseReady() is true, or a fabricated createJsonRpcResponse(messageId, {}) when false. Notifications must return HTTP 202 with no body.

Location

  • shenyu-plugin/shenyu-plugin-mcp-server/src/main/java/org/apache/shenyu/plugin/mcp/server/transport/ShenyuStreamableHttpServerTransportProvider.java:515-527, 792-806

Impact

After a tools/call/tools/list sets lastSentMessage, any subsequent notification (notifications/initialized, notifications/cancelled) sent with the same Mcp-Session-Id is answered with HTTP 200 carrying the stale previous JSON-RPC response (wrong id), causing client mis-correlation. A notification sent before any request gets a fabricated {"jsonrpc":"2.0","result":{}} with null id.

Suggested fix

In processWithExistingSession, detect message being a JSONRPCNotification (no id) and return a 202/empty-body result without invoking waitForTransportResponse; call resetCapturedMessage() after each completed response on the existing-session path.

Related existing

Distinct from MCP-01..05 (#6640-#6644, response-decorator body/leak issues). This is the transport-provider notification path.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions