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

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions