bamboo_engine/mcp/
error.rs1use 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}