barbacane_lib/mcp/
jsonrpc.rs1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Deserialize)]
5pub struct JsonRpcRequest {
6 pub jsonrpc: String,
7 pub id: Option<serde_json::Value>,
8 pub method: String,
9 #[serde(default)]
10 pub params: Option<serde_json::Value>,
11}
12
13#[derive(Debug, Serialize)]
15pub struct JsonRpcResponse {
16 pub jsonrpc: &'static str,
17 #[serde(skip_serializing_if = "Option::is_none")]
18 pub id: Option<serde_json::Value>,
19 #[serde(skip_serializing_if = "Option::is_none")]
20 pub result: Option<serde_json::Value>,
21 #[serde(skip_serializing_if = "Option::is_none")]
22 pub error: Option<JsonRpcError>,
23}
24
25#[derive(Debug, Serialize)]
27pub struct JsonRpcError {
28 pub code: i32,
29 pub message: String,
30 #[serde(skip_serializing_if = "Option::is_none")]
31 pub data: Option<serde_json::Value>,
32}
33
34pub const PARSE_ERROR: i32 = -32700;
36pub const INVALID_REQUEST: i32 = -32600;
37pub const METHOD_NOT_FOUND: i32 = -32601;
38pub const INVALID_PARAMS: i32 = -32602;
39pub const INTERNAL_ERROR: i32 = -32603;
40
41impl JsonRpcResponse {
42 pub fn success(id: Option<serde_json::Value>, result: serde_json::Value) -> Self {
43 Self {
44 jsonrpc: "2.0",
45 id,
46 result: Some(result),
47 error: None,
48 }
49 }
50
51 pub fn error(id: Option<serde_json::Value>, code: i32, message: impl Into<String>) -> Self {
52 Self {
53 jsonrpc: "2.0",
54 id,
55 result: None,
56 error: Some(JsonRpcError {
57 code,
58 message: message.into(),
59 data: None,
60 }),
61 }
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68
69 #[test]
70 fn parse_valid_request() {
71 let json = r#"{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}"#;
72 let req: JsonRpcRequest = serde_json::from_str(json).expect("should parse");
73 assert_eq!(req.jsonrpc, "2.0");
74 assert_eq!(req.method, "initialize");
75 assert_eq!(req.id, Some(serde_json::json!(1)));
76 }
77
78 #[test]
79 fn parse_notification_no_id() {
80 let json = r#"{"jsonrpc":"2.0","method":"notifications/initialized"}"#;
81 let req: JsonRpcRequest = serde_json::from_str(json).expect("should parse");
82 assert!(req.id.is_none());
83 assert!(req.params.is_none());
84 }
85
86 #[test]
87 fn parse_request_with_string_id() {
88 let json = r#"{"jsonrpc":"2.0","id":"abc","method":"tools/list"}"#;
89 let req: JsonRpcRequest = serde_json::from_str(json).expect("should parse");
90 assert_eq!(req.id, Some(serde_json::json!("abc")));
91 }
92
93 #[test]
94 fn parse_invalid_json() {
95 let result = serde_json::from_str::<JsonRpcRequest>("not json");
96 assert!(result.is_err());
97 }
98
99 #[test]
100 fn success_response_serialization() {
101 let resp = JsonRpcResponse::success(Some(serde_json::json!(1)), serde_json::json!({}));
102 let json = serde_json::to_value(&resp).expect("should serialize");
103 assert_eq!(json["jsonrpc"], "2.0");
104 assert_eq!(json["id"], 1);
105 assert!(json.get("error").is_none());
106 }
107
108 #[test]
109 fn error_response_serialization() {
110 let resp =
111 JsonRpcResponse::error(Some(serde_json::json!(1)), METHOD_NOT_FOUND, "not found");
112 let json = serde_json::to_value(&resp).expect("should serialize");
113 assert_eq!(json["error"]["code"], METHOD_NOT_FOUND);
114 assert_eq!(json["error"]["message"], "not found");
115 assert!(json.get("result").is_none());
116 }
117}