mcpkit_core/error/
jsonrpc.rs

1//! JSON-RPC error response type and conversions.
2//!
3//! This module provides the `JsonRpcError` type for wire format
4//! and conversions from `McpError`.
5
6use serde::{Deserialize, Serialize};
7
8use super::types::McpError;
9
10/// A JSON-RPC error response object.
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct JsonRpcError {
13    /// Error code.
14    pub code: i32,
15    /// Error message.
16    pub message: String,
17    /// Additional error data.
18    #[serde(skip_serializing_if = "Option::is_none")]
19    pub data: Option<serde_json::Value>,
20}
21
22impl JsonRpcError {
23    /// Create an "invalid params" error (-32602).
24    pub fn invalid_params(message: impl Into<String>) -> Self {
25        Self {
26            code: -32602,
27            message: message.into(),
28            data: None,
29        }
30    }
31
32    /// Create an "internal error" (-32603).
33    pub fn internal_error(message: impl Into<String>) -> Self {
34        Self {
35            code: -32603,
36            message: message.into(),
37            data: None,
38        }
39    }
40
41    /// Create a "method not found" error (-32601).
42    pub fn method_not_found(message: impl Into<String>) -> Self {
43        Self {
44            code: -32601,
45            message: message.into(),
46            data: None,
47        }
48    }
49
50    /// Create a "parse error" (-32700).
51    pub fn parse_error(message: impl Into<String>) -> Self {
52        Self {
53            code: -32700,
54            message: message.into(),
55            data: None,
56        }
57    }
58
59    /// Create an "invalid request" error (-32600).
60    pub fn invalid_request(message: impl Into<String>) -> Self {
61        Self {
62            code: -32600,
63            message: message.into(),
64            data: None,
65        }
66    }
67}
68
69impl From<&McpError> for JsonRpcError {
70    fn from(err: &McpError) -> Self {
71        let code = err.code();
72        let message = err.to_string();
73        let data = match err {
74            McpError::MethodNotFound {
75                method, available, ..
76            } => Some(serde_json::json!({
77                "method": method,
78                "available": available,
79            })),
80            McpError::InvalidParams(details) => Some(serde_json::json!({
81                "method": details.method,
82                "param_path": details.param_path,
83                "expected": details.expected,
84                "actual": details.actual,
85            })),
86            McpError::Transport(details) => Some(serde_json::json!({
87                "kind": format!("{:?}", details.kind),
88                "context": details.context,
89            })),
90            McpError::ToolExecution(details) => details
91                .data
92                .clone()
93                .or_else(|| Some(serde_json::json!({ "tool": details.tool }))),
94            McpError::HandshakeFailed(details) => Some(serde_json::json!({
95                "client_version": details.client_version,
96                "server_version": details.server_version,
97            })),
98            McpError::WithContext { source, .. } => {
99                let inner: Self = source.as_ref().into();
100                inner.data
101            }
102            _ => None,
103        };
104
105        Self {
106            code,
107            message,
108            data,
109        }
110    }
111}
112
113impl From<McpError> for JsonRpcError {
114    fn from(err: McpError) -> Self {
115        Self::from(&err)
116    }
117}