pulseengine_mcp_client/
error.rs

1//! Error types for MCP client operations
2
3use pulseengine_mcp_protocol::Error as ProtocolError;
4use thiserror::Error;
5
6/// Result type alias for client operations
7pub type ClientResult<T> = std::result::Result<T, ClientError>;
8
9/// Errors that can occur during MCP client operations
10#[derive(Debug, Error)]
11pub enum ClientError {
12    /// Transport-level errors (I/O, connection)
13    #[error("Transport error: {0}")]
14    Transport(String),
15
16    /// Protocol errors (invalid JSON-RPC, parse errors)
17    #[error("Protocol error: {0}")]
18    Protocol(String),
19
20    /// Server returned an error response
21    #[error("Server error: {message} (code: {code})")]
22    ServerError {
23        /// Error code from server
24        code: i32,
25        /// Error message from server
26        message: String,
27        /// Optional additional data
28        data: Option<serde_json::Value>,
29    },
30
31    /// Request timed out
32    #[error("Request timed out after {0:?}")]
33    Timeout(std::time::Duration),
34
35    /// Client not initialized (must call initialize first)
36    #[error("Client not initialized - call initialize() first")]
37    NotInitialized,
38
39    /// Response ID mismatch
40    #[error("Response ID mismatch: expected {expected}, got {actual}")]
41    IdMismatch {
42        /// Expected request ID
43        expected: String,
44        /// Actual response ID
45        actual: String,
46    },
47
48    /// Channel closed unexpectedly
49    #[error("Channel closed: {0}")]
50    ChannelClosed(String),
51
52    /// Serialization/deserialization error
53    #[error("Serialization error: {0}")]
54    Serialization(#[from] serde_json::Error),
55}
56
57impl ClientError {
58    /// Create a transport error
59    pub fn transport(msg: impl Into<String>) -> Self {
60        Self::Transport(msg.into())
61    }
62
63    /// Create a protocol error
64    pub fn protocol(msg: impl Into<String>) -> Self {
65        Self::Protocol(msg.into())
66    }
67
68    /// Create from a protocol error response
69    pub fn from_protocol_error(err: ProtocolError) -> Self {
70        Self::ServerError {
71            code: err.code as i32,
72            message: err.message,
73            data: err.data,
74        }
75    }
76
77    /// Check if this is a retryable error
78    pub fn is_retryable(&self) -> bool {
79        matches!(self, Self::Timeout(_) | Self::Transport(_))
80    }
81}
82
83impl From<std::io::Error> for ClientError {
84    fn from(err: std::io::Error) -> Self {
85        Self::Transport(err.to_string())
86    }
87}