Problem
When a @McpResource or @McpPrompt annotated method throws a runtime exception (e.g., IOException, NullPointerException),
the framework wraps it with ErrorCodes.INVALID_PARAMS (-32602).
However, the MCP specification defines distinct error codes for different failure scenarios:
- -32602 (INVALID_PARAMS): Invalid method parameter(s)
- -32603 (INTERNAL_ERROR): Internal JSON-RPC error
A runtime exception during method execution is an internal error, not an invalid parameter error.
Affected files
All four resource callbacks and all four prompt callbacks use INVALID_PARAMS in the catch block:
Resource:
- SyncMcpResourceMethodCallback.java:129
- AsyncMcpResourceMethodCallback.java:143
- SyncStatelessMcpResourceMethodCallback.java:124
- AsyncStatelessMcpResourceMethodCallback.java:137
Prompt:
- SyncMcpPromptMethodCallback.java:114
- AsyncMcpPromptMethodCallback.java:122
- SyncStatelessMcpPromptMethodCallback.java:108
- AsyncStatelessMcpPromptMethodCallback.java:119
Example (SyncMcpResourceMethodCallback.java:124-135)
catch (Exception e) {
if (e instanceof McpError mcpError && mcpError.getJsonRpcError() != null) {
throw mcpError;
}
throw McpError.builder(ErrorCodes.INVALID_PARAMS) // ← should be ErrorCodes.INTERNAL_ERROR
.message("Error invoking resource method: " + this.method.getName() + " in "
+ this.bean.getClass().getName() + ". /nCause: "
+ ErrorUtils.findCauseUsingPlainJava(e).getMessage())
.data(ErrorUtils.findCauseUsingPlainJava(e).getMessage())
.build();
}
Expected behavior
Runtime exceptions during method execution should be wrapped with ErrorCodes.INTERNAL_ERROR (-32603), matching the MCP
specification:
Additional note
The MCP SDK itself already follows this convention — McpStreamableServerSession uses INTERNAL_ERROR as the fallback when a
handler throws a non-McpError exception (line 184).
Environment
- mcp-annotations: 0.8.0
- mcp-core (SDK): 0.17.0
- Spring AI: 1.1.4
Problem
When a @McpResource or @McpPrompt annotated method throws a runtime exception (e.g., IOException, NullPointerException),
the framework wraps it with ErrorCodes.INVALID_PARAMS (-32602).
However, the MCP specification defines distinct error codes for different failure scenarios:
A runtime exception during method execution is an internal error, not an invalid parameter error.
Affected files
All four resource callbacks and all four prompt callbacks use INVALID_PARAMS in the catch block:
Resource:
Prompt:
Example (SyncMcpResourceMethodCallback.java:124-135)
catch (Exception e) {
if (e instanceof McpError mcpError && mcpError.getJsonRpcError() != null) {
throw mcpError;
}
}
Expected behavior
Runtime exceptions during method execution should be wrapped with ErrorCodes.INTERNAL_ERROR (-32603), matching the MCP
specification:
Additional note
The MCP SDK itself already follows this convention — McpStreamableServerSession uses INTERNAL_ERROR as the fallback when a
handler throws a non-McpError exception (line 184).
Environment