turul_mcp_json_rpc_server/
error.rs

1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use std::fmt;
4use thiserror::Error;
5
6use crate::types::RequestId;
7
8/// JSON-RPC error codes
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum JsonRpcErrorCode {
11    ParseError,
12    InvalidRequest,
13    MethodNotFound,
14    InvalidParams,
15    InternalError,
16    ServerError(i64), // -32099 to -32000
17}
18
19impl JsonRpcErrorCode {
20    pub fn code(&self) -> i64 {
21        match self {
22            JsonRpcErrorCode::ParseError => -32700,
23            JsonRpcErrorCode::InvalidRequest => -32600,
24            JsonRpcErrorCode::MethodNotFound => -32601,
25            JsonRpcErrorCode::InvalidParams => -32602,
26            JsonRpcErrorCode::InternalError => -32603,
27            JsonRpcErrorCode::ServerError(code) => *code,
28        }
29    }
30
31    pub fn message(&self) -> &'static str {
32        match self {
33            JsonRpcErrorCode::ParseError => "Parse error",
34            JsonRpcErrorCode::InvalidRequest => "Invalid Request",
35            JsonRpcErrorCode::MethodNotFound => "Method not found",
36            JsonRpcErrorCode::InvalidParams => "Invalid params",
37            JsonRpcErrorCode::InternalError => "Internal error",
38            JsonRpcErrorCode::ServerError(_) => "Server error",
39        }
40    }
41}
42
43impl fmt::Display for JsonRpcErrorCode {
44    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45        write!(f, "{}: {}", self.code(), self.message())
46    }
47}
48
49/// JSON-RPC Error object
50#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct JsonRpcErrorObject {
52    pub code: i64,
53    pub message: String,
54    #[serde(skip_serializing_if = "Option::is_none")]
55    pub data: Option<Value>,
56}
57
58impl JsonRpcErrorObject {
59    pub fn new(code: JsonRpcErrorCode, message: Option<String>, data: Option<Value>) -> Self {
60        Self {
61            code: code.code(),
62            message: message.unwrap_or_else(|| code.message().to_string()),
63            data,
64        }
65    }
66
67    pub fn parse_error(data: Option<Value>) -> Self {
68        Self::new(JsonRpcErrorCode::ParseError, None, data)
69    }
70
71    pub fn invalid_request(data: Option<Value>) -> Self {
72        Self::new(JsonRpcErrorCode::InvalidRequest, None, data)
73    }
74
75    pub fn method_not_found(method: &str) -> Self {
76        Self::new(
77            JsonRpcErrorCode::MethodNotFound,
78            Some(format!("Method '{}' not found", method)),
79            None,
80        )
81    }
82
83    pub fn invalid_params(message: &str) -> Self {
84        Self::new(
85            JsonRpcErrorCode::InvalidParams,
86            Some(message.to_string()),
87            None,
88        )
89    }
90
91    pub fn internal_error(message: Option<String>) -> Self {
92        Self::new(JsonRpcErrorCode::InternalError, message, None)
93    }
94
95    pub fn server_error(code: i64, message: &str, data: Option<Value>) -> Self {
96        assert!((-32099..=-32000).contains(&code), "Server error code must be in range -32099 to -32000");
97        Self::new(
98            JsonRpcErrorCode::ServerError(code),
99            Some(message.to_string()),
100            data,
101        )
102    }
103}
104
105/// JSON-RPC Error response
106#[derive(Debug, Clone, Serialize, Deserialize)]
107pub struct JsonRpcError {
108    #[serde(rename = "jsonrpc")]
109    pub version: String,
110    pub id: Option<RequestId>,
111    pub error: JsonRpcErrorObject,
112}
113
114impl JsonRpcError {
115    pub fn new(id: Option<RequestId>, error: JsonRpcErrorObject) -> Self {
116        Self {
117            version: crate::JSONRPC_VERSION.to_string(),
118            id,
119            error,
120        }
121    }
122
123    pub fn parse_error() -> Self {
124        Self::new(None, JsonRpcErrorObject::parse_error(None))
125    }
126
127    pub fn invalid_request(id: Option<RequestId>) -> Self {
128        Self::new(id, JsonRpcErrorObject::invalid_request(None))
129    }
130
131    pub fn method_not_found(id: RequestId, method: &str) -> Self {
132        Self::new(Some(id), JsonRpcErrorObject::method_not_found(method))
133    }
134
135    pub fn invalid_params(id: RequestId, message: &str) -> Self {
136        Self::new(Some(id), JsonRpcErrorObject::invalid_params(message))
137    }
138
139    pub fn internal_error(id: Option<RequestId>, message: Option<String>) -> Self {
140        Self::new(id, JsonRpcErrorObject::internal_error(message))
141    }
142}
143
144impl fmt::Display for JsonRpcError {
145    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
146        write!(f, "JSON-RPC Error {}: {}", self.error.code, self.error.message)
147    }
148}
149
150impl std::error::Error for JsonRpcError {}
151
152/// Errors that can occur during JSON-RPC processing
153#[derive(Debug, Error)]
154pub enum JsonRpcProcessingError {
155    #[error("JSON parse error: {0}")]
156    JsonParseError(#[from] serde_json::Error),
157    
158    #[error("JSON-RPC error: {0}")]
159    RpcError(#[from] JsonRpcError),
160    
161    #[error("Method handler error: {0}")]
162    HandlerError(String),
163    
164    #[error("Internal error: {0}")]
165    InternalError(String),
166}
167
168impl JsonRpcProcessingError {
169    pub fn to_rpc_error(&self, id: Option<RequestId>) -> JsonRpcError {
170        match self {
171            JsonRpcProcessingError::JsonParseError(_) => JsonRpcError::parse_error(),
172            JsonRpcProcessingError::RpcError(err) => err.clone(),
173            JsonRpcProcessingError::HandlerError(msg) => {
174                JsonRpcError::internal_error(id, Some(msg.clone()))
175            }
176            JsonRpcProcessingError::InternalError(msg) => {
177                JsonRpcError::internal_error(id, Some(msg.clone()))
178            }
179        }
180    }
181}
182
183#[cfg(test)]
184mod tests {
185    use super::*;
186
187    #[test]
188    fn test_error_codes() {
189        assert_eq!(JsonRpcErrorCode::ParseError.code(), -32700);
190        assert_eq!(JsonRpcErrorCode::MethodNotFound.code(), -32601);
191    }
192
193    #[test]
194    fn test_error_serialization() {
195        let error = JsonRpcError::method_not_found(RequestId::Number(1), "test");
196        let json = serde_json::to_string(&error).unwrap();
197        assert!(json.contains("Method 'test' not found"));
198    }
199}