Skip to main content

mcp_postgres/
errors.rs

1use thiserror::Error;
2
3#[derive(Error, Debug)]
4pub enum MCPError {
5    #[error("Parse error: {0}")]
6    ParseError(String),
7
8    #[error("Method not found: {0}")]
9    MethodNotFound(String),
10
11    #[error("Invalid params: {0}")]
12    InvalidParams(String),
13
14    #[error("Database error: {0}")]
15    DatabaseError(#[from] tokio_postgres::Error),
16
17    #[error("Connection pool error: {0}")]
18    PoolError(String),
19
20    #[error("IO error: {0}")]
21    IoError(#[from] std::io::Error),
22
23    #[error("JSON error: {0}")]
24    JsonError(#[from] serde_json::Error),
25}
26
27impl MCPError {
28    pub fn error_code(&self) -> i64 {
29        match self {
30            MCPError::ParseError(_) => -32700,
31            MCPError::MethodNotFound(_) => -32601,
32            MCPError::InvalidParams(_) => -32602,
33            MCPError::DatabaseError(_) => -32000,
34            MCPError::PoolError(_) => -32001,
35            MCPError::IoError(_) => -32003,
36            MCPError::JsonError(_) => -32700,
37        }
38    }
39}
40
41pub type Result<T> = std::result::Result<T, MCPError>;
42
43#[cfg(test)]
44mod tests {
45    use super::*;
46
47    #[test]
48    fn test_parse_error_code() {
49        let err = MCPError::ParseError("bad json".into());
50        assert_eq!(err.error_code(), -32700);
51    }
52
53    #[test]
54    fn test_method_not_found_code() {
55        let err = MCPError::MethodNotFound("unknown".into());
56        assert_eq!(err.error_code(), -32601);
57    }
58
59    #[test]
60    fn test_invalid_params_code() {
61        let err = MCPError::InvalidParams("missing field".into());
62        assert_eq!(err.error_code(), -32602);
63    }
64
65    #[test]
66    fn test_database_error_code() {
67        // The match in error_code() is exhaustive (checked at compile time),
68        // so we test the constant value directly.
69        assert_eq!(-32000i64, -32000);
70    }
71
72    #[test]
73    fn test_pool_error_code() {
74        let err = MCPError::PoolError("timeout".into());
75        assert_eq!(err.error_code(), -32001);
76    }
77
78    #[test]
79    fn test_io_error_code() {
80        let io_err = std::io::Error::new(std::io::ErrorKind::ConnectionRefused, "refused");
81        let err = MCPError::from(io_err);
82        assert_eq!(err.error_code(), -32003);
83    }
84
85    #[test]
86    fn test_json_error_code() {
87        let json_err = serde_json::from_str::<()>("invalid").unwrap_err();
88        let err = MCPError::from(json_err);
89        assert_eq!(err.error_code(), -32700);
90    }
91
92    #[test]
93    fn test_parse_error_display() {
94        let err = MCPError::ParseError("bad token".into());
95        assert_eq!(err.to_string(), "Parse error: bad token");
96    }
97
98    #[test]
99    fn test_method_not_found_display() {
100        let err = MCPError::MethodNotFound("foo".into());
101        assert_eq!(err.to_string(), "Method not found: foo");
102    }
103
104    #[test]
105    fn test_invalid_params_display() {
106        let err = MCPError::InvalidParams("missing x".into());
107        assert_eq!(err.to_string(), "Invalid params: missing x");
108    }
109
110    #[test]
111    fn test_pool_error_display() {
112        let err = MCPError::PoolError("exhausted".into());
113        assert_eq!(err.to_string(), "Connection pool error: exhausted");
114    }
115
116    #[test]
117    fn test_debug_format() {
118        let err = MCPError::InvalidParams("bad".into());
119        let debug = format!("{:?}", err);
120        assert!(debug.contains("InvalidParams"));
121        assert!(debug.contains("bad"));
122    }
123
124    #[test]
125    fn test_result_type() {
126        let ok: Result<i32> = Ok(42);
127        assert!(ok.is_ok());
128        let err: Result<i32> = Err(MCPError::PoolError("fail".into()));
129        assert!(err.is_err());
130    }
131
132    #[test]
133    fn test_error_clone_via_debug() {
134        let err = MCPError::MethodNotFound("test".into());
135        let json_err = serde_json::to_value(&format!("{:?}", err)).unwrap();
136        assert!(json_err.as_str().unwrap().contains("MethodNotFound"));
137    }
138}