turul_mcp_json_rpc_server/
dispatch.rs1use serde_json::Value;
2
3use crate::{
4 error::JsonRpcError, notification::JsonRpcNotification, request::JsonRpcRequest,
5 response::JsonRpcResponse, types::RequestId,
6};
7
8#[derive(Debug, Clone)]
10pub enum JsonRpcMessage {
11 Request(JsonRpcRequest),
12 Notification(JsonRpcNotification),
13}
14
15#[derive(Debug, Clone)]
17pub enum JsonRpcMessageResult {
18 Response(JsonRpcResponse),
20 Error(JsonRpcError),
22 NoResponse,
24}
25
26impl JsonRpcMessageResult {
27 pub fn to_json_string(&self) -> Option<String> {
29 match self {
30 JsonRpcMessageResult::Response(response) => serde_json::to_string(response).ok(),
31 JsonRpcMessageResult::Error(error) => serde_json::to_string(error).ok(),
32 JsonRpcMessageResult::NoResponse => None,
33 }
34 }
35
36 pub fn is_error(&self) -> bool {
38 matches!(self, JsonRpcMessageResult::Error(_))
39 }
40
41 pub fn needs_response(&self) -> bool {
43 !matches!(self, JsonRpcMessageResult::NoResponse)
44 }
45}
46
47pub fn parse_json_rpc_message(json_str: &str) -> Result<JsonRpcMessage, JsonRpcError> {
49 let value: Value = serde_json::from_str(json_str).map_err(|_| JsonRpcError::parse_error())?;
50
51 if !value.is_object() {
53 return Err(JsonRpcError::invalid_request(None));
54 }
55
56 let obj = value.as_object().unwrap();
57
58 match obj.get("jsonrpc") {
60 Some(version) if version == "2.0" => {}
61 _ => return Err(JsonRpcError::invalid_request(None)),
62 }
63
64 if obj.contains_key("id") {
66 serde_json::from_value::<JsonRpcRequest>(value.clone())
68 .map(JsonRpcMessage::Request)
69 .map_err(|_| {
70 let id = obj.get("id").and_then(|v| match v {
72 Value::String(s) => Some(RequestId::String(s.clone())),
73 Value::Number(n) => n.as_i64().map(RequestId::Number),
74 _ => None,
75 });
76 JsonRpcError::invalid_request(id)
77 })
78 } else {
79 serde_json::from_value::<JsonRpcNotification>(value)
81 .map(JsonRpcMessage::Notification)
82 .map_err(|_| JsonRpcError::invalid_request(None))
83 }
84}
85
86impl JsonRpcMessage {
88 pub fn method(&self) -> &str {
90 match self {
91 JsonRpcMessage::Request(req) => &req.method,
92 JsonRpcMessage::Notification(notif) => ¬if.method,
93 }
94 }
95
96 pub fn is_request(&self) -> bool {
98 matches!(self, JsonRpcMessage::Request(_))
99 }
100
101 pub fn is_notification(&self) -> bool {
103 matches!(self, JsonRpcMessage::Notification(_))
104 }
105
106 pub fn request_id(&self) -> Option<&RequestId> {
108 match self {
109 JsonRpcMessage::Request(req) => Some(&req.id),
110 JsonRpcMessage::Notification(_) => None,
111 }
112 }
113}
114
115pub fn parse_json_rpc_messages(json_str: &str) -> Vec<Result<JsonRpcMessage, JsonRpcError>> {
118 vec![parse_json_rpc_message(json_str)]
120}
121
122pub fn create_success_response(id: RequestId, result: Value) -> JsonRpcMessageResult {
124 JsonRpcMessageResult::Response(JsonRpcResponse::success(id, result))
125}
126
127pub fn create_error_response(
129 id: Option<RequestId>,
130 code: i64,
131 message: &str,
132) -> JsonRpcMessageResult {
133 let error_obj = crate::error::JsonRpcErrorObject {
134 code,
135 message: message.to_string(),
136 data: None,
137 };
138 JsonRpcMessageResult::Error(JsonRpcError::new(id, error_obj))
139}
140
141#[cfg(test)]
142mod tests {
143 use super::*;
144 use serde_json::json;
145
146 #[test]
147 fn test_parse_valid_request() {
148 let json = r#"{"jsonrpc": "2.0", "method": "test", "id": 1}"#;
149 let message = parse_json_rpc_message(json).unwrap();
150
151 assert!(message.is_request());
152 assert_eq!(message.method(), "test");
153 assert_eq!(message.request_id(), Some(&RequestId::Number(1)));
154 }
155
156 #[test]
157 fn test_parse_valid_notification() {
158 let json = r#"{"jsonrpc": "2.0", "method": "notify"}"#;
159 let message = parse_json_rpc_message(json).unwrap();
160
161 assert!(message.is_notification());
162 assert_eq!(message.method(), "notify");
163 assert_eq!(message.request_id(), None);
164 }
165
166 #[test]
167 fn test_parse_invalid_json() {
168 let json = r#"{"jsonrpc": "2.0", "method": "test""#; let result = parse_json_rpc_message(json);
170
171 assert!(result.is_err());
172 let error = result.unwrap_err();
173 assert_eq!(error.error.code, -32700); }
175
176 #[test]
177 fn test_parse_invalid_version() {
178 let json = r#"{"jsonrpc": "1.0", "method": "test", "id": 1}"#;
179 let result = parse_json_rpc_message(json);
180
181 assert!(result.is_err());
182 let error = result.unwrap_err();
183 assert_eq!(error.error.code, -32600); }
185
186 #[test]
187 fn test_message_result_to_json() {
188 let response = create_success_response(RequestId::Number(1), json!({"result": "success"}));
189
190 let json_str = response.to_json_string().unwrap();
191 assert!(json_str.contains("\"result\""));
192 assert!(json_str.contains("\"jsonrpc\":\"2.0\""));
193 }
194
195 #[test]
196 fn test_message_result_properties() {
197 let success = create_success_response(RequestId::Number(1), json!({}));
198 let error = create_error_response(Some(RequestId::Number(1)), -32601, "Not found");
199 let no_response = JsonRpcMessageResult::NoResponse;
200
201 assert!(!success.is_error());
202 assert!(success.needs_response());
203
204 assert!(error.is_error());
205 assert!(error.needs_response());
206
207 assert!(!no_response.is_error());
208 assert!(!no_response.needs_response());
209 }
210}