use thiserror::Error;
#[derive(Debug, Error)]
pub enum McpError {
#[error("failed to spawn MCP server '{command}': {reason}")]
SpawnFailed {
command: String,
reason: String,
},
#[error("failed to connect to MCP server at '{url}': {reason}")]
ConnectionFailed {
url: String,
reason: String,
},
#[error("MCP protocol error: {message}")]
ProtocolError {
message: String,
},
#[error("MCP I/O error: {message}")]
IoError {
message: String,
},
#[error("MCP tool '{tool_name}' timed out")]
Timeout {
tool_name: String,
},
#[error("MCP tool '{tool_name}' failed: {message}")]
ToolCallFailed {
tool_name: String,
message: String,
},
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn display_spawn_failed() {
let err = McpError::SpawnFailed {
command: "mcp-server".to_string(),
reason: "not found".to_string(),
};
assert_eq!(
err.to_string(),
"failed to spawn MCP server 'mcp-server': not found"
);
}
#[test]
fn display_connection_failed() {
let err = McpError::ConnectionFailed {
url: "http://localhost:8080".to_string(),
reason: "connection refused".to_string(),
};
assert_eq!(
err.to_string(),
"failed to connect to MCP server at 'http://localhost:8080': connection refused"
);
}
#[test]
fn display_protocol_error() {
let err = McpError::ProtocolError {
message: "invalid JSON".to_string(),
};
assert_eq!(err.to_string(), "MCP protocol error: invalid JSON");
}
#[test]
fn display_io_error() {
let err = McpError::IoError {
message: "broken pipe".to_string(),
};
assert_eq!(err.to_string(), "MCP I/O error: broken pipe");
}
#[test]
fn display_timeout() {
let err = McpError::Timeout {
tool_name: "search".to_string(),
};
assert_eq!(err.to_string(), "MCP tool 'search' timed out");
}
#[test]
fn display_tool_call_failed() {
let err = McpError::ToolCallFailed {
tool_name: "query".to_string(),
message: "not authorized".to_string(),
};
assert_eq!(err.to_string(), "MCP tool 'query' failed: not authorized");
}
}