DISCLAIMER: Codex-generated bug report
Bug description
With HttpServletStreamableServerTransportProvider in Java SDK 2.0.0, a request for an unknown or unsupported JSON-RPC method receives the correct -32601 Method not found
response, but the POST response's SSE stream remains open indefinitely.
Supported methods close their SSE streams normally after returning a response.
The MCP Streamable HTTP specification says that after the JSON-RPC response has been sent, the server should close the SSE stream:
https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#sending-messages-to-the-server
Environment
- MCP Java SDK: 2.0.0
- Transport:
HttpServletStreamableServerTransportProvider
- Jetty: 12.1.10
- Jakarta Servlet API: 6.1
- Java: 25.0.3
- Negotiated MCP protocol:
2025-06-18
The server advertises tools but not resources or prompts.
Steps to reproduce
Initialize a session:
curl --max-time 5 -i -X POST http://127.0.0.1:8080/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
--data-binary '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-06-18",
"capabilities": {},
"clientInfo": {
"name": "reproducer",
"version": "1.0"
}
}
}'
Copy the returned Mcp-Session-Id, send notifications/initialized, and then call an unsupported method:
curl --max-time 3 -i -X POST http://127.0.0.1:8080/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H 'MCP-Protocol-Version: 2025-06-18' \
-H 'Mcp-Session-Id: SESSION_ID' \
--data-binary '{
"jsonrpc": "2.0",
"id": 2,
"method": "resources/list",
"params": {}
}'
The server sends an SSE event promptly:
event: message
data: {"jsonrpc":"2.0","id":2,"error":{"code":-32601,"message":"Method not found: resources/list"}}
However, the HTTP response does not reach end-of-stream. Curl eventually reports:
curl: (28) Operation timed out after 3002 milliseconds
Calling a supported method such as tools/list returns its response and closes the stream immediately.
Expected behavior
After sending the -32601 JSON-RPC response, the server should complete the asynchronous servlet context and close the POST response's SSE stream.
Actual behavior
The JSON-RPC error is delivered, but the SSE stream and HTTP request remain open.
Apparent cause
In McpStreamableServerSession.responseStream, the missing-handler branch returns only:
return transport.sendMessage(
McpSchema.JSONRPCResponse.error(...));
The registered-handler branch ends with:
.flatMap(transport::sendMessage)
.then(transport.closeGracefully());
The missing-handler branch appears to need the same transport closure:
return transport.sendMessage(
McpSchema.JSONRPCResponse.error(...))
.then(transport.closeGracefully());
Impact
Clients that probe an unsupported method may wait indefinitely unless they impose a timeout. The server also retains the asynchronous servlet request until the client disconnects.
DISCLAIMER: Codex-generated bug report
Bug description
With
HttpServletStreamableServerTransportProviderin Java SDK 2.0.0, a request for an unknown or unsupported JSON-RPC method receives the correct-32601 Method not foundresponse, but the POST response's SSE stream remains open indefinitely.
Supported methods close their SSE streams normally after returning a response.
The MCP Streamable HTTP specification says that after the JSON-RPC response has been sent, the server should close the SSE stream:
https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#sending-messages-to-the-server
Environment
HttpServletStreamableServerTransportProvider2025-06-18The server advertises tools but not resources or prompts.
Steps to reproduce
Initialize a session:
Copy the returned
Mcp-Session-Id, sendnotifications/initialized, and then call an unsupported method:The server sends an SSE event promptly:
However, the HTTP response does not reach end-of-stream. Curl eventually reports:
Calling a supported method such as
tools/listreturns its response and closes the stream immediately.Expected behavior
After sending the
-32601JSON-RPC response, the server should complete the asynchronous servlet context and close the POST response's SSE stream.Actual behavior
The JSON-RPC error is delivered, but the SSE stream and HTTP request remain open.
Apparent cause
In
McpStreamableServerSession.responseStream, the missing-handler branch returns only:The registered-handler branch ends with:
The missing-handler branch appears to need the same transport closure:
Impact
Clients that probe an unsupported method may wait indefinitely unless they impose a timeout. The server also retains the asynchronous servlet request until the client disconnects.