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!(
97            (-32099..=-32000).contains(&code),
98            "Server error code must be in range -32099 to -32000"
99        );
100        Self::new(
101            JsonRpcErrorCode::ServerError(code),
102            Some(message.to_string()),
103            data,
104        )
105    }
106}
107
108/// JSON-RPC Error response
109#[derive(Debug, Clone, Serialize, Deserialize)]
110pub struct JsonRpcError {
111    #[serde(rename = "jsonrpc")]
112    pub version: String,
113    pub id: Option<RequestId>,
114    pub error: JsonRpcErrorObject,
115}
116
117impl JsonRpcError {
118    pub fn new(id: Option<RequestId>, error: JsonRpcErrorObject) -> Self {
119        Self {
120            version: crate::JSONRPC_VERSION.to_string(),
121            id,
122            error,
123        }
124    }
125
126    pub fn parse_error() -> Self {
127        Self::new(None, JsonRpcErrorObject::parse_error(None))
128    }
129
130    pub fn invalid_request(id: Option<RequestId>) -> Self {
131        Self::new(id, JsonRpcErrorObject::invalid_request(None))
132    }
133
134    pub fn method_not_found(id: RequestId, method: &str) -> Self {
135        Self::new(Some(id), JsonRpcErrorObject::method_not_found(method))
136    }
137
138    pub fn invalid_params(id: RequestId, message: &str) -> Self {
139        Self::new(Some(id), JsonRpcErrorObject::invalid_params(message))
140    }
141
142    pub fn internal_error(id: Option<RequestId>, message: Option<String>) -> Self {
143        Self::new(id, JsonRpcErrorObject::internal_error(message))
144    }
145}
146
147impl fmt::Display for JsonRpcError {
148    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
149        write!(
150            f,
151            "JSON-RPC Error {}: {}",
152            self.error.code, self.error.message
153        )
154    }
155}
156
157impl std::error::Error for JsonRpcError {}
158
159/// Transport-level errors for JSON-RPC processing (no domain logic)
160#[derive(Debug, Error)]
161pub enum JsonRpcTransportError {
162    #[error("JSON parse error: {0}")]
163    JsonParseError(#[from] serde_json::Error),
164
165    #[error("IO error: {0}")]
166    IoError(#[from] std::io::Error),
167
168    #[error("Protocol error: {0}")]
169    ProtocolError(String),
170}
171
172#[cfg(test)]
173mod tests {
174    use super::*;
175
176    #[test]
177    fn test_error_codes() {
178        assert_eq!(JsonRpcErrorCode::ParseError.code(), -32700);
179        assert_eq!(JsonRpcErrorCode::MethodNotFound.code(), -32601);
180    }
181
182    #[test]
183    fn test_error_serialization() {
184        let error = JsonRpcError::method_not_found(RequestId::Number(1), "test");
185        let json = serde_json::to_string(&error).unwrap();
186        assert!(json.contains("Method 'test' not found"));
187    }
188}