Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

package org.springaicommunity.mcp.method.prompt;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.function.BiFunction;
Expand Down Expand Up @@ -107,7 +108,10 @@ public GetPromptResult apply(McpSyncServerExchange exchange, GetPromptRequest re
return promptResult;
}
catch (Exception e) {
if (e instanceof McpError mcpError && mcpError.getJsonRpcError() != null) {

Throwable cause = e instanceof InvocationTargetException ite ? ite.getTargetException() : e;

if (cause instanceof McpError mcpError && mcpError.getJsonRpcError() != null) {
throw mcpError;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.util.Map;
import java.util.function.BiFunction;

import io.modelcontextprotocol.spec.McpSchema;
import org.junit.jupiter.api.Test;
import org.springaicommunity.mcp.annotation.McpArg;
import org.springaicommunity.mcp.annotation.McpMeta;
Expand Down Expand Up @@ -44,7 +45,10 @@ private static class TestPromptProvider {

@McpPrompt(name = "failing-prompt", description = "A prompt that throws an exception")
public GetPromptResult getFailingPrompt(GetPromptRequest request) {
throw new RuntimeException("Test exception");
if (request.arguments().get("type").toString().equals("runTimeException")) {
throw new RuntimeException("Test exception");
}
throw McpError.builder(McpSchema.ErrorCodes.INTERNAL_ERROR).message("Internal error").build();
}

@McpPrompt(name = "greeting", description = "A simple greeting prompt")
Expand Down Expand Up @@ -215,14 +219,27 @@ public void testMethodInvocationError() throws Exception {
.build();

McpSyncServerExchange exchange = mock(McpSyncServerExchange.class);
Map<String, Object> args = new HashMap<>();
args.put("name", "John");
GetPromptRequest request = new GetPromptRequest("failing-prompt", args);
GetPromptRequest runTimeExceptionRequest = new GetPromptRequest("failing-prompt",
Map.of("type", "runTimeException"));

// The new error handling should throw McpError instead of
// McpPromptMethodException
assertThatThrownBy(() -> callback.apply(exchange, request)).isInstanceOf(McpError.class)
.hasMessageContaining("Error invoking prompt method");
assertThatThrownBy(() -> callback.apply(exchange, runTimeExceptionRequest)).isInstanceOf(McpError.class)
.satisfies(t -> {
McpError e = (McpError) t;
assertThat(e.getJsonRpcError().code()).isEqualTo(McpSchema.ErrorCodes.INVALID_PARAMS);
assertThat(e.getJsonRpcError().message()).contains("Error invoking prompt method");
});

// McpError should be preserved
GetPromptRequest mcpErrorRequest = new GetPromptRequest("failing-prompt", Map.of("type", "mcpError"));

assertThatThrownBy(() -> callback.apply(exchange, mcpErrorRequest)).isInstanceOf(McpError.class)
.satisfies(t -> {
McpError e = (McpError) t;
assertThat(e.getJsonRpcError().code()).isEqualTo(McpSchema.ErrorCodes.INTERNAL_ERROR);
assertThat(e.getJsonRpcError().message()).isEqualTo("Internal error");
});
}

@Test
Expand Down