Title: Streamable servlet transport does not close SSE response for unknown methods · Issue #1050 · modelcontextprotocol/java-sdk · GitHub
Open Graph Title: Streamable servlet transport does not close SSE response for unknown methods · Issue #1050 · modelcontextprotocol/java-sdk
X Title: Streamable servlet transport does not close SSE response for unknown methods · Issue #1050 · modelcontextprotocol/java-sdk
Description: 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, bu...
Open Graph Description: 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 corr...
X Description: 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 corr...
Opengraph URL: https://github.com/modelcontextprotocol/java-sdk/issues/1050
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Streamable servlet transport does not close SSE response for unknown methods","articleBody":"# DISCLAIMER: Codex-generated bug report\n\n ## Bug description\n\n 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`\n response, but the POST response's SSE stream remains open indefinitely.\n\n Supported methods close their SSE streams normally after returning a response.\n\n The MCP Streamable HTTP specification says that after the JSON-RPC response has been sent, the server should close the SSE stream:\n\n https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#sending-messages-to-the-server\n\n ## Environment\n\n - MCP Java SDK: 2.0.0\n - Transport: `HttpServletStreamableServerTransportProvider`\n - Jetty: 12.1.10\n - Jakarta Servlet API: 6.1\n - Java: 25.0.3\n - Negotiated MCP protocol: `2025-06-18`\n\n The server advertises tools but not resources or prompts.\n\n ## Steps to reproduce\n\n Initialize a session:\n\n ```sh\n curl --max-time 5 -i -X POST http://127.0.0.1:8080/mcp \\\n -H 'Content-Type: application/json' \\\n -H 'Accept: application/json, text/event-stream' \\\n --data-binary '{\n \"jsonrpc\": \"2.0\",\n \"id\": 1,\n \"method\": \"initialize\",\n \"params\": {\n \"protocolVersion\": \"2025-06-18\",\n \"capabilities\": {},\n \"clientInfo\": {\n \"name\": \"reproducer\",\n \"version\": \"1.0\"\n }\n }\n }'\n ```\n\n Copy the returned `Mcp-Session-Id`, send `notifications/initialized`, and then call an unsupported method:\n\n ```sh\n curl --max-time 3 -i -X POST http://127.0.0.1:8080/mcp \\\n -H 'Content-Type: application/json' \\\n -H 'Accept: application/json, text/event-stream' \\\n -H 'MCP-Protocol-Version: 2025-06-18' \\\n -H 'Mcp-Session-Id: SESSION_ID' \\\n --data-binary '{\n \"jsonrpc\": \"2.0\",\n \"id\": 2,\n \"method\": \"resources/list\",\n \"params\": {}\n }'\n ```\n\n The server sends an SSE event promptly:\n\n ```text\n event: message\n data: {\"jsonrpc\":\"2.0\",\"id\":2,\"error\":{\"code\":-32601,\"message\":\"Method not found: resources/list\"}}\n ```\n\n However, the HTTP response does not reach end-of-stream. Curl eventually reports:\n\n ```text\n curl: (28) Operation timed out after 3002 milliseconds\n ```\n\n Calling a supported method such as `tools/list` returns its response and closes the stream immediately.\n\n ## Expected behavior\n\n After sending the `-32601` JSON-RPC response, the server should complete the asynchronous servlet context and close the POST response's SSE stream.\n\n ## Actual behavior\n\n The JSON-RPC error is delivered, but the SSE stream and HTTP request remain open.\n\n ## Apparent cause\n\n In `McpStreamableServerSession.responseStream`, the missing-handler branch returns only:\n\n ```java\n return transport.sendMessage(\n McpSchema.JSONRPCResponse.error(...));\n ```\n\n The registered-handler branch ends with:\n\n ```java\n .flatMap(transport::sendMessage)\n .then(transport.closeGracefully());\n ```\n\n The missing-handler branch appears to need the same transport closure:\n\n ```java\n return transport.sendMessage(\n McpSchema.JSONRPCResponse.error(...))\n .then(transport.closeGracefully());\n ```\n\n ## Impact\n\n 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.\n","author":{"url":"https://github.com/AlanBurlison","@type":"Person","name":"AlanBurlison"},"datePublished":"2026-07-01T11:03:28.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":2},"url":"https://github.com/1050/java-sdk/issues/1050"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:5d1a8398-d6a0-978c-d666-74c786bed1ee |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | C324:34684:7EED30F:AD82835:6A5E7508 |
| html-safe-nonce | 30c394ddb379fafc78b30fb7cce3ef2103ae7e078916a4776b8cefe36088960c |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJDMzI0OjM0Njg0OjdFRUQzMEY6QUQ4MjgzNTo2QTVFNzUwOCIsInZpc2l0b3JfaWQiOiI2OTAxNjc4OTQyMjQ2MDQwODQwIiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0= |
| visitor-hmac | 2e2480b7ec8a9031733d698242ccb5b8c65e1949d7bbfd69c6a1fe61325d7208 |
| hovercard-subject-tag | issue:4784911379 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/modelcontextprotocol/java-sdk/1050/issue_layout |
| twitter:image | https://opengraph.githubassets.com/8ab10b6f0201ef007cc146f04bbe24d50a33f4f7377d0cbbce66eaa2873d270f/modelcontextprotocol/java-sdk/issues/1050 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/8ab10b6f0201ef007cc146f04bbe24d50a33f4f7377d0cbbce66eaa2873d270f/modelcontextprotocol/java-sdk/issues/1050 |
| og:image:alt | 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 corr... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | AlanBurlison |
| hostname | github.com |
| expected-hostname | github.com |
| None | 71950bbe6bf7e15662b868c102fed9d1682c29a05970d9b2daa2e4dd3522c52e |
| turbo-cache-control | no-preview |
| go-import | github.com/modelcontextprotocol/java-sdk git https://github.com/modelcontextprotocol/java-sdk.git |
| octolytics-dimension-user_id | 182288589 |
| octolytics-dimension-user_login | modelcontextprotocol |
| octolytics-dimension-repository_id | 919609219 |
| octolytics-dimension-repository_nwo | modelcontextprotocol/java-sdk |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 919609219 |
| octolytics-dimension-repository_network_root_nwo | modelcontextprotocol/java-sdk |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 7514606601325843bc1c464d2d8bf5fe9af2c154 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width