- Implement MCP server with async/sync support and builder pattern configuration - Add Server stdio/SSE transport layers with robust error handling - Convert McpClient and McpServer to interfaces for better extensibility - Add sampling capabilities for LLM interactions (text/image) - Implement dynamic root management and runtime tool management - Add comprehensive prompt and resource capabilities - Add support for dynamic root management (add/remove roots at runtime) Architecture Changes - Introduce registration records for tools, resources, and prompts - Improve thread safety with concurrent collections - Enhance resource template handling - Implement builder patterns for Server/Client capabilities - Add support for server capabilities and implementation info Transport Layer: - Implement SseServerTransport with SSE endpoints - Add StdioServerTransport for process-based communication - Reorganize transport packages for better organization - Improve transport error handling and shutdown processes Documentation: - Add detailed MCP reference documentation - Include architecture diagrams and API documentation - Add comprehensive test coverage for all components - Include sample projects demonstrating stdio/SSE transports BREAKING CHANGES: Transport Package Reorganization - Move StdioClientTransport to o.s.ai.mcp.client.transport - Move SseClientTransport to o.s.ai.mcp.client.transport - Move ServerParameters to o.s.ai.mcp.client.transport - StdioClientTransport.errorHandler changed to private with setter method Migration: Use setErrorHandler() method instead of direct field access API Changes - Replace static factory methods with builder pattern - Update ServerCapabilities to use builder pattern - Make StdioClientTransport.errorHandler private with setter - Replace rootsListProvider with direct root management - Remove deprecated static factory methods Resolves #27,#25,#24,#11 Related to #12
4 KiB
4 KiB
MCP Error Handling Reference
McpError Class
org.springframework.ai.mcp.spec.McpError
The McpError class is a runtime exception that represents errors that occur during Model Context Protocol (MCP) operations. It extends RuntimeException and provides a way to encapsulate error information from the MCP protocol.
Overview
The McpError class is designed to handle various error scenarios that can occur during MCP communication, including protocol errors, transport errors, and application-specific errors.
Class Definition
public class McpError extends RuntimeException {
public McpError(Object error) {
super(error.toString());
}
}
Common Error Scenarios
-
Transport Errors
- Connection failures
- Timeout errors
- Protocol violations
-
Protocol Errors
- Invalid JSON-RPC messages
- Missing required fields
- Invalid method names
-
Application Errors
- Tool execution failures
- Resource access errors
- Invalid parameters
Error Handling Best Practices
Client-Side Error Handling
McpClient client = McpClient.using(transport)
.async();
client.sendRequest("method", params)
.onErrorResume(McpError.class, error -> {
// Handle MCP-specific errors
logger.error("MCP error occurred: {}", error.getMessage());
return Mono.empty();
})
.onErrorResume(Exception.class, error -> {
// Handle other exceptions
logger.error("Unexpected error: {}", error.getMessage());
return Mono.empty();
});
Server-Side Error Handling
McpServer.using(transport)
.tool(new McpSchema.Tool("example", "Example tool", inputSchema),
args -> {
try {
// Tool implementation
return new McpSchema.CallToolResult(result);
}
catch (Exception e) {
// Convert to MCP error
throw new McpError("Tool execution failed: " + e.getMessage());
}
})
.async();
Implementation Notes
- McpError is a runtime exception, so it doesn't require explicit declaration in method signatures
- The error message is created by calling toString() on the provided error object
- Error handling should be implemented at both client and server sides
- Reactive error handling using Project Reactor's error operators is recommended
- Consider logging errors for debugging and monitoring purposes
Error Recovery Strategies
- Retry Logic
client.sendRequest("method", params)
.retry(3) // Retry up to 3 times
.onErrorResume(McpError.class, error -> {
// Handle failure after retries
return Mono.empty();
});
- Fallback Values
client.sendRequest("method", params)
.onErrorReturn(McpError.class, fallbackValue);
- Circuit Breaking
// Using Resilience4j or similar library
CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("mcpClient");
client.sendRequest("method", params)
.transform(CircuitBreakerOperator.of(circuitBreaker));
Error Logging and Monitoring
client.sendRequest("method", params)
.doOnError(McpError.class, error -> {
// Log error details
logger.error("MCP error: {}", error.getMessage());
// Update metrics
errorCounter.increment();
});
Integration with Spring Error Handling
@ControllerAdvice
public class McpErrorHandler {
@ExceptionHandler(McpError.class)
public ResponseEntity<ErrorResponse> handleMcpError(McpError error) {
ErrorResponse response = new ErrorResponse(
"MCP_ERROR",
error.getMessage()
);
return ResponseEntity
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(response);
}
}
Testing Error Scenarios
@Test
void testMcpError() {
McpError error = new McpError("Test error");
assertEquals("Test error", error.getMessage());
assertThrows(McpError.class, () -> {
throw new McpError("Test error");
});
}