Open
Labels
Description
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.
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": []
}
Activity
JunJieLiu51520 commentedon Sep 27, 2025
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 ?
quaff commentedon Sep 28, 2025
See #519
AlanBurlison commentedon Jul 1, 2026
DISCLAIMER: Codex-generated comment:
This also occurs in the SDK 2.0.0 stateless servlet transport, through a slightly different path.
Environment
HttpServletStatelessServerTransport2025-06-18The server advertises tools but not resources or prompts.
Reproduction
Actual response
The response is HTTP 500 with JSON-RPC code
-32603. The body serializes the completeMcpError, includingstackTrace,cause,localizedMessage, and other Java exceptionproperties:
{ "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:{ "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 errorwriter. 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.Add a stateless server for MCP 2026-07-28
Add a stateless server for MCP 2026-07-28
Modern stateless server for MCP 2026-07-28 (#1170)
IdentityOverflow commentedon Nov 4, 2026
Confirming this is still present in 2.1.0 and on
main, and that it is not specific to the session-id path: every error the servlet transports write as a JSON body goes throughresponseError, which doesjsonMapper.writeValueAsString(mcpError)on the exception itself.HttpServletStatelessServerTransportL269,HttpServletStreamableServerTransportProviderL738,HttpServletSseServerTransportProviderL442 and L496 (2.1.0 line numbers). On the stateless transport that covers 415 (Content-Type), 400 (Accept, malformed body, unexpected message type) and the handler-failure 500s. With a default Jackson 2 mapper the body is about 20 KB with 80+ frames.Reproduced on a Jetty 12 deployment of
HttpServletStatelessServerTransport(Java 17, mcp-json-jackson2 2.1.0):returns 415 with
{"cause":null,"stackTrace":[.... Minimal reproducer without a server:Workaround that works today: register a Jackson serializer for
McpErroron the mapper you pass to the transport builder, writing{"jsonrpc":"2.0","id":null,"error":{"code":…,"message":…}}fromgetJsonRpcError(). One note for the fix:McpSchema.JSONRPCResponse's compact constructor rejects a nullid, and on these paths the id is unknown, so the envelope has to be built separately (JSON-RPC 2.0 prescribesid: nullthere).