Skip to main content

chant/mcp/
protocol.rs

1//! JSON-RPC 2.0 protocol types and MCP constants.
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6/// MCP Server info
7pub const SERVER_NAME: &str = "chant";
8pub const SERVER_VERSION: &str = env!("CARGO_PKG_VERSION");
9pub const PROTOCOL_VERSION: &str = "2024-11-05";
10
11/// JSON-RPC 2.0 Request
12#[derive(Debug, Deserialize)]
13pub struct JsonRpcRequest {
14    pub jsonrpc: String,
15    pub method: String,
16    #[serde(default)]
17    pub params: Option<Value>,
18    pub id: Option<Value>,
19}
20
21/// JSON-RPC 2.0 Response
22///
23/// Represents a JSON-RPC 2.0 response message. Either `result` or `error` will be present,
24/// but not both.
25///
26/// # Success Response
27///
28/// When the request succeeds, `result` contains the response data and `error` is `None`.
29///
30/// # Error Response
31///
32/// When the request fails, `error` contains error details and `result` is `None`.
33///
34/// # Fields
35///
36/// - `jsonrpc`: Version string, always `"2.0"`
37/// - `result`: Success data (tool result or handler response)
38/// - `error`: Error details if request failed
39/// - `id`: Request ID from the original request (for correlation)
40#[derive(Debug, Serialize)]
41pub struct JsonRpcResponse {
42    pub jsonrpc: String,
43    #[serde(skip_serializing_if = "Option::is_none")]
44    pub result: Option<Value>,
45    #[serde(skip_serializing_if = "Option::is_none")]
46    pub error: Option<JsonRpcError>,
47    pub id: Value,
48}
49
50/// JSON-RPC 2.0 Error
51///
52/// Represents an error in a JSON-RPC response.
53///
54/// # Error Codes
55///
56/// - `-32700`: Parse error (invalid JSON)
57/// - `-32600`: Invalid JSON-RPC version (jsonrpc != "2.0")
58/// - `-32603`: Server error (internal handler error)
59///
60/// # Fields
61///
62/// - `code`: JSON-RPC error code (negative integer)
63/// - `message`: Human-readable error description
64/// - `data`: Optional additional error context
65#[derive(Debug, Serialize)]
66pub struct JsonRpcError {
67    pub code: i32,
68    pub message: String,
69    #[serde(skip_serializing_if = "Option::is_none")]
70    pub data: Option<Value>,
71}
72
73impl JsonRpcResponse {
74    /// Create a successful response.
75    ///
76    /// # Arguments
77    ///
78    /// - `id`: Request ID to echo back
79    /// - `result`: Response data (typically a JSON object)
80    ///
81    /// # Returns
82    ///
83    /// A response with `result` set and `error` as `None`.
84    pub fn success(id: Value, result: Value) -> Self {
85        Self {
86            jsonrpc: "2.0".to_string(),
87            result: Some(result),
88            error: None,
89            id,
90        }
91    }
92
93    /// Create an error response.
94    ///
95    /// # Arguments
96    ///
97    /// - `id`: Request ID to echo back
98    /// - `code`: JSON-RPC error code (negative integer)
99    ///   - `-32700`: Parse error
100    ///   - `-32600`: Invalid JSON-RPC version
101    ///   - `-32603`: Server error
102    /// - `message`: Human-readable error description
103    ///
104    /// # Returns
105    ///
106    /// A response with `error` set and `result` as `None`.
107    pub fn error(id: Value, code: i32, message: &str) -> Self {
108        Self {
109            jsonrpc: "2.0".to_string(),
110            result: None,
111            error: Some(JsonRpcError {
112                code,
113                message: message.to_string(),
114                data: None,
115            }),
116            id,
117        }
118    }
119}