Skip to main content

bamboo_engine/mcp/
error.rs

1use thiserror::Error;
2
3#[derive(Error, Debug, Clone)]
4pub enum McpError {
5    #[error("Transport error: {0}")]
6    Transport(String),
7
8    #[error("Protocol error: {0}")]
9    Protocol(String),
10
11    #[error("Connection error: {0}")]
12    Connection(String),
13
14    #[error("Timeout error: {0}")]
15    Timeout(String),
16
17    #[error("Tool execution error: {0}")]
18    ToolExecution(String),
19
20    #[error("Server not found: {0}")]
21    ServerNotFound(String),
22
23    #[error("Tool not found: {0}")]
24    ToolNotFound(String),
25
26    #[error("Serialization error: {0}")]
27    Serialization(String),
28
29    #[error("Invalid configuration: {0}")]
30    InvalidConfig(String),
31
32    #[error("Server disconnected")]
33    Disconnected,
34
35    #[error("Server already running: {0}")]
36    AlreadyRunning(String),
37
38    #[error("Server not running: {0}")]
39    NotRunning(String),
40}
41
42impl From<serde_json::Error> for McpError {
43    fn from(e: serde_json::Error) -> Self {
44        McpError::Serialization(e.to_string())
45    }
46}
47
48impl From<std::io::Error> for McpError {
49    fn from(e: std::io::Error) -> Self {
50        McpError::Transport(e.to_string())
51    }
52}
53
54impl From<reqwest::Error> for McpError {
55    fn from(e: reqwest::Error) -> Self {
56        McpError::Transport(e.to_string())
57    }
58}
59
60pub type Result<T> = std::result::Result<T, McpError>;
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65
66    #[test]
67    fn test_error_display_transport() {
68        let error = McpError::Transport("connection failed".to_string());
69        assert_eq!(format!("{}", error), "Transport error: connection failed");
70    }
71
72    #[test]
73    fn test_error_display_protocol() {
74        let error = McpError::Protocol("invalid message".to_string());
75        assert_eq!(format!("{}", error), "Protocol error: invalid message");
76    }
77
78    #[test]
79    fn test_error_display_connection() {
80        let error = McpError::Connection("timeout".to_string());
81        assert_eq!(format!("{}", error), "Connection error: timeout");
82    }
83
84    #[test]
85    fn test_error_display_timeout() {
86        let error = McpError::Timeout("request timed out".to_string());
87        assert_eq!(format!("{}", error), "Timeout error: request timed out");
88    }
89
90    #[test]
91    fn test_error_display_tool_execution() {
92        let error = McpError::ToolExecution("tool failed".to_string());
93        assert_eq!(format!("{}", error), "Tool execution error: tool failed");
94    }
95
96    #[test]
97    fn test_error_display_server_not_found() {
98        let error = McpError::ServerNotFound("test-server".to_string());
99        assert_eq!(format!("{}", error), "Server not found: test-server");
100    }
101
102    #[test]
103    fn test_error_display_tool_not_found() {
104        let error = McpError::ToolNotFound("test-tool".to_string());
105        assert_eq!(format!("{}", error), "Tool not found: test-tool");
106    }
107
108    #[test]
109    fn test_error_display_serialization() {
110        let error = McpError::Serialization("invalid JSON".to_string());
111        assert_eq!(format!("{}", error), "Serialization error: invalid JSON");
112    }
113
114    #[test]
115    fn test_error_display_invalid_config() {
116        let error = McpError::InvalidConfig("missing field".to_string());
117        assert_eq!(format!("{}", error), "Invalid configuration: missing field");
118    }
119
120    #[test]
121    fn test_error_display_disconnected() {
122        let error = McpError::Disconnected;
123        assert_eq!(format!("{}", error), "Server disconnected");
124    }
125
126    #[test]
127    fn test_error_display_already_running() {
128        let error = McpError::AlreadyRunning("server1".to_string());
129        assert_eq!(format!("{}", error), "Server already running: server1");
130    }
131
132    #[test]
133    fn test_error_display_not_running() {
134        let error = McpError::NotRunning("server1".to_string());
135        assert_eq!(format!("{}", error), "Server not running: server1");
136    }
137
138    #[test]
139    fn test_from_serde_json_error() {
140        let json_err = serde_json::from_str::<serde_json::Value>("invalid json");
141        let mcp_error = McpError::from(json_err.unwrap_err());
142        match mcp_error {
143            McpError::Serialization(_) => {}
144            _ => panic!("Expected Serialization error"),
145        }
146    }
147
148    #[test]
149    fn test_from_io_error() {
150        let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
151        let mcp_error = McpError::from(io_err);
152        match mcp_error {
153            McpError::Transport(_) => {}
154            _ => panic!("Expected Transport error"),
155        }
156    }
157
158    #[test]
159    fn test_error_clone() {
160        let error = McpError::ServerNotFound("test".to_string());
161        let cloned = error.clone();
162        assert_eq!(format!("{}", error), format!("{}", cloned));
163    }
164
165    #[test]
166    fn test_error_debug() {
167        let error = McpError::Disconnected;
168        let debug_str = format!("{:?}", error);
169        assert!(debug_str.contains("Disconnected"));
170    }
171}