Skip to content

Simplify error response when accessing MCP without session ID #577

Description

@Strange-Satwik

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": []
}

Activity

  1. JunJieLiu51520 commented on Sep 27, 2025

    @JunJieLiu51520
    Contributor

    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 ?

    Image @tzolov What do you think?
  2. quaff commented on Sep 28, 2025

    @quaff
    Contributor

    See #519

  3. AlanBurlison commented on Jul 1, 2026

    @AlanBurlison

    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 complete McpError, including stackTrace, 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.handleRequest correctly constructs an McpError using METHOD_NOT_FOUND, but propagates it with Mono.error(...).

    HttpServletStatelessServerTransport.doPost blocks on that publisher, catches the exception, replaces it with INTERNAL_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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions