1use std::{borrow::Cow, sync::Arc};
2mod annotated;
3mod capabilities;
4mod content;
5mod elicitation_schema;
6mod extension;
7mod meta;
8mod prompt;
9mod resource;
10mod serde_impl;
11mod task;
12mod tool;
13pub use annotated::*;
14pub use capabilities::*;
15pub use content::*;
16pub use elicitation_schema::*;
17pub use extension::*;
18pub use meta::*;
19pub use prompt::*;
20pub use resource::*;
21use serde::{Deserialize, Serialize, de::DeserializeOwned};
22use serde_json::Value;
23pub use task::*;
24pub use tool::*;
25
26pub type JsonObject<F = Value> = serde_json::Map<String, F>;
31
32pub fn object(value: serde_json::Value) -> JsonObject {
37 debug_assert!(value.is_object());
38 match value {
39 serde_json::Value::Object(map) => map,
40 _ => JsonObject::default(),
41 }
42}
43
44#[cfg(feature = "macros")]
46#[cfg_attr(docsrs, doc(cfg(feature = "macros")))]
47#[macro_export]
48macro_rules! object {
49 ({$($tt:tt)*}) => {
50 $crate::model::object(serde_json::json! {
51 {$($tt)*}
52 })
53 };
54}
55
56#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy, Eq)]
60#[serde(deny_unknown_fields)]
61#[cfg_attr(feature = "server", derive(schemars::JsonSchema))]
62pub struct EmptyObject {}
63
64pub trait ConstString: Default {
65 const VALUE: &str;
66 fn as_str(&self) -> &'static str {
67 Self::VALUE
68 }
69}
70#[macro_export]
71macro_rules! const_string {
72 ($name:ident = $value:literal) => {
73 #[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
74 pub struct $name;
75
76 impl ConstString for $name {
77 const VALUE: &str = $value;
78 }
79
80 impl serde::Serialize for $name {
81 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
82 where
83 S: serde::Serializer,
84 {
85 $value.serialize(serializer)
86 }
87 }
88
89 impl<'de> serde::Deserialize<'de> for $name {
90 fn deserialize<D>(deserializer: D) -> Result<$name, D::Error>
91 where
92 D: serde::Deserializer<'de>,
93 {
94 let s: String = serde::Deserialize::deserialize(deserializer)?;
95 if s == $value {
96 Ok($name)
97 } else {
98 Err(serde::de::Error::custom(format!(concat!(
99 "expect const string value \"",
100 $value,
101 "\""
102 ))))
103 }
104 }
105 }
106
107 #[cfg(feature = "schemars")]
108 impl schemars::JsonSchema for $name {
109 fn schema_name() -> Cow<'static, str> {
110 Cow::Borrowed(stringify!($name))
111 }
112
113 fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
114 use serde_json::{Map, json};
115
116 let mut schema_map = Map::new();
117 schema_map.insert("type".to_string(), json!("string"));
118 schema_map.insert("format".to_string(), json!("const"));
119 schema_map.insert("const".to_string(), json!($value));
120
121 schemars::Schema::from(schema_map)
122 }
123 }
124 };
125}
126
127const_string!(JsonRpcVersion2_0 = "2.0");
128
129#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd)]
138#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
139pub struct ProtocolVersion(Cow<'static, str>);
140
141impl Default for ProtocolVersion {
142 fn default() -> Self {
143 Self::LATEST
144 }
145}
146
147impl std::fmt::Display for ProtocolVersion {
148 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
149 self.0.fmt(f)
150 }
151}
152
153impl ProtocolVersion {
154 pub const V_2025_06_18: Self = Self(Cow::Borrowed("2025-06-18"));
155 pub const V_2025_03_26: Self = Self(Cow::Borrowed("2025-03-26"));
156 pub const V_2024_11_05: Self = Self(Cow::Borrowed("2024-11-05"));
157 pub const LATEST: Self = Self::V_2025_03_26;
159}
160
161impl Serialize for ProtocolVersion {
162 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
163 where
164 S: serde::Serializer,
165 {
166 self.0.serialize(serializer)
167 }
168}
169
170impl<'de> Deserialize<'de> for ProtocolVersion {
171 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
172 where
173 D: serde::Deserializer<'de>,
174 {
175 let s: String = Deserialize::deserialize(deserializer)?;
176 #[allow(clippy::single_match)]
177 match s.as_str() {
178 "2024-11-05" => return Ok(ProtocolVersion::V_2024_11_05),
179 "2025-03-26" => return Ok(ProtocolVersion::V_2025_03_26),
180 "2025-06-18" => return Ok(ProtocolVersion::V_2025_06_18),
181 _ => {}
182 }
183 Ok(ProtocolVersion(Cow::Owned(s)))
184 }
185}
186
187#[derive(Debug, Clone, Eq, PartialEq, Hash)]
192pub enum NumberOrString {
193 Number(i64),
195 String(Arc<str>),
197}
198
199impl NumberOrString {
200 pub fn into_json_value(self) -> Value {
201 match self {
202 NumberOrString::Number(n) => Value::Number(serde_json::Number::from(n)),
203 NumberOrString::String(s) => Value::String(s.to_string()),
204 }
205 }
206}
207
208impl std::fmt::Display for NumberOrString {
209 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
210 match self {
211 NumberOrString::Number(n) => n.fmt(f),
212 NumberOrString::String(s) => s.fmt(f),
213 }
214 }
215}
216
217impl Serialize for NumberOrString {
218 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
219 where
220 S: serde::Serializer,
221 {
222 match self {
223 NumberOrString::Number(n) => n.serialize(serializer),
224 NumberOrString::String(s) => s.serialize(serializer),
225 }
226 }
227}
228
229impl<'de> Deserialize<'de> for NumberOrString {
230 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
231 where
232 D: serde::Deserializer<'de>,
233 {
234 let value: Value = Deserialize::deserialize(deserializer)?;
235 match value {
236 Value::Number(n) => {
237 if let Some(i) = n.as_i64() {
238 Ok(NumberOrString::Number(i))
239 } else if let Some(u) = n.as_u64() {
240 if u <= i64::MAX as u64 {
242 Ok(NumberOrString::Number(u as i64))
243 } else {
244 Err(serde::de::Error::custom("Number too large for i64"))
245 }
246 } else {
247 Err(serde::de::Error::custom("Expected an integer"))
248 }
249 }
250 Value::String(s) => Ok(NumberOrString::String(s.into())),
251 _ => Err(serde::de::Error::custom("Expect number or string")),
252 }
253 }
254}
255
256#[cfg(feature = "schemars")]
257impl schemars::JsonSchema for NumberOrString {
258 fn schema_name() -> Cow<'static, str> {
259 Cow::Borrowed("NumberOrString")
260 }
261
262 fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
263 use serde_json::{Map, json};
264
265 let mut number_schema = Map::new();
266 number_schema.insert("type".to_string(), json!("number"));
267
268 let mut string_schema = Map::new();
269 string_schema.insert("type".to_string(), json!("string"));
270
271 let mut schema_map = Map::new();
272 schema_map.insert("oneOf".to_string(), json!([number_schema, string_schema]));
273
274 schemars::Schema::from(schema_map)
275 }
276}
277
278pub type RequestId = NumberOrString;
280
281#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Hash, Eq)]
286#[serde(transparent)]
287#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
288pub struct ProgressToken(pub NumberOrString);
289
290#[derive(Debug, Clone, Default)]
301#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
302pub struct Request<M = String, P = JsonObject> {
303 pub method: M,
304 pub params: P,
305 #[cfg_attr(feature = "schemars", schemars(skip))]
309 pub extensions: Extensions,
310}
311
312impl<M: Default, P> Request<M, P> {
313 pub fn new(params: P) -> Self {
314 Self {
315 method: Default::default(),
316 params,
317 extensions: Extensions::default(),
318 }
319 }
320}
321
322impl<M, P> GetExtensions for Request<M, P> {
323 fn extensions(&self) -> &Extensions {
324 &self.extensions
325 }
326 fn extensions_mut(&mut self) -> &mut Extensions {
327 &mut self.extensions
328 }
329}
330
331#[derive(Debug, Clone, Default)]
332#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
333pub struct RequestOptionalParam<M = String, P = JsonObject> {
334 pub method: M,
335 pub params: Option<P>,
337 #[cfg_attr(feature = "schemars", schemars(skip))]
341 pub extensions: Extensions,
342}
343
344impl<M: Default, P> RequestOptionalParam<M, P> {
345 pub fn with_param(params: P) -> Self {
346 Self {
347 method: Default::default(),
348 params: Some(params),
349 extensions: Extensions::default(),
350 }
351 }
352}
353
354#[derive(Debug, Clone, Default)]
355#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
356pub struct RequestNoParam<M = String> {
357 pub method: M,
358 #[cfg_attr(feature = "schemars", schemars(skip))]
362 pub extensions: Extensions,
363}
364
365impl<M> GetExtensions for RequestNoParam<M> {
366 fn extensions(&self) -> &Extensions {
367 &self.extensions
368 }
369 fn extensions_mut(&mut self) -> &mut Extensions {
370 &mut self.extensions
371 }
372}
373#[derive(Debug, Clone, Default)]
374#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
375pub struct Notification<M = String, P = JsonObject> {
376 pub method: M,
377 pub params: P,
378 #[cfg_attr(feature = "schemars", schemars(skip))]
382 pub extensions: Extensions,
383}
384
385impl<M: Default, P> Notification<M, P> {
386 pub fn new(params: P) -> Self {
387 Self {
388 method: Default::default(),
389 params,
390 extensions: Extensions::default(),
391 }
392 }
393}
394
395#[derive(Debug, Clone, Default)]
396#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
397pub struct NotificationNoParam<M = String> {
398 pub method: M,
399 #[cfg_attr(feature = "schemars", schemars(skip))]
403 pub extensions: Extensions,
404}
405
406#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
407#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
408pub struct JsonRpcRequest<R = Request> {
409 pub jsonrpc: JsonRpcVersion2_0,
410 pub id: RequestId,
411 #[serde(flatten)]
412 pub request: R,
413}
414
415type DefaultResponse = JsonObject;
416#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
417#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
418pub struct JsonRpcResponse<R = JsonObject> {
419 pub jsonrpc: JsonRpcVersion2_0,
420 pub id: RequestId,
421 pub result: R,
422}
423
424#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
425#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
426pub struct JsonRpcError {
427 pub jsonrpc: JsonRpcVersion2_0,
428 pub id: RequestId,
429 pub error: ErrorData,
430}
431
432#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
433#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
434pub struct JsonRpcNotification<N = Notification> {
435 pub jsonrpc: JsonRpcVersion2_0,
436 #[serde(flatten)]
437 pub notification: N,
438}
439
440#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
445#[serde(transparent)]
446#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
447pub struct ErrorCode(pub i32);
448
449impl ErrorCode {
450 pub const RESOURCE_NOT_FOUND: Self = Self(-32002);
451 pub const INVALID_REQUEST: Self = Self(-32600);
452 pub const METHOD_NOT_FOUND: Self = Self(-32601);
453 pub const INVALID_PARAMS: Self = Self(-32602);
454 pub const INTERNAL_ERROR: Self = Self(-32603);
455 pub const PARSE_ERROR: Self = Self(-32700);
456}
457
458#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
463#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
464pub struct ErrorData {
465 pub code: ErrorCode,
467
468 pub message: Cow<'static, str>,
470
471 #[serde(skip_serializing_if = "Option::is_none")]
474 pub data: Option<Value>,
475}
476
477impl ErrorData {
478 pub fn new(
479 code: ErrorCode,
480 message: impl Into<Cow<'static, str>>,
481 data: Option<Value>,
482 ) -> Self {
483 Self {
484 code,
485 message: message.into(),
486 data,
487 }
488 }
489 pub fn resource_not_found(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
490 Self::new(ErrorCode::RESOURCE_NOT_FOUND, message, data)
491 }
492 pub fn parse_error(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
493 Self::new(ErrorCode::PARSE_ERROR, message, data)
494 }
495 pub fn invalid_request(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
496 Self::new(ErrorCode::INVALID_REQUEST, message, data)
497 }
498 pub fn method_not_found<M: ConstString>() -> Self {
499 Self::new(ErrorCode::METHOD_NOT_FOUND, M::VALUE, None)
500 }
501 pub fn invalid_params(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
502 Self::new(ErrorCode::INVALID_PARAMS, message, data)
503 }
504 pub fn internal_error(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
505 Self::new(ErrorCode::INTERNAL_ERROR, message, data)
506 }
507}
508
509#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
515#[serde(untagged)]
516#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
517pub enum JsonRpcMessage<Req = Request, Resp = DefaultResponse, Noti = Notification> {
518 Request(JsonRpcRequest<Req>),
520 Response(JsonRpcResponse<Resp>),
522 Notification(JsonRpcNotification<Noti>),
524 Error(JsonRpcError),
526}
527
528impl<Req, Resp, Not> JsonRpcMessage<Req, Resp, Not> {
529 #[inline]
530 pub const fn request(request: Req, id: RequestId) -> Self {
531 JsonRpcMessage::Request(JsonRpcRequest {
532 jsonrpc: JsonRpcVersion2_0,
533 id,
534 request,
535 })
536 }
537 #[inline]
538 pub const fn response(response: Resp, id: RequestId) -> Self {
539 JsonRpcMessage::Response(JsonRpcResponse {
540 jsonrpc: JsonRpcVersion2_0,
541 id,
542 result: response,
543 })
544 }
545 #[inline]
546 pub const fn error(error: ErrorData, id: RequestId) -> Self {
547 JsonRpcMessage::Error(JsonRpcError {
548 jsonrpc: JsonRpcVersion2_0,
549 id,
550 error,
551 })
552 }
553 #[inline]
554 pub const fn notification(notification: Not) -> Self {
555 JsonRpcMessage::Notification(JsonRpcNotification {
556 jsonrpc: JsonRpcVersion2_0,
557 notification,
558 })
559 }
560 pub fn into_request(self) -> Option<(Req, RequestId)> {
561 match self {
562 JsonRpcMessage::Request(r) => Some((r.request, r.id)),
563 _ => None,
564 }
565 }
566 pub fn into_response(self) -> Option<(Resp, RequestId)> {
567 match self {
568 JsonRpcMessage::Response(r) => Some((r.result, r.id)),
569 _ => None,
570 }
571 }
572 pub fn into_notification(self) -> Option<Not> {
573 match self {
574 JsonRpcMessage::Notification(n) => Some(n.notification),
575 _ => None,
576 }
577 }
578 pub fn into_error(self) -> Option<(ErrorData, RequestId)> {
579 match self {
580 JsonRpcMessage::Error(e) => Some((e.error, e.id)),
581 _ => None,
582 }
583 }
584 pub fn into_result(self) -> Option<(Result<Resp, ErrorData>, RequestId)> {
585 match self {
586 JsonRpcMessage::Response(r) => Some((Ok(r.result), r.id)),
587 JsonRpcMessage::Error(e) => Some((Err(e.error), e.id)),
588
589 _ => None,
590 }
591 }
592}
593
594pub type EmptyResult = EmptyObject;
601
602impl From<()> for EmptyResult {
603 fn from(_value: ()) -> Self {
604 EmptyResult {}
605 }
606}
607
608impl From<EmptyResult> for () {
609 fn from(_value: EmptyResult) {}
610}
611
612#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
614#[serde(transparent)]
615#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
616pub struct CustomResult(pub Value);
617
618impl CustomResult {
619 pub fn new(result: Value) -> Self {
620 Self(result)
621 }
622
623 pub fn result_as<T: DeserializeOwned>(&self) -> Result<T, serde_json::Error> {
625 serde_json::from_value(self.0.clone())
626 }
627}
628
629#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
630#[serde(rename_all = "camelCase")]
631#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
632pub struct CancelledNotificationParam {
633 pub request_id: RequestId,
634 pub reason: Option<String>,
635}
636
637const_string!(CancelledNotificationMethod = "notifications/cancelled");
638
639pub type CancelledNotification =
648 Notification<CancelledNotificationMethod, CancelledNotificationParam>;
649
650#[derive(Debug, Clone)]
655#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
656pub struct CustomNotification {
657 pub method: String,
658 pub params: Option<Value>,
659 #[cfg_attr(feature = "schemars", schemars(skip))]
663 pub extensions: Extensions,
664}
665
666impl CustomNotification {
667 pub fn new(method: impl Into<String>, params: Option<Value>) -> Self {
668 Self {
669 method: method.into(),
670 params,
671 extensions: Extensions::default(),
672 }
673 }
674
675 pub fn params_as<T: DeserializeOwned>(&self) -> Result<Option<T>, serde_json::Error> {
677 self.params
678 .as_ref()
679 .map(|params| serde_json::from_value(params.clone()))
680 .transpose()
681 }
682}
683
684#[derive(Debug, Clone)]
689#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
690pub struct CustomRequest {
691 pub method: String,
692 pub params: Option<Value>,
693 #[cfg_attr(feature = "schemars", schemars(skip))]
697 pub extensions: Extensions,
698}
699
700impl CustomRequest {
701 pub fn new(method: impl Into<String>, params: Option<Value>) -> Self {
702 Self {
703 method: method.into(),
704 params,
705 extensions: Extensions::default(),
706 }
707 }
708
709 pub fn params_as<T: DeserializeOwned>(&self) -> Result<Option<T>, serde_json::Error> {
711 self.params
712 .as_ref()
713 .map(|params| serde_json::from_value(params.clone()))
714 .transpose()
715 }
716}
717
718const_string!(InitializeResultMethod = "initialize");
719pub type InitializeRequest = Request<InitializeResultMethod, InitializeRequestParams>;
722
723const_string!(InitializedNotificationMethod = "notifications/initialized");
724pub type InitializedNotification = NotificationNoParam<InitializedNotificationMethod>;
726
727#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
732#[serde(rename_all = "camelCase")]
733#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
734pub struct InitializeRequestParams {
735 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
737 pub meta: Option<Meta>,
738 pub protocol_version: ProtocolVersion,
740 pub capabilities: ClientCapabilities,
742 pub client_info: Implementation,
744}
745
746impl RequestParamsMeta for InitializeRequestParams {
747 fn meta(&self) -> Option<&Meta> {
748 self.meta.as_ref()
749 }
750 fn meta_mut(&mut self) -> &mut Option<Meta> {
751 &mut self.meta
752 }
753}
754
755#[deprecated(since = "0.13.0", note = "Use InitializeRequestParams instead")]
757pub type InitializeRequestParam = InitializeRequestParams;
758
759#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
764#[serde(rename_all = "camelCase")]
765#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
766pub struct InitializeResult {
767 pub protocol_version: ProtocolVersion,
769 pub capabilities: ServerCapabilities,
771 pub server_info: Implementation,
773 #[serde(skip_serializing_if = "Option::is_none")]
775 pub instructions: Option<String>,
776}
777
778pub type ServerInfo = InitializeResult;
779pub type ClientInfo = InitializeRequestParams;
780
781#[allow(clippy::derivable_impls)]
782impl Default for ServerInfo {
783 fn default() -> Self {
784 ServerInfo {
785 protocol_version: ProtocolVersion::default(),
786 capabilities: ServerCapabilities::default(),
787 server_info: Implementation::from_build_env(),
788 instructions: None,
789 }
790 }
791}
792
793#[allow(clippy::derivable_impls)]
794impl Default for ClientInfo {
795 fn default() -> Self {
796 ClientInfo {
797 meta: None,
798 protocol_version: ProtocolVersion::default(),
799 capabilities: ClientCapabilities::default(),
800 client_info: Implementation::from_build_env(),
801 }
802 }
803}
804
805#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
815#[serde(rename_all = "camelCase")]
816#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
817pub struct Icon {
818 pub src: String,
820 #[serde(skip_serializing_if = "Option::is_none")]
822 pub mime_type: Option<String>,
823 #[serde(skip_serializing_if = "Option::is_none")]
825 pub sizes: Option<Vec<String>>,
826}
827
828#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
829#[serde(rename_all = "camelCase")]
830#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
831pub struct Implementation {
832 pub name: String,
833 #[serde(skip_serializing_if = "Option::is_none")]
834 pub title: Option<String>,
835 pub version: String,
836 #[serde(skip_serializing_if = "Option::is_none")]
837 pub icons: Option<Vec<Icon>>,
838 #[serde(skip_serializing_if = "Option::is_none")]
839 pub website_url: Option<String>,
840}
841
842impl Default for Implementation {
843 fn default() -> Self {
844 Self::from_build_env()
845 }
846}
847
848impl Implementation {
849 pub fn from_build_env() -> Self {
850 Implementation {
851 name: env!("CARGO_CRATE_NAME").to_owned(),
852 title: None,
853 version: env!("CARGO_PKG_VERSION").to_owned(),
854 icons: None,
855 website_url: None,
856 }
857 }
858}
859
860#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
861#[serde(rename_all = "camelCase")]
862#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
863pub struct PaginatedRequestParams {
864 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
866 pub meta: Option<Meta>,
867 #[serde(skip_serializing_if = "Option::is_none")]
868 pub cursor: Option<String>,
869}
870
871impl RequestParamsMeta for PaginatedRequestParams {
872 fn meta(&self) -> Option<&Meta> {
873 self.meta.as_ref()
874 }
875 fn meta_mut(&mut self) -> &mut Option<Meta> {
876 &mut self.meta
877 }
878}
879
880#[deprecated(since = "0.13.0", note = "Use PaginatedRequestParams instead")]
882pub type PaginatedRequestParam = PaginatedRequestParams;
883const_string!(PingRequestMethod = "ping");
888pub type PingRequest = RequestNoParam<PingRequestMethod>;
889
890const_string!(ProgressNotificationMethod = "notifications/progress");
891#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
892#[serde(rename_all = "camelCase")]
893#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
894pub struct ProgressNotificationParam {
895 pub progress_token: ProgressToken,
896 pub progress: f64,
898 #[serde(skip_serializing_if = "Option::is_none")]
900 pub total: Option<f64>,
901 #[serde(skip_serializing_if = "Option::is_none")]
903 pub message: Option<String>,
904}
905
906pub type ProgressNotification = Notification<ProgressNotificationMethod, ProgressNotificationParam>;
907
908pub type Cursor = String;
909
910macro_rules! paginated_result {
911 ($t:ident {
912 $i_item: ident: $t_item: ty
913 }) => {
914 #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
915 #[serde(rename_all = "camelCase")]
916 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
917 pub struct $t {
918 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
919 pub meta: Option<Meta>,
920 #[serde(skip_serializing_if = "Option::is_none")]
921 pub next_cursor: Option<Cursor>,
922 pub $i_item: $t_item,
923 }
924
925 impl $t {
926 pub fn with_all_items(
927 items: $t_item,
928 ) -> Self {
929 Self {
930 meta: None,
931 next_cursor: None,
932 $i_item: items,
933 }
934 }
935 }
936 };
937}
938
939const_string!(ListResourcesRequestMethod = "resources/list");
944pub type ListResourcesRequest =
946 RequestOptionalParam<ListResourcesRequestMethod, PaginatedRequestParams>;
947
948paginated_result!(ListResourcesResult {
949 resources: Vec<Resource>
950});
951
952const_string!(ListResourceTemplatesRequestMethod = "resources/templates/list");
953pub type ListResourceTemplatesRequest =
955 RequestOptionalParam<ListResourceTemplatesRequestMethod, PaginatedRequestParams>;
956
957paginated_result!(ListResourceTemplatesResult {
958 resource_templates: Vec<ResourceTemplate>
959});
960
961const_string!(ReadResourceRequestMethod = "resources/read");
962#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
964#[serde(rename_all = "camelCase")]
965#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
966pub struct ReadResourceRequestParams {
967 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
969 pub meta: Option<Meta>,
970 pub uri: String,
972}
973
974impl RequestParamsMeta for ReadResourceRequestParams {
975 fn meta(&self) -> Option<&Meta> {
976 self.meta.as_ref()
977 }
978 fn meta_mut(&mut self) -> &mut Option<Meta> {
979 &mut self.meta
980 }
981}
982
983#[deprecated(since = "0.13.0", note = "Use ReadResourceRequestParams instead")]
985pub type ReadResourceRequestParam = ReadResourceRequestParams;
986
987#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
989#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
990pub struct ReadResourceResult {
991 pub contents: Vec<ResourceContents>,
993}
994
995pub type ReadResourceRequest = Request<ReadResourceRequestMethod, ReadResourceRequestParams>;
997
998const_string!(ResourceListChangedNotificationMethod = "notifications/resources/list_changed");
999pub type ResourceListChangedNotification =
1001 NotificationNoParam<ResourceListChangedNotificationMethod>;
1002
1003const_string!(SubscribeRequestMethod = "resources/subscribe");
1004#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1006#[serde(rename_all = "camelCase")]
1007#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1008pub struct SubscribeRequestParams {
1009 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1011 pub meta: Option<Meta>,
1012 pub uri: String,
1014}
1015
1016impl RequestParamsMeta for SubscribeRequestParams {
1017 fn meta(&self) -> Option<&Meta> {
1018 self.meta.as_ref()
1019 }
1020 fn meta_mut(&mut self) -> &mut Option<Meta> {
1021 &mut self.meta
1022 }
1023}
1024
1025#[deprecated(since = "0.13.0", note = "Use SubscribeRequestParams instead")]
1027pub type SubscribeRequestParam = SubscribeRequestParams;
1028
1029pub type SubscribeRequest = Request<SubscribeRequestMethod, SubscribeRequestParams>;
1031
1032const_string!(UnsubscribeRequestMethod = "resources/unsubscribe");
1033#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1035#[serde(rename_all = "camelCase")]
1036#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1037pub struct UnsubscribeRequestParams {
1038 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1040 pub meta: Option<Meta>,
1041 pub uri: String,
1043}
1044
1045impl RequestParamsMeta for UnsubscribeRequestParams {
1046 fn meta(&self) -> Option<&Meta> {
1047 self.meta.as_ref()
1048 }
1049 fn meta_mut(&mut self) -> &mut Option<Meta> {
1050 &mut self.meta
1051 }
1052}
1053
1054#[deprecated(since = "0.13.0", note = "Use UnsubscribeRequestParams instead")]
1056pub type UnsubscribeRequestParam = UnsubscribeRequestParams;
1057
1058pub type UnsubscribeRequest = Request<UnsubscribeRequestMethod, UnsubscribeRequestParams>;
1060
1061const_string!(ResourceUpdatedNotificationMethod = "notifications/resources/updated");
1062#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1064#[serde(rename_all = "camelCase")]
1065#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1066pub struct ResourceUpdatedNotificationParam {
1067 pub uri: String,
1069}
1070pub type ResourceUpdatedNotification =
1072 Notification<ResourceUpdatedNotificationMethod, ResourceUpdatedNotificationParam>;
1073
1074const_string!(ListPromptsRequestMethod = "prompts/list");
1079pub type ListPromptsRequest =
1081 RequestOptionalParam<ListPromptsRequestMethod, PaginatedRequestParams>;
1082
1083paginated_result!(ListPromptsResult {
1084 prompts: Vec<Prompt>
1085});
1086
1087const_string!(GetPromptRequestMethod = "prompts/get");
1088#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1090#[serde(rename_all = "camelCase")]
1091#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1092pub struct GetPromptRequestParams {
1093 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1095 pub meta: Option<Meta>,
1096 pub name: String,
1097 #[serde(skip_serializing_if = "Option::is_none")]
1098 pub arguments: Option<JsonObject>,
1099}
1100
1101impl RequestParamsMeta for GetPromptRequestParams {
1102 fn meta(&self) -> Option<&Meta> {
1103 self.meta.as_ref()
1104 }
1105 fn meta_mut(&mut self) -> &mut Option<Meta> {
1106 &mut self.meta
1107 }
1108}
1109
1110#[deprecated(since = "0.13.0", note = "Use GetPromptRequestParams instead")]
1112pub type GetPromptRequestParam = GetPromptRequestParams;
1113
1114pub type GetPromptRequest = Request<GetPromptRequestMethod, GetPromptRequestParams>;
1116
1117const_string!(PromptListChangedNotificationMethod = "notifications/prompts/list_changed");
1118pub type PromptListChangedNotification = NotificationNoParam<PromptListChangedNotificationMethod>;
1120
1121const_string!(ToolListChangedNotificationMethod = "notifications/tools/list_changed");
1122pub type ToolListChangedNotification = NotificationNoParam<ToolListChangedNotificationMethod>;
1124
1125#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
1131#[serde(rename_all = "lowercase")] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1133pub enum LoggingLevel {
1134 Debug,
1135 Info,
1136 Notice,
1137 Warning,
1138 Error,
1139 Critical,
1140 Alert,
1141 Emergency,
1142}
1143
1144const_string!(SetLevelRequestMethod = "logging/setLevel");
1145#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1147#[serde(rename_all = "camelCase")]
1148#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1149pub struct SetLevelRequestParams {
1150 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1152 pub meta: Option<Meta>,
1153 pub level: LoggingLevel,
1155}
1156
1157impl RequestParamsMeta for SetLevelRequestParams {
1158 fn meta(&self) -> Option<&Meta> {
1159 self.meta.as_ref()
1160 }
1161 fn meta_mut(&mut self) -> &mut Option<Meta> {
1162 &mut self.meta
1163 }
1164}
1165
1166#[deprecated(since = "0.13.0", note = "Use SetLevelRequestParams instead")]
1168pub type SetLevelRequestParam = SetLevelRequestParams;
1169
1170pub type SetLevelRequest = Request<SetLevelRequestMethod, SetLevelRequestParams>;
1172
1173const_string!(LoggingMessageNotificationMethod = "notifications/message");
1174#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1176#[serde(rename_all = "camelCase")]
1177#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1178pub struct LoggingMessageNotificationParam {
1179 pub level: LoggingLevel,
1181 #[serde(skip_serializing_if = "Option::is_none")]
1183 pub logger: Option<String>,
1184 pub data: Value,
1186}
1187pub type LoggingMessageNotification =
1189 Notification<LoggingMessageNotificationMethod, LoggingMessageNotificationParam>;
1190
1191const_string!(CreateMessageRequestMethod = "sampling/createMessage");
1196pub type CreateMessageRequest = Request<CreateMessageRequestMethod, CreateMessageRequestParams>;
1197
1198#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1203#[serde(rename_all = "camelCase")]
1204#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1205pub enum Role {
1206 User,
1208 Assistant,
1210}
1211
1212#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1218#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1219pub struct SamplingMessage {
1220 pub role: Role,
1222 pub content: Content,
1224}
1225
1226#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1231#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1232pub enum ContextInclusion {
1233 #[serde(rename = "allServers")]
1235 AllServers,
1236 #[serde(rename = "none")]
1238 None,
1239 #[serde(rename = "thisServer")]
1241 ThisServer,
1242}
1243
1244#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1253#[serde(rename_all = "camelCase")]
1254#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1255pub struct CreateMessageRequestParams {
1256 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1258 pub meta: Option<Meta>,
1259 #[serde(skip_serializing_if = "Option::is_none")]
1261 pub task: Option<JsonObject>,
1262 pub messages: Vec<SamplingMessage>,
1264 #[serde(skip_serializing_if = "Option::is_none")]
1266 pub model_preferences: Option<ModelPreferences>,
1267 #[serde(skip_serializing_if = "Option::is_none")]
1269 pub system_prompt: Option<String>,
1270 #[serde(skip_serializing_if = "Option::is_none")]
1272 pub include_context: Option<ContextInclusion>,
1273 #[serde(skip_serializing_if = "Option::is_none")]
1275 pub temperature: Option<f32>,
1276 pub max_tokens: u32,
1278 #[serde(skip_serializing_if = "Option::is_none")]
1280 pub stop_sequences: Option<Vec<String>>,
1281 #[serde(skip_serializing_if = "Option::is_none")]
1283 pub metadata: Option<Value>,
1284}
1285
1286impl RequestParamsMeta for CreateMessageRequestParams {
1287 fn meta(&self) -> Option<&Meta> {
1288 self.meta.as_ref()
1289 }
1290 fn meta_mut(&mut self) -> &mut Option<Meta> {
1291 &mut self.meta
1292 }
1293}
1294
1295impl TaskAugmentedRequestParamsMeta for CreateMessageRequestParams {
1296 fn task(&self) -> Option<&JsonObject> {
1297 self.task.as_ref()
1298 }
1299 fn task_mut(&mut self) -> &mut Option<JsonObject> {
1300 &mut self.task
1301 }
1302}
1303
1304#[deprecated(since = "0.13.0", note = "Use CreateMessageRequestParams instead")]
1306pub type CreateMessageRequestParam = CreateMessageRequestParams;
1307
1308#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1314#[serde(rename_all = "camelCase")]
1315#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1316pub struct ModelPreferences {
1317 #[serde(skip_serializing_if = "Option::is_none")]
1319 pub hints: Option<Vec<ModelHint>>,
1320 #[serde(skip_serializing_if = "Option::is_none")]
1322 pub cost_priority: Option<f32>,
1323 #[serde(skip_serializing_if = "Option::is_none")]
1325 pub speed_priority: Option<f32>,
1326 #[serde(skip_serializing_if = "Option::is_none")]
1328 pub intelligence_priority: Option<f32>,
1329}
1330
1331#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1336#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1337pub struct ModelHint {
1338 #[serde(skip_serializing_if = "Option::is_none")]
1340 pub name: Option<String>,
1341}
1342
1343#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
1352#[serde(rename_all = "camelCase")]
1353#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1354pub struct CompletionContext {
1355 #[serde(skip_serializing_if = "Option::is_none")]
1357 pub arguments: Option<std::collections::HashMap<String, String>>,
1358}
1359
1360impl CompletionContext {
1361 pub fn new() -> Self {
1363 Self::default()
1364 }
1365
1366 pub fn with_arguments(arguments: std::collections::HashMap<String, String>) -> Self {
1368 Self {
1369 arguments: Some(arguments),
1370 }
1371 }
1372
1373 pub fn get_argument(&self, name: &str) -> Option<&String> {
1375 self.arguments.as_ref()?.get(name)
1376 }
1377
1378 pub fn has_arguments(&self) -> bool {
1380 self.arguments.as_ref().is_some_and(|args| !args.is_empty())
1381 }
1382
1383 pub fn argument_names(&self) -> impl Iterator<Item = &str> {
1385 self.arguments
1386 .as_ref()
1387 .into_iter()
1388 .flat_map(|args| args.keys())
1389 .map(|k| k.as_str())
1390 }
1391}
1392
1393#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1394#[serde(rename_all = "camelCase")]
1395#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1396pub struct CompleteRequestParams {
1397 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1399 pub meta: Option<Meta>,
1400 pub r#ref: Reference,
1401 pub argument: ArgumentInfo,
1402 #[serde(skip_serializing_if = "Option::is_none")]
1404 pub context: Option<CompletionContext>,
1405}
1406
1407impl RequestParamsMeta for CompleteRequestParams {
1408 fn meta(&self) -> Option<&Meta> {
1409 self.meta.as_ref()
1410 }
1411 fn meta_mut(&mut self) -> &mut Option<Meta> {
1412 &mut self.meta
1413 }
1414}
1415
1416#[deprecated(since = "0.13.0", note = "Use CompleteRequestParams instead")]
1418pub type CompleteRequestParam = CompleteRequestParams;
1419
1420pub type CompleteRequest = Request<CompleteRequestMethod, CompleteRequestParams>;
1421
1422#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
1423#[serde(rename_all = "camelCase")]
1424#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1425pub struct CompletionInfo {
1426 pub values: Vec<String>,
1427 #[serde(skip_serializing_if = "Option::is_none")]
1428 pub total: Option<u32>,
1429 #[serde(skip_serializing_if = "Option::is_none")]
1430 pub has_more: Option<bool>,
1431}
1432
1433impl CompletionInfo {
1434 pub const MAX_VALUES: usize = 100;
1436
1437 pub fn new(values: Vec<String>) -> Result<Self, String> {
1439 if values.len() > Self::MAX_VALUES {
1440 return Err(format!(
1441 "Too many completion values: {} (max: {})",
1442 values.len(),
1443 Self::MAX_VALUES
1444 ));
1445 }
1446 Ok(Self {
1447 values,
1448 total: None,
1449 has_more: None,
1450 })
1451 }
1452
1453 pub fn with_all_values(values: Vec<String>) -> Result<Self, String> {
1455 let completion = Self::new(values)?;
1456 Ok(Self {
1457 total: Some(completion.values.len() as u32),
1458 has_more: Some(false),
1459 ..completion
1460 })
1461 }
1462
1463 pub fn with_pagination(
1465 values: Vec<String>,
1466 total: Option<u32>,
1467 has_more: bool,
1468 ) -> Result<Self, String> {
1469 let completion = Self::new(values)?;
1470 Ok(Self {
1471 total,
1472 has_more: Some(has_more),
1473 ..completion
1474 })
1475 }
1476
1477 pub fn has_more_results(&self) -> bool {
1479 self.has_more.unwrap_or(false)
1480 }
1481
1482 pub fn total_available(&self) -> Option<u32> {
1484 self.total
1485 }
1486
1487 pub fn validate(&self) -> Result<(), String> {
1489 if self.values.len() > Self::MAX_VALUES {
1490 return Err(format!(
1491 "Too many completion values: {} (max: {})",
1492 self.values.len(),
1493 Self::MAX_VALUES
1494 ));
1495 }
1496 Ok(())
1497 }
1498}
1499
1500#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
1501#[serde(rename_all = "camelCase")]
1502#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1503pub struct CompleteResult {
1504 pub completion: CompletionInfo,
1505}
1506
1507#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1508#[serde(tag = "type")]
1509#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1510pub enum Reference {
1511 #[serde(rename = "ref/resource")]
1512 Resource(ResourceReference),
1513 #[serde(rename = "ref/prompt")]
1514 Prompt(PromptReference),
1515}
1516
1517impl Reference {
1518 pub fn for_prompt(name: impl Into<String>) -> Self {
1520 Self::Prompt(PromptReference {
1524 name: name.into(),
1525 title: None,
1526 })
1527 }
1528
1529 pub fn for_resource(uri: impl Into<String>) -> Self {
1531 Self::Resource(ResourceReference { uri: uri.into() })
1532 }
1533
1534 pub fn reference_type(&self) -> &'static str {
1536 match self {
1537 Self::Prompt(_) => "ref/prompt",
1538 Self::Resource(_) => "ref/resource",
1539 }
1540 }
1541
1542 pub fn as_prompt_name(&self) -> Option<&str> {
1544 match self {
1545 Self::Prompt(prompt_ref) => Some(&prompt_ref.name),
1546 _ => None,
1547 }
1548 }
1549
1550 pub fn as_resource_uri(&self) -> Option<&str> {
1552 match self {
1553 Self::Resource(resource_ref) => Some(&resource_ref.uri),
1554 _ => None,
1555 }
1556 }
1557}
1558
1559#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1560#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1561pub struct ResourceReference {
1562 pub uri: String,
1563}
1564
1565#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1566#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1567pub struct PromptReference {
1568 pub name: String,
1569 #[serde(skip_serializing_if = "Option::is_none")]
1570 pub title: Option<String>,
1571}
1572
1573const_string!(CompleteRequestMethod = "completion/complete");
1574#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1575#[serde(rename_all = "camelCase")]
1576#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1577pub struct ArgumentInfo {
1578 pub name: String,
1579 pub value: String,
1580}
1581
1582#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1587#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1588pub struct Root {
1589 pub uri: String,
1590 #[serde(skip_serializing_if = "Option::is_none")]
1591 pub name: Option<String>,
1592}
1593
1594const_string!(ListRootsRequestMethod = "roots/list");
1595pub type ListRootsRequest = RequestNoParam<ListRootsRequestMethod>;
1596
1597#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
1598#[serde(rename_all = "camelCase")]
1599#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1600pub struct ListRootsResult {
1601 pub roots: Vec<Root>,
1602}
1603
1604const_string!(RootsListChangedNotificationMethod = "notifications/roots/list_changed");
1605pub type RootsListChangedNotification = NotificationNoParam<RootsListChangedNotificationMethod>;
1606
1607const_string!(ElicitationCreateRequestMethod = "elicitation/create");
1614const_string!(ElicitationResponseNotificationMethod = "notifications/elicitation/response");
1615
1616#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
1623#[serde(rename_all = "lowercase")]
1624#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1625pub enum ElicitationAction {
1626 Accept,
1628 Decline,
1630 Cancel,
1632}
1633
1634#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1655#[serde(rename_all = "camelCase")]
1656#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1657pub struct CreateElicitationRequestParams {
1658 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1660 pub meta: Option<Meta>,
1661
1662 pub message: String,
1666
1667 pub requested_schema: ElicitationSchema,
1671}
1672
1673impl RequestParamsMeta for CreateElicitationRequestParams {
1674 fn meta(&self) -> Option<&Meta> {
1675 self.meta.as_ref()
1676 }
1677 fn meta_mut(&mut self) -> &mut Option<Meta> {
1678 &mut self.meta
1679 }
1680}
1681
1682#[deprecated(since = "0.13.0", note = "Use CreateElicitationRequestParams instead")]
1684pub type CreateElicitationRequestParam = CreateElicitationRequestParams;
1685
1686#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1691#[serde(rename_all = "camelCase")]
1692#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1693pub struct CreateElicitationResult {
1694 pub action: ElicitationAction,
1696
1697 #[serde(skip_serializing_if = "Option::is_none")]
1701 pub content: Option<Value>,
1702}
1703
1704pub type CreateElicitationRequest =
1706 Request<ElicitationCreateRequestMethod, CreateElicitationRequestParams>;
1707
1708#[derive(Debug, Serialize, Clone, PartialEq)]
1717#[serde(rename_all = "camelCase")]
1718#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1719pub struct CallToolResult {
1720 pub content: Vec<Content>,
1722 #[serde(skip_serializing_if = "Option::is_none")]
1724 pub structured_content: Option<Value>,
1725 #[serde(skip_serializing_if = "Option::is_none")]
1727 pub is_error: Option<bool>,
1728 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1730 pub meta: Option<Meta>,
1731}
1732
1733impl CallToolResult {
1734 pub fn success(content: Vec<Content>) -> Self {
1736 CallToolResult {
1737 content,
1738 structured_content: None,
1739 is_error: Some(false),
1740 meta: None,
1741 }
1742 }
1743 pub fn error(content: Vec<Content>) -> Self {
1745 CallToolResult {
1746 content,
1747 structured_content: None,
1748 is_error: Some(true),
1749 meta: None,
1750 }
1751 }
1752 pub fn structured(value: Value) -> Self {
1767 CallToolResult {
1768 content: vec![Content::text(value.to_string())],
1769 structured_content: Some(value),
1770 is_error: Some(false),
1771 meta: None,
1772 }
1773 }
1774 pub fn structured_error(value: Value) -> Self {
1793 CallToolResult {
1794 content: vec![Content::text(value.to_string())],
1795 structured_content: Some(value),
1796 is_error: Some(true),
1797 meta: None,
1798 }
1799 }
1800
1801 pub fn into_typed<T>(self) -> Result<T, serde_json::Error>
1808 where
1809 T: DeserializeOwned,
1810 {
1811 let raw_text = match (self.structured_content, &self.content.first()) {
1812 (Some(value), _) => return serde_json::from_value(value),
1813 (None, Some(contents)) => {
1814 if let Some(text) = contents.as_text() {
1815 let text = &text.text;
1816 Some(text)
1817 } else {
1818 None
1819 }
1820 }
1821 (None, None) => None,
1822 };
1823 if let Some(text) = raw_text {
1824 return serde_json::from_str(text);
1825 }
1826 serde_json::from_value(serde_json::Value::Null)
1827 }
1828}
1829
1830impl<'de> Deserialize<'de> for CallToolResult {
1832 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1833 where
1834 D: serde::Deserializer<'de>,
1835 {
1836 #[derive(Deserialize)]
1837 #[serde(rename_all = "camelCase")]
1838 struct CallToolResultHelper {
1839 #[serde(skip_serializing_if = "Option::is_none")]
1840 content: Option<Vec<Content>>,
1841 #[serde(skip_serializing_if = "Option::is_none")]
1842 structured_content: Option<Value>,
1843 #[serde(skip_serializing_if = "Option::is_none")]
1844 is_error: Option<bool>,
1845 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1847 meta: Option<Meta>,
1848 }
1849
1850 let helper = CallToolResultHelper::deserialize(deserializer)?;
1851 let result = CallToolResult {
1852 content: helper.content.unwrap_or_default(),
1853 structured_content: helper.structured_content,
1854 is_error: helper.is_error,
1855 meta: helper.meta,
1856 };
1857
1858 if result.content.is_empty() && result.structured_content.is_none() {
1860 return Err(serde::de::Error::custom(
1861 "CallToolResult must have either content or structured_content",
1862 ));
1863 }
1864
1865 Ok(result)
1866 }
1867}
1868
1869const_string!(ListToolsRequestMethod = "tools/list");
1870pub type ListToolsRequest = RequestOptionalParam<ListToolsRequestMethod, PaginatedRequestParams>;
1872
1873paginated_result!(
1874 ListToolsResult {
1875 tools: Vec<Tool>
1876 }
1877);
1878
1879const_string!(CallToolRequestMethod = "tools/call");
1880#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1888#[serde(rename_all = "camelCase")]
1889#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1890pub struct CallToolRequestParams {
1891 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1893 pub meta: Option<Meta>,
1894 pub name: Cow<'static, str>,
1896 #[serde(skip_serializing_if = "Option::is_none")]
1898 pub arguments: Option<JsonObject>,
1899 #[serde(skip_serializing_if = "Option::is_none")]
1901 pub task: Option<JsonObject>,
1902}
1903
1904impl RequestParamsMeta for CallToolRequestParams {
1905 fn meta(&self) -> Option<&Meta> {
1906 self.meta.as_ref()
1907 }
1908 fn meta_mut(&mut self) -> &mut Option<Meta> {
1909 &mut self.meta
1910 }
1911}
1912
1913impl TaskAugmentedRequestParamsMeta for CallToolRequestParams {
1914 fn task(&self) -> Option<&JsonObject> {
1915 self.task.as_ref()
1916 }
1917 fn task_mut(&mut self) -> &mut Option<JsonObject> {
1918 &mut self.task
1919 }
1920}
1921
1922#[deprecated(since = "0.13.0", note = "Use CallToolRequestParams instead")]
1924pub type CallToolRequestParam = CallToolRequestParams;
1925
1926pub type CallToolRequest = Request<CallToolRequestMethod, CallToolRequestParams>;
1928
1929#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1934#[serde(rename_all = "camelCase")]
1935#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1936pub struct CreateMessageResult {
1937 pub model: String,
1939 #[serde(skip_serializing_if = "Option::is_none")]
1941 pub stop_reason: Option<String>,
1942 #[serde(flatten)]
1944 pub message: SamplingMessage,
1945}
1946
1947impl CreateMessageResult {
1948 pub const STOP_REASON_END_TURN: &str = "endTurn";
1949 pub const STOP_REASON_END_SEQUENCE: &str = "stopSequence";
1950 pub const STOP_REASON_END_MAX_TOKEN: &str = "maxTokens";
1951}
1952
1953#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1954#[serde(rename_all = "camelCase")]
1955#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1956pub struct GetPromptResult {
1957 #[serde(skip_serializing_if = "Option::is_none")]
1958 pub description: Option<String>,
1959 pub messages: Vec<PromptMessage>,
1960}
1961
1962const_string!(GetTaskInfoMethod = "tasks/get");
1967pub type GetTaskInfoRequest = Request<GetTaskInfoMethod, GetTaskInfoParams>;
1968
1969#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1970#[serde(rename_all = "camelCase")]
1971#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1972pub struct GetTaskInfoParams {
1973 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1975 pub meta: Option<Meta>,
1976 pub task_id: String,
1977}
1978
1979impl RequestParamsMeta for GetTaskInfoParams {
1980 fn meta(&self) -> Option<&Meta> {
1981 self.meta.as_ref()
1982 }
1983 fn meta_mut(&mut self) -> &mut Option<Meta> {
1984 &mut self.meta
1985 }
1986}
1987
1988#[deprecated(since = "0.13.0", note = "Use GetTaskInfoParams instead")]
1990pub type GetTaskInfoParam = GetTaskInfoParams;
1991
1992const_string!(ListTasksMethod = "tasks/list");
1993pub type ListTasksRequest = RequestOptionalParam<ListTasksMethod, PaginatedRequestParams>;
1994
1995const_string!(GetTaskResultMethod = "tasks/result");
1996pub type GetTaskResultRequest = Request<GetTaskResultMethod, GetTaskResultParams>;
1997
1998#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1999#[serde(rename_all = "camelCase")]
2000#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2001pub struct GetTaskResultParams {
2002 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
2004 pub meta: Option<Meta>,
2005 pub task_id: String,
2006}
2007
2008impl RequestParamsMeta for GetTaskResultParams {
2009 fn meta(&self) -> Option<&Meta> {
2010 self.meta.as_ref()
2011 }
2012 fn meta_mut(&mut self) -> &mut Option<Meta> {
2013 &mut self.meta
2014 }
2015}
2016
2017#[deprecated(since = "0.13.0", note = "Use GetTaskResultParams instead")]
2019pub type GetTaskResultParam = GetTaskResultParams;
2020
2021const_string!(CancelTaskMethod = "tasks/cancel");
2022pub type CancelTaskRequest = Request<CancelTaskMethod, CancelTaskParams>;
2023
2024#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2025#[serde(rename_all = "camelCase")]
2026#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2027pub struct CancelTaskParams {
2028 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
2030 pub meta: Option<Meta>,
2031 pub task_id: String,
2032}
2033
2034impl RequestParamsMeta for CancelTaskParams {
2035 fn meta(&self) -> Option<&Meta> {
2036 self.meta.as_ref()
2037 }
2038 fn meta_mut(&mut self) -> &mut Option<Meta> {
2039 &mut self.meta
2040 }
2041}
2042
2043#[deprecated(since = "0.13.0", note = "Use CancelTaskParams instead")]
2045pub type CancelTaskParam = CancelTaskParams;
2046#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2047#[serde(rename_all = "camelCase")]
2048#[serde(deny_unknown_fields)]
2049#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2050pub struct GetTaskInfoResult {
2051 #[serde(skip_serializing_if = "Option::is_none")]
2052 pub task: Option<crate::model::Task>,
2053}
2054
2055#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
2056#[serde(rename_all = "camelCase")]
2057#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2058pub struct ListTasksResult {
2059 pub tasks: Vec<crate::model::Task>,
2060 #[serde(skip_serializing_if = "Option::is_none")]
2061 pub next_cursor: Option<String>,
2062 #[serde(skip_serializing_if = "Option::is_none")]
2063 pub total: Option<u64>,
2064}
2065
2066macro_rules! ts_union {
2071 (
2072 export type $U:ident =
2073 $($rest:tt)*
2074 ) => {
2075 ts_union!(@declare $U { $($rest)* });
2076 ts_union!(@impl_from $U { $($rest)* });
2077 };
2078 (@declare $U:ident { $($variant:tt)* }) => {
2079 ts_union!(@declare_variant $U { } {$($variant)*} );
2080 };
2081 (@declare_variant $U:ident { $($declared:tt)* } {$(|)? box $V:ident $($rest:tt)*}) => {
2082 ts_union!(@declare_variant $U { $($declared)* $V(Box<$V>), } {$($rest)*});
2083 };
2084 (@declare_variant $U:ident { $($declared:tt)* } {$(|)? $V:ident $($rest:tt)*}) => {
2085 ts_union!(@declare_variant $U { $($declared)* $V($V), } {$($rest)*});
2086 };
2087 (@declare_variant $U:ident { $($declared:tt)* } { ; }) => {
2088 ts_union!(@declare_end $U { $($declared)* } );
2089 };
2090 (@declare_end $U:ident { $($declared:tt)* }) => {
2091 #[derive(Debug, Serialize, Deserialize, Clone)]
2092 #[serde(untagged)]
2093 #[allow(clippy::large_enum_variant)]
2094 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2095 pub enum $U {
2096 $($declared)*
2097 }
2098 };
2099 (@impl_from $U: ident {$(|)? box $V:ident $($rest:tt)*}) => {
2100 impl From<$V> for $U {
2101 fn from(value: $V) -> Self {
2102 $U::$V(Box::new(value))
2103 }
2104 }
2105 ts_union!(@impl_from $U {$($rest)*});
2106 };
2107 (@impl_from $U: ident {$(|)? $V:ident $($rest:tt)*}) => {
2108 impl From<$V> for $U {
2109 fn from(value: $V) -> Self {
2110 $U::$V(value)
2111 }
2112 }
2113 ts_union!(@impl_from $U {$($rest)*});
2114 };
2115 (@impl_from $U: ident { ; }) => {};
2116 (@impl_from $U: ident { }) => {};
2117}
2118
2119ts_union!(
2120 export type ClientRequest =
2121 | PingRequest
2122 | InitializeRequest
2123 | CompleteRequest
2124 | SetLevelRequest
2125 | GetPromptRequest
2126 | ListPromptsRequest
2127 | ListResourcesRequest
2128 | ListResourceTemplatesRequest
2129 | ReadResourceRequest
2130 | SubscribeRequest
2131 | UnsubscribeRequest
2132 | CallToolRequest
2133 | ListToolsRequest
2134 | GetTaskInfoRequest
2135 | ListTasksRequest
2136 | GetTaskResultRequest
2137 | CancelTaskRequest
2138 | CustomRequest;
2139);
2140
2141impl ClientRequest {
2142 pub fn method(&self) -> &str {
2143 match &self {
2144 ClientRequest::PingRequest(r) => r.method.as_str(),
2145 ClientRequest::InitializeRequest(r) => r.method.as_str(),
2146 ClientRequest::CompleteRequest(r) => r.method.as_str(),
2147 ClientRequest::SetLevelRequest(r) => r.method.as_str(),
2148 ClientRequest::GetPromptRequest(r) => r.method.as_str(),
2149 ClientRequest::ListPromptsRequest(r) => r.method.as_str(),
2150 ClientRequest::ListResourcesRequest(r) => r.method.as_str(),
2151 ClientRequest::ListResourceTemplatesRequest(r) => r.method.as_str(),
2152 ClientRequest::ReadResourceRequest(r) => r.method.as_str(),
2153 ClientRequest::SubscribeRequest(r) => r.method.as_str(),
2154 ClientRequest::UnsubscribeRequest(r) => r.method.as_str(),
2155 ClientRequest::CallToolRequest(r) => r.method.as_str(),
2156 ClientRequest::ListToolsRequest(r) => r.method.as_str(),
2157 ClientRequest::GetTaskInfoRequest(r) => r.method.as_str(),
2158 ClientRequest::ListTasksRequest(r) => r.method.as_str(),
2159 ClientRequest::GetTaskResultRequest(r) => r.method.as_str(),
2160 ClientRequest::CancelTaskRequest(r) => r.method.as_str(),
2161 ClientRequest::CustomRequest(r) => r.method.as_str(),
2162 }
2163 }
2164}
2165
2166ts_union!(
2167 export type ClientNotification =
2168 | CancelledNotification
2169 | ProgressNotification
2170 | InitializedNotification
2171 | RootsListChangedNotification
2172 | CustomNotification;
2173);
2174
2175ts_union!(
2176 export type ClientResult =
2177 box CreateMessageResult
2178 | ListRootsResult
2179 | CreateElicitationResult
2180 | EmptyResult
2181 | CustomResult;
2182);
2183
2184impl ClientResult {
2185 pub fn empty(_: ()) -> ClientResult {
2186 ClientResult::EmptyResult(EmptyResult {})
2187 }
2188}
2189
2190pub type ClientJsonRpcMessage = JsonRpcMessage<ClientRequest, ClientResult, ClientNotification>;
2191
2192ts_union!(
2193 export type ServerRequest =
2194 | PingRequest
2195 | CreateMessageRequest
2196 | ListRootsRequest
2197 | CreateElicitationRequest
2198 | CustomRequest;
2199);
2200
2201ts_union!(
2202 export type ServerNotification =
2203 | CancelledNotification
2204 | ProgressNotification
2205 | LoggingMessageNotification
2206 | ResourceUpdatedNotification
2207 | ResourceListChangedNotification
2208 | ToolListChangedNotification
2209 | PromptListChangedNotification
2210 | CustomNotification;
2211);
2212
2213ts_union!(
2214 export type ServerResult =
2215 | InitializeResult
2216 | CompleteResult
2217 | GetPromptResult
2218 | ListPromptsResult
2219 | ListResourcesResult
2220 | ListResourceTemplatesResult
2221 | ReadResourceResult
2222 | CallToolResult
2223 | ListToolsResult
2224 | CreateElicitationResult
2225 | EmptyResult
2226 | CreateTaskResult
2227 | ListTasksResult
2228 | GetTaskInfoResult
2229 | TaskResult
2230 | CustomResult
2231 ;
2232);
2233
2234impl ServerResult {
2235 pub fn empty(_: ()) -> ServerResult {
2236 ServerResult::EmptyResult(EmptyResult {})
2237 }
2238}
2239
2240pub type ServerJsonRpcMessage = JsonRpcMessage<ServerRequest, ServerResult, ServerNotification>;
2241
2242impl TryInto<CancelledNotification> for ServerNotification {
2243 type Error = ServerNotification;
2244 fn try_into(self) -> Result<CancelledNotification, Self::Error> {
2245 if let ServerNotification::CancelledNotification(t) = self {
2246 Ok(t)
2247 } else {
2248 Err(self)
2249 }
2250 }
2251}
2252
2253impl TryInto<CancelledNotification> for ClientNotification {
2254 type Error = ClientNotification;
2255 fn try_into(self) -> Result<CancelledNotification, Self::Error> {
2256 if let ClientNotification::CancelledNotification(t) = self {
2257 Ok(t)
2258 } else {
2259 Err(self)
2260 }
2261 }
2262}
2263
2264#[cfg(test)]
2269mod tests {
2270 use serde_json::json;
2271
2272 use super::*;
2273
2274 #[test]
2275 fn test_notification_serde() {
2276 let raw = json!( {
2277 "jsonrpc": JsonRpcVersion2_0,
2278 "method": InitializedNotificationMethod,
2279 });
2280 let message: ClientJsonRpcMessage =
2281 serde_json::from_value(raw.clone()).expect("invalid notification");
2282 match &message {
2283 ClientJsonRpcMessage::Notification(JsonRpcNotification {
2284 notification: ClientNotification::InitializedNotification(_n),
2285 ..
2286 }) => {}
2287 _ => panic!("Expected Notification"),
2288 }
2289 let json = serde_json::to_value(message).expect("valid json");
2290 assert_eq!(json, raw);
2291 }
2292
2293 #[test]
2294 fn test_custom_client_notification_roundtrip() {
2295 let raw = json!( {
2296 "jsonrpc": JsonRpcVersion2_0,
2297 "method": "notifications/custom",
2298 "params": {"foo": "bar"},
2299 });
2300
2301 let message: ClientJsonRpcMessage =
2302 serde_json::from_value(raw.clone()).expect("invalid notification");
2303 match &message {
2304 ClientJsonRpcMessage::Notification(JsonRpcNotification {
2305 notification: ClientNotification::CustomNotification(notification),
2306 ..
2307 }) => {
2308 assert_eq!(notification.method, "notifications/custom");
2309 assert_eq!(
2310 notification
2311 .params
2312 .as_ref()
2313 .and_then(|p| p.get("foo"))
2314 .expect("foo present"),
2315 "bar"
2316 );
2317 }
2318 _ => panic!("Expected custom client notification"),
2319 }
2320
2321 let json = serde_json::to_value(message).expect("valid json");
2322 assert_eq!(json, raw);
2323 }
2324
2325 #[test]
2326 fn test_custom_server_notification_roundtrip() {
2327 let raw = json!( {
2328 "jsonrpc": JsonRpcVersion2_0,
2329 "method": "notifications/custom-server",
2330 "params": {"hello": "world"},
2331 });
2332
2333 let message: ServerJsonRpcMessage =
2334 serde_json::from_value(raw.clone()).expect("invalid notification");
2335 match &message {
2336 ServerJsonRpcMessage::Notification(JsonRpcNotification {
2337 notification: ServerNotification::CustomNotification(notification),
2338 ..
2339 }) => {
2340 assert_eq!(notification.method, "notifications/custom-server");
2341 assert_eq!(
2342 notification
2343 .params
2344 .as_ref()
2345 .and_then(|p| p.get("hello"))
2346 .expect("hello present"),
2347 "world"
2348 );
2349 }
2350 _ => panic!("Expected custom server notification"),
2351 }
2352
2353 let json = serde_json::to_value(message).expect("valid json");
2354 assert_eq!(json, raw);
2355 }
2356
2357 #[test]
2358 fn test_custom_request_roundtrip() {
2359 let raw = json!( {
2360 "jsonrpc": JsonRpcVersion2_0,
2361 "id": 42,
2362 "method": "requests/custom",
2363 "params": {"foo": "bar"},
2364 });
2365
2366 let message: ClientJsonRpcMessage =
2367 serde_json::from_value(raw.clone()).expect("invalid request");
2368 match &message {
2369 ClientJsonRpcMessage::Request(JsonRpcRequest { id, request, .. }) => {
2370 assert_eq!(id, &RequestId::Number(42));
2371 match request {
2372 ClientRequest::CustomRequest(custom) => {
2373 let expected_request = json!({
2374 "method": "requests/custom",
2375 "params": {"foo": "bar"},
2376 });
2377 let actual_request =
2378 serde_json::to_value(custom).expect("serialize custom request");
2379 assert_eq!(actual_request, expected_request);
2380 }
2381 other => panic!("Expected custom request, got: {other:?}"),
2382 }
2383 }
2384 other => panic!("Expected request, got: {other:?}"),
2385 }
2386
2387 let json = serde_json::to_value(message).expect("valid json");
2388 assert_eq!(json, raw);
2389 }
2390
2391 #[test]
2392 fn test_request_conversion() {
2393 let raw = json!( {
2394 "jsonrpc": JsonRpcVersion2_0,
2395 "id": 1,
2396 "method": "request",
2397 "params": {"key": "value"},
2398 });
2399 let message: JsonRpcMessage = serde_json::from_value(raw.clone()).expect("invalid request");
2400
2401 match &message {
2402 JsonRpcMessage::Request(r) => {
2403 assert_eq!(r.id, RequestId::Number(1));
2404 assert_eq!(r.request.method, "request");
2405 assert_eq!(
2406 &r.request.params,
2407 json!({"key": "value"})
2408 .as_object()
2409 .expect("should be an object")
2410 );
2411 }
2412 _ => panic!("Expected Request"),
2413 }
2414 let json = serde_json::to_value(&message).expect("valid json");
2415 assert_eq!(json, raw);
2416 }
2417
2418 #[test]
2419 fn test_initial_request_response_serde() {
2420 let request = json!({
2421 "jsonrpc": "2.0",
2422 "id": 1,
2423 "method": "initialize",
2424 "params": {
2425 "protocolVersion": "2024-11-05",
2426 "capabilities": {
2427 "roots": {
2428 "listChanged": true
2429 },
2430 "sampling": {}
2431 },
2432 "clientInfo": {
2433 "name": "ExampleClient",
2434 "version": "1.0.0"
2435 }
2436 }
2437 });
2438 let raw_response_json = json!({
2439 "jsonrpc": "2.0",
2440 "id": 1,
2441 "result": {
2442 "protocolVersion": "2024-11-05",
2443 "capabilities": {
2444 "logging": {},
2445 "prompts": {
2446 "listChanged": true
2447 },
2448 "resources": {
2449 "subscribe": true,
2450 "listChanged": true
2451 },
2452 "tools": {
2453 "listChanged": true
2454 }
2455 },
2456 "serverInfo": {
2457 "name": "ExampleServer",
2458 "version": "1.0.0"
2459 }
2460 }
2461 });
2462 let request: ClientJsonRpcMessage =
2463 serde_json::from_value(request.clone()).expect("invalid request");
2464 let (request, id) = request.into_request().expect("should be a request");
2465 assert_eq!(id, RequestId::Number(1));
2466 #[allow(deprecated)]
2467 match request {
2468 ClientRequest::InitializeRequest(Request {
2469 method: _,
2470 params:
2471 InitializeRequestParam {
2472 meta: _,
2473 protocol_version: _,
2474 capabilities,
2475 client_info,
2476 },
2477 ..
2478 }) => {
2479 assert_eq!(capabilities.roots.unwrap().list_changed, Some(true));
2480 assert_eq!(capabilities.sampling.unwrap().len(), 0);
2481 assert_eq!(client_info.name, "ExampleClient");
2482 assert_eq!(client_info.version, "1.0.0");
2483 }
2484 _ => panic!("Expected InitializeRequest"),
2485 }
2486 let server_response: ServerJsonRpcMessage =
2487 serde_json::from_value(raw_response_json.clone()).expect("invalid response");
2488 let (response, id) = server_response
2489 .clone()
2490 .into_response()
2491 .expect("expect response");
2492 assert_eq!(id, RequestId::Number(1));
2493 match response {
2494 ServerResult::InitializeResult(InitializeResult {
2495 protocol_version: _,
2496 capabilities,
2497 server_info,
2498 instructions,
2499 }) => {
2500 assert_eq!(capabilities.logging.unwrap().len(), 0);
2501 assert_eq!(capabilities.prompts.unwrap().list_changed, Some(true));
2502 assert_eq!(
2503 capabilities.resources.as_ref().unwrap().subscribe,
2504 Some(true)
2505 );
2506 assert_eq!(capabilities.resources.unwrap().list_changed, Some(true));
2507 assert_eq!(capabilities.tools.unwrap().list_changed, Some(true));
2508 assert_eq!(server_info.name, "ExampleServer");
2509 assert_eq!(server_info.version, "1.0.0");
2510 assert_eq!(server_info.icons, None);
2511 assert_eq!(instructions, None);
2512 }
2513 other => panic!("Expected InitializeResult, got {other:?}"),
2514 }
2515
2516 let server_response_json: Value = serde_json::to_value(&server_response).expect("msg");
2517
2518 assert_eq!(server_response_json, raw_response_json);
2519 }
2520
2521 #[test]
2522 fn test_negative_and_large_request_ids() {
2523 let negative_id_json = json!({
2525 "jsonrpc": "2.0",
2526 "id": -1,
2527 "method": "test",
2528 "params": {}
2529 });
2530
2531 let message: JsonRpcMessage =
2532 serde_json::from_value(negative_id_json.clone()).expect("Should parse negative ID");
2533
2534 match &message {
2535 JsonRpcMessage::Request(r) => {
2536 assert_eq!(r.id, RequestId::Number(-1));
2537 }
2538 _ => panic!("Expected Request"),
2539 }
2540
2541 let serialized = serde_json::to_value(&message).expect("Should serialize");
2543 assert_eq!(serialized, negative_id_json);
2544
2545 let large_negative_json = json!({
2547 "jsonrpc": "2.0",
2548 "id": -9007199254740991i64, "method": "test",
2550 "params": {}
2551 });
2552
2553 let message: JsonRpcMessage = serde_json::from_value(large_negative_json.clone())
2554 .expect("Should parse large negative ID");
2555
2556 match &message {
2557 JsonRpcMessage::Request(r) => {
2558 assert_eq!(r.id, RequestId::Number(-9007199254740991i64));
2559 }
2560 _ => panic!("Expected Request"),
2561 }
2562
2563 let large_positive_json = json!({
2565 "jsonrpc": "2.0",
2566 "id": 9007199254740991i64,
2567 "method": "test",
2568 "params": {}
2569 });
2570
2571 let message: JsonRpcMessage = serde_json::from_value(large_positive_json.clone())
2572 .expect("Should parse large positive ID");
2573
2574 match &message {
2575 JsonRpcMessage::Request(r) => {
2576 assert_eq!(r.id, RequestId::Number(9007199254740991i64));
2577 }
2578 _ => panic!("Expected Request"),
2579 }
2580
2581 let zero_id_json = json!({
2583 "jsonrpc": "2.0",
2584 "id": 0,
2585 "method": "test",
2586 "params": {}
2587 });
2588
2589 let message: JsonRpcMessage =
2590 serde_json::from_value(zero_id_json.clone()).expect("Should parse zero ID");
2591
2592 match &message {
2593 JsonRpcMessage::Request(r) => {
2594 assert_eq!(r.id, RequestId::Number(0));
2595 }
2596 _ => panic!("Expected Request"),
2597 }
2598 }
2599
2600 #[test]
2601 fn test_protocol_version_order() {
2602 let v1 = ProtocolVersion::V_2024_11_05;
2603 let v2 = ProtocolVersion::V_2025_03_26;
2604 assert!(v1 < v2);
2605 }
2606
2607 #[test]
2608 fn test_icon_serialization() {
2609 let icon = Icon {
2610 src: "https://example.com/icon.png".to_string(),
2611 mime_type: Some("image/png".to_string()),
2612 sizes: Some(vec!["48x48".to_string()]),
2613 };
2614
2615 let json = serde_json::to_value(&icon).unwrap();
2616 assert_eq!(json["src"], "https://example.com/icon.png");
2617 assert_eq!(json["mimeType"], "image/png");
2618 assert_eq!(json["sizes"][0], "48x48");
2619
2620 let deserialized: Icon = serde_json::from_value(json).unwrap();
2622 assert_eq!(deserialized, icon);
2623 }
2624
2625 #[test]
2626 fn test_icon_minimal() {
2627 let icon = Icon {
2628 src: "data:image/svg+xml;base64,PHN2Zy8+".to_string(),
2629 mime_type: None,
2630 sizes: None,
2631 };
2632
2633 let json = serde_json::to_value(&icon).unwrap();
2634 assert_eq!(json["src"], "data:image/svg+xml;base64,PHN2Zy8+");
2635 assert!(json.get("mimeType").is_none());
2636 assert!(json.get("sizes").is_none());
2637 }
2638
2639 #[test]
2640 fn test_implementation_with_icons() {
2641 let implementation = Implementation {
2642 name: "test-server".to_string(),
2643 title: Some("Test Server".to_string()),
2644 version: "1.0.0".to_string(),
2645 icons: Some(vec![
2646 Icon {
2647 src: "https://example.com/icon.png".to_string(),
2648 mime_type: Some("image/png".to_string()),
2649 sizes: Some(vec!["48x48".to_string()]),
2650 },
2651 Icon {
2652 src: "https://example.com/icon.svg".to_string(),
2653 mime_type: Some("image/svg+xml".to_string()),
2654 sizes: Some(vec!["any".to_string()]),
2655 },
2656 ]),
2657 website_url: Some("https://example.com".to_string()),
2658 };
2659
2660 let json = serde_json::to_value(&implementation).unwrap();
2661 assert_eq!(json["name"], "test-server");
2662 assert_eq!(json["websiteUrl"], "https://example.com");
2663 assert!(json["icons"].is_array());
2664 assert_eq!(json["icons"][0]["src"], "https://example.com/icon.png");
2665 assert_eq!(json["icons"][0]["sizes"][0], "48x48");
2666 assert_eq!(json["icons"][1]["mimeType"], "image/svg+xml");
2667 assert_eq!(json["icons"][1]["sizes"][0], "any");
2668 }
2669
2670 #[test]
2671 fn test_backward_compatibility() {
2672 let old_json = json!({
2674 "name": "legacy-server",
2675 "version": "0.9.0"
2676 });
2677
2678 let implementation: Implementation = serde_json::from_value(old_json).unwrap();
2679 assert_eq!(implementation.name, "legacy-server");
2680 assert_eq!(implementation.version, "0.9.0");
2681 assert_eq!(implementation.icons, None);
2682 assert_eq!(implementation.website_url, None);
2683 }
2684
2685 #[test]
2686 fn test_initialize_with_icons() {
2687 let init_result = InitializeResult {
2688 protocol_version: ProtocolVersion::default(),
2689 capabilities: ServerCapabilities::default(),
2690 server_info: Implementation {
2691 name: "icon-server".to_string(),
2692 title: None,
2693 version: "2.0.0".to_string(),
2694 icons: Some(vec![Icon {
2695 src: "https://example.com/server.png".to_string(),
2696 mime_type: Some("image/png".to_string()),
2697 sizes: Some(vec!["48x48".to_string()]),
2698 }]),
2699 website_url: Some("https://docs.example.com".to_string()),
2700 },
2701 instructions: None,
2702 };
2703
2704 let json = serde_json::to_value(&init_result).unwrap();
2705 assert!(json["serverInfo"]["icons"].is_array());
2706 assert_eq!(
2707 json["serverInfo"]["icons"][0]["src"],
2708 "https://example.com/server.png"
2709 );
2710 assert_eq!(json["serverInfo"]["icons"][0]["sizes"][0], "48x48");
2711 assert_eq!(json["serverInfo"]["websiteUrl"], "https://docs.example.com");
2712 }
2713}