Repository navigation
Simplify error response when accessing MCP without session ID #577
Description
Activity
Extending from this issue, I hope to refactor abs mcptransport, because i found so many responseError method in different child class, for example, why public interface McpStatelessServerTransport {
child class not extends McpServerTransport ?
@tzolov What do you think?See #519
- addedenhancementNew feature or requestNew feature or request
on Feb 20, 2026 DISCLAIMER: Codex-generated comment:
This also occurs in the SDK 2.0.0 stateless servlet transport, through a slightly different path.
Environment
- MCP Java SDK: 2.0.0
- Transport:
HttpServletStatelessServerTransport - Jetty: 12.1.10
- Jakarta Servlet API: 6.1
- Java: 25.0.3
- MCP protocol:
2025-06-18
The server advertises tools but not resources or prompts.
Reproduction
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' \ -H 'MCP-Protocol-Version: 2025-06-18' \ --data-binary '{ "jsonrpc": "2.0", "id": 1, "method": "resources/list", "params": {} }'
Actual response
The response is HTTP 500 with JSON-RPC code
-32603. The body serializes the completeMcpError, includingstackTrace,cause,localizedMessage, and other Java exception
properties:HTTP/1.1 500 Server Error Content-Type: application/json;charset=utf-8
{ "jsonRpcError": { "code": -32603, "message": "Failed to handle request: Missing handler for request type: resources/list" }, "cause": null, "localizedMessage": "Failed to handle request: Missing handler for request type: resources/list", "message": "Failed to handle request: Missing handler for request type: resources/list", "stackTrace": [ { "className": "io.modelcontextprotocol.spec.McpError$Builder", "methodName": "build", "fileName": "McpError.java" }, { "className": "io.modelcontextprotocol.server.transport.HttpServletStatelessServerTransport", "methodName": "doPost", "fileName": "HttpServletStatelessServerTransport.java" } ] }Expected response
The request should complete as a normal JSON-RPC response with the original request ID and
-32601 Method not found, without serialized exception internals. For example:HTTP/1.1 200 OK Content-Type: application/json;charset=utf-8
{ "jsonrpc": "2.0", "id": 1, "error": { "code": -32601, "message": "Method not found: resources/list" } }Apparent cause
DefaultMcpStatelessServerHandler.handleRequestcorrectly constructs anMcpErrorusingMETHOD_NOT_FOUND, but propagates it withMono.error(...).HttpServletStatelessServerTransport.doPostblocks on that publisher, catches the exception, replaces it withINTERNAL_ERROR, and passes the exception object to its JSON error
writer. Jackson then serializes the Java exception properties.The missing-handler branch could instead return a normal
JSONRPCResponse.error(...), consistent with how errors from registered handlers are converted into JSON-RPC responses.
Description:
Currently, when accessing the MCP Streamable HTTP server at https://host:port/mcp without providing a session ID, the server responds with the full exception stack trace and detailed error information.
Issue:
Returning the complete stack trace in the response is not user-friendly and may expose internal details unnecessarily.
https://github.com/modelcontextprotocol/java-sdk/blob/7f16cd0b9dc72f5adc3358a903bebb0f909dda3e/mcp-core/src/main/java/io/modelcontextprotocol/server/transport/HttpServletStreamableServerTransportProvider.java#L264C4-L264C100
Suggestion:
Instead of returning the full error, return a simple, clear message indicating there is an issue with the request headers or the session ID
stack trace
{ "cause": null, "stackTrace": [ { "moduleName": null, "moduleVersion": null, "classLoaderName": null, "methodName": "doGet", "fileName": "HttpServletStreamableServerTransportProvider.java", "lineNumber": 268, "className": "com.ibm.modelcontextprotocol.server.transport.HttpServletStreamableServerTransportProvider", "nativeMethod": false }, { "moduleName": null, "moduleVersion": null, "classLoaderName": null, "methodName": "service", "fileName": "HttpServlet.java", "lineNumber": 527, "className": "jakarta.servlet.http.HttpServlet", "nativeMethod": false }, { "moduleName": null, "moduleVersion": null, "classLoaderName": null, "methodName": "service", "fileName": "HttpServlet.java", "lineNumber": 614, "className": "jakarta.servlet.http.HttpServlet", "nativeMethod": false } ], "jsonRpcError": null, "message": "text/event-stream required in Accept header; Session ID required in mcp-session-id header", "localizedMessage": "text/event-stream required in Accept header; Session ID required in mcp-session-id header", "suppressed": [] }