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 tool;
12pub use annotated::*;
13pub use capabilities::*;
14pub use content::*;
15pub use elicitation_schema::*;
16pub use extension::*;
17pub use meta::*;
18pub use prompt::*;
19pub use resource::*;
20use serde::{Deserialize, Serialize, de::DeserializeOwned};
21use serde_json::Value;
22pub use tool::*;
23
24pub type JsonObject<F = Value> = serde_json::Map<String, F>;
29
30pub fn object(value: serde_json::Value) -> JsonObject {
35 debug_assert!(value.is_object());
36 match value {
37 serde_json::Value::Object(map) => map,
38 _ => JsonObject::default(),
39 }
40}
41
42#[cfg(feature = "macros")]
44#[cfg_attr(docsrs, doc(cfg(feature = "macros")))]
45#[macro_export]
46macro_rules! object {
47 ({$($tt:tt)*}) => {
48 $crate::model::object(serde_json::json! {
49 {$($tt)*}
50 })
51 };
52}
53
54#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy, Eq)]
58#[cfg_attr(feature = "server", derive(schemars::JsonSchema))]
59pub struct EmptyObject {}
60
61pub trait ConstString: Default {
62 const VALUE: &str;
63 fn as_str(&self) -> &'static str {
64 Self::VALUE
65 }
66}
67#[macro_export]
68macro_rules! const_string {
69 ($name:ident = $value:literal) => {
70 #[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
71 pub struct $name;
72
73 impl ConstString for $name {
74 const VALUE: &str = $value;
75 }
76
77 impl serde::Serialize for $name {
78 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
79 where
80 S: serde::Serializer,
81 {
82 $value.serialize(serializer)
83 }
84 }
85
86 impl<'de> serde::Deserialize<'de> for $name {
87 fn deserialize<D>(deserializer: D) -> Result<$name, D::Error>
88 where
89 D: serde::Deserializer<'de>,
90 {
91 let s: String = serde::Deserialize::deserialize(deserializer)?;
92 if s == $value {
93 Ok($name)
94 } else {
95 Err(serde::de::Error::custom(format!(concat!(
96 "expect const string value \"",
97 $value,
98 "\""
99 ))))
100 }
101 }
102 }
103
104 #[cfg(feature = "schemars")]
105 impl schemars::JsonSchema for $name {
106 fn schema_name() -> Cow<'static, str> {
107 Cow::Borrowed(stringify!($name))
108 }
109
110 fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
111 use serde_json::{Map, json};
112
113 let mut schema_map = Map::new();
114 schema_map.insert("type".to_string(), json!("string"));
115 schema_map.insert("format".to_string(), json!("const"));
116 schema_map.insert("const".to_string(), json!($value));
117
118 schemars::Schema::from(schema_map)
119 }
120 }
121 };
122}
123
124const_string!(JsonRpcVersion2_0 = "2.0");
125
126#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd)]
135#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
136pub struct ProtocolVersion(Cow<'static, str>);
137
138impl Default for ProtocolVersion {
139 fn default() -> Self {
140 Self::LATEST
141 }
142}
143
144impl std::fmt::Display for ProtocolVersion {
145 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
146 self.0.fmt(f)
147 }
148}
149
150impl ProtocolVersion {
151 pub const V_2025_06_18: Self = Self(Cow::Borrowed("2025-06-18"));
152 pub const V_2025_03_26: Self = Self(Cow::Borrowed("2025-03-26"));
153 pub const V_2024_11_05: Self = Self(Cow::Borrowed("2024-11-05"));
154 pub const LATEST: Self = Self::V_2025_03_26;
156}
157
158impl Serialize for ProtocolVersion {
159 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
160 where
161 S: serde::Serializer,
162 {
163 self.0.serialize(serializer)
164 }
165}
166
167impl<'de> Deserialize<'de> for ProtocolVersion {
168 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
169 where
170 D: serde::Deserializer<'de>,
171 {
172 let s: String = Deserialize::deserialize(deserializer)?;
173 #[allow(clippy::single_match)]
174 match s.as_str() {
175 "2024-11-05" => return Ok(ProtocolVersion::V_2024_11_05),
176 "2025-03-26" => return Ok(ProtocolVersion::V_2025_03_26),
177 "2025-06-18" => return Ok(ProtocolVersion::V_2025_06_18),
178 _ => {}
179 }
180 Ok(ProtocolVersion(Cow::Owned(s)))
181 }
182}
183
184#[derive(Debug, Clone, Eq, PartialEq, Hash)]
189pub enum NumberOrString {
190 Number(i64),
192 String(Arc<str>),
194}
195
196impl NumberOrString {
197 pub fn into_json_value(self) -> Value {
198 match self {
199 NumberOrString::Number(n) => Value::Number(serde_json::Number::from(n)),
200 NumberOrString::String(s) => Value::String(s.to_string()),
201 }
202 }
203}
204
205impl std::fmt::Display for NumberOrString {
206 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
207 match self {
208 NumberOrString::Number(n) => n.fmt(f),
209 NumberOrString::String(s) => s.fmt(f),
210 }
211 }
212}
213
214impl Serialize for NumberOrString {
215 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
216 where
217 S: serde::Serializer,
218 {
219 match self {
220 NumberOrString::Number(n) => n.serialize(serializer),
221 NumberOrString::String(s) => s.serialize(serializer),
222 }
223 }
224}
225
226impl<'de> Deserialize<'de> for NumberOrString {
227 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
228 where
229 D: serde::Deserializer<'de>,
230 {
231 let value: Value = Deserialize::deserialize(deserializer)?;
232 match value {
233 Value::Number(n) => {
234 if let Some(i) = n.as_i64() {
235 Ok(NumberOrString::Number(i))
236 } else if let Some(u) = n.as_u64() {
237 if u <= i64::MAX as u64 {
239 Ok(NumberOrString::Number(u as i64))
240 } else {
241 Err(serde::de::Error::custom("Number too large for i64"))
242 }
243 } else {
244 Err(serde::de::Error::custom("Expected an integer"))
245 }
246 }
247 Value::String(s) => Ok(NumberOrString::String(s.into())),
248 _ => Err(serde::de::Error::custom("Expect number or string")),
249 }
250 }
251}
252
253#[cfg(feature = "schemars")]
254impl schemars::JsonSchema for NumberOrString {
255 fn schema_name() -> Cow<'static, str> {
256 Cow::Borrowed("NumberOrString")
257 }
258
259 fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
260 use serde_json::{Map, json};
261
262 let mut number_schema = Map::new();
263 number_schema.insert("type".to_string(), json!("number"));
264
265 let mut string_schema = Map::new();
266 string_schema.insert("type".to_string(), json!("string"));
267
268 let mut schema_map = Map::new();
269 schema_map.insert("oneOf".to_string(), json!([number_schema, string_schema]));
270
271 schemars::Schema::from(schema_map)
272 }
273}
274
275pub type RequestId = NumberOrString;
277
278#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Hash, Eq)]
283#[serde(transparent)]
284#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
285pub struct ProgressToken(pub NumberOrString);
286
287#[derive(Debug, Clone, Default)]
298#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
299pub struct Request<M = String, P = JsonObject> {
300 pub method: M,
301 pub params: P,
302 #[cfg_attr(feature = "schemars", schemars(skip))]
306 pub extensions: Extensions,
307}
308
309impl<M: Default, P> Request<M, P> {
310 pub fn new(params: P) -> Self {
311 Self {
312 method: Default::default(),
313 params,
314 extensions: Extensions::default(),
315 }
316 }
317}
318
319impl<M, P> GetExtensions for Request<M, P> {
320 fn extensions(&self) -> &Extensions {
321 &self.extensions
322 }
323 fn extensions_mut(&mut self) -> &mut Extensions {
324 &mut self.extensions
325 }
326}
327
328#[derive(Debug, Clone, Default)]
329#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
330pub struct RequestOptionalParam<M = String, P = JsonObject> {
331 pub method: M,
332 pub params: Option<P>,
334 #[cfg_attr(feature = "schemars", schemars(skip))]
338 pub extensions: Extensions,
339}
340
341impl<M: Default, P> RequestOptionalParam<M, P> {
342 pub fn with_param(params: P) -> Self {
343 Self {
344 method: Default::default(),
345 params: Some(params),
346 extensions: Extensions::default(),
347 }
348 }
349}
350
351#[derive(Debug, Clone, Default)]
352#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
353pub struct RequestNoParam<M = String> {
354 pub method: M,
355 #[cfg_attr(feature = "schemars", schemars(skip))]
359 pub extensions: Extensions,
360}
361
362impl<M> GetExtensions for RequestNoParam<M> {
363 fn extensions(&self) -> &Extensions {
364 &self.extensions
365 }
366 fn extensions_mut(&mut self) -> &mut Extensions {
367 &mut self.extensions
368 }
369}
370#[derive(Debug, Clone, Default)]
371#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
372pub struct Notification<M = String, P = JsonObject> {
373 pub method: M,
374 pub params: P,
375 #[cfg_attr(feature = "schemars", schemars(skip))]
379 pub extensions: Extensions,
380}
381
382impl<M: Default, P> Notification<M, P> {
383 pub fn new(params: P) -> Self {
384 Self {
385 method: Default::default(),
386 params,
387 extensions: Extensions::default(),
388 }
389 }
390}
391
392#[derive(Debug, Clone, Default)]
393#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
394pub struct NotificationNoParam<M = String> {
395 pub method: M,
396 #[cfg_attr(feature = "schemars", schemars(skip))]
400 pub extensions: Extensions,
401}
402
403#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
404#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
405pub struct JsonRpcRequest<R = Request> {
406 pub jsonrpc: JsonRpcVersion2_0,
407 pub id: RequestId,
408 #[serde(flatten)]
409 pub request: R,
410}
411
412type DefaultResponse = JsonObject;
413#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
414#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
415pub struct JsonRpcResponse<R = JsonObject> {
416 pub jsonrpc: JsonRpcVersion2_0,
417 pub id: RequestId,
418 pub result: R,
419}
420
421#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
422#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
423pub struct JsonRpcError {
424 pub jsonrpc: JsonRpcVersion2_0,
425 pub id: RequestId,
426 pub error: ErrorData,
427}
428
429#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
430#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
431pub struct JsonRpcNotification<N = Notification> {
432 pub jsonrpc: JsonRpcVersion2_0,
433 #[serde(flatten)]
434 pub notification: N,
435}
436
437#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
442#[serde(transparent)]
443#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
444pub struct ErrorCode(pub i32);
445
446impl ErrorCode {
447 pub const RESOURCE_NOT_FOUND: Self = Self(-32002);
448 pub const INVALID_REQUEST: Self = Self(-32600);
449 pub const METHOD_NOT_FOUND: Self = Self(-32601);
450 pub const INVALID_PARAMS: Self = Self(-32602);
451 pub const INTERNAL_ERROR: Self = Self(-32603);
452 pub const PARSE_ERROR: Self = Self(-32700);
453}
454
455#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
460#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
461pub struct ErrorData {
462 pub code: ErrorCode,
464
465 pub message: Cow<'static, str>,
467
468 #[serde(skip_serializing_if = "Option::is_none")]
471 pub data: Option<Value>,
472}
473
474impl ErrorData {
475 pub fn new(
476 code: ErrorCode,
477 message: impl Into<Cow<'static, str>>,
478 data: Option<Value>,
479 ) -> Self {
480 Self {
481 code,
482 message: message.into(),
483 data,
484 }
485 }
486 pub fn resource_not_found(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
487 Self::new(ErrorCode::RESOURCE_NOT_FOUND, message, data)
488 }
489 pub fn parse_error(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
490 Self::new(ErrorCode::PARSE_ERROR, message, data)
491 }
492 pub fn invalid_request(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
493 Self::new(ErrorCode::INVALID_REQUEST, message, data)
494 }
495 pub fn method_not_found<M: ConstString>() -> Self {
496 Self::new(ErrorCode::METHOD_NOT_FOUND, M::VALUE, None)
497 }
498 pub fn invalid_params(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
499 Self::new(ErrorCode::INVALID_PARAMS, message, data)
500 }
501 pub fn internal_error(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
502 Self::new(ErrorCode::INTERNAL_ERROR, message, data)
503 }
504}
505
506#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
512#[serde(untagged)]
513#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
514pub enum JsonRpcMessage<Req = Request, Resp = DefaultResponse, Noti = Notification> {
515 Request(JsonRpcRequest<Req>),
517 Response(JsonRpcResponse<Resp>),
519 Notification(JsonRpcNotification<Noti>),
521 Error(JsonRpcError),
523}
524
525impl<Req, Resp, Not> JsonRpcMessage<Req, Resp, Not> {
526 #[inline]
527 pub const fn request(request: Req, id: RequestId) -> Self {
528 JsonRpcMessage::Request(JsonRpcRequest {
529 jsonrpc: JsonRpcVersion2_0,
530 id,
531 request,
532 })
533 }
534 #[inline]
535 pub const fn response(response: Resp, id: RequestId) -> Self {
536 JsonRpcMessage::Response(JsonRpcResponse {
537 jsonrpc: JsonRpcVersion2_0,
538 id,
539 result: response,
540 })
541 }
542 #[inline]
543 pub const fn error(error: ErrorData, id: RequestId) -> Self {
544 JsonRpcMessage::Error(JsonRpcError {
545 jsonrpc: JsonRpcVersion2_0,
546 id,
547 error,
548 })
549 }
550 #[inline]
551 pub const fn notification(notification: Not) -> Self {
552 JsonRpcMessage::Notification(JsonRpcNotification {
553 jsonrpc: JsonRpcVersion2_0,
554 notification,
555 })
556 }
557 pub fn into_request(self) -> Option<(Req, RequestId)> {
558 match self {
559 JsonRpcMessage::Request(r) => Some((r.request, r.id)),
560 _ => None,
561 }
562 }
563 pub fn into_response(self) -> Option<(Resp, RequestId)> {
564 match self {
565 JsonRpcMessage::Response(r) => Some((r.result, r.id)),
566 _ => None,
567 }
568 }
569 pub fn into_notification(self) -> Option<Not> {
570 match self {
571 JsonRpcMessage::Notification(n) => Some(n.notification),
572 _ => None,
573 }
574 }
575 pub fn into_error(self) -> Option<(ErrorData, RequestId)> {
576 match self {
577 JsonRpcMessage::Error(e) => Some((e.error, e.id)),
578 _ => None,
579 }
580 }
581 pub fn into_result(self) -> Option<(Result<Resp, ErrorData>, RequestId)> {
582 match self {
583 JsonRpcMessage::Response(r) => Some((Ok(r.result), r.id)),
584 JsonRpcMessage::Error(e) => Some((Err(e.error), e.id)),
585
586 _ => None,
587 }
588 }
589}
590
591pub type EmptyResult = EmptyObject;
598
599impl From<()> for EmptyResult {
600 fn from(_value: ()) -> Self {
601 EmptyResult {}
602 }
603}
604
605impl From<EmptyResult> for () {
606 fn from(_value: EmptyResult) {}
607}
608
609#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
610#[serde(rename_all = "camelCase")]
611#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
612pub struct CancelledNotificationParam {
613 pub request_id: RequestId,
614 pub reason: Option<String>,
615}
616
617const_string!(CancelledNotificationMethod = "notifications/cancelled");
618
619pub type CancelledNotification =
628 Notification<CancelledNotificationMethod, CancelledNotificationParam>;
629
630#[derive(Debug, Clone)]
635#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
636pub struct CustomClientNotification {
637 pub method: String,
638 pub params: Option<Value>,
639 #[cfg_attr(feature = "schemars", schemars(skip))]
643 pub extensions: Extensions,
644}
645
646impl CustomClientNotification {
647 pub fn new(method: impl Into<String>, params: Option<Value>) -> Self {
648 Self {
649 method: method.into(),
650 params,
651 extensions: Extensions::default(),
652 }
653 }
654
655 pub fn params_as<T: DeserializeOwned>(&self) -> Result<Option<T>, serde_json::Error> {
657 self.params
658 .as_ref()
659 .map(|params| serde_json::from_value(params.clone()))
660 .transpose()
661 }
662}
663
664const_string!(InitializeResultMethod = "initialize");
665pub type InitializeRequest = Request<InitializeResultMethod, InitializeRequestParam>;
668
669const_string!(InitializedNotificationMethod = "notifications/initialized");
670pub type InitializedNotification = NotificationNoParam<InitializedNotificationMethod>;
672
673#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
678#[serde(rename_all = "camelCase")]
679#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
680pub struct InitializeRequestParam {
681 pub protocol_version: ProtocolVersion,
683 pub capabilities: ClientCapabilities,
685 pub client_info: Implementation,
687}
688
689#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
694#[serde(rename_all = "camelCase")]
695#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
696pub struct InitializeResult {
697 pub protocol_version: ProtocolVersion,
699 pub capabilities: ServerCapabilities,
701 pub server_info: Implementation,
703 #[serde(skip_serializing_if = "Option::is_none")]
705 pub instructions: Option<String>,
706}
707
708pub type ServerInfo = InitializeResult;
709pub type ClientInfo = InitializeRequestParam;
710
711#[allow(clippy::derivable_impls)]
712impl Default for ServerInfo {
713 fn default() -> Self {
714 ServerInfo {
715 protocol_version: ProtocolVersion::default(),
716 capabilities: ServerCapabilities::default(),
717 server_info: Implementation::from_build_env(),
718 instructions: None,
719 }
720 }
721}
722
723#[allow(clippy::derivable_impls)]
724impl Default for ClientInfo {
725 fn default() -> Self {
726 ClientInfo {
727 protocol_version: ProtocolVersion::default(),
728 capabilities: ClientCapabilities::default(),
729 client_info: Implementation::from_build_env(),
730 }
731 }
732}
733
734#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
744#[serde(rename_all = "camelCase")]
745#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
746pub struct Icon {
747 pub src: String,
749 #[serde(skip_serializing_if = "Option::is_none")]
751 pub mime_type: Option<String>,
752 #[serde(skip_serializing_if = "Option::is_none")]
754 pub sizes: Option<Vec<String>>,
755}
756
757#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
758#[serde(rename_all = "camelCase")]
759#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
760pub struct Implementation {
761 pub name: String,
762 #[serde(skip_serializing_if = "Option::is_none")]
763 pub title: Option<String>,
764 pub version: String,
765 #[serde(skip_serializing_if = "Option::is_none")]
766 pub icons: Option<Vec<Icon>>,
767 #[serde(skip_serializing_if = "Option::is_none")]
768 pub website_url: Option<String>,
769}
770
771impl Default for Implementation {
772 fn default() -> Self {
773 Self::from_build_env()
774 }
775}
776
777impl Implementation {
778 pub fn from_build_env() -> Self {
779 Implementation {
780 name: env!("CARGO_CRATE_NAME").to_owned(),
781 title: None,
782 version: env!("CARGO_PKG_VERSION").to_owned(),
783 icons: None,
784 website_url: None,
785 }
786 }
787}
788
789#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
790#[serde(rename_all = "camelCase")]
791#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
792pub struct PaginatedRequestParam {
793 #[serde(skip_serializing_if = "Option::is_none")]
794 pub cursor: Option<String>,
795}
796const_string!(PingRequestMethod = "ping");
801pub type PingRequest = RequestNoParam<PingRequestMethod>;
802
803const_string!(ProgressNotificationMethod = "notifications/progress");
804#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
805#[serde(rename_all = "camelCase")]
806#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
807pub struct ProgressNotificationParam {
808 pub progress_token: ProgressToken,
809 pub progress: f64,
811 #[serde(skip_serializing_if = "Option::is_none")]
813 pub total: Option<f64>,
814 #[serde(skip_serializing_if = "Option::is_none")]
816 pub message: Option<String>,
817}
818
819pub type ProgressNotification = Notification<ProgressNotificationMethod, ProgressNotificationParam>;
820
821pub type Cursor = String;
822
823macro_rules! paginated_result {
824 ($t:ident {
825 $i_item: ident: $t_item: ty
826 }) => {
827 #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
828 #[serde(rename_all = "camelCase")]
829 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
830 pub struct $t {
831 #[serde(skip_serializing_if = "Option::is_none")]
832 pub next_cursor: Option<Cursor>,
833 pub $i_item: $t_item,
834 }
835
836 impl $t {
837 pub fn with_all_items(
838 items: $t_item,
839 ) -> Self {
840 Self {
841 next_cursor: None,
842 $i_item: items,
843 }
844 }
845 }
846 };
847}
848
849const_string!(ListResourcesRequestMethod = "resources/list");
854pub type ListResourcesRequest =
856 RequestOptionalParam<ListResourcesRequestMethod, PaginatedRequestParam>;
857
858paginated_result!(ListResourcesResult {
859 resources: Vec<Resource>
860});
861
862const_string!(ListResourceTemplatesRequestMethod = "resources/templates/list");
863pub type ListResourceTemplatesRequest =
865 RequestOptionalParam<ListResourceTemplatesRequestMethod, PaginatedRequestParam>;
866
867paginated_result!(ListResourceTemplatesResult {
868 resource_templates: Vec<ResourceTemplate>
869});
870
871const_string!(ReadResourceRequestMethod = "resources/read");
872#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
874#[serde(rename_all = "camelCase")]
875#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
876pub struct ReadResourceRequestParam {
877 pub uri: String,
879}
880
881#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
883#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
884pub struct ReadResourceResult {
885 pub contents: Vec<ResourceContents>,
887}
888
889pub type ReadResourceRequest = Request<ReadResourceRequestMethod, ReadResourceRequestParam>;
891
892const_string!(ResourceListChangedNotificationMethod = "notifications/resources/list_changed");
893pub type ResourceListChangedNotification =
895 NotificationNoParam<ResourceListChangedNotificationMethod>;
896
897const_string!(SubscribeRequestMethod = "resources/subscribe");
898#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
900#[serde(rename_all = "camelCase")]
901#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
902pub struct SubscribeRequestParam {
903 pub uri: String,
905}
906pub type SubscribeRequest = Request<SubscribeRequestMethod, SubscribeRequestParam>;
908
909const_string!(UnsubscribeRequestMethod = "resources/unsubscribe");
910#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
912#[serde(rename_all = "camelCase")]
913#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
914pub struct UnsubscribeRequestParam {
915 pub uri: String,
917}
918pub type UnsubscribeRequest = Request<UnsubscribeRequestMethod, UnsubscribeRequestParam>;
920
921const_string!(ResourceUpdatedNotificationMethod = "notifications/resources/updated");
922#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
924#[serde(rename_all = "camelCase")]
925#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
926pub struct ResourceUpdatedNotificationParam {
927 pub uri: String,
929}
930pub type ResourceUpdatedNotification =
932 Notification<ResourceUpdatedNotificationMethod, ResourceUpdatedNotificationParam>;
933
934const_string!(ListPromptsRequestMethod = "prompts/list");
939pub type ListPromptsRequest = RequestOptionalParam<ListPromptsRequestMethod, PaginatedRequestParam>;
941
942paginated_result!(ListPromptsResult {
943 prompts: Vec<Prompt>
944});
945
946const_string!(GetPromptRequestMethod = "prompts/get");
947#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
949#[serde(rename_all = "camelCase")]
950#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
951pub struct GetPromptRequestParam {
952 pub name: String,
953 #[serde(skip_serializing_if = "Option::is_none")]
954 pub arguments: Option<JsonObject>,
955}
956pub type GetPromptRequest = Request<GetPromptRequestMethod, GetPromptRequestParam>;
958
959const_string!(PromptListChangedNotificationMethod = "notifications/prompts/list_changed");
960pub type PromptListChangedNotification = NotificationNoParam<PromptListChangedNotificationMethod>;
962
963const_string!(ToolListChangedNotificationMethod = "notifications/tools/list_changed");
964pub type ToolListChangedNotification = NotificationNoParam<ToolListChangedNotificationMethod>;
966
967#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
973#[serde(rename_all = "lowercase")] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
975pub enum LoggingLevel {
976 Debug,
977 Info,
978 Notice,
979 Warning,
980 Error,
981 Critical,
982 Alert,
983 Emergency,
984}
985
986const_string!(SetLevelRequestMethod = "logging/setLevel");
987#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
989#[serde(rename_all = "camelCase")]
990#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
991pub struct SetLevelRequestParam {
992 pub level: LoggingLevel,
994}
995pub type SetLevelRequest = Request<SetLevelRequestMethod, SetLevelRequestParam>;
997
998const_string!(LoggingMessageNotificationMethod = "notifications/message");
999#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1001#[serde(rename_all = "camelCase")]
1002#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1003pub struct LoggingMessageNotificationParam {
1004 pub level: LoggingLevel,
1006 #[serde(skip_serializing_if = "Option::is_none")]
1008 pub logger: Option<String>,
1009 pub data: Value,
1011}
1012pub type LoggingMessageNotification =
1014 Notification<LoggingMessageNotificationMethod, LoggingMessageNotificationParam>;
1015
1016const_string!(CreateMessageRequestMethod = "sampling/createMessage");
1021pub type CreateMessageRequest = Request<CreateMessageRequestMethod, CreateMessageRequestParam>;
1022
1023#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1028#[serde(rename_all = "camelCase")]
1029#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1030pub enum Role {
1031 User,
1033 Assistant,
1035}
1036
1037#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1043#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1044pub struct SamplingMessage {
1045 pub role: Role,
1047 pub content: Content,
1049}
1050
1051#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1056#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1057pub enum ContextInclusion {
1058 #[serde(rename = "allServers")]
1060 AllServers,
1061 #[serde(rename = "none")]
1063 None,
1064 #[serde(rename = "thisServer")]
1066 ThisServer,
1067}
1068
1069#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1075#[serde(rename_all = "camelCase")]
1076#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1077pub struct CreateMessageRequestParam {
1078 pub messages: Vec<SamplingMessage>,
1080 #[serde(skip_serializing_if = "Option::is_none")]
1082 pub model_preferences: Option<ModelPreferences>,
1083 #[serde(skip_serializing_if = "Option::is_none")]
1085 pub system_prompt: Option<String>,
1086 #[serde(skip_serializing_if = "Option::is_none")]
1088 pub include_context: Option<ContextInclusion>,
1089 #[serde(skip_serializing_if = "Option::is_none")]
1091 pub temperature: Option<f32>,
1092 pub max_tokens: u32,
1094 #[serde(skip_serializing_if = "Option::is_none")]
1096 pub stop_sequences: Option<Vec<String>>,
1097 #[serde(skip_serializing_if = "Option::is_none")]
1099 pub metadata: Option<Value>,
1100}
1101
1102#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1108#[serde(rename_all = "camelCase")]
1109#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1110pub struct ModelPreferences {
1111 #[serde(skip_serializing_if = "Option::is_none")]
1113 pub hints: Option<Vec<ModelHint>>,
1114 #[serde(skip_serializing_if = "Option::is_none")]
1116 pub cost_priority: Option<f32>,
1117 #[serde(skip_serializing_if = "Option::is_none")]
1119 pub speed_priority: Option<f32>,
1120 #[serde(skip_serializing_if = "Option::is_none")]
1122 pub intelligence_priority: Option<f32>,
1123}
1124
1125#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1130#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1131pub struct ModelHint {
1132 #[serde(skip_serializing_if = "Option::is_none")]
1134 pub name: Option<String>,
1135}
1136
1137#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
1146#[serde(rename_all = "camelCase")]
1147#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1148pub struct CompletionContext {
1149 #[serde(skip_serializing_if = "Option::is_none")]
1151 pub arguments: Option<std::collections::HashMap<String, String>>,
1152}
1153
1154impl CompletionContext {
1155 pub fn new() -> Self {
1157 Self::default()
1158 }
1159
1160 pub fn with_arguments(arguments: std::collections::HashMap<String, String>) -> Self {
1162 Self {
1163 arguments: Some(arguments),
1164 }
1165 }
1166
1167 pub fn get_argument(&self, name: &str) -> Option<&String> {
1169 self.arguments.as_ref()?.get(name)
1170 }
1171
1172 pub fn has_arguments(&self) -> bool {
1174 self.arguments.as_ref().is_some_and(|args| !args.is_empty())
1175 }
1176
1177 pub fn argument_names(&self) -> impl Iterator<Item = &str> {
1179 self.arguments
1180 .as_ref()
1181 .into_iter()
1182 .flat_map(|args| args.keys())
1183 .map(|k| k.as_str())
1184 }
1185}
1186
1187#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1188#[serde(rename_all = "camelCase")]
1189#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1190pub struct CompleteRequestParam {
1191 pub r#ref: Reference,
1192 pub argument: ArgumentInfo,
1193 #[serde(skip_serializing_if = "Option::is_none")]
1195 pub context: Option<CompletionContext>,
1196}
1197
1198pub type CompleteRequest = Request<CompleteRequestMethod, CompleteRequestParam>;
1199
1200#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
1201#[serde(rename_all = "camelCase")]
1202#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1203pub struct CompletionInfo {
1204 pub values: Vec<String>,
1205 #[serde(skip_serializing_if = "Option::is_none")]
1206 pub total: Option<u32>,
1207 #[serde(skip_serializing_if = "Option::is_none")]
1208 pub has_more: Option<bool>,
1209}
1210
1211impl CompletionInfo {
1212 pub const MAX_VALUES: usize = 100;
1214
1215 pub fn new(values: Vec<String>) -> Result<Self, String> {
1217 if values.len() > Self::MAX_VALUES {
1218 return Err(format!(
1219 "Too many completion values: {} (max: {})",
1220 values.len(),
1221 Self::MAX_VALUES
1222 ));
1223 }
1224 Ok(Self {
1225 values,
1226 total: None,
1227 has_more: None,
1228 })
1229 }
1230
1231 pub fn with_all_values(values: Vec<String>) -> Result<Self, String> {
1233 let completion = Self::new(values)?;
1234 Ok(Self {
1235 total: Some(completion.values.len() as u32),
1236 has_more: Some(false),
1237 ..completion
1238 })
1239 }
1240
1241 pub fn with_pagination(
1243 values: Vec<String>,
1244 total: Option<u32>,
1245 has_more: bool,
1246 ) -> Result<Self, String> {
1247 let completion = Self::new(values)?;
1248 Ok(Self {
1249 total,
1250 has_more: Some(has_more),
1251 ..completion
1252 })
1253 }
1254
1255 pub fn has_more_results(&self) -> bool {
1257 self.has_more.unwrap_or(false)
1258 }
1259
1260 pub fn total_available(&self) -> Option<u32> {
1262 self.total
1263 }
1264
1265 pub fn validate(&self) -> Result<(), String> {
1267 if self.values.len() > Self::MAX_VALUES {
1268 return Err(format!(
1269 "Too many completion values: {} (max: {})",
1270 self.values.len(),
1271 Self::MAX_VALUES
1272 ));
1273 }
1274 Ok(())
1275 }
1276}
1277
1278#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
1279#[serde(rename_all = "camelCase")]
1280#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1281pub struct CompleteResult {
1282 pub completion: CompletionInfo,
1283}
1284
1285#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1286#[serde(tag = "type")]
1287#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1288pub enum Reference {
1289 #[serde(rename = "ref/resource")]
1290 Resource(ResourceReference),
1291 #[serde(rename = "ref/prompt")]
1292 Prompt(PromptReference),
1293}
1294
1295impl Reference {
1296 pub fn for_prompt(name: impl Into<String>) -> Self {
1298 Self::Prompt(PromptReference {
1302 name: name.into(),
1303 title: None,
1304 })
1305 }
1306
1307 pub fn for_resource(uri: impl Into<String>) -> Self {
1309 Self::Resource(ResourceReference { uri: uri.into() })
1310 }
1311
1312 pub fn reference_type(&self) -> &'static str {
1314 match self {
1315 Self::Prompt(_) => "ref/prompt",
1316 Self::Resource(_) => "ref/resource",
1317 }
1318 }
1319
1320 pub fn as_prompt_name(&self) -> Option<&str> {
1322 match self {
1323 Self::Prompt(prompt_ref) => Some(&prompt_ref.name),
1324 _ => None,
1325 }
1326 }
1327
1328 pub fn as_resource_uri(&self) -> Option<&str> {
1330 match self {
1331 Self::Resource(resource_ref) => Some(&resource_ref.uri),
1332 _ => None,
1333 }
1334 }
1335}
1336
1337#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1338#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1339pub struct ResourceReference {
1340 pub uri: String,
1341}
1342
1343#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1344#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1345pub struct PromptReference {
1346 pub name: String,
1347 #[serde(skip_serializing_if = "Option::is_none")]
1348 pub title: Option<String>,
1349}
1350
1351const_string!(CompleteRequestMethod = "completion/complete");
1352#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1353#[serde(rename_all = "camelCase")]
1354#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1355pub struct ArgumentInfo {
1356 pub name: String,
1357 pub value: String,
1358}
1359
1360#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1365#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1366pub struct Root {
1367 pub uri: String,
1368 #[serde(skip_serializing_if = "Option::is_none")]
1369 pub name: Option<String>,
1370}
1371
1372const_string!(ListRootsRequestMethod = "roots/list");
1373pub type ListRootsRequest = RequestNoParam<ListRootsRequestMethod>;
1374
1375#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
1376#[serde(rename_all = "camelCase")]
1377#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1378pub struct ListRootsResult {
1379 pub roots: Vec<Root>,
1380}
1381
1382const_string!(RootsListChangedNotificationMethod = "notifications/roots/list_changed");
1383pub type RootsListChangedNotification = NotificationNoParam<RootsListChangedNotificationMethod>;
1384
1385const_string!(ElicitationCreateRequestMethod = "elicitation/create");
1392const_string!(ElicitationResponseNotificationMethod = "notifications/elicitation/response");
1393
1394#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
1401#[serde(rename_all = "lowercase")]
1402#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1403pub enum ElicitationAction {
1404 Accept,
1406 Decline,
1408 Cancel,
1410}
1411
1412#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1432#[serde(rename_all = "camelCase")]
1433#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1434pub struct CreateElicitationRequestParam {
1435 pub message: String,
1439
1440 pub requested_schema: ElicitationSchema,
1444}
1445
1446#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1451#[serde(rename_all = "camelCase")]
1452#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1453pub struct CreateElicitationResult {
1454 pub action: ElicitationAction,
1456
1457 #[serde(skip_serializing_if = "Option::is_none")]
1461 pub content: Option<Value>,
1462}
1463
1464pub type CreateElicitationRequest =
1466 Request<ElicitationCreateRequestMethod, CreateElicitationRequestParam>;
1467
1468#[derive(Debug, Serialize, Clone, PartialEq)]
1477#[serde(rename_all = "camelCase")]
1478#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1479pub struct CallToolResult {
1480 pub content: Vec<Content>,
1482 #[serde(skip_serializing_if = "Option::is_none")]
1484 pub structured_content: Option<Value>,
1485 #[serde(skip_serializing_if = "Option::is_none")]
1487 pub is_error: Option<bool>,
1488 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1490 pub meta: Option<Meta>,
1491}
1492
1493impl CallToolResult {
1494 pub fn success(content: Vec<Content>) -> Self {
1496 CallToolResult {
1497 content,
1498 structured_content: None,
1499 is_error: Some(false),
1500 meta: None,
1501 }
1502 }
1503 pub fn error(content: Vec<Content>) -> Self {
1505 CallToolResult {
1506 content,
1507 structured_content: None,
1508 is_error: Some(true),
1509 meta: None,
1510 }
1511 }
1512 pub fn structured(value: Value) -> Self {
1527 CallToolResult {
1528 content: vec![Content::text(value.to_string())],
1529 structured_content: Some(value),
1530 is_error: Some(false),
1531 meta: None,
1532 }
1533 }
1534 pub fn structured_error(value: Value) -> Self {
1553 CallToolResult {
1554 content: vec![Content::text(value.to_string())],
1555 structured_content: Some(value),
1556 is_error: Some(true),
1557 meta: None,
1558 }
1559 }
1560
1561 pub fn into_typed<T>(self) -> Result<T, serde_json::Error>
1568 where
1569 T: DeserializeOwned,
1570 {
1571 let raw_text = match (self.structured_content, &self.content.first()) {
1572 (Some(value), _) => return serde_json::from_value(value),
1573 (None, Some(contents)) => {
1574 if let Some(text) = contents.as_text() {
1575 let text = &text.text;
1576 Some(text)
1577 } else {
1578 None
1579 }
1580 }
1581 (None, None) => None,
1582 };
1583 if let Some(text) = raw_text {
1584 return serde_json::from_str(text);
1585 }
1586 serde_json::from_value(serde_json::Value::Null)
1587 }
1588}
1589
1590impl<'de> Deserialize<'de> for CallToolResult {
1592 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1593 where
1594 D: serde::Deserializer<'de>,
1595 {
1596 #[derive(Deserialize)]
1597 #[serde(rename_all = "camelCase")]
1598 struct CallToolResultHelper {
1599 #[serde(skip_serializing_if = "Option::is_none")]
1600 content: Option<Vec<Content>>,
1601 #[serde(skip_serializing_if = "Option::is_none")]
1602 structured_content: Option<Value>,
1603 #[serde(skip_serializing_if = "Option::is_none")]
1604 is_error: Option<bool>,
1605 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1607 meta: Option<Meta>,
1608 }
1609
1610 let helper = CallToolResultHelper::deserialize(deserializer)?;
1611 let result = CallToolResult {
1612 content: helper.content.unwrap_or_default(),
1613 structured_content: helper.structured_content,
1614 is_error: helper.is_error,
1615 meta: helper.meta,
1616 };
1617
1618 if result.content.is_empty() && result.structured_content.is_none() {
1620 return Err(serde::de::Error::custom(
1621 "CallToolResult must have either content or structured_content",
1622 ));
1623 }
1624
1625 Ok(result)
1626 }
1627}
1628
1629const_string!(ListToolsRequestMethod = "tools/list");
1630pub type ListToolsRequest = RequestOptionalParam<ListToolsRequestMethod, PaginatedRequestParam>;
1632
1633paginated_result!(
1634 ListToolsResult {
1635 tools: Vec<Tool>
1636 }
1637);
1638
1639const_string!(CallToolRequestMethod = "tools/call");
1640#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1645#[serde(rename_all = "camelCase")]
1646#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1647pub struct CallToolRequestParam {
1648 pub name: Cow<'static, str>,
1650 #[serde(skip_serializing_if = "Option::is_none")]
1652 pub arguments: Option<JsonObject>,
1653}
1654
1655pub type CallToolRequest = Request<CallToolRequestMethod, CallToolRequestParam>;
1657
1658#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1663#[serde(rename_all = "camelCase")]
1664#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1665pub struct CreateMessageResult {
1666 pub model: String,
1668 #[serde(skip_serializing_if = "Option::is_none")]
1670 pub stop_reason: Option<String>,
1671 #[serde(flatten)]
1673 pub message: SamplingMessage,
1674}
1675
1676impl CreateMessageResult {
1677 pub const STOP_REASON_END_TURN: &str = "endTurn";
1678 pub const STOP_REASON_END_SEQUENCE: &str = "stopSequence";
1679 pub const STOP_REASON_END_MAX_TOKEN: &str = "maxTokens";
1680}
1681
1682#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1683#[serde(rename_all = "camelCase")]
1684#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1685pub struct GetPromptResult {
1686 #[serde(skip_serializing_if = "Option::is_none")]
1687 pub description: Option<String>,
1688 pub messages: Vec<PromptMessage>,
1689}
1690
1691macro_rules! ts_union {
1696 (
1697 export type $U:ident =
1698 $($rest:tt)*
1699 ) => {
1700 ts_union!(@declare $U { $($rest)* });
1701 ts_union!(@impl_from $U { $($rest)* });
1702 };
1703 (@declare $U:ident { $($variant:tt)* }) => {
1704 ts_union!(@declare_variant $U { } {$($variant)*} );
1705 };
1706 (@declare_variant $U:ident { $($declared:tt)* } {$(|)? box $V:ident $($rest:tt)*}) => {
1707 ts_union!(@declare_variant $U { $($declared)* $V(Box<$V>), } {$($rest)*});
1708 };
1709 (@declare_variant $U:ident { $($declared:tt)* } {$(|)? $V:ident $($rest:tt)*}) => {
1710 ts_union!(@declare_variant $U { $($declared)* $V($V), } {$($rest)*});
1711 };
1712 (@declare_variant $U:ident { $($declared:tt)* } { ; }) => {
1713 ts_union!(@declare_end $U { $($declared)* } );
1714 };
1715 (@declare_end $U:ident { $($declared:tt)* }) => {
1716 #[derive(Debug, Serialize, Deserialize, Clone)]
1717 #[serde(untagged)]
1718 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1719 pub enum $U {
1720 $($declared)*
1721 }
1722 };
1723 (@impl_from $U: ident {$(|)? box $V:ident $($rest:tt)*}) => {
1724 impl From<$V> for $U {
1725 fn from(value: $V) -> Self {
1726 $U::$V(Box::new(value))
1727 }
1728 }
1729 ts_union!(@impl_from $U {$($rest)*});
1730 };
1731 (@impl_from $U: ident {$(|)? $V:ident $($rest:tt)*}) => {
1732 impl From<$V> for $U {
1733 fn from(value: $V) -> Self {
1734 $U::$V(value)
1735 }
1736 }
1737 ts_union!(@impl_from $U {$($rest)*});
1738 };
1739 (@impl_from $U: ident { ; }) => {};
1740 (@impl_from $U: ident { }) => {};
1741}
1742
1743ts_union!(
1744 export type ClientRequest =
1745 | PingRequest
1746 | InitializeRequest
1747 | CompleteRequest
1748 | SetLevelRequest
1749 | GetPromptRequest
1750 | ListPromptsRequest
1751 | ListResourcesRequest
1752 | ListResourceTemplatesRequest
1753 | ReadResourceRequest
1754 | SubscribeRequest
1755 | UnsubscribeRequest
1756 | CallToolRequest
1757 | ListToolsRequest;
1758);
1759
1760impl ClientRequest {
1761 pub fn method(&self) -> &'static str {
1762 match &self {
1763 ClientRequest::PingRequest(r) => r.method.as_str(),
1764 ClientRequest::InitializeRequest(r) => r.method.as_str(),
1765 ClientRequest::CompleteRequest(r) => r.method.as_str(),
1766 ClientRequest::SetLevelRequest(r) => r.method.as_str(),
1767 ClientRequest::GetPromptRequest(r) => r.method.as_str(),
1768 ClientRequest::ListPromptsRequest(r) => r.method.as_str(),
1769 ClientRequest::ListResourcesRequest(r) => r.method.as_str(),
1770 ClientRequest::ListResourceTemplatesRequest(r) => r.method.as_str(),
1771 ClientRequest::ReadResourceRequest(r) => r.method.as_str(),
1772 ClientRequest::SubscribeRequest(r) => r.method.as_str(),
1773 ClientRequest::UnsubscribeRequest(r) => r.method.as_str(),
1774 ClientRequest::CallToolRequest(r) => r.method.as_str(),
1775 ClientRequest::ListToolsRequest(r) => r.method.as_str(),
1776 }
1777 }
1778}
1779
1780ts_union!(
1781 export type ClientNotification =
1782 | CancelledNotification
1783 | ProgressNotification
1784 | InitializedNotification
1785 | RootsListChangedNotification
1786 | CustomClientNotification;
1787);
1788
1789ts_union!(
1790 export type ClientResult = box CreateMessageResult | ListRootsResult | CreateElicitationResult | EmptyResult;
1791);
1792
1793impl ClientResult {
1794 pub fn empty(_: ()) -> ClientResult {
1795 ClientResult::EmptyResult(EmptyResult {})
1796 }
1797}
1798
1799pub type ClientJsonRpcMessage = JsonRpcMessage<ClientRequest, ClientResult, ClientNotification>;
1800
1801ts_union!(
1802 export type ServerRequest =
1803 | PingRequest
1804 | CreateMessageRequest
1805 | ListRootsRequest
1806 | CreateElicitationRequest;
1807);
1808
1809ts_union!(
1810 export type ServerNotification =
1811 | CancelledNotification
1812 | ProgressNotification
1813 | LoggingMessageNotification
1814 | ResourceUpdatedNotification
1815 | ResourceListChangedNotification
1816 | ToolListChangedNotification
1817 | PromptListChangedNotification;
1818);
1819
1820ts_union!(
1821 export type ServerResult =
1822 | InitializeResult
1823 | CompleteResult
1824 | GetPromptResult
1825 | ListPromptsResult
1826 | ListResourcesResult
1827 | ListResourceTemplatesResult
1828 | ReadResourceResult
1829 | CallToolResult
1830 | ListToolsResult
1831 | CreateElicitationResult
1832 | EmptyResult
1833 ;
1834);
1835
1836impl ServerResult {
1837 pub fn empty(_: ()) -> ServerResult {
1838 ServerResult::EmptyResult(EmptyResult {})
1839 }
1840}
1841
1842pub type ServerJsonRpcMessage = JsonRpcMessage<ServerRequest, ServerResult, ServerNotification>;
1843
1844impl TryInto<CancelledNotification> for ServerNotification {
1845 type Error = ServerNotification;
1846 fn try_into(self) -> Result<CancelledNotification, Self::Error> {
1847 if let ServerNotification::CancelledNotification(t) = self {
1848 Ok(t)
1849 } else {
1850 Err(self)
1851 }
1852 }
1853}
1854
1855impl TryInto<CancelledNotification> for ClientNotification {
1856 type Error = ClientNotification;
1857 fn try_into(self) -> Result<CancelledNotification, Self::Error> {
1858 if let ClientNotification::CancelledNotification(t) = self {
1859 Ok(t)
1860 } else {
1861 Err(self)
1862 }
1863 }
1864}
1865
1866#[cfg(test)]
1871mod tests {
1872 use serde_json::json;
1873
1874 use super::*;
1875
1876 #[test]
1877 fn test_notification_serde() {
1878 let raw = json!( {
1879 "jsonrpc": JsonRpcVersion2_0,
1880 "method": InitializedNotificationMethod,
1881 });
1882 let message: ClientJsonRpcMessage =
1883 serde_json::from_value(raw.clone()).expect("invalid notification");
1884 match &message {
1885 ClientJsonRpcMessage::Notification(JsonRpcNotification {
1886 notification: ClientNotification::InitializedNotification(_n),
1887 ..
1888 }) => {}
1889 _ => panic!("Expected Notification"),
1890 }
1891 let json = serde_json::to_value(message).expect("valid json");
1892 assert_eq!(json, raw);
1893 }
1894
1895 #[test]
1896 fn test_custom_client_notification_roundtrip() {
1897 let raw = json!( {
1898 "jsonrpc": JsonRpcVersion2_0,
1899 "method": "notifications/custom",
1900 "params": {"foo": "bar"},
1901 });
1902
1903 let message: ClientJsonRpcMessage =
1904 serde_json::from_value(raw.clone()).expect("invalid notification");
1905 match &message {
1906 ClientJsonRpcMessage::Notification(JsonRpcNotification {
1907 notification: ClientNotification::CustomClientNotification(notification),
1908 ..
1909 }) => {
1910 assert_eq!(notification.method, "notifications/custom");
1911 assert_eq!(
1912 notification
1913 .params
1914 .as_ref()
1915 .and_then(|p| p.get("foo"))
1916 .expect("foo present"),
1917 "bar"
1918 );
1919 }
1920 _ => panic!("Expected custom client notification"),
1921 }
1922
1923 let json = serde_json::to_value(message).expect("valid json");
1924 assert_eq!(json, raw);
1925 }
1926
1927 #[test]
1928 fn test_request_conversion() {
1929 let raw = json!( {
1930 "jsonrpc": JsonRpcVersion2_0,
1931 "id": 1,
1932 "method": "request",
1933 "params": {"key": "value"},
1934 });
1935 let message: JsonRpcMessage = serde_json::from_value(raw.clone()).expect("invalid request");
1936
1937 match &message {
1938 JsonRpcMessage::Request(r) => {
1939 assert_eq!(r.id, RequestId::Number(1));
1940 assert_eq!(r.request.method, "request");
1941 assert_eq!(
1942 &r.request.params,
1943 json!({"key": "value"})
1944 .as_object()
1945 .expect("should be an object")
1946 );
1947 }
1948 _ => panic!("Expected Request"),
1949 }
1950 let json = serde_json::to_value(&message).expect("valid json");
1951 assert_eq!(json, raw);
1952 }
1953
1954 #[test]
1955 fn test_initial_request_response_serde() {
1956 let request = json!({
1957 "jsonrpc": "2.0",
1958 "id": 1,
1959 "method": "initialize",
1960 "params": {
1961 "protocolVersion": "2024-11-05",
1962 "capabilities": {
1963 "roots": {
1964 "listChanged": true
1965 },
1966 "sampling": {}
1967 },
1968 "clientInfo": {
1969 "name": "ExampleClient",
1970 "version": "1.0.0"
1971 }
1972 }
1973 });
1974 let raw_response_json = json!({
1975 "jsonrpc": "2.0",
1976 "id": 1,
1977 "result": {
1978 "protocolVersion": "2024-11-05",
1979 "capabilities": {
1980 "logging": {},
1981 "prompts": {
1982 "listChanged": true
1983 },
1984 "resources": {
1985 "subscribe": true,
1986 "listChanged": true
1987 },
1988 "tools": {
1989 "listChanged": true
1990 }
1991 },
1992 "serverInfo": {
1993 "name": "ExampleServer",
1994 "version": "1.0.0"
1995 }
1996 }
1997 });
1998 let request: ClientJsonRpcMessage =
1999 serde_json::from_value(request.clone()).expect("invalid request");
2000 let (request, id) = request.into_request().expect("should be a request");
2001 assert_eq!(id, RequestId::Number(1));
2002 match request {
2003 ClientRequest::InitializeRequest(Request {
2004 method: _,
2005 params:
2006 InitializeRequestParam {
2007 protocol_version: _,
2008 capabilities,
2009 client_info,
2010 },
2011 ..
2012 }) => {
2013 assert_eq!(capabilities.roots.unwrap().list_changed, Some(true));
2014 assert_eq!(capabilities.sampling.unwrap().len(), 0);
2015 assert_eq!(client_info.name, "ExampleClient");
2016 assert_eq!(client_info.version, "1.0.0");
2017 }
2018 _ => panic!("Expected InitializeRequest"),
2019 }
2020 let server_response: ServerJsonRpcMessage =
2021 serde_json::from_value(raw_response_json.clone()).expect("invalid response");
2022 let (response, id) = server_response
2023 .clone()
2024 .into_response()
2025 .expect("expect response");
2026 assert_eq!(id, RequestId::Number(1));
2027 match response {
2028 ServerResult::InitializeResult(InitializeResult {
2029 protocol_version: _,
2030 capabilities,
2031 server_info,
2032 instructions,
2033 }) => {
2034 assert_eq!(capabilities.logging.unwrap().len(), 0);
2035 assert_eq!(capabilities.prompts.unwrap().list_changed, Some(true));
2036 assert_eq!(
2037 capabilities.resources.as_ref().unwrap().subscribe,
2038 Some(true)
2039 );
2040 assert_eq!(capabilities.resources.unwrap().list_changed, Some(true));
2041 assert_eq!(capabilities.tools.unwrap().list_changed, Some(true));
2042 assert_eq!(server_info.name, "ExampleServer");
2043 assert_eq!(server_info.version, "1.0.0");
2044 assert_eq!(server_info.icons, None);
2045 assert_eq!(instructions, None);
2046 }
2047 other => panic!("Expected InitializeResult, got {other:?}"),
2048 }
2049
2050 let server_response_json: Value = serde_json::to_value(&server_response).expect("msg");
2051
2052 assert_eq!(server_response_json, raw_response_json);
2053 }
2054
2055 #[test]
2056 fn test_negative_and_large_request_ids() {
2057 let negative_id_json = json!({
2059 "jsonrpc": "2.0",
2060 "id": -1,
2061 "method": "test",
2062 "params": {}
2063 });
2064
2065 let message: JsonRpcMessage =
2066 serde_json::from_value(negative_id_json.clone()).expect("Should parse negative ID");
2067
2068 match &message {
2069 JsonRpcMessage::Request(r) => {
2070 assert_eq!(r.id, RequestId::Number(-1));
2071 }
2072 _ => panic!("Expected Request"),
2073 }
2074
2075 let serialized = serde_json::to_value(&message).expect("Should serialize");
2077 assert_eq!(serialized, negative_id_json);
2078
2079 let large_negative_json = json!({
2081 "jsonrpc": "2.0",
2082 "id": -9007199254740991i64, "method": "test",
2084 "params": {}
2085 });
2086
2087 let message: JsonRpcMessage = serde_json::from_value(large_negative_json.clone())
2088 .expect("Should parse large negative ID");
2089
2090 match &message {
2091 JsonRpcMessage::Request(r) => {
2092 assert_eq!(r.id, RequestId::Number(-9007199254740991i64));
2093 }
2094 _ => panic!("Expected Request"),
2095 }
2096
2097 let large_positive_json = json!({
2099 "jsonrpc": "2.0",
2100 "id": 9007199254740991i64,
2101 "method": "test",
2102 "params": {}
2103 });
2104
2105 let message: JsonRpcMessage = serde_json::from_value(large_positive_json.clone())
2106 .expect("Should parse large positive ID");
2107
2108 match &message {
2109 JsonRpcMessage::Request(r) => {
2110 assert_eq!(r.id, RequestId::Number(9007199254740991i64));
2111 }
2112 _ => panic!("Expected Request"),
2113 }
2114
2115 let zero_id_json = json!({
2117 "jsonrpc": "2.0",
2118 "id": 0,
2119 "method": "test",
2120 "params": {}
2121 });
2122
2123 let message: JsonRpcMessage =
2124 serde_json::from_value(zero_id_json.clone()).expect("Should parse zero ID");
2125
2126 match &message {
2127 JsonRpcMessage::Request(r) => {
2128 assert_eq!(r.id, RequestId::Number(0));
2129 }
2130 _ => panic!("Expected Request"),
2131 }
2132 }
2133
2134 #[test]
2135 fn test_protocol_version_order() {
2136 let v1 = ProtocolVersion::V_2024_11_05;
2137 let v2 = ProtocolVersion::V_2025_03_26;
2138 assert!(v1 < v2);
2139 }
2140
2141 #[test]
2142 fn test_icon_serialization() {
2143 let icon = Icon {
2144 src: "https://example.com/icon.png".to_string(),
2145 mime_type: Some("image/png".to_string()),
2146 sizes: Some(vec!["48x48".to_string()]),
2147 };
2148
2149 let json = serde_json::to_value(&icon).unwrap();
2150 assert_eq!(json["src"], "https://example.com/icon.png");
2151 assert_eq!(json["mimeType"], "image/png");
2152 assert_eq!(json["sizes"][0], "48x48");
2153
2154 let deserialized: Icon = serde_json::from_value(json).unwrap();
2156 assert_eq!(deserialized, icon);
2157 }
2158
2159 #[test]
2160 fn test_icon_minimal() {
2161 let icon = Icon {
2162 src: "data:image/svg+xml;base64,PHN2Zy8+".to_string(),
2163 mime_type: None,
2164 sizes: None,
2165 };
2166
2167 let json = serde_json::to_value(&icon).unwrap();
2168 assert_eq!(json["src"], "data:image/svg+xml;base64,PHN2Zy8+");
2169 assert!(json.get("mimeType").is_none());
2170 assert!(json.get("sizes").is_none());
2171 }
2172
2173 #[test]
2174 fn test_implementation_with_icons() {
2175 let implementation = Implementation {
2176 name: "test-server".to_string(),
2177 title: Some("Test Server".to_string()),
2178 version: "1.0.0".to_string(),
2179 icons: Some(vec![
2180 Icon {
2181 src: "https://example.com/icon.png".to_string(),
2182 mime_type: Some("image/png".to_string()),
2183 sizes: Some(vec!["48x48".to_string()]),
2184 },
2185 Icon {
2186 src: "https://example.com/icon.svg".to_string(),
2187 mime_type: Some("image/svg+xml".to_string()),
2188 sizes: Some(vec!["any".to_string()]),
2189 },
2190 ]),
2191 website_url: Some("https://example.com".to_string()),
2192 };
2193
2194 let json = serde_json::to_value(&implementation).unwrap();
2195 assert_eq!(json["name"], "test-server");
2196 assert_eq!(json["websiteUrl"], "https://example.com");
2197 assert!(json["icons"].is_array());
2198 assert_eq!(json["icons"][0]["src"], "https://example.com/icon.png");
2199 assert_eq!(json["icons"][0]["sizes"][0], "48x48");
2200 assert_eq!(json["icons"][1]["mimeType"], "image/svg+xml");
2201 assert_eq!(json["icons"][1]["sizes"][0], "any");
2202 }
2203
2204 #[test]
2205 fn test_backward_compatibility() {
2206 let old_json = json!({
2208 "name": "legacy-server",
2209 "version": "0.9.0"
2210 });
2211
2212 let implementation: Implementation = serde_json::from_value(old_json).unwrap();
2213 assert_eq!(implementation.name, "legacy-server");
2214 assert_eq!(implementation.version, "0.9.0");
2215 assert_eq!(implementation.icons, None);
2216 assert_eq!(implementation.website_url, None);
2217 }
2218
2219 #[test]
2220 fn test_initialize_with_icons() {
2221 let init_result = InitializeResult {
2222 protocol_version: ProtocolVersion::default(),
2223 capabilities: ServerCapabilities::default(),
2224 server_info: Implementation {
2225 name: "icon-server".to_string(),
2226 title: None,
2227 version: "2.0.0".to_string(),
2228 icons: Some(vec![Icon {
2229 src: "https://example.com/server.png".to_string(),
2230 mime_type: Some("image/png".to_string()),
2231 sizes: Some(vec!["48x48".to_string()]),
2232 }]),
2233 website_url: Some("https://docs.example.com".to_string()),
2234 },
2235 instructions: None,
2236 };
2237
2238 let json = serde_json::to_value(&init_result).unwrap();
2239 assert!(json["serverInfo"]["icons"].is_array());
2240 assert_eq!(
2241 json["serverInfo"]["icons"][0]["src"],
2242 "https://example.com/server.png"
2243 );
2244 assert_eq!(json["serverInfo"]["icons"][0]["sizes"][0], "48x48");
2245 assert_eq!(json["serverInfo"]["websiteUrl"], "https://docs.example.com");
2246 }
2247}