Skip to content

Commit a360b7d

Browse files
committed
feat: improve error handling by extracting root cause messages
- Add findRootCause() utility method utility to traverse exception chains - Update McpServerSession and McpStreamableServerSession to use root cause messages - Ensures meaningful error messages are returned instead of wrapped exception messages Signed-off-by: Christian Tzolov <[email protected]>
1 parent b026492 commit a360b7d

File tree

3 files changed

+16
-5
lines changed

3 files changed

+16
-5
lines changed

mcp-core/src/main/java/io/modelcontextprotocol/spec/McpError.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,13 @@ public McpError build() {
7878

7979
}
8080

81+
public static Throwable findRootCause(Throwable throwable) {
82+
Assert.notNull(throwable, "throwable must not be null");
83+
Throwable rootCause = throwable;
84+
while (rootCause.getCause() != null && rootCause.getCause() != rootCause) {
85+
rootCause = rootCause.getCause();
86+
}
87+
return rootCause;
88+
}
89+
8190
}

mcp-core/src/main/java/io/modelcontextprotocol/spec/McpServerSession.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -224,9 +224,12 @@ public Mono<Void> handle(McpSchema.JSONRPCMessage message) {
224224
else if (message instanceof McpSchema.JSONRPCRequest request) {
225225
logger.debug("Received request: {}", request);
226226
return handleIncomingRequest(request, transportContext).onErrorResume(error -> {
227+
McpSchema.JSONRPCResponse.JSONRPCError jsonRpcError = (error instanceof McpError mcpError
228+
&& mcpError.getJsonRpcError() != null) ? mcpError.getJsonRpcError()
229+
: new McpSchema.JSONRPCResponse.JSONRPCError(McpSchema.ErrorCodes.INTERNAL_ERROR,
230+
McpError.findRootCause(error).getMessage(), null);
227231
var errorResponse = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), null,
228-
new McpSchema.JSONRPCResponse.JSONRPCError(McpSchema.ErrorCodes.INTERNAL_ERROR,
229-
error.getMessage(), null));
232+
jsonRpcError);
230233
// TODO: Should the error go to SSE or back as POST return?
231234
return this.transport.sendMessage(errorResponse).then(Mono.empty());
232235
}).flatMap(this.transport::sendMessage);
@@ -287,7 +290,7 @@ private Mono<McpSchema.JSONRPCResponse> handleIncomingRequest(McpSchema.JSONRPCR
287290
&& mcpError.getJsonRpcError() != null) ? mcpError.getJsonRpcError()
288291
// TODO: add error message through the data field
289292
: new McpSchema.JSONRPCResponse.JSONRPCError(McpSchema.ErrorCodes.INTERNAL_ERROR,
290-
error.getMessage(), null);
293+
McpError.findRootCause(error).getMessage(), null);
291294
return Mono.just(
292295
new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), null, jsonRpcError));
293296
});

mcp-core/src/main/java/io/modelcontextprotocol/spec/McpStreamableServerSession.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,9 +181,8 @@ public Mono<Void> responseStream(McpSchema.JSONRPCRequest jsonrpcRequest, McpStr
181181
.onErrorResume(e -> {
182182
McpSchema.JSONRPCResponse.JSONRPCError jsonRpcError = (e instanceof McpError mcpError
183183
&& mcpError.getJsonRpcError() != null) ? mcpError.getJsonRpcError()
184-
// TODO: add error message through the data field
185184
: new McpSchema.JSONRPCResponse.JSONRPCError(McpSchema.ErrorCodes.INTERNAL_ERROR,
186-
e.getMessage(), null);
185+
McpError.findRootCause(e).getMessage(), null);
187186

188187
var errorResponse = new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, jsonrpcRequest.id(),
189188
null, jsonRpcError);

0 commit comments

Comments
 (0)