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}