Skip to main content

tenx_mcp/
error.rs

1use std::time::Duration;
2use thiserror::Error;
3
4#[derive(Error, Debug, Clone)]
5pub enum MCPError {
6    #[error("IO error: {message}")]
7    Io { message: String },
8
9    #[error("JSON serialization error: {message}")]
10    Json { message: String },
11
12    #[error("Transport error: {0}")]
13    Transport(String),
14
15    #[error("Transport connection failed: {message}")]
16    TransportConnectionFailed { message: String },
17
18    #[error("Transport disconnected unexpectedly")]
19    TransportDisconnected,
20
21    #[error("Protocol error: {0}")]
22    Protocol(String),
23
24    #[error("Invalid request: {0}")]
25    InvalidRequest(String),
26
27    #[error("Method not found: {0}")]
28    MethodNotFound(String),
29
30    #[error("Invalid parameters for method '{method}': {message}")]
31    InvalidParams { method: String, message: String },
32
33    #[error("Internal error: {0}")]
34    InternalError(String),
35
36    #[error("Connection closed")]
37    ConnectionClosed,
38
39    #[error("Request timeout after {duration:?} for request id: {request_id}")]
40    Timeout {
41        duration: Duration,
42        request_id: String,
43    },
44
45    #[error("Request with id {0} not found")]
46    RequestNotFound(String),
47
48    #[error("Handler error for {handler_type}: {message}")]
49    HandlerError {
50        handler_type: String,
51        message: String,
52    },
53
54    #[error("Resource not found: {uri}")]
55    ResourceNotFound { uri: String },
56
57    #[error("Tool execution failed for '{tool}': {message}")]
58    ToolExecutionFailed { tool: String, message: String },
59
60    #[error("Message too large: {size} bytes exceeds maximum of {max_size} bytes")]
61    MessageTooLarge { size: usize, max_size: usize },
62
63    #[error("Invalid message format: {message}")]
64    InvalidMessageFormat { message: String },
65
66    #[error("Codec error: {message}")]
67    CodecError { message: String },
68}
69
70impl MCPError {
71    /// Create an InvalidParams error with method context
72    pub fn invalid_params(method: impl Into<String>, message: impl Into<String>) -> Self {
73        Self::InvalidParams {
74            method: method.into(),
75            message: message.into(),
76        }
77    }
78
79    /// Create a Timeout error with duration and request context
80    pub fn timeout(duration: Duration, request_id: impl Into<String>) -> Self {
81        Self::Timeout {
82            duration,
83            request_id: request_id.into(),
84        }
85    }
86
87    /// Create a HandlerError with type context
88    pub fn handler_error(handler_type: impl Into<String>, message: impl Into<String>) -> Self {
89        Self::HandlerError {
90            handler_type: handler_type.into(),
91            message: message.into(),
92        }
93    }
94
95    /// Create a ToolExecutionFailed error
96    pub fn tool_execution_failed(tool: impl Into<String>, message: impl Into<String>) -> Self {
97        Self::ToolExecutionFailed {
98            tool: tool.into(),
99            message: message.into(),
100        }
101    }
102
103    /// Check if this error is retryable
104    pub fn is_retryable(&self) -> bool {
105        matches!(
106            self,
107            Self::Io { .. }
108                | Self::TransportConnectionFailed { .. }
109                | Self::TransportDisconnected
110                | Self::ConnectionClosed
111                | Self::Timeout { .. }
112        )
113    }
114}
115
116impl From<std::io::Error> for MCPError {
117    fn from(err: std::io::Error) -> Self {
118        Self::Io {
119            message: err.to_string(),
120        }
121    }
122}
123
124impl From<serde_json::Error> for MCPError {
125    fn from(err: serde_json::Error) -> Self {
126        Self::Json {
127            message: err.to_string(),
128        }
129    }
130}
131
132pub type Result<T> = std::result::Result<T, MCPError>;