1use serde::{Deserialize, Serialize};
6use serde_json::Value;
7
8pub const JSONRPC_VERSION: &str = "2.0";
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct JsonRpcRequest {
14 pub jsonrpc: String,
16 pub method: String,
18 #[serde(skip_serializing_if = "Option::is_none")]
20 pub params: Option<Value>,
21 #[serde(skip_serializing_if = "Option::is_none")]
23 pub id: Option<RequestId>,
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize)]
28pub struct JsonRpcResponse {
29 pub jsonrpc: String,
31 #[serde(skip_serializing_if = "Option::is_none")]
33 pub result: Option<Value>,
34 #[serde(skip_serializing_if = "Option::is_none")]
36 pub error: Option<JsonRpcError>,
37 pub id: Option<RequestId>,
39}
40
41#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct JsonRpcNotification {
44 pub jsonrpc: String,
46 pub method: String,
48 #[serde(skip_serializing_if = "Option::is_none")]
50 pub params: Option<Value>,
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize)]
55pub struct JsonRpcError {
56 pub code: i32,
58 pub message: String,
60 #[serde(skip_serializing_if = "Option::is_none")]
62 pub data: Option<Value>,
63}
64
65#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
67#[serde(untagged)]
68pub enum RequestId {
69 String(String),
70 Number(i64),
71}
72
73impl From<String> for RequestId {
74 fn from(s: String) -> Self {
75 Self::String(s)
76 }
77}
78
79impl From<i64> for RequestId {
80 fn from(n: i64) -> Self {
81 Self::Number(n)
82 }
83}
84
85impl std::fmt::Display for RequestId {
86 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87 match self {
88 Self::String(s) => write!(f, "{}", s),
89 Self::Number(n) => write!(f, "{}", n),
90 }
91 }
92}
93
94#[derive(Debug, Clone, Copy, PartialEq, Eq)]
96pub enum ErrorCode {
97 ParseError = -32700,
99 InvalidRequest = -32600,
101 MethodNotFound = -32601,
103 InvalidParams = -32602,
105 InternalError = -32603,
107}
108
109impl ErrorCode {
110 pub fn message(&self) -> &'static str {
112 match self {
113 Self::ParseError => "Parse error",
114 Self::InvalidRequest => "Invalid Request",
115 Self::MethodNotFound => "Method not found",
116 Self::InvalidParams => "Invalid params",
117 Self::InternalError => "Internal error",
118 }
119 }
120
121 pub fn as_i32(&self) -> i32 {
123 *self as i32
124 }
125}
126
127impl JsonRpcError {
128 pub fn new(code: ErrorCode) -> Self {
130 Self {
131 code: code.as_i32(),
132 message: code.message().to_string(),
133 data: None,
134 }
135 }
136
137 pub fn with_data(code: ErrorCode, data: Value) -> Self {
139 Self {
140 code: code.as_i32(),
141 message: code.message().to_string(),
142 data: Some(data),
143 }
144 }
145
146 pub fn custom(code: ErrorCode, message: String) -> Self {
148 Self {
149 code: code.as_i32(),
150 message,
151 data: None,
152 }
153 }
154}
155
156impl JsonRpcResponse {
157 pub fn success(id: Option<RequestId>, result: Value) -> Self {
159 Self {
160 jsonrpc: JSONRPC_VERSION.to_string(),
161 result: Some(result),
162 error: None,
163 id,
164 }
165 }
166
167 pub fn error(id: Option<RequestId>, error: JsonRpcError) -> Self {
169 Self {
170 jsonrpc: JSONRPC_VERSION.to_string(),
171 result: None,
172 error: Some(error),
173 id,
174 }
175 }
176}
177
178impl JsonRpcRequest {
179 pub fn new(method: String, params: Option<Value>, id: Option<RequestId>) -> Self {
181 Self {
182 jsonrpc: JSONRPC_VERSION.to_string(),
183 method,
184 params,
185 id,
186 }
187 }
188}
189
190impl JsonRpcNotification {
191 pub fn new(method: String, params: Option<Value>) -> Self {
193 Self {
194 jsonrpc: JSONRPC_VERSION.to_string(),
195 method,
196 params,
197 }
198 }
199}
200
201#[derive(Debug, Clone)]
203pub enum JsonRpcMessage {
204 Request(JsonRpcRequest),
205 Notification(JsonRpcNotification),
206}
207
208impl JsonRpcMessage {
209 pub fn from_value(value: Value) -> Result<Self, JsonRpcError> {
211 if value.get("id").is_some() {
213 match serde_json::from_value::<JsonRpcRequest>(value) {
214 Ok(req) => Ok(Self::Request(req)),
215 Err(e) => {
216 tracing::debug!("MCP request did not parse: {e}");
219 Err(JsonRpcError::custom(
220 ErrorCode::InvalidRequest,
221 "Failed to parse request".to_string(),
222 ))
223 }
224 }
225 } else {
226 match serde_json::from_value::<JsonRpcNotification>(value) {
228 Ok(notif) => Ok(Self::Notification(notif)),
229 Err(e) => {
230 tracing::debug!("MCP notification did not parse: {e}");
231 Err(JsonRpcError::custom(
232 ErrorCode::InvalidRequest,
233 "Failed to parse notification".to_string(),
234 ))
235 }
236 }
237 }
238 }
239
240 pub fn method(&self) -> &str {
242 match self {
243 Self::Request(req) => &req.method,
244 Self::Notification(notif) => ¬if.method,
245 }
246 }
247
248 pub fn params(&self) -> Option<&Value> {
250 match self {
251 Self::Request(req) => req.params.as_ref(),
252 Self::Notification(notif) => notif.params.as_ref(),
253 }
254 }
255
256 pub fn id(&self) -> Option<&RequestId> {
258 match self {
259 Self::Request(req) => req.id.as_ref(),
260 Self::Notification(_) => None,
261 }
262 }
263}