1use crate::error::JsonRpcError;
29use serde::{Deserialize, Serialize};
30use std::borrow::Cow;
31
32pub const JSONRPC_VERSION: &str = "2.0";
34
35#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
40#[serde(untagged)]
41pub enum RequestId {
42 Number(u64),
44 String(String),
46}
47
48impl RequestId {
49 #[must_use]
51 pub fn number(id: u64) -> Self {
52 Self::Number(id)
53 }
54
55 #[must_use]
57 pub fn string(id: impl Into<String>) -> Self {
58 Self::String(id.into())
59 }
60}
61
62impl From<u64> for RequestId {
63 fn from(id: u64) -> Self {
64 Self::Number(id)
65 }
66}
67
68impl From<String> for RequestId {
69 fn from(id: String) -> Self {
70 Self::String(id)
71 }
72}
73
74impl From<&str> for RequestId {
75 fn from(id: &str) -> Self {
76 Self::String(id.to_string())
77 }
78}
79
80impl std::fmt::Display for RequestId {
81 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
82 match self {
83 Self::Number(n) => write!(f, "{n}"),
84 Self::String(s) => write!(f, "{s}"),
85 }
86 }
87}
88
89#[derive(Debug, Clone, Serialize, Deserialize)]
94pub struct Request {
95 pub jsonrpc: Cow<'static, str>,
97 pub id: RequestId,
99 pub method: Cow<'static, str>,
101 #[serde(skip_serializing_if = "Option::is_none")]
103 pub params: Option<serde_json::Value>,
104}
105
106impl Request {
107 #[must_use]
109 pub fn new(method: impl Into<Cow<'static, str>>, id: impl Into<RequestId>) -> Self {
110 Self {
111 jsonrpc: Cow::Borrowed(JSONRPC_VERSION),
112 id: id.into(),
113 method: method.into(),
114 params: None,
115 }
116 }
117
118 #[must_use]
120 pub fn with_params(
121 method: impl Into<Cow<'static, str>>,
122 id: impl Into<RequestId>,
123 params: serde_json::Value,
124 ) -> Self {
125 Self {
126 jsonrpc: Cow::Borrowed(JSONRPC_VERSION),
127 id: id.into(),
128 method: method.into(),
129 params: Some(params),
130 }
131 }
132
133 #[must_use]
135 pub fn params(mut self, params: serde_json::Value) -> Self {
136 self.params = Some(params);
137 self
138 }
139
140 #[must_use]
142 pub fn method(&self) -> &str {
143 &self.method
144 }
145}
146
147#[derive(Debug, Clone, Serialize, Deserialize)]
152pub struct Response {
153 pub jsonrpc: Cow<'static, str>,
155 pub id: RequestId,
157 #[serde(skip_serializing_if = "Option::is_none")]
159 pub result: Option<serde_json::Value>,
160 #[serde(skip_serializing_if = "Option::is_none")]
162 pub error: Option<JsonRpcError>,
163}
164
165impl Response {
166 #[must_use]
168 pub fn success(id: impl Into<RequestId>, result: serde_json::Value) -> Self {
169 Self {
170 jsonrpc: Cow::Borrowed(JSONRPC_VERSION),
171 id: id.into(),
172 result: Some(result),
173 error: None,
174 }
175 }
176
177 #[must_use]
179 pub fn error(id: impl Into<RequestId>, error: JsonRpcError) -> Self {
180 Self {
181 jsonrpc: Cow::Borrowed(JSONRPC_VERSION),
182 id: id.into(),
183 result: None,
184 error: Some(error),
185 }
186 }
187
188 #[must_use]
190 pub fn is_success(&self) -> bool {
191 self.result.is_some() && self.error.is_none()
192 }
193
194 #[must_use]
196 pub fn is_error(&self) -> bool {
197 self.error.is_some()
198 }
199
200 pub fn into_result(self) -> Result<serde_json::Value, JsonRpcError> {
204 if let Some(error) = self.error {
205 Err(error)
206 } else {
207 self.result.ok_or_else(|| JsonRpcError {
208 code: -32603,
209 message: "Response contained neither result nor error".to_string(),
210 data: None,
211 })
212 }
213 }
214}
215
216#[derive(Debug, Clone, Serialize, Deserialize)]
221pub struct Notification {
222 pub jsonrpc: Cow<'static, str>,
224 pub method: Cow<'static, str>,
226 #[serde(skip_serializing_if = "Option::is_none")]
228 pub params: Option<serde_json::Value>,
229}
230
231impl Notification {
232 #[must_use]
234 pub fn new(method: impl Into<Cow<'static, str>>) -> Self {
235 Self {
236 jsonrpc: Cow::Borrowed(JSONRPC_VERSION),
237 method: method.into(),
238 params: None,
239 }
240 }
241
242 #[must_use]
244 pub fn with_params(
245 method: impl Into<Cow<'static, str>>,
246 params: serde_json::Value,
247 ) -> Self {
248 Self {
249 jsonrpc: Cow::Borrowed(JSONRPC_VERSION),
250 method: method.into(),
251 params: Some(params),
252 }
253 }
254
255 #[must_use]
257 pub fn params(mut self, params: serde_json::Value) -> Self {
258 self.params = Some(params);
259 self
260 }
261
262 #[must_use]
264 pub fn method(&self) -> &str {
265 &self.method
266 }
267}
268
269#[derive(Debug, Clone, Serialize, Deserialize)]
274#[serde(untagged)]
275pub enum Message {
276 Request(Request),
278 Response(Response),
280 Notification(Notification),
282}
283
284impl Message {
285 #[must_use]
287 pub fn method(&self) -> Option<&str> {
288 match self {
289 Self::Request(r) => Some(&r.method),
290 Self::Notification(n) => Some(&n.method),
291 Self::Response(_) => None,
292 }
293 }
294
295 #[must_use]
297 pub fn id(&self) -> Option<&RequestId> {
298 match self {
299 Self::Request(r) => Some(&r.id),
300 Self::Response(r) => Some(&r.id),
301 Self::Notification(_) => None,
302 }
303 }
304
305 #[must_use]
307 pub fn is_request(&self) -> bool {
308 matches!(self, Self::Request(_))
309 }
310
311 #[must_use]
313 pub fn is_response(&self) -> bool {
314 matches!(self, Self::Response(_))
315 }
316
317 #[must_use]
319 pub fn is_notification(&self) -> bool {
320 matches!(self, Self::Notification(_))
321 }
322
323 #[must_use]
325 pub fn as_request(&self) -> Option<&Request> {
326 match self {
327 Self::Request(r) => Some(r),
328 _ => None,
329 }
330 }
331
332 #[must_use]
334 pub fn as_response(&self) -> Option<&Response> {
335 match self {
336 Self::Response(r) => Some(r),
337 _ => None,
338 }
339 }
340
341 #[must_use]
343 pub fn as_notification(&self) -> Option<&Notification> {
344 match self {
345 Self::Notification(n) => Some(n),
346 _ => None,
347 }
348 }
349}
350
351impl From<Request> for Message {
352 fn from(r: Request) -> Self {
353 Self::Request(r)
354 }
355}
356
357impl From<Response> for Message {
358 fn from(r: Response) -> Self {
359 Self::Response(r)
360 }
361}
362
363impl From<Notification> for Message {
364 fn from(n: Notification) -> Self {
365 Self::Notification(n)
366 }
367}
368
369#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
374#[serde(untagged)]
375pub enum ProgressToken {
376 Number(u64),
378 String(String),
380}
381
382impl std::fmt::Display for ProgressToken {
383 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
384 match self {
385 Self::Number(n) => write!(f, "{n}"),
386 Self::String(s) => write!(f, "{s}"),
387 }
388 }
389}
390
391#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
396#[serde(transparent)]
397pub struct Cursor(pub String);
398
399impl Cursor {
400 #[must_use]
402 pub fn new(cursor: impl Into<String>) -> Self {
403 Self(cursor.into())
404 }
405}
406
407impl std::fmt::Display for Cursor {
408 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
409 write!(f, "{}", self.0)
410 }
411}
412
413impl From<String> for Cursor {
414 fn from(s: String) -> Self {
415 Self(s)
416 }
417}
418
419impl From<&str> for Cursor {
420 fn from(s: &str) -> Self {
421 Self(s.to_string())
422 }
423}
424
425#[cfg(test)]
426mod tests {
427 use super::*;
428
429 #[test]
430 fn test_request_serialization() {
431 let request = Request::new("tools/list", 1u64);
432 let json = serde_json::to_string(&request).unwrap();
433 assert!(json.contains("\"jsonrpc\":\"2.0\""));
434 assert!(json.contains("\"method\":\"tools/list\""));
435 assert!(json.contains("\"id\":1"));
436 }
437
438 #[test]
439 fn test_request_with_params() {
440 let request = Request::with_params(
441 "tools/call",
442 1u64,
443 serde_json::json!({"name": "search", "arguments": {"query": "test"}}),
444 );
445 let json = serde_json::to_string(&request).unwrap();
446 assert!(json.contains("\"params\""));
447 assert!(json.contains("\"name\":\"search\""));
448 }
449
450 #[test]
451 fn test_response_success() {
452 let response = Response::success(1u64, serde_json::json!({"tools": []}));
453 assert!(response.is_success());
454 assert!(!response.is_error());
455
456 let result = response.into_result().unwrap();
457 assert!(result.get("tools").is_some());
458 }
459
460 #[test]
461 fn test_response_error() {
462 let error = JsonRpcError {
463 code: -32601,
464 message: "Method not found".to_string(),
465 data: None,
466 };
467 let response = Response::error(1u64, error);
468 assert!(!response.is_success());
469 assert!(response.is_error());
470
471 let err = response.into_result().unwrap_err();
472 assert_eq!(err.code, -32601);
473 }
474
475 #[test]
476 fn test_notification() {
477 let notification = Notification::with_params(
478 "notifications/progress",
479 serde_json::json!({"progress": 50, "total": 100}),
480 );
481 let json = serde_json::to_string(¬ification).unwrap();
482 assert!(json.contains("\"method\":\"notifications/progress\""));
483 assert!(!json.contains("\"id\"")); }
485
486 #[test]
487 fn test_message_parsing() {
488 let json = r#"{"jsonrpc":"2.0","id":1,"method":"test"}"#;
490 let msg: Message = serde_json::from_str(json).unwrap();
491 assert!(msg.is_request());
492 assert_eq!(msg.method(), Some("test"));
493
494 let json = r#"{"jsonrpc":"2.0","id":1,"result":{}}"#;
496 let msg: Message = serde_json::from_str(json).unwrap();
497 assert!(msg.is_response());
498
499 let json = r#"{"jsonrpc":"2.0","method":"notify"}"#;
501 let msg: Message = serde_json::from_str(json).unwrap();
502 assert!(msg.is_notification());
503 }
504
505 #[test]
506 fn test_request_id_types() {
507 let request = Request::new("test", 42u64);
509 let json = serde_json::to_string(&request).unwrap();
510 assert!(json.contains("\"id\":42"));
511
512 let request = Request::new("test", "req-001");
514 let json = serde_json::to_string(&request).unwrap();
515 assert!(json.contains("\"id\":\"req-001\""));
516 }
517}