Skip to main content

mcp_protocol/
error.rs

1//! # MCP Protocol Errors
2//!
3//! **Comprehensive error handling** for MCP protocol operations
4//! - JSON-RPC 2.0 compliant error codes
5//! - Integration with protocol_transport_core error system
6//! - Authentication and authorization error handling
7
8use protocol_transport_core::{ProtocolError, TransportError};
9use thiserror::Error;
10
11/// **MCP-specific errors**
12#[derive(Error, Debug)]
13pub enum McpError {
14    #[error("JSON-RPC error: {0}")]
15    JsonRpc(String),
16
17    #[error("Authentication failed: {0}")]
18    Authentication(String),
19
20    #[error("Authorization failed: {0}")]
21    Authorization(String),
22
23    #[error("Tool not found: {0}")]
24    ToolNotFound(String),
25
26    #[error("Tool execution failed: {0}")]
27    ToolExecutionFailed(String),
28
29    #[error("Memory operation failed: {0}")]
30    MemoryOperationFailed(String),
31
32    #[error("Invalid tool parameters: {0}")]
33    InvalidToolParameters(String),
34
35    #[error("Protocol version mismatch: expected {expected}, got {actual}")]
36    ProtocolVersionMismatch { expected: String, actual: String },
37
38    #[error("Server capability not supported: {0}")]
39    UnsupportedCapability(String),
40
41    #[error("Request timeout: {0}")]
42    Timeout(String),
43
44    #[error("External MCP server error: {0}")]
45    ExternalServerError(String),
46
47    #[error("Transport error: {0}")]
48    Transport(#[from] TransportError),
49
50    #[error("Protocol error: {0}")]
51    Protocol(#[from] ProtocolError),
52
53    #[error("Serialization error: {0}")]
54    Serialization(#[from] serde_json::Error),
55}
56
57impl McpError {
58    /// Check if error is retryable
59    pub fn is_retryable(&self) -> bool {
60        match self {
61            McpError::Timeout(_) => true,
62            McpError::ExternalServerError(_) => true,
63            McpError::Transport(te) => te.is_retryable(),
64            McpError::Protocol(pe) => pe.is_retryable(),
65            _ => false,
66        }
67    }
68
69    /// Check if error is due to authentication
70    pub fn is_auth_error(&self) -> bool {
71        matches!(
72            self,
73            McpError::Authentication(_) | McpError::Authorization(_)
74        )
75    }
76
77    /// Convert to JSON-RPC error code
78    pub fn to_jsonrpc_code(&self) -> i32 {
79        match self {
80            McpError::JsonRpc(_) => -32603,
81            McpError::Authentication(_) => -32001,
82            McpError::Authorization(_) => -32002,
83            McpError::ToolNotFound(_) => -32601,
84            McpError::ToolExecutionFailed(_) => -32603,
85            McpError::MemoryOperationFailed(_) => -32603,
86            McpError::InvalidToolParameters(_) => -32602,
87            McpError::ProtocolVersionMismatch { .. } => -32600,
88            McpError::UnsupportedCapability(_) => -32601,
89            McpError::Timeout(_) => -32003,
90            McpError::ExternalServerError(_) => -32004,
91            McpError::Transport(_) => -32603,
92            McpError::Protocol(_) => -32603,
93            McpError::Serialization(_) => -32700,
94        }
95    }
96}
97
98/// **Result type for MCP operations**
99pub type McpResult<T> = Result<T, McpError>;
100
101/// **Convert McpError to ProtocolError**
102impl From<McpError> for ProtocolError {
103    fn from(err: McpError) -> Self {
104        match err {
105            McpError::Transport(te) => ProtocolError::Transport(te),
106            McpError::Protocol(pe) => pe,
107            McpError::Serialization(se) => ProtocolError::Serialization(se),
108            other => ProtocolError::Internal(other.to_string()),
109        }
110    }
111}