Skip to content

Commit cd2c21c

Browse files
docs: document best practice for handling argument errors in MCP tools (#891)
Resolves #356 Clarify the two-tier error model: - Recoverable tool errors: use CallToolResult with isError(true) - Protocol-level errors: throw McpError / let exceptions propagate as JSON-RPC errors Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
1 parent 22e7bd4 commit cd2c21c

File tree

1 file changed

+39
-0
lines changed

1 file changed

+39
-0
lines changed

docs/server.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,3 +795,42 @@ Supported logging levels (in order of increasing severity): DEBUG (0), INFO (1),
795795
## Error Handling
796796

797797
The SDK provides comprehensive error handling through the McpError class, covering protocol compatibility, transport communication, JSON-RPC messaging, tool execution, resource management, prompt handling, timeouts, and connection issues. This unified error handling approach ensures consistent and reliable error management across both synchronous and asynchronous operations.
798+
799+
### Error Handling in Tool Implementations
800+
801+
#### Two Tiers of Errors
802+
803+
MCP distinguishes between two categories of errors in tool execution:
804+
805+
**1. Tool-Level Errors (Recoverable by the LLM)**
806+
807+
Use `CallToolResult` with `isError(true)` for validation failures, missing arguments, or domain errors the LLM can act on and retry.
808+
809+
```java
810+
// Example: Domain validation failure (e.g., invalid email format)
811+
if (!emailAddress.matches("^[A-Za-z0-9+_.-]+@(.+)$")) {
812+
return CallToolResult.builder()
813+
.content(List.of(new McpSchema.TextContent("Invalid argument: 'email' must be a valid email address.")))
814+
.isError(true)
815+
.build();
816+
}
817+
```
818+
819+
The LLM receives this as part of the normal tool response and can self-correct in a subsequent interaction.
820+
821+
**2. Protocol-Level Errors (Unrecoverable)**
822+
823+
Uncaught exceptions from a tool handler are mapped to a JSON-RPC error response. Use this only for truly unexpected failures (e.g., infrastructure errors such as DB timeout), not for input validation.
824+
825+
```java
826+
// This propagates as a JSON-RPC error — use sparingly
827+
throw new McpError(McpSchema.ErrorCodes.INTERNAL_ERROR, "Unexpected failure");
828+
```
829+
830+
#### Decision Guide
831+
832+
| Situation | Approach |
833+
|------------------------------------|---------------------------------------|
834+
| Domain validation failure | `CallToolResult` with `isError=true` |
835+
| Infrastructure / unexpected error | Throw `McpError` or let it propagate |
836+
| Partial success with a warning | `CallToolResult` with warning in text |

0 commit comments

Comments
 (0)