pulseengine_mcp_client/
error.rs1use pulseengine_mcp_protocol::Error as ProtocolError;
4use thiserror::Error;
5
6pub type ClientResult<T> = std::result::Result<T, ClientError>;
8
9#[derive(Debug, Error)]
11pub enum ClientError {
12 #[error("Transport error: {0}")]
14 Transport(String),
15
16 #[error("Protocol error: {0}")]
18 Protocol(String),
19
20 #[error("Server error: {message} (code: {code})")]
22 ServerError {
23 code: i32,
25 message: String,
27 data: Option<serde_json::Value>,
29 },
30
31 #[error("Request timed out after {0:?}")]
33 Timeout(std::time::Duration),
34
35 #[error("Client not initialized - call initialize() first")]
37 NotInitialized,
38
39 #[error("Response ID mismatch: expected {expected}, got {actual}")]
41 IdMismatch {
42 expected: String,
44 actual: String,
46 },
47
48 #[error("Channel closed: {0}")]
50 ChannelClosed(String),
51
52 #[error("Serialization error: {0}")]
54 Serialization(#[from] serde_json::Error),
55}
56
57impl ClientError {
58 pub fn transport(msg: impl Into<String>) -> Self {
60 Self::Transport(msg.into())
61 }
62
63 pub fn protocol(msg: impl Into<String>) -> Self {
65 Self::Protocol(msg.into())
66 }
67
68 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 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}