spring-projects / spring-projects/spring-ai

MCP server transports serialize `McpError` instead of JSON-RPC error responses

Open
#6,855 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

status: waiting-for-triage
Dominant language
Java
Stars
9.5k
Forks
2.9k
Avg merge
1d 7h
Merged PRs (30d)
6

Description

Bug description

When an MCP server transport returns an error, the HTTP response body contains the serialized McpError exception rather than a JSON-RPC error response.

Since McpError extends RuntimeException, the response includes exception fields such as cause, localizedMessage, stackTrace, and suppressed. This occurs in the Stateless, SSE, and Streamable transports for both WebMVC and WebFlux.

A similar issue was reported for the Java SDK servlet transports in modelcontextprotocol/java-sdk#955.

Environment

  • Spring AI 2.0.1
  • Java 17

Steps to reproduce

Trigger an error response from one of the affected transports. For example:

  • send malformed JSON to a Stateless endpoint
  • omit the session ID when calling an SSE message endpoint
  • send another initialization request to an already initialized Streamable session

The response body contains the exception object:

{
  "jsonRpcError": {
    "code": -32600,
    "message": "Invalid message format"
  },
  "cause": null,
  "localizedMessage": "Invalid message format",
  "message": "Invalid message format",
  "stackTrace": [
    {
      "className": "...",
      "methodName": "..."
    }
  ],
  "suppressed": []
}

Expected behavior

The response body should contain only the JSON-RPC error response:

{
  "jsonrpc": "2.0",
  "error": {
    "code": -32600,
    "message": "Invalid message format"
  }
}

The existing HTTP status should be retained. The response should include the request ID when it is available and omit the id member when it is not.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing error handling in the Stateless, SSE, and Streamable transports for both WebMVC and WebFlux, using the malformed JSON, missing session ID, and repeated initialization cases as entry points. Done means each transport returns only the JSON-RPC error response, preserves the existing HTTP status, includes the request ID when available, and omits id otherwise.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.