1use serde::{Deserialize, Deserializer, Serialize, Serializer};
7use serde_json::Value;
8use std::fmt;
9
10use crate::types::RequestId;
11
12pub const JSONRPC_VERSION: &str = "2.0";
14
15#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct JsonRpcVersion;
18
19impl Serialize for JsonRpcVersion {
20 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
21 where
22 S: Serializer,
23 {
24 serializer.serialize_str(JSONRPC_VERSION)
25 }
26}
27
28impl<'de> Deserialize<'de> for JsonRpcVersion {
29 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
30 where
31 D: Deserializer<'de>,
32 {
33 let version = String::deserialize(deserializer)?;
34 if version == JSONRPC_VERSION {
35 Ok(JsonRpcVersion)
36 } else {
37 Err(serde::de::Error::custom(format!(
38 "Invalid JSON-RPC version: expected '{JSONRPC_VERSION}', got '{version}'"
39 )))
40 }
41 }
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize)]
46pub struct JsonRpcRequest {
47 pub jsonrpc: JsonRpcVersion,
49 pub method: String,
51 #[serde(skip_serializing_if = "Option::is_none")]
53 pub params: Option<Value>,
54 pub id: RequestId,
56}
57
58#[derive(Debug, Clone, Serialize, Deserialize)]
60#[serde(untagged)]
61pub enum JsonRpcResponsePayload {
62 Success {
64 result: Value,
66 },
67 Error {
69 error: JsonRpcError,
71 },
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize)]
76pub struct JsonRpcResponse {
77 pub jsonrpc: JsonRpcVersion,
79 #[serde(flatten)]
81 pub payload: JsonRpcResponsePayload,
82 pub id: ResponseId,
84}
85
86#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
88#[serde(transparent)]
89pub struct ResponseId(pub Option<RequestId>);
90
91impl ResponseId {
92 pub fn from_request(id: RequestId) -> Self {
94 Self(Some(id))
95 }
96
97 pub fn null() -> Self {
99 Self(None)
100 }
101
102 pub fn as_request_id(&self) -> Option<&RequestId> {
104 self.0.as_ref()
105 }
106
107 pub fn is_null(&self) -> bool {
109 self.0.is_none()
110 }
111}
112
113#[derive(Debug, Clone, Serialize, Deserialize)]
115pub struct JsonRpcNotification {
116 pub jsonrpc: JsonRpcVersion,
118 pub method: String,
120 #[serde(skip_serializing_if = "Option::is_none")]
122 pub params: Option<Value>,
123}
124
125#[derive(Debug, Clone, Serialize, Deserialize)]
127pub struct JsonRpcError {
128 pub code: i32,
130 pub message: String,
132 #[serde(skip_serializing_if = "Option::is_none")]
134 pub data: Option<Value>,
135}
136
137#[derive(Debug, Clone, Serialize, Deserialize)]
145#[serde(transparent)]
146#[deprecated(
147 since = "2.2.3",
148 note = "JSON-RPC batching removed from MCP 2025-06-18 spec (PR #416). This type exists only for defensive handling and will be removed."
149)]
150pub struct JsonRpcBatch<T> {
151 pub items: Vec<T>,
153}
154
155#[derive(Debug, Clone, Copy, PartialEq, Eq)]
157pub enum JsonRpcErrorCode {
158 ParseError,
160 InvalidRequest,
162 MethodNotFound,
164 InvalidParams,
166 InternalError,
168 ApplicationError(i32),
170}
171
172impl JsonRpcErrorCode {
173 pub fn code(&self) -> i32 {
175 match self {
176 Self::ParseError => -32700,
177 Self::InvalidRequest => -32600,
178 Self::MethodNotFound => -32601,
179 Self::InvalidParams => -32602,
180 Self::InternalError => -32603,
181 Self::ApplicationError(code) => *code,
182 }
183 }
184
185 pub fn message(&self) -> &'static str {
187 match self {
188 Self::ParseError => "Parse error",
189 Self::InvalidRequest => "Invalid Request",
190 Self::MethodNotFound => "Method not found",
191 Self::InvalidParams => "Invalid params",
192 Self::InternalError => "Internal error",
193 Self::ApplicationError(_) => "Application error",
194 }
195 }
196}
197
198impl fmt::Display for JsonRpcErrorCode {
199 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
200 write!(f, "{} ({})", self.message(), self.code())
201 }
202}
203
204impl From<JsonRpcErrorCode> for JsonRpcError {
205 fn from(code: JsonRpcErrorCode) -> Self {
206 Self {
207 code: code.code(),
208 message: code.message().to_string(),
209 data: None,
210 }
211 }
212}
213
214impl From<i32> for JsonRpcErrorCode {
215 fn from(code: i32) -> Self {
216 match code {
217 -32700 => Self::ParseError,
218 -32600 => Self::InvalidRequest,
219 -32601 => Self::MethodNotFound,
220 -32602 => Self::InvalidParams,
221 -32603 => Self::InternalError,
222 other => Self::ApplicationError(other),
223 }
224 }
225}
226
227#[derive(Debug, Clone, Serialize, Deserialize)]
233#[serde(untagged)]
234pub enum JsonRpcMessage {
235 Request(JsonRpcRequest),
237 Response(JsonRpcResponse),
239 Notification(JsonRpcNotification),
241 #[deprecated(since = "2.2.3", note = "Batching removed from MCP spec")]
246 #[allow(deprecated)] RequestBatch(JsonRpcBatch<JsonRpcRequest>),
248 #[deprecated(since = "2.2.3", note = "Batching removed from MCP spec")]
253 #[allow(deprecated)] ResponseBatch(JsonRpcBatch<JsonRpcResponse>),
255 #[deprecated(since = "2.2.3", note = "Batching removed from MCP spec")]
260 #[allow(deprecated)] MessageBatch(JsonRpcBatch<JsonRpcMessage>),
262}
263
264impl JsonRpcRequest {
265 pub fn new(method: String, params: Option<Value>, id: RequestId) -> Self {
267 Self {
268 jsonrpc: JsonRpcVersion,
269 method,
270 params,
271 id,
272 }
273 }
274
275 pub fn without_params(method: String, id: RequestId) -> Self {
277 Self::new(method, None, id)
278 }
279
280 pub fn with_params<P: Serialize>(
282 method: String,
283 params: P,
284 id: RequestId,
285 ) -> Result<Self, serde_json::Error> {
286 let params_value = serde_json::to_value(params)?;
287 Ok(Self::new(method, Some(params_value), id))
288 }
289}
290
291impl JsonRpcResponse {
292 pub fn success(result: Value, id: RequestId) -> Self {
294 Self {
295 jsonrpc: JsonRpcVersion,
296 payload: JsonRpcResponsePayload::Success { result },
297 id: ResponseId::from_request(id),
298 }
299 }
300
301 pub fn error_response(error: JsonRpcError, id: RequestId) -> Self {
303 Self {
304 jsonrpc: JsonRpcVersion,
305 payload: JsonRpcResponsePayload::Error { error },
306 id: ResponseId::from_request(id),
307 }
308 }
309
310 pub fn parse_error(message: Option<String>) -> Self {
312 let error = JsonRpcError {
313 code: JsonRpcErrorCode::ParseError.code(),
314 message: message.unwrap_or_else(|| JsonRpcErrorCode::ParseError.message().to_string()),
315 data: None,
316 };
317 Self {
318 jsonrpc: JsonRpcVersion,
319 payload: JsonRpcResponsePayload::Error { error },
320 id: ResponseId::null(),
321 }
322 }
323
324 pub fn is_success(&self) -> bool {
326 matches!(self.payload, JsonRpcResponsePayload::Success { .. })
327 }
328
329 pub fn is_error(&self) -> bool {
331 matches!(self.payload, JsonRpcResponsePayload::Error { .. })
332 }
333
334 pub fn result(&self) -> Option<&Value> {
336 match &self.payload {
337 JsonRpcResponsePayload::Success { result } => Some(result),
338 JsonRpcResponsePayload::Error { .. } => None,
339 }
340 }
341
342 pub fn error(&self) -> Option<&JsonRpcError> {
344 match &self.payload {
345 JsonRpcResponsePayload::Success { .. } => None,
346 JsonRpcResponsePayload::Error { error } => Some(error),
347 }
348 }
349
350 pub fn request_id(&self) -> Option<&RequestId> {
352 self.id.as_request_id()
353 }
354
355 pub fn is_parse_error(&self) -> bool {
357 self.id.is_null()
358 }
359
360 pub fn result_mut(&mut self) -> Option<&mut Value> {
362 match &mut self.payload {
363 JsonRpcResponsePayload::Success { result } => Some(result),
364 JsonRpcResponsePayload::Error { .. } => None,
365 }
366 }
367
368 pub fn error_mut(&mut self) -> Option<&mut JsonRpcError> {
370 match &mut self.payload {
371 JsonRpcResponsePayload::Success { .. } => None,
372 JsonRpcResponsePayload::Error { error } => Some(error),
373 }
374 }
375
376 pub fn set_result(&mut self, result: Value) {
378 self.payload = JsonRpcResponsePayload::Success { result };
379 }
380
381 pub fn set_error(&mut self, error: JsonRpcError) {
383 self.payload = JsonRpcResponsePayload::Error { error };
384 }
385}
386
387impl JsonRpcNotification {
388 pub fn new(method: String, params: Option<Value>) -> Self {
390 Self {
391 jsonrpc: JsonRpcVersion,
392 method,
393 params,
394 }
395 }
396
397 pub fn without_params(method: String) -> Self {
399 Self::new(method, None)
400 }
401
402 pub fn with_params<P: Serialize>(method: String, params: P) -> Result<Self, serde_json::Error> {
404 let params_value = serde_json::to_value(params)?;
405 Ok(Self::new(method, Some(params_value)))
406 }
407}
408
409#[allow(deprecated)]
412impl<T> JsonRpcBatch<T> {
413 pub fn new(items: Vec<T>) -> Self {
415 Self { items }
416 }
417
418 pub fn empty() -> Self {
420 Self::new(Vec::new())
421 }
422
423 pub fn push(&mut self, item: T) {
425 self.items.push(item);
426 }
427
428 pub fn len(&self) -> usize {
430 self.items.len()
431 }
432
433 pub fn is_empty(&self) -> bool {
435 self.items.is_empty()
436 }
437
438 pub fn iter(&self) -> impl Iterator<Item = &T> {
440 self.items.iter()
441 }
442}
443
444#[allow(deprecated)]
445impl<T> IntoIterator for JsonRpcBatch<T> {
446 type Item = T;
447 type IntoIter = std::vec::IntoIter<T>;
448
449 fn into_iter(self) -> Self::IntoIter {
450 self.items.into_iter()
451 }
452}
453
454#[allow(deprecated)]
455impl<T> From<Vec<T>> for JsonRpcBatch<T> {
456 fn from(items: Vec<T>) -> Self {
457 Self::new(items)
458 }
459}
460
461pub mod utils {
463 use super::*;
464
465 pub fn parse_message(json: &str) -> Result<JsonRpcMessage, serde_json::Error> {
467 serde_json::from_str(json)
468 }
469
470 pub fn serialize_message(message: &JsonRpcMessage) -> Result<String, serde_json::Error> {
472 serde_json::to_string(message)
473 }
474
475 pub fn is_batch(json: &str) -> bool {
477 json.trim_start().starts_with('[')
478 }
479
480 pub fn extract_method(json: &str) -> Option<String> {
482 if let Ok(value) = serde_json::from_str::<serde_json::Value>(json)
484 && let Some(method) = value.get("method")
485 {
486 return method.as_str().map(String::from);
487 }
488 None
489 }
490}
491
492#[cfg(test)]
493#[allow(deprecated)] mod tests {
495 use super::*;
496 use serde_json::json;
497
498 #[test]
499 fn test_jsonrpc_version() {
500 let version = JsonRpcVersion;
501 let json = serde_json::to_string(&version).unwrap();
502 assert_eq!(json, "\"2.0\"");
503
504 let parsed: JsonRpcVersion = serde_json::from_str(&json).unwrap();
505 assert_eq!(parsed, version);
506 }
507
508 #[test]
509 fn test_request_creation() {
510 let request = JsonRpcRequest::new(
511 "test_method".to_string(),
512 Some(json!({"key": "value"})),
513 RequestId::String("test-id".to_string()),
514 );
515
516 assert_eq!(request.method, "test_method");
517 assert!(request.params.is_some());
518 }
519
520 #[test]
521 fn test_response_creation() {
522 let response = JsonRpcResponse::success(
523 json!({"result": "success"}),
524 RequestId::String("test-id".to_string()),
525 );
526
527 assert!(response.is_success());
528 assert!(!response.is_error());
529 assert!(response.result().is_some());
530 assert!(response.error().is_none());
531 assert!(!response.is_parse_error());
532 }
533
534 #[test]
535 fn test_error_response() {
536 let error = JsonRpcError::from(JsonRpcErrorCode::MethodNotFound);
537 let response =
538 JsonRpcResponse::error_response(error, RequestId::String("test-id".to_string()));
539
540 assert!(!response.is_success());
541 assert!(response.is_error());
542 assert!(response.result().is_none());
543 assert!(response.error().is_some());
544 assert!(!response.is_parse_error());
545 }
546
547 #[test]
548 fn test_parse_error_response() {
549 let response = JsonRpcResponse::parse_error(Some("Invalid JSON".to_string()));
550
551 assert!(!response.is_success());
552 assert!(response.is_error());
553 assert!(response.result().is_none());
554 assert!(response.error().is_some());
555 assert!(response.is_parse_error());
556 assert!(response.request_id().is_none());
557
558 let error = response.error().unwrap();
560 assert_eq!(error.code, JsonRpcErrorCode::ParseError.code());
561 assert_eq!(error.message, "Invalid JSON");
562 }
563
564 #[test]
565 fn test_notification() {
566 let notification = JsonRpcNotification::without_params("test_notification".to_string());
567 assert_eq!(notification.method, "test_notification");
568 assert!(notification.params.is_none());
569 }
570
571 #[test]
572 fn test_batch() {
573 let mut batch = JsonRpcBatch::<JsonRpcRequest>::empty();
574 assert!(batch.is_empty());
575
576 batch.push(JsonRpcRequest::without_params(
577 "method1".to_string(),
578 RequestId::String("1".to_string()),
579 ));
580 batch.push(JsonRpcRequest::without_params(
581 "method2".to_string(),
582 RequestId::String("2".to_string()),
583 ));
584
585 assert_eq!(batch.len(), 2);
586 assert!(!batch.is_empty());
587 }
588
589 #[test]
590 fn test_serialization() {
591 let request = JsonRpcRequest::new(
592 "test_method".to_string(),
593 Some(json!({"param": "value"})),
594 RequestId::String("123".to_string()),
595 );
596
597 let json = serde_json::to_string(&request).unwrap();
598 let parsed: JsonRpcRequest = serde_json::from_str(&json).unwrap();
599
600 assert_eq!(parsed.method, request.method);
601 assert_eq!(parsed.params, request.params);
602 }
603
604 #[test]
605 fn test_utils() {
606 let json = r#"{"jsonrpc":"2.0","method":"test","id":"123"}"#;
607
608 assert!(!utils::is_batch(json));
609 assert_eq!(utils::extract_method(json), Some("test".to_string()));
610
611 let batch_json = r#"[{"jsonrpc":"2.0","method":"test","id":"123"}]"#;
612 assert!(utils::is_batch(batch_json));
613 }
614
615 #[test]
616 fn test_error_codes() {
617 let parse_error = JsonRpcErrorCode::ParseError;
618 assert_eq!(parse_error.code(), -32700);
619 assert_eq!(parse_error.message(), "Parse error");
620
621 let app_error = JsonRpcErrorCode::ApplicationError(-32001);
622 assert_eq!(app_error.code(), -32001);
623 }
624}