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#[macro_export]
47macro_rules! object {
48 ({$($tt:tt)*}) => {
49 $crate::model::object(serde_json::json! {
50 {$($tt)*}
51 })
52 };
53}
54
55#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy, Eq)]
59#[serde(deny_unknown_fields)]
60#[cfg_attr(feature = "server", derive(schemars::JsonSchema))]
61pub struct EmptyObject {}
62
63pub trait ConstString: Default {
64 const VALUE: &str;
65 fn as_str(&self) -> &'static str {
66 Self::VALUE
67 }
68}
69#[macro_export]
70macro_rules! const_string {
71 ($name:ident = $value:literal) => {
72 #[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
73 pub struct $name;
74
75 impl ConstString for $name {
76 const VALUE: &str = $value;
77 }
78
79 impl serde::Serialize for $name {
80 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
81 where
82 S: serde::Serializer,
83 {
84 $value.serialize(serializer)
85 }
86 }
87
88 impl<'de> serde::Deserialize<'de> for $name {
89 fn deserialize<D>(deserializer: D) -> Result<$name, D::Error>
90 where
91 D: serde::Deserializer<'de>,
92 {
93 let s: String = serde::Deserialize::deserialize(deserializer)?;
94 if s == $value {
95 Ok($name)
96 } else {
97 Err(serde::de::Error::custom(format!(concat!(
98 "expect const string value \"",
99 $value,
100 "\""
101 ))))
102 }
103 }
104 }
105
106 #[cfg(feature = "schemars")]
107 impl schemars::JsonSchema for $name {
108 fn schema_name() -> Cow<'static, str> {
109 Cow::Borrowed(stringify!($name))
110 }
111
112 fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
113 use serde_json::{Map, json};
114
115 let mut schema_map = Map::new();
116 schema_map.insert("type".to_string(), json!("string"));
117 schema_map.insert("format".to_string(), json!("const"));
118 schema_map.insert("const".to_string(), json!($value));
119
120 schemars::Schema::from(schema_map)
121 }
122 }
123 };
124}
125
126const_string!(JsonRpcVersion2_0 = "2.0");
127
128#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd)]
137#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
138pub struct ProtocolVersion(Cow<'static, str>);
139
140impl Default for ProtocolVersion {
141 fn default() -> Self {
142 Self::LATEST
143 }
144}
145
146impl std::fmt::Display for ProtocolVersion {
147 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
148 self.0.fmt(f)
149 }
150}
151
152impl ProtocolVersion {
153 pub const V_2025_06_18: Self = Self(Cow::Borrowed("2025-06-18"));
154 pub const V_2025_03_26: Self = Self(Cow::Borrowed("2025-03-26"));
155 pub const V_2024_11_05: Self = Self(Cow::Borrowed("2024-11-05"));
156 pub const LATEST: Self = Self::V_2025_06_18;
157
158 pub const KNOWN_VERSIONS: &[Self] =
160 &[Self::V_2024_11_05, Self::V_2025_03_26, Self::V_2025_06_18];
161
162 pub fn as_str(&self) -> &str {
164 &self.0
165 }
166}
167
168impl Serialize for ProtocolVersion {
169 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
170 where
171 S: serde::Serializer,
172 {
173 self.0.serialize(serializer)
174 }
175}
176
177impl<'de> Deserialize<'de> for ProtocolVersion {
178 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
179 where
180 D: serde::Deserializer<'de>,
181 {
182 let s: String = Deserialize::deserialize(deserializer)?;
183 #[allow(clippy::single_match)]
184 match s.as_str() {
185 "2024-11-05" => return Ok(ProtocolVersion::V_2024_11_05),
186 "2025-03-26" => return Ok(ProtocolVersion::V_2025_03_26),
187 "2025-06-18" => return Ok(ProtocolVersion::V_2025_06_18),
188 _ => {}
189 }
190 Ok(ProtocolVersion(Cow::Owned(s)))
191 }
192}
193
194#[derive(Debug, Clone, Eq, PartialEq, Hash)]
199pub enum NumberOrString {
200 Number(i64),
202 String(Arc<str>),
204}
205
206impl NumberOrString {
207 pub fn into_json_value(self) -> Value {
208 match self {
209 NumberOrString::Number(n) => Value::Number(serde_json::Number::from(n)),
210 NumberOrString::String(s) => Value::String(s.to_string()),
211 }
212 }
213}
214
215impl std::fmt::Display for NumberOrString {
216 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
217 match self {
218 NumberOrString::Number(n) => n.fmt(f),
219 NumberOrString::String(s) => s.fmt(f),
220 }
221 }
222}
223
224impl Serialize for NumberOrString {
225 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
226 where
227 S: serde::Serializer,
228 {
229 match self {
230 NumberOrString::Number(n) => n.serialize(serializer),
231 NumberOrString::String(s) => s.serialize(serializer),
232 }
233 }
234}
235
236impl<'de> Deserialize<'de> for NumberOrString {
237 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
238 where
239 D: serde::Deserializer<'de>,
240 {
241 let value: Value = Deserialize::deserialize(deserializer)?;
242 match value {
243 Value::Number(n) => {
244 if let Some(i) = n.as_i64() {
245 Ok(NumberOrString::Number(i))
246 } else if let Some(u) = n.as_u64() {
247 if u <= i64::MAX as u64 {
249 Ok(NumberOrString::Number(u as i64))
250 } else {
251 Err(serde::de::Error::custom("Number too large for i64"))
252 }
253 } else {
254 Err(serde::de::Error::custom("Expected an integer"))
255 }
256 }
257 Value::String(s) => Ok(NumberOrString::String(s.into())),
258 _ => Err(serde::de::Error::custom("Expect number or string")),
259 }
260 }
261}
262
263#[cfg(feature = "schemars")]
264impl schemars::JsonSchema for NumberOrString {
265 fn schema_name() -> Cow<'static, str> {
266 Cow::Borrowed("NumberOrString")
267 }
268
269 fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
270 use serde_json::{Map, json};
271
272 let mut number_schema = Map::new();
273 number_schema.insert("type".to_string(), json!("number"));
274
275 let mut string_schema = Map::new();
276 string_schema.insert("type".to_string(), json!("string"));
277
278 let mut schema_map = Map::new();
279 schema_map.insert("oneOf".to_string(), json!([number_schema, string_schema]));
280
281 schemars::Schema::from(schema_map)
282 }
283}
284
285pub type RequestId = NumberOrString;
287
288#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Hash, Eq)]
293#[serde(transparent)]
294#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
295pub struct ProgressToken(pub NumberOrString);
296
297#[derive(Debug, Clone, Default)]
308#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
309#[non_exhaustive]
310pub struct Request<M = String, P = JsonObject> {
311 pub method: M,
312 pub params: P,
313 #[cfg_attr(feature = "schemars", schemars(skip))]
317 pub extensions: Extensions,
318}
319
320impl<M: Default, P> Request<M, P> {
321 pub fn new(params: P) -> Self {
322 Self {
323 method: Default::default(),
324 params,
325 extensions: Extensions::default(),
326 }
327 }
328}
329
330impl<M, P> GetExtensions for Request<M, P> {
331 fn extensions(&self) -> &Extensions {
332 &self.extensions
333 }
334 fn extensions_mut(&mut self) -> &mut Extensions {
335 &mut self.extensions
336 }
337}
338
339#[derive(Debug, Clone, Default)]
340#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
341pub struct RequestOptionalParam<M = String, P = JsonObject> {
342 pub method: M,
343 pub params: Option<P>,
345 #[cfg_attr(feature = "schemars", schemars(skip))]
349 pub extensions: Extensions,
350}
351
352impl<M: Default, P> RequestOptionalParam<M, P> {
353 pub fn with_param(params: P) -> Self {
354 Self {
355 method: Default::default(),
356 params: Some(params),
357 extensions: Extensions::default(),
358 }
359 }
360}
361
362#[derive(Debug, Clone, Default)]
363#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
364pub struct RequestNoParam<M = String> {
365 pub method: M,
366 #[cfg_attr(feature = "schemars", schemars(skip))]
370 pub extensions: Extensions,
371}
372
373impl<M> GetExtensions for RequestNoParam<M> {
374 fn extensions(&self) -> &Extensions {
375 &self.extensions
376 }
377 fn extensions_mut(&mut self) -> &mut Extensions {
378 &mut self.extensions
379 }
380}
381#[derive(Debug, Clone, Default)]
382#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
383#[non_exhaustive]
384pub struct Notification<M = String, P = JsonObject> {
385 pub method: M,
386 pub params: P,
387 #[cfg_attr(feature = "schemars", schemars(skip))]
391 pub extensions: Extensions,
392}
393
394impl<M: Default, P> Notification<M, P> {
395 pub fn new(params: P) -> Self {
396 Self {
397 method: Default::default(),
398 params,
399 extensions: Extensions::default(),
400 }
401 }
402}
403
404#[derive(Debug, Clone, Default)]
405#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
406pub struct NotificationNoParam<M = String> {
407 pub method: M,
408 #[cfg_attr(feature = "schemars", schemars(skip))]
412 pub extensions: Extensions,
413}
414
415#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
416#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
417pub struct JsonRpcRequest<R = Request> {
418 pub jsonrpc: JsonRpcVersion2_0,
419 pub id: RequestId,
420 #[serde(flatten)]
421 pub request: R,
422}
423
424impl<R> JsonRpcRequest<R> {
425 pub fn new(id: RequestId, request: R) -> Self {
427 Self {
428 jsonrpc: JsonRpcVersion2_0,
429 id,
430 request,
431 }
432 }
433}
434
435type DefaultResponse = JsonObject;
436#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
437#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
438pub struct JsonRpcResponse<R = JsonObject> {
439 pub jsonrpc: JsonRpcVersion2_0,
440 pub id: RequestId,
441 pub result: R,
442}
443
444#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
445#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
446pub struct JsonRpcError {
447 pub jsonrpc: JsonRpcVersion2_0,
448 pub id: RequestId,
449 pub error: ErrorData,
450}
451
452impl JsonRpcError {
453 pub fn new(id: RequestId, error: ErrorData) -> Self {
455 Self {
456 jsonrpc: JsonRpcVersion2_0,
457 id,
458 error,
459 }
460 }
461}
462
463#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
464#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
465pub struct JsonRpcNotification<N = Notification> {
466 pub jsonrpc: JsonRpcVersion2_0,
467 #[serde(flatten)]
468 pub notification: N,
469}
470
471#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
476#[serde(transparent)]
477#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
478pub struct ErrorCode(pub i32);
479
480impl ErrorCode {
481 pub const RESOURCE_NOT_FOUND: Self = Self(-32002);
482 pub const INVALID_REQUEST: Self = Self(-32600);
483 pub const METHOD_NOT_FOUND: Self = Self(-32601);
484 pub const INVALID_PARAMS: Self = Self(-32602);
485 pub const INTERNAL_ERROR: Self = Self(-32603);
486 pub const PARSE_ERROR: Self = Self(-32700);
487 pub const URL_ELICITATION_REQUIRED: Self = Self(-32042);
488}
489
490#[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq)]
495#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
496pub struct ErrorData {
497 pub code: ErrorCode,
499
500 pub message: Cow<'static, str>,
502
503 #[serde(skip_serializing_if = "Option::is_none")]
506 pub data: Option<Value>,
507}
508
509impl ErrorData {
510 pub fn new(
511 code: ErrorCode,
512 message: impl Into<Cow<'static, str>>,
513 data: Option<Value>,
514 ) -> Self {
515 Self {
516 code,
517 message: message.into(),
518 data,
519 }
520 }
521 pub fn resource_not_found(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
522 Self::new(ErrorCode::RESOURCE_NOT_FOUND, message, data)
523 }
524 pub fn parse_error(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
525 Self::new(ErrorCode::PARSE_ERROR, message, data)
526 }
527 pub fn invalid_request(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
528 Self::new(ErrorCode::INVALID_REQUEST, message, data)
529 }
530 pub fn method_not_found<M: ConstString>() -> Self {
531 Self::new(ErrorCode::METHOD_NOT_FOUND, M::VALUE, None)
532 }
533 pub fn invalid_params(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
534 Self::new(ErrorCode::INVALID_PARAMS, message, data)
535 }
536 pub fn internal_error(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
537 Self::new(ErrorCode::INTERNAL_ERROR, message, data)
538 }
539 pub fn url_elicitation_required(
540 message: impl Into<Cow<'static, str>>,
541 data: Option<Value>,
542 ) -> Self {
543 Self::new(ErrorCode::URL_ELICITATION_REQUIRED, message, data)
544 }
545}
546
547#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
553#[serde(untagged)]
554#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
555pub enum JsonRpcMessage<Req = Request, Resp = DefaultResponse, Noti = Notification> {
556 Request(JsonRpcRequest<Req>),
558 Response(JsonRpcResponse<Resp>),
560 Notification(JsonRpcNotification<Noti>),
562 Error(JsonRpcError),
564}
565
566impl<Req, Resp, Not> JsonRpcMessage<Req, Resp, Not> {
567 #[inline]
568 pub const fn request(request: Req, id: RequestId) -> Self {
569 JsonRpcMessage::Request(JsonRpcRequest {
570 jsonrpc: JsonRpcVersion2_0,
571 id,
572 request,
573 })
574 }
575 #[inline]
576 pub const fn response(response: Resp, id: RequestId) -> Self {
577 JsonRpcMessage::Response(JsonRpcResponse {
578 jsonrpc: JsonRpcVersion2_0,
579 id,
580 result: response,
581 })
582 }
583 #[inline]
584 pub const fn error(error: ErrorData, id: RequestId) -> Self {
585 JsonRpcMessage::Error(JsonRpcError {
586 jsonrpc: JsonRpcVersion2_0,
587 id,
588 error,
589 })
590 }
591 #[inline]
592 pub const fn notification(notification: Not) -> Self {
593 JsonRpcMessage::Notification(JsonRpcNotification {
594 jsonrpc: JsonRpcVersion2_0,
595 notification,
596 })
597 }
598 pub fn into_request(self) -> Option<(Req, RequestId)> {
599 match self {
600 JsonRpcMessage::Request(r) => Some((r.request, r.id)),
601 _ => None,
602 }
603 }
604 pub fn into_response(self) -> Option<(Resp, RequestId)> {
605 match self {
606 JsonRpcMessage::Response(r) => Some((r.result, r.id)),
607 _ => None,
608 }
609 }
610 pub fn into_notification(self) -> Option<Not> {
611 match self {
612 JsonRpcMessage::Notification(n) => Some(n.notification),
613 _ => None,
614 }
615 }
616 pub fn into_error(self) -> Option<(ErrorData, RequestId)> {
617 match self {
618 JsonRpcMessage::Error(e) => Some((e.error, e.id)),
619 _ => None,
620 }
621 }
622 pub fn into_result(self) -> Option<(Result<Resp, ErrorData>, RequestId)> {
623 match self {
624 JsonRpcMessage::Response(r) => Some((Ok(r.result), r.id)),
625 JsonRpcMessage::Error(e) => Some((Err(e.error), e.id)),
626
627 _ => None,
628 }
629 }
630}
631
632pub type EmptyResult = EmptyObject;
639
640impl From<()> for EmptyResult {
641 fn from(_value: ()) -> Self {
642 EmptyResult {}
643 }
644}
645
646impl From<EmptyResult> for () {
647 fn from(_value: EmptyResult) {}
648}
649
650#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
652#[serde(transparent)]
653#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
654pub struct CustomResult(pub Value);
655
656impl CustomResult {
657 pub fn new(result: Value) -> Self {
658 Self(result)
659 }
660
661 pub fn result_as<T: DeserializeOwned>(&self) -> Result<T, serde_json::Error> {
663 serde_json::from_value(self.0.clone())
664 }
665}
666
667#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
668#[serde(rename_all = "camelCase")]
669#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
670pub struct CancelledNotificationParam {
671 pub request_id: RequestId,
672 pub reason: Option<String>,
673}
674
675const_string!(CancelledNotificationMethod = "notifications/cancelled");
676
677pub type CancelledNotification =
686 Notification<CancelledNotificationMethod, CancelledNotificationParam>;
687
688#[derive(Debug, Clone)]
693#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
694pub struct CustomNotification {
695 pub method: String,
696 pub params: Option<Value>,
697 #[cfg_attr(feature = "schemars", schemars(skip))]
701 pub extensions: Extensions,
702}
703
704impl CustomNotification {
705 pub fn new(method: impl Into<String>, params: Option<Value>) -> Self {
706 Self {
707 method: method.into(),
708 params,
709 extensions: Extensions::default(),
710 }
711 }
712
713 pub fn params_as<T: DeserializeOwned>(&self) -> Result<Option<T>, serde_json::Error> {
715 self.params
716 .as_ref()
717 .map(|params| serde_json::from_value(params.clone()))
718 .transpose()
719 }
720}
721
722#[derive(Debug, Clone)]
727#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
728pub struct CustomRequest {
729 pub method: String,
730 pub params: Option<Value>,
731 #[cfg_attr(feature = "schemars", schemars(skip))]
735 pub extensions: Extensions,
736}
737
738impl CustomRequest {
739 pub fn new(method: impl Into<String>, params: Option<Value>) -> Self {
740 Self {
741 method: method.into(),
742 params,
743 extensions: Extensions::default(),
744 }
745 }
746
747 pub fn params_as<T: DeserializeOwned>(&self) -> Result<Option<T>, serde_json::Error> {
749 self.params
750 .as_ref()
751 .map(|params| serde_json::from_value(params.clone()))
752 .transpose()
753 }
754}
755
756const_string!(InitializeResultMethod = "initialize");
757pub type InitializeRequest = Request<InitializeResultMethod, InitializeRequestParams>;
760
761const_string!(InitializedNotificationMethod = "notifications/initialized");
762pub type InitializedNotification = NotificationNoParam<InitializedNotificationMethod>;
764
765#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
770#[serde(rename_all = "camelCase")]
771#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
772#[non_exhaustive]
773pub struct InitializeRequestParams {
774 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
776 pub meta: Option<Meta>,
777 pub protocol_version: ProtocolVersion,
779 pub capabilities: ClientCapabilities,
781 pub client_info: Implementation,
783}
784
785impl InitializeRequestParams {
786 pub fn new(capabilities: ClientCapabilities, client_info: Implementation) -> Self {
788 Self {
789 meta: None,
790 protocol_version: ProtocolVersion::default(),
791 capabilities,
792 client_info,
793 }
794 }
795
796 pub fn with_protocol_version(mut self, protocol_version: ProtocolVersion) -> Self {
797 self.protocol_version = protocol_version;
798 self
799 }
800}
801
802impl RequestParamsMeta for InitializeRequestParams {
803 fn meta(&self) -> Option<&Meta> {
804 self.meta.as_ref()
805 }
806 fn meta_mut(&mut self) -> &mut Option<Meta> {
807 &mut self.meta
808 }
809}
810
811#[deprecated(since = "0.13.0", note = "Use InitializeRequestParams instead")]
813pub type InitializeRequestParam = InitializeRequestParams;
814
815#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
820#[serde(rename_all = "camelCase")]
821#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
822#[non_exhaustive]
823pub struct InitializeResult {
824 pub protocol_version: ProtocolVersion,
826 pub capabilities: ServerCapabilities,
828 pub server_info: Implementation,
830 #[serde(skip_serializing_if = "Option::is_none")]
832 pub instructions: Option<String>,
833}
834
835impl InitializeResult {
836 pub fn new(capabilities: ServerCapabilities) -> Self {
838 Self {
839 protocol_version: ProtocolVersion::default(),
840 capabilities,
841 server_info: Implementation::from_build_env(),
842 instructions: None,
843 }
844 }
845
846 pub fn with_instructions(mut self, instructions: impl Into<String>) -> Self {
848 self.instructions = Some(instructions.into());
849 self
850 }
851
852 pub fn with_server_info(mut self, server_info: Implementation) -> Self {
854 self.server_info = server_info;
855 self
856 }
857
858 pub fn with_protocol_version(mut self, protocol_version: ProtocolVersion) -> Self {
860 self.protocol_version = protocol_version;
861 self
862 }
863}
864
865pub type ServerInfo = InitializeResult;
866pub type ClientInfo = InitializeRequestParams;
867
868#[allow(clippy::derivable_impls)]
869impl Default for ServerInfo {
870 fn default() -> Self {
871 ServerInfo {
872 protocol_version: ProtocolVersion::default(),
873 capabilities: ServerCapabilities::default(),
874 server_info: Implementation::from_build_env(),
875 instructions: None,
876 }
877 }
878}
879
880#[allow(clippy::derivable_impls)]
881impl Default for ClientInfo {
882 fn default() -> Self {
883 ClientInfo {
884 meta: None,
885 protocol_version: ProtocolVersion::default(),
886 capabilities: ClientCapabilities::default(),
887 client_info: Implementation::from_build_env(),
888 }
889 }
890}
891
892#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
902#[serde(rename_all = "camelCase")]
903#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
904#[non_exhaustive]
905pub struct Icon {
906 pub src: String,
908 #[serde(skip_serializing_if = "Option::is_none")]
910 pub mime_type: Option<String>,
911 #[serde(skip_serializing_if = "Option::is_none")]
913 pub sizes: Option<Vec<String>>,
914}
915
916impl Icon {
917 pub fn new(src: impl Into<String>) -> Self {
919 Self {
920 src: src.into(),
921 mime_type: None,
922 sizes: None,
923 }
924 }
925
926 pub fn with_mime_type(mut self, mime_type: impl Into<String>) -> Self {
928 self.mime_type = Some(mime_type.into());
929 self
930 }
931
932 pub fn with_sizes(mut self, sizes: Vec<String>) -> Self {
934 self.sizes = Some(sizes);
935 self
936 }
937}
938
939#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
940#[serde(rename_all = "camelCase")]
941#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
942#[non_exhaustive]
943pub struct Implementation {
944 pub name: String,
945 #[serde(skip_serializing_if = "Option::is_none")]
946 pub title: Option<String>,
947 pub version: String,
948 #[serde(skip_serializing_if = "Option::is_none")]
949 pub description: Option<String>,
950 #[serde(skip_serializing_if = "Option::is_none")]
951 pub icons: Option<Vec<Icon>>,
952 #[serde(skip_serializing_if = "Option::is_none")]
953 pub website_url: Option<String>,
954}
955
956impl Default for Implementation {
957 fn default() -> Self {
958 Self::from_build_env()
959 }
960}
961
962impl Implementation {
963 pub fn new(name: impl Into<String>, version: impl Into<String>) -> Self {
965 Self {
966 name: name.into(),
967 title: None,
968 version: version.into(),
969 description: None,
970 icons: None,
971 website_url: None,
972 }
973 }
974
975 pub fn from_build_env() -> Self {
976 Implementation {
977 name: env!("CARGO_CRATE_NAME").to_owned(),
978 title: None,
979 version: env!("CARGO_PKG_VERSION").to_owned(),
980 description: None,
981 icons: None,
982 website_url: None,
983 }
984 }
985
986 pub fn with_title(mut self, title: impl Into<String>) -> Self {
988 self.title = Some(title.into());
989 self
990 }
991
992 pub fn with_description(mut self, description: impl Into<String>) -> Self {
994 self.description = Some(description.into());
995 self
996 }
997
998 pub fn with_icons(mut self, icons: Vec<Icon>) -> Self {
1000 self.icons = Some(icons);
1001 self
1002 }
1003
1004 pub fn with_website_url(mut self, website_url: impl Into<String>) -> Self {
1006 self.website_url = Some(website_url.into());
1007 self
1008 }
1009}
1010
1011#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
1012#[serde(rename_all = "camelCase")]
1013#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1014#[non_exhaustive]
1015pub struct PaginatedRequestParams {
1016 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1018 pub meta: Option<Meta>,
1019 #[serde(skip_serializing_if = "Option::is_none")]
1020 pub cursor: Option<String>,
1021}
1022
1023impl PaginatedRequestParams {
1024 pub fn with_cursor(mut self, cursor: Option<String>) -> Self {
1025 self.cursor = cursor;
1026 self
1027 }
1028}
1029
1030impl RequestParamsMeta for PaginatedRequestParams {
1031 fn meta(&self) -> Option<&Meta> {
1032 self.meta.as_ref()
1033 }
1034 fn meta_mut(&mut self) -> &mut Option<Meta> {
1035 &mut self.meta
1036 }
1037}
1038
1039#[deprecated(since = "0.13.0", note = "Use PaginatedRequestParams instead")]
1041pub type PaginatedRequestParam = PaginatedRequestParams;
1042const_string!(PingRequestMethod = "ping");
1047pub type PingRequest = RequestNoParam<PingRequestMethod>;
1048
1049const_string!(ProgressNotificationMethod = "notifications/progress");
1050#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1051#[serde(rename_all = "camelCase")]
1052#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1053pub struct ProgressNotificationParam {
1054 pub progress_token: ProgressToken,
1055 pub progress: f64,
1057 #[serde(skip_serializing_if = "Option::is_none")]
1059 pub total: Option<f64>,
1060 #[serde(skip_serializing_if = "Option::is_none")]
1062 pub message: Option<String>,
1063}
1064
1065impl ProgressNotificationParam {
1066 pub fn new(progress_token: ProgressToken, progress: f64) -> Self {
1068 Self {
1069 progress_token,
1070 progress,
1071 total: None,
1072 message: None,
1073 }
1074 }
1075
1076 pub fn with_total(mut self, total: f64) -> Self {
1078 self.total = Some(total);
1079 self
1080 }
1081
1082 pub fn with_message(mut self, message: impl Into<String>) -> Self {
1084 self.message = Some(message.into());
1085 self
1086 }
1087}
1088
1089pub type ProgressNotification = Notification<ProgressNotificationMethod, ProgressNotificationParam>;
1090
1091pub type Cursor = String;
1092
1093macro_rules! paginated_result {
1094 ($t:ident {
1095 $i_item: ident: $t_item: ty
1096 }) => {
1097 #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
1098 #[serde(rename_all = "camelCase")]
1099 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1100 pub struct $t {
1101 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1102 pub meta: Option<Meta>,
1103 #[serde(skip_serializing_if = "Option::is_none")]
1104 pub next_cursor: Option<Cursor>,
1105 pub $i_item: $t_item,
1106 }
1107
1108 impl $t {
1109 pub fn with_all_items(
1110 items: $t_item,
1111 ) -> Self {
1112 Self {
1113 meta: None,
1114 next_cursor: None,
1115 $i_item: items,
1116 }
1117 }
1118 }
1119 };
1120}
1121
1122const_string!(ListResourcesRequestMethod = "resources/list");
1127pub type ListResourcesRequest =
1129 RequestOptionalParam<ListResourcesRequestMethod, PaginatedRequestParams>;
1130
1131paginated_result!(ListResourcesResult {
1132 resources: Vec<Resource>
1133});
1134
1135const_string!(ListResourceTemplatesRequestMethod = "resources/templates/list");
1136pub type ListResourceTemplatesRequest =
1138 RequestOptionalParam<ListResourceTemplatesRequestMethod, PaginatedRequestParams>;
1139
1140paginated_result!(ListResourceTemplatesResult {
1141 resource_templates: Vec<ResourceTemplate>
1142});
1143
1144const_string!(ReadResourceRequestMethod = "resources/read");
1145#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1147#[serde(rename_all = "camelCase")]
1148#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1149#[non_exhaustive]
1150pub struct ReadResourceRequestParams {
1151 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1153 pub meta: Option<Meta>,
1154 pub uri: String,
1156}
1157
1158impl ReadResourceRequestParams {
1159 pub fn new(uri: impl Into<String>) -> Self {
1161 Self {
1162 meta: None,
1163 uri: uri.into(),
1164 }
1165 }
1166
1167 pub fn with_meta(mut self, meta: Meta) -> Self {
1169 self.meta = Some(meta);
1170 self
1171 }
1172}
1173
1174impl RequestParamsMeta for ReadResourceRequestParams {
1175 fn meta(&self) -> Option<&Meta> {
1176 self.meta.as_ref()
1177 }
1178 fn meta_mut(&mut self) -> &mut Option<Meta> {
1179 &mut self.meta
1180 }
1181}
1182
1183#[deprecated(since = "0.13.0", note = "Use ReadResourceRequestParams instead")]
1185pub type ReadResourceRequestParam = ReadResourceRequestParams;
1186
1187#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1189#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1190#[non_exhaustive]
1191pub struct ReadResourceResult {
1192 pub contents: Vec<ResourceContents>,
1194}
1195
1196impl ReadResourceResult {
1197 pub fn new(contents: Vec<ResourceContents>) -> Self {
1199 Self { contents }
1200 }
1201}
1202
1203pub type ReadResourceRequest = Request<ReadResourceRequestMethod, ReadResourceRequestParams>;
1205
1206const_string!(ResourceListChangedNotificationMethod = "notifications/resources/list_changed");
1207pub type ResourceListChangedNotification =
1209 NotificationNoParam<ResourceListChangedNotificationMethod>;
1210
1211const_string!(SubscribeRequestMethod = "resources/subscribe");
1212#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1214#[serde(rename_all = "camelCase")]
1215#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1216#[non_exhaustive]
1217pub struct SubscribeRequestParams {
1218 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1220 pub meta: Option<Meta>,
1221 pub uri: String,
1223}
1224
1225impl SubscribeRequestParams {
1226 pub fn new(uri: impl Into<String>) -> Self {
1228 Self {
1229 meta: None,
1230 uri: uri.into(),
1231 }
1232 }
1233}
1234
1235impl RequestParamsMeta for SubscribeRequestParams {
1236 fn meta(&self) -> Option<&Meta> {
1237 self.meta.as_ref()
1238 }
1239 fn meta_mut(&mut self) -> &mut Option<Meta> {
1240 &mut self.meta
1241 }
1242}
1243
1244#[deprecated(since = "0.13.0", note = "Use SubscribeRequestParams instead")]
1246pub type SubscribeRequestParam = SubscribeRequestParams;
1247
1248pub type SubscribeRequest = Request<SubscribeRequestMethod, SubscribeRequestParams>;
1250
1251const_string!(UnsubscribeRequestMethod = "resources/unsubscribe");
1252#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1254#[serde(rename_all = "camelCase")]
1255#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1256#[non_exhaustive]
1257pub struct UnsubscribeRequestParams {
1258 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1260 pub meta: Option<Meta>,
1261 pub uri: String,
1263}
1264
1265impl RequestParamsMeta for UnsubscribeRequestParams {
1266 fn meta(&self) -> Option<&Meta> {
1267 self.meta.as_ref()
1268 }
1269 fn meta_mut(&mut self) -> &mut Option<Meta> {
1270 &mut self.meta
1271 }
1272}
1273
1274#[deprecated(since = "0.13.0", note = "Use UnsubscribeRequestParams instead")]
1276pub type UnsubscribeRequestParam = UnsubscribeRequestParams;
1277
1278pub type UnsubscribeRequest = Request<UnsubscribeRequestMethod, UnsubscribeRequestParams>;
1280
1281const_string!(ResourceUpdatedNotificationMethod = "notifications/resources/updated");
1282#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1284#[serde(rename_all = "camelCase")]
1285#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1286pub struct ResourceUpdatedNotificationParam {
1287 pub uri: String,
1289}
1290
1291impl ResourceUpdatedNotificationParam {
1292 pub fn new(uri: impl Into<String>) -> Self {
1294 Self { uri: uri.into() }
1295 }
1296}
1297
1298pub type ResourceUpdatedNotification =
1300 Notification<ResourceUpdatedNotificationMethod, ResourceUpdatedNotificationParam>;
1301
1302const_string!(ListPromptsRequestMethod = "prompts/list");
1307pub type ListPromptsRequest =
1309 RequestOptionalParam<ListPromptsRequestMethod, PaginatedRequestParams>;
1310
1311paginated_result!(ListPromptsResult {
1312 prompts: Vec<Prompt>
1313});
1314
1315const_string!(GetPromptRequestMethod = "prompts/get");
1316#[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq)]
1318#[serde(rename_all = "camelCase")]
1319#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1320#[non_exhaustive]
1321pub struct GetPromptRequestParams {
1322 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1324 pub meta: Option<Meta>,
1325 pub name: String,
1326 #[serde(skip_serializing_if = "Option::is_none")]
1327 pub arguments: Option<JsonObject>,
1328}
1329
1330impl GetPromptRequestParams {
1331 pub fn new(name: impl Into<String>) -> Self {
1333 Self {
1334 meta: None,
1335 name: name.into(),
1336 arguments: None,
1337 }
1338 }
1339
1340 pub fn with_arguments(mut self, arguments: JsonObject) -> Self {
1342 self.arguments = Some(arguments);
1343 self
1344 }
1345
1346 pub fn with_meta(mut self, meta: Meta) -> Self {
1348 self.meta = Some(meta);
1349 self
1350 }
1351}
1352
1353impl RequestParamsMeta for GetPromptRequestParams {
1354 fn meta(&self) -> Option<&Meta> {
1355 self.meta.as_ref()
1356 }
1357 fn meta_mut(&mut self) -> &mut Option<Meta> {
1358 &mut self.meta
1359 }
1360}
1361
1362#[deprecated(since = "0.13.0", note = "Use GetPromptRequestParams instead")]
1364pub type GetPromptRequestParam = GetPromptRequestParams;
1365
1366pub type GetPromptRequest = Request<GetPromptRequestMethod, GetPromptRequestParams>;
1368
1369const_string!(PromptListChangedNotificationMethod = "notifications/prompts/list_changed");
1370pub type PromptListChangedNotification = NotificationNoParam<PromptListChangedNotificationMethod>;
1372
1373const_string!(ToolListChangedNotificationMethod = "notifications/tools/list_changed");
1374pub type ToolListChangedNotification = NotificationNoParam<ToolListChangedNotificationMethod>;
1376
1377#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
1383#[serde(rename_all = "lowercase")] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1385pub enum LoggingLevel {
1386 Debug,
1387 Info,
1388 Notice,
1389 Warning,
1390 Error,
1391 Critical,
1392 Alert,
1393 Emergency,
1394}
1395
1396const_string!(SetLevelRequestMethod = "logging/setLevel");
1397#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1399#[serde(rename_all = "camelCase")]
1400#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1401#[non_exhaustive]
1402pub struct SetLevelRequestParams {
1403 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1405 pub meta: Option<Meta>,
1406 pub level: LoggingLevel,
1408}
1409
1410impl SetLevelRequestParams {
1411 pub fn new(level: LoggingLevel) -> Self {
1413 Self { meta: None, level }
1414 }
1415}
1416
1417impl RequestParamsMeta for SetLevelRequestParams {
1418 fn meta(&self) -> Option<&Meta> {
1419 self.meta.as_ref()
1420 }
1421 fn meta_mut(&mut self) -> &mut Option<Meta> {
1422 &mut self.meta
1423 }
1424}
1425
1426#[deprecated(since = "0.13.0", note = "Use SetLevelRequestParams instead")]
1428pub type SetLevelRequestParam = SetLevelRequestParams;
1429
1430pub type SetLevelRequest = Request<SetLevelRequestMethod, SetLevelRequestParams>;
1432
1433const_string!(LoggingMessageNotificationMethod = "notifications/message");
1434#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1436#[serde(rename_all = "camelCase")]
1437#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1438pub struct LoggingMessageNotificationParam {
1439 pub level: LoggingLevel,
1441 #[serde(skip_serializing_if = "Option::is_none")]
1443 pub logger: Option<String>,
1444 pub data: Value,
1446}
1447
1448impl LoggingMessageNotificationParam {
1449 pub fn new(level: LoggingLevel, data: Value) -> Self {
1451 Self {
1452 level,
1453 logger: None,
1454 data,
1455 }
1456 }
1457
1458 pub fn with_logger(mut self, logger: impl Into<String>) -> Self {
1460 self.logger = Some(logger.into());
1461 self
1462 }
1463}
1464
1465pub type LoggingMessageNotification =
1467 Notification<LoggingMessageNotificationMethod, LoggingMessageNotificationParam>;
1468
1469const_string!(CreateMessageRequestMethod = "sampling/createMessage");
1474pub type CreateMessageRequest = Request<CreateMessageRequestMethod, CreateMessageRequestParams>;
1475
1476#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1481#[serde(rename_all = "camelCase")]
1482#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1483pub enum Role {
1484 User,
1486 Assistant,
1488}
1489
1490#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1492#[serde(rename_all = "lowercase")]
1493#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1494pub enum ToolChoiceMode {
1495 Auto,
1497 Required,
1499 None,
1501}
1502
1503impl Default for ToolChoiceMode {
1504 fn default() -> Self {
1505 Self::Auto
1506 }
1507}
1508
1509#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
1511#[serde(rename_all = "camelCase")]
1512#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1513#[non_exhaustive]
1514pub struct ToolChoice {
1515 #[serde(skip_serializing_if = "Option::is_none")]
1516 pub mode: Option<ToolChoiceMode>,
1517}
1518
1519impl ToolChoice {
1520 pub fn auto() -> Self {
1521 Self {
1522 mode: Some(ToolChoiceMode::Auto),
1523 }
1524 }
1525
1526 pub fn required() -> Self {
1527 Self {
1528 mode: Some(ToolChoiceMode::Required),
1529 }
1530 }
1531
1532 pub fn none() -> Self {
1533 Self {
1534 mode: Some(ToolChoiceMode::None),
1535 }
1536 }
1537}
1538
1539#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1541#[serde(untagged)]
1542#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1543pub enum SamplingContent<T> {
1544 Single(T),
1545 Multiple(Vec<T>),
1546}
1547
1548impl<T> SamplingContent<T> {
1549 pub fn into_vec(self) -> Vec<T> {
1551 match self {
1552 SamplingContent::Single(item) => vec![item],
1553 SamplingContent::Multiple(items) => items,
1554 }
1555 }
1556
1557 pub fn is_empty(&self) -> bool {
1559 match self {
1560 SamplingContent::Single(_) => false,
1561 SamplingContent::Multiple(items) => items.is_empty(),
1562 }
1563 }
1564
1565 pub fn len(&self) -> usize {
1567 match self {
1568 SamplingContent::Single(_) => 1,
1569 SamplingContent::Multiple(items) => items.len(),
1570 }
1571 }
1572}
1573
1574impl<T> Default for SamplingContent<T> {
1575 fn default() -> Self {
1576 SamplingContent::Multiple(Vec::new())
1577 }
1578}
1579
1580impl<T> SamplingContent<T> {
1581 pub fn first(&self) -> Option<&T> {
1583 match self {
1584 SamplingContent::Single(item) => Some(item),
1585 SamplingContent::Multiple(items) => items.first(),
1586 }
1587 }
1588
1589 pub fn iter(&self) -> impl Iterator<Item = &T> {
1591 let items: Vec<&T> = match self {
1592 SamplingContent::Single(item) => vec![item],
1593 SamplingContent::Multiple(items) => items.iter().collect(),
1594 };
1595 items.into_iter()
1596 }
1597}
1598
1599impl SamplingMessageContent {
1600 pub fn as_text(&self) -> Option<&RawTextContent> {
1602 match self {
1603 SamplingMessageContent::Text(text) => Some(text),
1604 _ => None,
1605 }
1606 }
1607
1608 pub fn as_tool_use(&self) -> Option<&ToolUseContent> {
1610 match self {
1611 SamplingMessageContent::ToolUse(tool_use) => Some(tool_use),
1612 _ => None,
1613 }
1614 }
1615
1616 pub fn as_tool_result(&self) -> Option<&ToolResultContent> {
1618 match self {
1619 SamplingMessageContent::ToolResult(tool_result) => Some(tool_result),
1620 _ => None,
1621 }
1622 }
1623}
1624
1625impl<T> From<T> for SamplingContent<T> {
1626 fn from(item: T) -> Self {
1627 SamplingContent::Single(item)
1628 }
1629}
1630
1631impl<T> From<Vec<T>> for SamplingContent<T> {
1632 fn from(items: Vec<T>) -> Self {
1633 SamplingContent::Multiple(items)
1634 }
1635}
1636
1637#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1643#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1644#[non_exhaustive]
1645pub struct SamplingMessage {
1646 pub role: Role,
1648 pub content: SamplingContent<SamplingMessageContent>,
1650 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1651 pub meta: Option<Meta>,
1652}
1653
1654#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1656#[serde(tag = "type", rename_all = "snake_case")]
1657#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1658pub enum SamplingMessageContent {
1659 Text(RawTextContent),
1660 Image(RawImageContent),
1661 Audio(RawAudioContent),
1662 ToolUse(ToolUseContent),
1664 ToolResult(ToolResultContent),
1666}
1667
1668impl SamplingMessageContent {
1669 pub fn text(text: impl Into<String>) -> Self {
1671 Self::Text(RawTextContent {
1672 text: text.into(),
1673 meta: None,
1674 })
1675 }
1676
1677 pub fn tool_use(id: impl Into<String>, name: impl Into<String>, input: JsonObject) -> Self {
1678 Self::ToolUse(ToolUseContent::new(id, name, input))
1679 }
1680
1681 pub fn tool_result(tool_use_id: impl Into<String>, content: Vec<Content>) -> Self {
1682 Self::ToolResult(ToolResultContent::new(tool_use_id, content))
1683 }
1684}
1685
1686impl SamplingMessage {
1687 pub fn new(role: Role, content: impl Into<SamplingMessageContent>) -> Self {
1688 Self {
1689 role,
1690 content: SamplingContent::Single(content.into()),
1691 meta: None,
1692 }
1693 }
1694
1695 pub fn new_multiple(role: Role, contents: Vec<SamplingMessageContent>) -> Self {
1696 Self {
1697 role,
1698 content: SamplingContent::Multiple(contents),
1699 meta: None,
1700 }
1701 }
1702
1703 pub fn user_text(text: impl Into<String>) -> Self {
1704 Self::new(Role::User, SamplingMessageContent::text(text))
1705 }
1706
1707 pub fn assistant_text(text: impl Into<String>) -> Self {
1708 Self::new(Role::Assistant, SamplingMessageContent::text(text))
1709 }
1710
1711 pub fn user_tool_result(tool_use_id: impl Into<String>, content: Vec<Content>) -> Self {
1712 Self::new(
1713 Role::User,
1714 SamplingMessageContent::tool_result(tool_use_id, content),
1715 )
1716 }
1717
1718 pub fn assistant_tool_use(
1719 id: impl Into<String>,
1720 name: impl Into<String>,
1721 input: JsonObject,
1722 ) -> Self {
1723 Self::new(
1724 Role::Assistant,
1725 SamplingMessageContent::tool_use(id, name, input),
1726 )
1727 }
1728}
1729
1730impl From<RawTextContent> for SamplingMessageContent {
1732 fn from(text: RawTextContent) -> Self {
1733 SamplingMessageContent::Text(text)
1734 }
1735}
1736
1737impl From<String> for SamplingMessageContent {
1739 fn from(text: String) -> Self {
1740 SamplingMessageContent::text(text)
1741 }
1742}
1743
1744impl From<&str> for SamplingMessageContent {
1745 fn from(text: &str) -> Self {
1746 SamplingMessageContent::text(text)
1747 }
1748}
1749
1750impl TryFrom<Content> for SamplingMessageContent {
1753 type Error = &'static str;
1754
1755 fn try_from(content: Content) -> Result<Self, Self::Error> {
1756 match content.raw {
1757 RawContent::Text(text) => Ok(SamplingMessageContent::Text(text)),
1758 RawContent::Image(image) => Ok(SamplingMessageContent::Image(image)),
1759 RawContent::Audio(audio) => Ok(SamplingMessageContent::Audio(audio)),
1760 RawContent::Resource(_) => {
1761 Err("Resource content is not supported in sampling messages")
1762 }
1763 RawContent::ResourceLink(_) => {
1764 Err("ResourceLink content is not supported in sampling messages")
1765 }
1766 }
1767 }
1768}
1769
1770impl TryFrom<Content> for SamplingContent<SamplingMessageContent> {
1772 type Error = &'static str;
1773
1774 fn try_from(content: Content) -> Result<Self, Self::Error> {
1775 Ok(SamplingContent::Single(content.try_into()?))
1776 }
1777}
1778
1779#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1784#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1785pub enum ContextInclusion {
1786 #[serde(rename = "allServers")]
1788 AllServers,
1789 #[serde(rename = "none")]
1791 None,
1792 #[serde(rename = "thisServer")]
1794 ThisServer,
1795}
1796
1797#[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq)]
1806#[serde(rename_all = "camelCase")]
1807#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1808#[non_exhaustive]
1809pub struct CreateMessageRequestParams {
1810 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1812 pub meta: Option<Meta>,
1813 #[serde(skip_serializing_if = "Option::is_none")]
1815 pub task: Option<JsonObject>,
1816 pub messages: Vec<SamplingMessage>,
1818 #[serde(skip_serializing_if = "Option::is_none")]
1820 pub model_preferences: Option<ModelPreferences>,
1821 #[serde(skip_serializing_if = "Option::is_none")]
1823 pub system_prompt: Option<String>,
1824 #[serde(skip_serializing_if = "Option::is_none")]
1826 pub include_context: Option<ContextInclusion>,
1827 #[serde(skip_serializing_if = "Option::is_none")]
1829 pub temperature: Option<f32>,
1830 pub max_tokens: u32,
1832 #[serde(skip_serializing_if = "Option::is_none")]
1834 pub stop_sequences: Option<Vec<String>>,
1835 #[serde(skip_serializing_if = "Option::is_none")]
1837 pub metadata: Option<Value>,
1838 #[serde(skip_serializing_if = "Option::is_none")]
1840 pub tools: Option<Vec<Tool>>,
1841 #[serde(skip_serializing_if = "Option::is_none")]
1843 pub tool_choice: Option<ToolChoice>,
1844}
1845
1846impl RequestParamsMeta for CreateMessageRequestParams {
1847 fn meta(&self) -> Option<&Meta> {
1848 self.meta.as_ref()
1849 }
1850 fn meta_mut(&mut self) -> &mut Option<Meta> {
1851 &mut self.meta
1852 }
1853}
1854
1855impl TaskAugmentedRequestParamsMeta for CreateMessageRequestParams {
1856 fn task(&self) -> Option<&JsonObject> {
1857 self.task.as_ref()
1858 }
1859 fn task_mut(&mut self) -> &mut Option<JsonObject> {
1860 &mut self.task
1861 }
1862}
1863
1864impl CreateMessageRequestParams {
1865 pub fn new(messages: Vec<SamplingMessage>, max_tokens: u32) -> Self {
1867 Self {
1868 meta: None,
1869 task: None,
1870 messages,
1871 model_preferences: None,
1872 system_prompt: None,
1873 include_context: None,
1874 temperature: None,
1875 max_tokens,
1876 stop_sequences: None,
1877 metadata: None,
1878 tools: None,
1879 tool_choice: None,
1880 }
1881 }
1882
1883 pub fn with_model_preferences(mut self, model_preferences: ModelPreferences) -> Self {
1885 self.model_preferences = Some(model_preferences);
1886 self
1887 }
1888
1889 pub fn with_system_prompt(mut self, system_prompt: impl Into<String>) -> Self {
1891 self.system_prompt = Some(system_prompt.into());
1892 self
1893 }
1894
1895 pub fn with_include_context(mut self, include_context: ContextInclusion) -> Self {
1897 self.include_context = Some(include_context);
1898 self
1899 }
1900
1901 pub fn with_temperature(mut self, temperature: f32) -> Self {
1903 self.temperature = Some(temperature);
1904 self
1905 }
1906
1907 pub fn with_stop_sequences(mut self, stop_sequences: Vec<String>) -> Self {
1909 self.stop_sequences = Some(stop_sequences);
1910 self
1911 }
1912
1913 pub fn with_metadata(mut self, metadata: Value) -> Self {
1915 self.metadata = Some(metadata);
1916 self
1917 }
1918
1919 pub fn with_tools(mut self, tools: Vec<Tool>) -> Self {
1921 self.tools = Some(tools);
1922 self
1923 }
1924
1925 pub fn with_tool_choice(mut self, tool_choice: ToolChoice) -> Self {
1927 self.tool_choice = Some(tool_choice);
1928 self
1929 }
1930
1931 pub fn validate(&self) -> Result<(), String> {
1939 for msg in &self.messages {
1940 for content in msg.content.iter() {
1941 match content {
1943 SamplingMessageContent::ToolUse(_) if msg.role != Role::Assistant => {
1944 return Err("ToolUse content is only allowed in assistant messages".into());
1945 }
1946 SamplingMessageContent::ToolResult(_) if msg.role != Role::User => {
1947 return Err("ToolResult content is only allowed in user messages".into());
1948 }
1949 _ => {}
1950 }
1951 }
1952
1953 let contents: Vec<_> = msg.content.iter().collect();
1955 let has_tool_result = contents
1956 .iter()
1957 .any(|c| matches!(c, SamplingMessageContent::ToolResult(_)));
1958 if has_tool_result
1959 && contents
1960 .iter()
1961 .any(|c| !matches!(c, SamplingMessageContent::ToolResult(_)))
1962 {
1963 return Err(
1964 "SamplingMessage with tool result content MUST NOT contain other content types"
1965 .into(),
1966 );
1967 }
1968 }
1969
1970 self.validate_tool_use_result_balance()?;
1972
1973 Ok(())
1974 }
1975
1976 fn validate_tool_use_result_balance(&self) -> Result<(), String> {
1977 let mut pending_tool_use_ids: Vec<String> = Vec::new();
1978 for msg in &self.messages {
1979 if msg.role == Role::Assistant {
1980 for content in msg.content.iter() {
1981 if let SamplingMessageContent::ToolUse(tu) = content {
1982 pending_tool_use_ids.push(tu.id.clone());
1983 }
1984 }
1985 } else if msg.role == Role::User {
1986 for content in msg.content.iter() {
1987 if let SamplingMessageContent::ToolResult(tr) = content {
1988 if !pending_tool_use_ids.contains(&tr.tool_use_id) {
1989 return Err(format!(
1990 "ToolResult with toolUseId '{}' has no matching ToolUse",
1991 tr.tool_use_id
1992 ));
1993 }
1994 pending_tool_use_ids.retain(|id| id != &tr.tool_use_id);
1995 }
1996 }
1997 }
1998 }
1999 if !pending_tool_use_ids.is_empty() {
2000 return Err(format!(
2001 "ToolUse with id(s) {:?} not balanced with ToolResult",
2002 pending_tool_use_ids
2003 ));
2004 }
2005 Ok(())
2006 }
2007}
2008
2009#[deprecated(since = "0.13.0", note = "Use CreateMessageRequestParams instead")]
2011pub type CreateMessageRequestParam = CreateMessageRequestParams;
2012
2013#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2019#[serde(rename_all = "camelCase")]
2020#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2021#[non_exhaustive]
2022pub struct ModelPreferences {
2023 #[serde(skip_serializing_if = "Option::is_none")]
2025 pub hints: Option<Vec<ModelHint>>,
2026 #[serde(skip_serializing_if = "Option::is_none")]
2028 pub cost_priority: Option<f32>,
2029 #[serde(skip_serializing_if = "Option::is_none")]
2031 pub speed_priority: Option<f32>,
2032 #[serde(skip_serializing_if = "Option::is_none")]
2034 pub intelligence_priority: Option<f32>,
2035}
2036
2037impl ModelPreferences {
2038 pub fn new() -> Self {
2040 Self {
2041 hints: None,
2042 cost_priority: None,
2043 speed_priority: None,
2044 intelligence_priority: None,
2045 }
2046 }
2047
2048 pub fn with_hints(mut self, hints: Vec<ModelHint>) -> Self {
2050 self.hints = Some(hints);
2051 self
2052 }
2053
2054 pub fn with_cost_priority(mut self, cost_priority: f32) -> Self {
2056 self.cost_priority = Some(cost_priority);
2057 self
2058 }
2059
2060 pub fn with_speed_priority(mut self, speed_priority: f32) -> Self {
2062 self.speed_priority = Some(speed_priority);
2063 self
2064 }
2065
2066 pub fn with_intelligence_priority(mut self, intelligence_priority: f32) -> Self {
2068 self.intelligence_priority = Some(intelligence_priority);
2069 self
2070 }
2071}
2072
2073impl Default for ModelPreferences {
2074 fn default() -> Self {
2075 Self::new()
2076 }
2077}
2078
2079#[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq)]
2084#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2085#[non_exhaustive]
2086pub struct ModelHint {
2087 #[serde(skip_serializing_if = "Option::is_none")]
2089 pub name: Option<String>,
2090}
2091
2092impl ModelHint {
2093 pub fn new(name: impl Into<String>) -> Self {
2095 Self {
2096 name: Some(name.into()),
2097 }
2098 }
2099}
2100
2101#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
2110#[serde(rename_all = "camelCase")]
2111#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2112pub struct CompletionContext {
2113 #[serde(skip_serializing_if = "Option::is_none")]
2115 pub arguments: Option<std::collections::HashMap<String, String>>,
2116}
2117
2118impl CompletionContext {
2119 pub fn new() -> Self {
2121 Self::default()
2122 }
2123
2124 pub fn with_arguments(arguments: std::collections::HashMap<String, String>) -> Self {
2126 Self {
2127 arguments: Some(arguments),
2128 }
2129 }
2130
2131 pub fn get_argument(&self, name: &str) -> Option<&String> {
2133 self.arguments.as_ref()?.get(name)
2134 }
2135
2136 pub fn has_arguments(&self) -> bool {
2138 self.arguments.as_ref().is_some_and(|args| !args.is_empty())
2139 }
2140
2141 pub fn argument_names(&self) -> impl Iterator<Item = &str> {
2143 self.arguments
2144 .as_ref()
2145 .into_iter()
2146 .flat_map(|args| args.keys())
2147 .map(|k| k.as_str())
2148 }
2149}
2150
2151#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2152#[serde(rename_all = "camelCase")]
2153#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2154#[non_exhaustive]
2155pub struct CompleteRequestParams {
2156 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
2158 pub meta: Option<Meta>,
2159 pub r#ref: Reference,
2160 pub argument: ArgumentInfo,
2161 #[serde(skip_serializing_if = "Option::is_none")]
2163 pub context: Option<CompletionContext>,
2164}
2165
2166impl CompleteRequestParams {
2167 pub fn new(r#ref: Reference, argument: ArgumentInfo) -> Self {
2169 Self {
2170 meta: None,
2171 r#ref,
2172 argument,
2173 context: None,
2174 }
2175 }
2176
2177 pub fn with_context(mut self, context: CompletionContext) -> Self {
2179 self.context = Some(context);
2180 self
2181 }
2182}
2183
2184impl RequestParamsMeta for CompleteRequestParams {
2185 fn meta(&self) -> Option<&Meta> {
2186 self.meta.as_ref()
2187 }
2188 fn meta_mut(&mut self) -> &mut Option<Meta> {
2189 &mut self.meta
2190 }
2191}
2192
2193#[deprecated(since = "0.13.0", note = "Use CompleteRequestParams instead")]
2195pub type CompleteRequestParam = CompleteRequestParams;
2196
2197pub type CompleteRequest = Request<CompleteRequestMethod, CompleteRequestParams>;
2198
2199#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
2200#[serde(rename_all = "camelCase")]
2201#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2202pub struct CompletionInfo {
2203 pub values: Vec<String>,
2204 #[serde(skip_serializing_if = "Option::is_none")]
2205 pub total: Option<u32>,
2206 #[serde(skip_serializing_if = "Option::is_none")]
2207 pub has_more: Option<bool>,
2208}
2209
2210impl CompletionInfo {
2211 pub const MAX_VALUES: usize = 100;
2213
2214 pub fn new(values: Vec<String>) -> Result<Self, String> {
2216 if values.len() > Self::MAX_VALUES {
2217 return Err(format!(
2218 "Too many completion values: {} (max: {})",
2219 values.len(),
2220 Self::MAX_VALUES
2221 ));
2222 }
2223 Ok(Self {
2224 values,
2225 total: None,
2226 has_more: None,
2227 })
2228 }
2229
2230 pub fn with_all_values(values: Vec<String>) -> Result<Self, String> {
2232 let completion = Self::new(values)?;
2233 Ok(Self {
2234 total: Some(completion.values.len() as u32),
2235 has_more: Some(false),
2236 ..completion
2237 })
2238 }
2239
2240 pub fn with_pagination(
2242 values: Vec<String>,
2243 total: Option<u32>,
2244 has_more: bool,
2245 ) -> Result<Self, String> {
2246 let completion = Self::new(values)?;
2247 Ok(Self {
2248 total,
2249 has_more: Some(has_more),
2250 ..completion
2251 })
2252 }
2253
2254 pub fn has_more_results(&self) -> bool {
2256 self.has_more.unwrap_or(false)
2257 }
2258
2259 pub fn total_available(&self) -> Option<u32> {
2261 self.total
2262 }
2263
2264 pub fn validate(&self) -> Result<(), String> {
2266 if self.values.len() > Self::MAX_VALUES {
2267 return Err(format!(
2268 "Too many completion values: {} (max: {})",
2269 self.values.len(),
2270 Self::MAX_VALUES
2271 ));
2272 }
2273 Ok(())
2274 }
2275}
2276
2277#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
2278#[serde(rename_all = "camelCase")]
2279#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2280#[non_exhaustive]
2281pub struct CompleteResult {
2282 pub completion: CompletionInfo,
2283}
2284
2285impl CompleteResult {
2286 pub fn new(completion: CompletionInfo) -> Self {
2288 Self { completion }
2289 }
2290}
2291
2292#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2293#[serde(tag = "type")]
2294#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2295pub enum Reference {
2296 #[serde(rename = "ref/resource")]
2297 Resource(ResourceReference),
2298 #[serde(rename = "ref/prompt")]
2299 Prompt(PromptReference),
2300}
2301
2302impl Reference {
2303 pub fn for_prompt(name: impl Into<String>) -> Self {
2305 Self::Prompt(PromptReference {
2309 name: name.into(),
2310 title: None,
2311 })
2312 }
2313
2314 pub fn for_resource(uri: impl Into<String>) -> Self {
2316 Self::Resource(ResourceReference { uri: uri.into() })
2317 }
2318
2319 pub fn reference_type(&self) -> &'static str {
2321 match self {
2322 Self::Prompt(_) => "ref/prompt",
2323 Self::Resource(_) => "ref/resource",
2324 }
2325 }
2326
2327 pub fn as_prompt_name(&self) -> Option<&str> {
2329 match self {
2330 Self::Prompt(prompt_ref) => Some(&prompt_ref.name),
2331 _ => None,
2332 }
2333 }
2334
2335 pub fn as_resource_uri(&self) -> Option<&str> {
2337 match self {
2338 Self::Resource(resource_ref) => Some(&resource_ref.uri),
2339 _ => None,
2340 }
2341 }
2342}
2343
2344#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2345#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2346pub struct ResourceReference {
2347 pub uri: String,
2348}
2349
2350#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2351#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2352#[non_exhaustive]
2353pub struct PromptReference {
2354 pub name: String,
2355 #[serde(skip_serializing_if = "Option::is_none")]
2356 pub title: Option<String>,
2357}
2358
2359const_string!(CompleteRequestMethod = "completion/complete");
2360#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2361#[serde(rename_all = "camelCase")]
2362#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2363pub struct ArgumentInfo {
2364 pub name: String,
2365 pub value: String,
2366}
2367
2368#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2373#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2374#[non_exhaustive]
2375pub struct Root {
2376 pub uri: String,
2377 #[serde(skip_serializing_if = "Option::is_none")]
2378 pub name: Option<String>,
2379}
2380
2381const_string!(ListRootsRequestMethod = "roots/list");
2382pub type ListRootsRequest = RequestNoParam<ListRootsRequestMethod>;
2383
2384#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
2385#[serde(rename_all = "camelCase")]
2386#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2387#[non_exhaustive]
2388pub struct ListRootsResult {
2389 pub roots: Vec<Root>,
2390}
2391
2392const_string!(RootsListChangedNotificationMethod = "notifications/roots/list_changed");
2393pub type RootsListChangedNotification = NotificationNoParam<RootsListChangedNotificationMethod>;
2394
2395const_string!(ElicitationCreateRequestMethod = "elicitation/create");
2402const_string!(ElicitationResponseNotificationMethod = "notifications/elicitation/response");
2403const_string!(ElicitationCompletionNotificationMethod = "notifications/elicitation/complete");
2404
2405#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
2412#[serde(rename_all = "lowercase")]
2413#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2414pub enum ElicitationAction {
2415 Accept,
2417 Decline,
2419 Cancel,
2421}
2422
2423#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2426#[serde(tag = "mode")]
2427#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2428enum CreateElicitationRequestParamDeserializeHelper {
2429 #[serde(rename = "form", rename_all = "camelCase")]
2430 FormElicitationParam {
2431 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
2432 meta: Option<Meta>,
2433 message: String,
2434 requested_schema: ElicitationSchema,
2435 },
2436 #[serde(rename = "url", rename_all = "camelCase")]
2437 UrlElicitationParam {
2438 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
2439 meta: Option<Meta>,
2440 message: String,
2441 url: String,
2442 elicitation_id: String,
2443 },
2444 #[serde(untagged, rename_all = "camelCase")]
2445 FormElicitationParamBackwardsCompat {
2446 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
2447 meta: Option<Meta>,
2448 message: String,
2449 requested_schema: ElicitationSchema,
2450 },
2451}
2452
2453impl TryFrom<CreateElicitationRequestParamDeserializeHelper> for CreateElicitationRequestParams {
2454 type Error = serde_json::Error;
2455
2456 fn try_from(
2457 value: CreateElicitationRequestParamDeserializeHelper,
2458 ) -> Result<Self, Self::Error> {
2459 match value {
2460 CreateElicitationRequestParamDeserializeHelper::FormElicitationParam {
2461 meta,
2462 message,
2463 requested_schema,
2464 }
2465 | CreateElicitationRequestParamDeserializeHelper::FormElicitationParamBackwardsCompat {
2466 meta,
2467 message,
2468 requested_schema,
2469 } => Ok(CreateElicitationRequestParams::FormElicitationParams {
2470 meta,
2471 message,
2472 requested_schema,
2473 }),
2474 CreateElicitationRequestParamDeserializeHelper::UrlElicitationParam {
2475 meta,
2476 message,
2477 url,
2478 elicitation_id,
2479 } => Ok(CreateElicitationRequestParams::UrlElicitationParams {
2480 meta,
2481 message,
2482 url,
2483 elicitation_id,
2484 }),
2485 }
2486 }
2487}
2488
2489#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2520#[serde(
2521 tag = "mode",
2522 try_from = "CreateElicitationRequestParamDeserializeHelper"
2523)]
2524#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2525pub enum CreateElicitationRequestParams {
2526 #[serde(rename = "form", rename_all = "camelCase")]
2527 FormElicitationParams {
2528 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
2530 meta: Option<Meta>,
2531 message: String,
2535
2536 requested_schema: ElicitationSchema,
2540 },
2541 #[serde(rename = "url", rename_all = "camelCase")]
2542 UrlElicitationParams {
2543 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
2545 meta: Option<Meta>,
2546 message: String,
2550
2551 url: String,
2554 elicitation_id: String,
2556 },
2557}
2558
2559impl RequestParamsMeta for CreateElicitationRequestParams {
2560 fn meta(&self) -> Option<&Meta> {
2561 match self {
2562 CreateElicitationRequestParams::FormElicitationParams { meta, .. } => meta.as_ref(),
2563 CreateElicitationRequestParams::UrlElicitationParams { meta, .. } => meta.as_ref(),
2564 }
2565 }
2566 fn meta_mut(&mut self) -> &mut Option<Meta> {
2567 match self {
2568 CreateElicitationRequestParams::FormElicitationParams { meta, .. } => meta,
2569 CreateElicitationRequestParams::UrlElicitationParams { meta, .. } => meta,
2570 }
2571 }
2572}
2573
2574#[deprecated(since = "0.13.0", note = "Use CreateElicitationRequestParams instead")]
2576pub type CreateElicitationRequestParam = CreateElicitationRequestParams;
2577
2578#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2583#[serde(rename_all = "camelCase")]
2584#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2585pub struct CreateElicitationResult {
2586 pub action: ElicitationAction,
2588
2589 #[serde(skip_serializing_if = "Option::is_none")]
2593 pub content: Option<Value>,
2594}
2595
2596impl CreateElicitationResult {
2597 pub fn new(action: ElicitationAction) -> Self {
2599 Self {
2600 action,
2601 content: None,
2602 }
2603 }
2604
2605 pub fn with_content(mut self, content: Value) -> Self {
2607 self.content = Some(content);
2608 self
2609 }
2610}
2611
2612pub type CreateElicitationRequest =
2614 Request<ElicitationCreateRequestMethod, CreateElicitationRequestParams>;
2615
2616#[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq)]
2618#[serde(rename_all = "camelCase")]
2619#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2620pub struct ElicitationResponseNotificationParam {
2621 pub elicitation_id: String,
2622}
2623
2624impl ElicitationResponseNotificationParam {
2625 pub fn new(elicitation_id: impl Into<String>) -> Self {
2627 Self {
2628 elicitation_id: elicitation_id.into(),
2629 }
2630 }
2631}
2632
2633pub type ElicitationCompletionNotification =
2635 Notification<ElicitationCompletionNotificationMethod, ElicitationResponseNotificationParam>;
2636
2637#[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq)]
2646#[serde(rename_all = "camelCase")]
2647#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2648#[non_exhaustive]
2649pub struct CallToolResult {
2650 pub content: Vec<Content>,
2652 #[serde(skip_serializing_if = "Option::is_none")]
2654 pub structured_content: Option<Value>,
2655 #[serde(skip_serializing_if = "Option::is_none")]
2657 pub is_error: Option<bool>,
2658 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
2660 pub meta: Option<Meta>,
2661}
2662
2663impl CallToolResult {
2664 pub fn success(content: Vec<Content>) -> Self {
2666 CallToolResult {
2667 content,
2668 structured_content: None,
2669 is_error: Some(false),
2670 meta: None,
2671 }
2672 }
2673 pub fn error(content: Vec<Content>) -> Self {
2675 CallToolResult {
2676 content,
2677 structured_content: None,
2678 is_error: Some(true),
2679 meta: None,
2680 }
2681 }
2682 pub fn structured(value: Value) -> Self {
2697 CallToolResult {
2698 content: vec![Content::text(value.to_string())],
2699 structured_content: Some(value),
2700 is_error: Some(false),
2701 meta: None,
2702 }
2703 }
2704 pub fn structured_error(value: Value) -> Self {
2723 CallToolResult {
2724 content: vec![Content::text(value.to_string())],
2725 structured_content: Some(value),
2726 is_error: Some(true),
2727 meta: None,
2728 }
2729 }
2730
2731 pub fn with_meta(mut self, meta: Option<Meta>) -> Self {
2733 self.meta = meta;
2734 self
2735 }
2736
2737 pub fn into_typed<T>(self) -> Result<T, serde_json::Error>
2744 where
2745 T: DeserializeOwned,
2746 {
2747 let raw_text = match (self.structured_content, &self.content.first()) {
2748 (Some(value), _) => return serde_json::from_value(value),
2749 (None, Some(contents)) => {
2750 if let Some(text) = contents.as_text() {
2751 let text = &text.text;
2752 Some(text)
2753 } else {
2754 None
2755 }
2756 }
2757 (None, None) => None,
2758 };
2759 if let Some(text) = raw_text {
2760 return serde_json::from_str(text);
2761 }
2762 serde_json::from_value(serde_json::Value::Null)
2763 }
2764}
2765
2766const_string!(ListToolsRequestMethod = "tools/list");
2767pub type ListToolsRequest = RequestOptionalParam<ListToolsRequestMethod, PaginatedRequestParams>;
2769
2770paginated_result!(
2771 ListToolsResult {
2772 tools: Vec<Tool>
2773 }
2774);
2775
2776const_string!(CallToolRequestMethod = "tools/call");
2777#[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq)]
2785#[serde(rename_all = "camelCase")]
2786#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2787#[non_exhaustive]
2788pub struct CallToolRequestParams {
2789 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
2791 pub meta: Option<Meta>,
2792 pub name: Cow<'static, str>,
2794 #[serde(skip_serializing_if = "Option::is_none")]
2796 pub arguments: Option<JsonObject>,
2797 #[serde(skip_serializing_if = "Option::is_none")]
2799 pub task: Option<JsonObject>,
2800}
2801
2802impl CallToolRequestParams {
2803 pub fn new(name: impl Into<Cow<'static, str>>) -> Self {
2805 Self {
2806 meta: None,
2807 name: name.into(),
2808 arguments: None,
2809 task: None,
2810 }
2811 }
2812
2813 pub fn with_arguments(mut self, arguments: JsonObject) -> Self {
2815 self.arguments = Some(arguments);
2816 self
2817 }
2818
2819 pub fn with_task(mut self, task: JsonObject) -> Self {
2821 self.task = Some(task);
2822 self
2823 }
2824}
2825
2826impl RequestParamsMeta for CallToolRequestParams {
2827 fn meta(&self) -> Option<&Meta> {
2828 self.meta.as_ref()
2829 }
2830 fn meta_mut(&mut self) -> &mut Option<Meta> {
2831 &mut self.meta
2832 }
2833}
2834
2835impl TaskAugmentedRequestParamsMeta for CallToolRequestParams {
2836 fn task(&self) -> Option<&JsonObject> {
2837 self.task.as_ref()
2838 }
2839 fn task_mut(&mut self) -> &mut Option<JsonObject> {
2840 &mut self.task
2841 }
2842}
2843
2844#[deprecated(since = "0.13.0", note = "Use CallToolRequestParams instead")]
2846pub type CallToolRequestParam = CallToolRequestParams;
2847
2848pub type CallToolRequest = Request<CallToolRequestMethod, CallToolRequestParams>;
2850
2851#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2857#[serde(rename_all = "camelCase")]
2858#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2859#[non_exhaustive]
2860pub struct CreateMessageResult {
2861 pub model: String,
2863 #[serde(skip_serializing_if = "Option::is_none")]
2865 pub stop_reason: Option<String>,
2866 #[serde(flatten)]
2868 pub message: SamplingMessage,
2869}
2870
2871impl CreateMessageResult {
2872 pub fn new(message: SamplingMessage, model: String) -> Self {
2874 Self {
2875 message,
2876 model,
2877 stop_reason: None,
2878 }
2879 }
2880
2881 pub const STOP_REASON_END_TURN: &str = "endTurn";
2882 pub const STOP_REASON_END_SEQUENCE: &str = "stopSequence";
2883 pub const STOP_REASON_END_MAX_TOKEN: &str = "maxTokens";
2884 pub const STOP_REASON_TOOL_USE: &str = "toolUse";
2885
2886 pub fn with_stop_reason(mut self, stop_reason: impl Into<String>) -> Self {
2888 self.stop_reason = Some(stop_reason.into());
2889 self
2890 }
2891
2892 pub fn with_model(mut self, model: impl Into<String>) -> Self {
2894 self.model = model.into();
2895 self
2896 }
2897
2898 pub fn validate(&self) -> Result<(), String> {
2900 if self.message.role != Role::Assistant {
2901 return Err("CreateMessageResult role must be 'assistant'".into());
2902 }
2903 Ok(())
2904 }
2905}
2906
2907#[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq)]
2908#[serde(rename_all = "camelCase")]
2909#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2910#[non_exhaustive]
2911pub struct GetPromptResult {
2912 #[serde(skip_serializing_if = "Option::is_none")]
2913 pub description: Option<String>,
2914 pub messages: Vec<PromptMessage>,
2915}
2916
2917impl GetPromptResult {
2918 pub fn new(messages: Vec<PromptMessage>) -> Self {
2920 Self {
2921 description: None,
2922 messages,
2923 }
2924 }
2925
2926 pub fn with_description<D: Into<String>>(mut self, description: D) -> Self {
2928 self.description = Some(description.into());
2929 self
2930 }
2931}
2932
2933const_string!(GetTaskInfoMethod = "tasks/get");
2938pub type GetTaskInfoRequest = Request<GetTaskInfoMethod, GetTaskInfoParams>;
2939
2940#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2941#[serde(rename_all = "camelCase")]
2942#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2943pub struct GetTaskInfoParams {
2944 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
2946 pub meta: Option<Meta>,
2947 pub task_id: String,
2948}
2949
2950impl RequestParamsMeta for GetTaskInfoParams {
2951 fn meta(&self) -> Option<&Meta> {
2952 self.meta.as_ref()
2953 }
2954 fn meta_mut(&mut self) -> &mut Option<Meta> {
2955 &mut self.meta
2956 }
2957}
2958
2959#[deprecated(since = "0.13.0", note = "Use GetTaskInfoParams instead")]
2961pub type GetTaskInfoParam = GetTaskInfoParams;
2962
2963const_string!(ListTasksMethod = "tasks/list");
2964pub type ListTasksRequest = RequestOptionalParam<ListTasksMethod, PaginatedRequestParams>;
2965
2966const_string!(GetTaskResultMethod = "tasks/result");
2967pub type GetTaskResultRequest = Request<GetTaskResultMethod, GetTaskResultParams>;
2968
2969#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2970#[serde(rename_all = "camelCase")]
2971#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2972pub struct GetTaskResultParams {
2973 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
2975 pub meta: Option<Meta>,
2976 pub task_id: String,
2977}
2978
2979impl RequestParamsMeta for GetTaskResultParams {
2980 fn meta(&self) -> Option<&Meta> {
2981 self.meta.as_ref()
2982 }
2983 fn meta_mut(&mut self) -> &mut Option<Meta> {
2984 &mut self.meta
2985 }
2986}
2987
2988#[deprecated(since = "0.13.0", note = "Use GetTaskResultParams instead")]
2990pub type GetTaskResultParam = GetTaskResultParams;
2991
2992const_string!(CancelTaskMethod = "tasks/cancel");
2993pub type CancelTaskRequest = Request<CancelTaskMethod, CancelTaskParams>;
2994
2995#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2996#[serde(rename_all = "camelCase")]
2997#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2998pub struct CancelTaskParams {
2999 #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
3001 pub meta: Option<Meta>,
3002 pub task_id: String,
3003}
3004
3005impl RequestParamsMeta for CancelTaskParams {
3006 fn meta(&self) -> Option<&Meta> {
3007 self.meta.as_ref()
3008 }
3009 fn meta_mut(&mut self) -> &mut Option<Meta> {
3010 &mut self.meta
3011 }
3012}
3013
3014#[deprecated(since = "0.13.0", note = "Use CancelTaskParams instead")]
3016pub type CancelTaskParam = CancelTaskParams;
3017#[deprecated(since = "0.15.0", note = "Use GetTaskResult instead")]
3019pub type GetTaskInfoResult = GetTaskResult;
3020
3021#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
3022#[serde(rename_all = "camelCase")]
3023#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3024#[non_exhaustive]
3025pub struct ListTasksResult {
3026 pub tasks: Vec<crate::model::Task>,
3027 #[serde(skip_serializing_if = "Option::is_none")]
3028 pub next_cursor: Option<String>,
3029 #[serde(skip_serializing_if = "Option::is_none")]
3030 pub total: Option<u64>,
3031}
3032
3033impl ListTasksResult {
3034 pub fn new(tasks: Vec<crate::model::Task>) -> Self {
3036 Self {
3037 tasks,
3038 next_cursor: None,
3039 total: None,
3040 }
3041 }
3042}
3043
3044macro_rules! ts_union {
3049 (
3050 export type $U:ident =
3051 $($rest:tt)*
3052 ) => {
3053 ts_union!(@declare $U { $($rest)* });
3054 ts_union!(@impl_from $U { $($rest)* });
3055 };
3056 (@declare $U:ident { $($variant:tt)* }) => {
3057 ts_union!(@declare_variant $U { } {$($variant)*} );
3058 };
3059 (@declare_variant $U:ident { $($declared:tt)* } {$(|)? box $V:ident $($rest:tt)*}) => {
3060 ts_union!(@declare_variant $U { $($declared)* $V(Box<$V>), } {$($rest)*});
3061 };
3062 (@declare_variant $U:ident { $($declared:tt)* } {$(|)? $V:ident $($rest:tt)*}) => {
3063 ts_union!(@declare_variant $U { $($declared)* $V($V), } {$($rest)*});
3064 };
3065 (@declare_variant $U:ident { $($declared:tt)* } { ; }) => {
3066 ts_union!(@declare_end $U { $($declared)* } );
3067 };
3068 (@declare_end $U:ident { $($declared:tt)* }) => {
3069 #[derive(Debug, Serialize, Deserialize, Clone)]
3070 #[serde(untagged)]
3071 #[allow(clippy::large_enum_variant)]
3072 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3073 pub enum $U {
3074 $($declared)*
3075 }
3076 };
3077 (@impl_from $U: ident {$(|)? box $V:ident $($rest:tt)*}) => {
3078 impl From<$V> for $U {
3079 fn from(value: $V) -> Self {
3080 $U::$V(Box::new(value))
3081 }
3082 }
3083 ts_union!(@impl_from $U {$($rest)*});
3084 };
3085 (@impl_from $U: ident {$(|)? $V:ident $($rest:tt)*}) => {
3086 impl From<$V> for $U {
3087 fn from(value: $V) -> Self {
3088 $U::$V(value)
3089 }
3090 }
3091 ts_union!(@impl_from $U {$($rest)*});
3092 };
3093 (@impl_from $U: ident { ; }) => {};
3094 (@impl_from $U: ident { }) => {};
3095}
3096
3097ts_union!(
3098 export type ClientRequest =
3099 | PingRequest
3100 | InitializeRequest
3101 | CompleteRequest
3102 | SetLevelRequest
3103 | GetPromptRequest
3104 | ListPromptsRequest
3105 | ListResourcesRequest
3106 | ListResourceTemplatesRequest
3107 | ReadResourceRequest
3108 | SubscribeRequest
3109 | UnsubscribeRequest
3110 | CallToolRequest
3111 | ListToolsRequest
3112 | GetTaskInfoRequest
3113 | ListTasksRequest
3114 | GetTaskResultRequest
3115 | CancelTaskRequest
3116 | CustomRequest;
3117);
3118
3119impl ClientRequest {
3120 pub fn method(&self) -> &str {
3121 match &self {
3122 ClientRequest::PingRequest(r) => r.method.as_str(),
3123 ClientRequest::InitializeRequest(r) => r.method.as_str(),
3124 ClientRequest::CompleteRequest(r) => r.method.as_str(),
3125 ClientRequest::SetLevelRequest(r) => r.method.as_str(),
3126 ClientRequest::GetPromptRequest(r) => r.method.as_str(),
3127 ClientRequest::ListPromptsRequest(r) => r.method.as_str(),
3128 ClientRequest::ListResourcesRequest(r) => r.method.as_str(),
3129 ClientRequest::ListResourceTemplatesRequest(r) => r.method.as_str(),
3130 ClientRequest::ReadResourceRequest(r) => r.method.as_str(),
3131 ClientRequest::SubscribeRequest(r) => r.method.as_str(),
3132 ClientRequest::UnsubscribeRequest(r) => r.method.as_str(),
3133 ClientRequest::CallToolRequest(r) => r.method.as_str(),
3134 ClientRequest::ListToolsRequest(r) => r.method.as_str(),
3135 ClientRequest::GetTaskInfoRequest(r) => r.method.as_str(),
3136 ClientRequest::ListTasksRequest(r) => r.method.as_str(),
3137 ClientRequest::GetTaskResultRequest(r) => r.method.as_str(),
3138 ClientRequest::CancelTaskRequest(r) => r.method.as_str(),
3139 ClientRequest::CustomRequest(r) => r.method.as_str(),
3140 }
3141 }
3142}
3143
3144ts_union!(
3145 export type ClientNotification =
3146 | CancelledNotification
3147 | ProgressNotification
3148 | InitializedNotification
3149 | RootsListChangedNotification
3150 | CustomNotification;
3151);
3152
3153ts_union!(
3154 export type ClientResult =
3155 box CreateMessageResult
3156 | ListRootsResult
3157 | CreateElicitationResult
3158 | EmptyResult
3159 | CustomResult;
3160);
3161
3162impl ClientResult {
3163 pub fn empty(_: ()) -> ClientResult {
3164 ClientResult::EmptyResult(EmptyResult {})
3165 }
3166}
3167
3168pub type ClientJsonRpcMessage = JsonRpcMessage<ClientRequest, ClientResult, ClientNotification>;
3169
3170ts_union!(
3171 export type ServerRequest =
3172 | PingRequest
3173 | CreateMessageRequest
3174 | ListRootsRequest
3175 | CreateElicitationRequest
3176 | CustomRequest;
3177);
3178
3179ts_union!(
3180 export type ServerNotification =
3181 | CancelledNotification
3182 | ProgressNotification
3183 | LoggingMessageNotification
3184 | ResourceUpdatedNotification
3185 | ResourceListChangedNotification
3186 | ToolListChangedNotification
3187 | PromptListChangedNotification
3188 | ElicitationCompletionNotification
3189 | CustomNotification;
3190);
3191
3192ts_union!(
3193 export type ServerResult =
3194 | InitializeResult
3195 | CompleteResult
3196 | GetPromptResult
3197 | ListPromptsResult
3198 | ListResourcesResult
3199 | ListResourceTemplatesResult
3200 | ReadResourceResult
3201 | CallToolResult
3202 | ListToolsResult
3203 | CreateElicitationResult
3204 | EmptyResult
3205 | CreateTaskResult
3206 | ListTasksResult
3207 | GetTaskResult
3208 | CancelTaskResult
3209 | CustomResult
3210 | GetTaskPayloadResult
3211 ;
3212);
3213
3214impl ServerResult {
3215 pub fn empty(_: ()) -> ServerResult {
3216 ServerResult::EmptyResult(EmptyResult {})
3217 }
3218}
3219
3220pub type ServerJsonRpcMessage = JsonRpcMessage<ServerRequest, ServerResult, ServerNotification>;
3221
3222impl TryInto<CancelledNotification> for ServerNotification {
3223 type Error = ServerNotification;
3224 fn try_into(self) -> Result<CancelledNotification, Self::Error> {
3225 if let ServerNotification::CancelledNotification(t) = self {
3226 Ok(t)
3227 } else {
3228 Err(self)
3229 }
3230 }
3231}
3232
3233impl TryInto<CancelledNotification> for ClientNotification {
3234 type Error = ClientNotification;
3235 fn try_into(self) -> Result<CancelledNotification, Self::Error> {
3236 if let ClientNotification::CancelledNotification(t) = self {
3237 Ok(t)
3238 } else {
3239 Err(self)
3240 }
3241 }
3242}
3243
3244#[cfg(test)]
3249mod tests {
3250 use serde_json::json;
3251
3252 use super::*;
3253
3254 #[test]
3255 fn test_notification_serde() {
3256 let raw = json!( {
3257 "jsonrpc": JsonRpcVersion2_0,
3258 "method": InitializedNotificationMethod,
3259 });
3260 let message: ClientJsonRpcMessage =
3261 serde_json::from_value(raw.clone()).expect("invalid notification");
3262 match &message {
3263 ClientJsonRpcMessage::Notification(JsonRpcNotification {
3264 notification: ClientNotification::InitializedNotification(_n),
3265 ..
3266 }) => {}
3267 _ => panic!("Expected Notification"),
3268 }
3269 let json = serde_json::to_value(message).expect("valid json");
3270 assert_eq!(json, raw);
3271 }
3272
3273 #[test]
3274 fn test_custom_client_notification_roundtrip() {
3275 let raw = json!( {
3276 "jsonrpc": JsonRpcVersion2_0,
3277 "method": "notifications/custom",
3278 "params": {"foo": "bar"},
3279 });
3280
3281 let message: ClientJsonRpcMessage =
3282 serde_json::from_value(raw.clone()).expect("invalid notification");
3283 match &message {
3284 ClientJsonRpcMessage::Notification(JsonRpcNotification {
3285 notification: ClientNotification::CustomNotification(notification),
3286 ..
3287 }) => {
3288 assert_eq!(notification.method, "notifications/custom");
3289 assert_eq!(
3290 notification
3291 .params
3292 .as_ref()
3293 .and_then(|p| p.get("foo"))
3294 .expect("foo present"),
3295 "bar"
3296 );
3297 }
3298 _ => panic!("Expected custom client notification"),
3299 }
3300
3301 let json = serde_json::to_value(message).expect("valid json");
3302 assert_eq!(json, raw);
3303 }
3304
3305 #[test]
3306 fn test_custom_server_notification_roundtrip() {
3307 let raw = json!( {
3308 "jsonrpc": JsonRpcVersion2_0,
3309 "method": "notifications/custom-server",
3310 "params": {"hello": "world"},
3311 });
3312
3313 let message: ServerJsonRpcMessage =
3314 serde_json::from_value(raw.clone()).expect("invalid notification");
3315 match &message {
3316 ServerJsonRpcMessage::Notification(JsonRpcNotification {
3317 notification: ServerNotification::CustomNotification(notification),
3318 ..
3319 }) => {
3320 assert_eq!(notification.method, "notifications/custom-server");
3321 assert_eq!(
3322 notification
3323 .params
3324 .as_ref()
3325 .and_then(|p| p.get("hello"))
3326 .expect("hello present"),
3327 "world"
3328 );
3329 }
3330 _ => panic!("Expected custom server notification"),
3331 }
3332
3333 let json = serde_json::to_value(message).expect("valid json");
3334 assert_eq!(json, raw);
3335 }
3336
3337 #[test]
3338 fn test_custom_request_roundtrip() {
3339 let raw = json!( {
3340 "jsonrpc": JsonRpcVersion2_0,
3341 "id": 42,
3342 "method": "requests/custom",
3343 "params": {"foo": "bar"},
3344 });
3345
3346 let message: ClientJsonRpcMessage =
3347 serde_json::from_value(raw.clone()).expect("invalid request");
3348 match &message {
3349 ClientJsonRpcMessage::Request(JsonRpcRequest { id, request, .. }) => {
3350 assert_eq!(id, &RequestId::Number(42));
3351 match request {
3352 ClientRequest::CustomRequest(custom) => {
3353 let expected_request = json!({
3354 "method": "requests/custom",
3355 "params": {"foo": "bar"},
3356 });
3357 let actual_request =
3358 serde_json::to_value(custom).expect("serialize custom request");
3359 assert_eq!(actual_request, expected_request);
3360 }
3361 other => panic!("Expected custom request, got: {other:?}"),
3362 }
3363 }
3364 other => panic!("Expected request, got: {other:?}"),
3365 }
3366
3367 let json = serde_json::to_value(message).expect("valid json");
3368 assert_eq!(json, raw);
3369 }
3370
3371 #[test]
3372 fn test_request_conversion() {
3373 let raw = json!( {
3374 "jsonrpc": JsonRpcVersion2_0,
3375 "id": 1,
3376 "method": "request",
3377 "params": {"key": "value"},
3378 });
3379 let message: JsonRpcMessage = serde_json::from_value(raw.clone()).expect("invalid request");
3380
3381 match &message {
3382 JsonRpcMessage::Request(r) => {
3383 assert_eq!(r.id, RequestId::Number(1));
3384 assert_eq!(r.request.method, "request");
3385 assert_eq!(
3386 &r.request.params,
3387 json!({"key": "value"})
3388 .as_object()
3389 .expect("should be an object")
3390 );
3391 }
3392 _ => panic!("Expected Request"),
3393 }
3394 let json = serde_json::to_value(&message).expect("valid json");
3395 assert_eq!(json, raw);
3396 }
3397
3398 #[test]
3399 fn test_initial_request_response_serde() {
3400 let request = json!({
3401 "jsonrpc": "2.0",
3402 "id": 1,
3403 "method": "initialize",
3404 "params": {
3405 "protocolVersion": "2024-11-05",
3406 "capabilities": {
3407 "roots": {
3408 "listChanged": true
3409 },
3410 "sampling": {}
3411 },
3412 "clientInfo": {
3413 "name": "ExampleClient",
3414 "version": "1.0.0"
3415 }
3416 }
3417 });
3418 let raw_response_json = json!({
3419 "jsonrpc": "2.0",
3420 "id": 1,
3421 "result": {
3422 "protocolVersion": "2024-11-05",
3423 "capabilities": {
3424 "logging": {},
3425 "prompts": {
3426 "listChanged": true
3427 },
3428 "resources": {
3429 "subscribe": true,
3430 "listChanged": true
3431 },
3432 "tools": {
3433 "listChanged": true
3434 }
3435 },
3436 "serverInfo": {
3437 "name": "ExampleServer",
3438 "version": "1.0.0"
3439 }
3440 }
3441 });
3442 let request: ClientJsonRpcMessage =
3443 serde_json::from_value(request.clone()).expect("invalid request");
3444 let (request, id) = request.into_request().expect("should be a request");
3445 assert_eq!(id, RequestId::Number(1));
3446 #[allow(deprecated)]
3447 match request {
3448 ClientRequest::InitializeRequest(Request {
3449 method: _,
3450 params:
3451 InitializeRequestParam {
3452 meta: _,
3453 protocol_version: _,
3454 capabilities,
3455 client_info,
3456 },
3457 ..
3458 }) => {
3459 assert_eq!(capabilities.roots.unwrap().list_changed, Some(true));
3460 let sampling = capabilities.sampling.unwrap();
3461 assert_eq!(sampling.tools, None);
3462 assert_eq!(sampling.context, None);
3463 assert_eq!(client_info.name, "ExampleClient");
3464 assert_eq!(client_info.version, "1.0.0");
3465 }
3466 _ => panic!("Expected InitializeRequest"),
3467 }
3468 let server_response: ServerJsonRpcMessage =
3469 serde_json::from_value(raw_response_json.clone()).expect("invalid response");
3470 let (response, id) = server_response
3471 .clone()
3472 .into_response()
3473 .expect("expect response");
3474 assert_eq!(id, RequestId::Number(1));
3475 match response {
3476 ServerResult::InitializeResult(InitializeResult {
3477 protocol_version: _,
3478 capabilities,
3479 server_info,
3480 instructions,
3481 }) => {
3482 assert_eq!(capabilities.logging.unwrap().len(), 0);
3483 assert_eq!(capabilities.prompts.unwrap().list_changed, Some(true));
3484 assert_eq!(
3485 capabilities.resources.as_ref().unwrap().subscribe,
3486 Some(true)
3487 );
3488 assert_eq!(capabilities.resources.unwrap().list_changed, Some(true));
3489 assert_eq!(capabilities.tools.unwrap().list_changed, Some(true));
3490 assert_eq!(server_info.name, "ExampleServer");
3491 assert_eq!(server_info.version, "1.0.0");
3492 assert_eq!(server_info.icons, None);
3493 assert_eq!(instructions, None);
3494 }
3495 other => panic!("Expected InitializeResult, got {other:?}"),
3496 }
3497
3498 let server_response_json: Value = serde_json::to_value(&server_response).expect("msg");
3499
3500 assert_eq!(server_response_json, raw_response_json);
3501 }
3502
3503 #[test]
3504 fn test_negative_and_large_request_ids() {
3505 let negative_id_json = json!({
3507 "jsonrpc": "2.0",
3508 "id": -1,
3509 "method": "test",
3510 "params": {}
3511 });
3512
3513 let message: JsonRpcMessage =
3514 serde_json::from_value(negative_id_json.clone()).expect("Should parse negative ID");
3515
3516 match &message {
3517 JsonRpcMessage::Request(r) => {
3518 assert_eq!(r.id, RequestId::Number(-1));
3519 }
3520 _ => panic!("Expected Request"),
3521 }
3522
3523 let serialized = serde_json::to_value(&message).expect("Should serialize");
3525 assert_eq!(serialized, negative_id_json);
3526
3527 let large_negative_json = json!({
3529 "jsonrpc": "2.0",
3530 "id": -9007199254740991i64, "method": "test",
3532 "params": {}
3533 });
3534
3535 let message: JsonRpcMessage = serde_json::from_value(large_negative_json.clone())
3536 .expect("Should parse large negative ID");
3537
3538 match &message {
3539 JsonRpcMessage::Request(r) => {
3540 assert_eq!(r.id, RequestId::Number(-9007199254740991i64));
3541 }
3542 _ => panic!("Expected Request"),
3543 }
3544
3545 let large_positive_json = json!({
3547 "jsonrpc": "2.0",
3548 "id": 9007199254740991i64,
3549 "method": "test",
3550 "params": {}
3551 });
3552
3553 let message: JsonRpcMessage = serde_json::from_value(large_positive_json.clone())
3554 .expect("Should parse large positive ID");
3555
3556 match &message {
3557 JsonRpcMessage::Request(r) => {
3558 assert_eq!(r.id, RequestId::Number(9007199254740991i64));
3559 }
3560 _ => panic!("Expected Request"),
3561 }
3562
3563 let zero_id_json = json!({
3565 "jsonrpc": "2.0",
3566 "id": 0,
3567 "method": "test",
3568 "params": {}
3569 });
3570
3571 let message: JsonRpcMessage =
3572 serde_json::from_value(zero_id_json.clone()).expect("Should parse zero ID");
3573
3574 match &message {
3575 JsonRpcMessage::Request(r) => {
3576 assert_eq!(r.id, RequestId::Number(0));
3577 }
3578 _ => panic!("Expected Request"),
3579 }
3580 }
3581
3582 #[test]
3583 fn test_protocol_version_order() {
3584 let v1 = ProtocolVersion::V_2024_11_05;
3585 let v2 = ProtocolVersion::V_2025_03_26;
3586 assert!(v1 < v2);
3587 }
3588
3589 #[test]
3590 fn test_icon_serialization() {
3591 let icon = Icon {
3592 src: "https://example.com/icon.png".to_string(),
3593 mime_type: Some("image/png".to_string()),
3594 sizes: Some(vec!["48x48".to_string()]),
3595 };
3596
3597 let json = serde_json::to_value(&icon).unwrap();
3598 assert_eq!(json["src"], "https://example.com/icon.png");
3599 assert_eq!(json["mimeType"], "image/png");
3600 assert_eq!(json["sizes"][0], "48x48");
3601
3602 let deserialized: Icon = serde_json::from_value(json).unwrap();
3604 assert_eq!(deserialized, icon);
3605 }
3606
3607 #[test]
3608 fn test_icon_minimal() {
3609 let icon = Icon {
3610 src: "data:image/svg+xml;base64,PHN2Zy8+".to_string(),
3611 mime_type: None,
3612 sizes: None,
3613 };
3614
3615 let json = serde_json::to_value(&icon).unwrap();
3616 assert_eq!(json["src"], "data:image/svg+xml;base64,PHN2Zy8+");
3617 assert!(json.get("mimeType").is_none());
3618 assert!(json.get("sizes").is_none());
3619 }
3620
3621 #[test]
3622 fn test_implementation_with_icons() {
3623 let implementation = Implementation {
3624 name: "test-server".to_string(),
3625 title: Some("Test Server".to_string()),
3626 version: "1.0.0".to_string(),
3627 description: Some("A test server for unit testing".to_string()),
3628 icons: Some(vec![
3629 Icon {
3630 src: "https://example.com/icon.png".to_string(),
3631 mime_type: Some("image/png".to_string()),
3632 sizes: Some(vec!["48x48".to_string()]),
3633 },
3634 Icon {
3635 src: "https://example.com/icon.svg".to_string(),
3636 mime_type: Some("image/svg+xml".to_string()),
3637 sizes: Some(vec!["any".to_string()]),
3638 },
3639 ]),
3640 website_url: Some("https://example.com".to_string()),
3641 };
3642
3643 let json = serde_json::to_value(&implementation).unwrap();
3644 assert_eq!(json["name"], "test-server");
3645 assert_eq!(json["description"], "A test server for unit testing");
3646 assert_eq!(json["websiteUrl"], "https://example.com");
3647 assert!(json["icons"].is_array());
3648 assert_eq!(json["icons"][0]["src"], "https://example.com/icon.png");
3649 assert_eq!(json["icons"][0]["sizes"][0], "48x48");
3650 assert_eq!(json["icons"][1]["mimeType"], "image/svg+xml");
3651 assert_eq!(json["icons"][1]["sizes"][0], "any");
3652 }
3653
3654 #[test]
3655 fn test_backward_compatibility() {
3656 let old_json = json!({
3658 "name": "legacy-server",
3659 "version": "0.9.0"
3660 });
3661
3662 let implementation: Implementation = serde_json::from_value(old_json).unwrap();
3663 assert_eq!(implementation.name, "legacy-server");
3664 assert_eq!(implementation.version, "0.9.0");
3665 assert_eq!(implementation.description, None);
3666 assert_eq!(implementation.icons, None);
3667 assert_eq!(implementation.website_url, None);
3668 }
3669
3670 #[test]
3671 fn test_initialize_with_icons() {
3672 let init_result = InitializeResult {
3673 protocol_version: ProtocolVersion::default(),
3674 capabilities: ServerCapabilities::default(),
3675 server_info: Implementation {
3676 name: "icon-server".to_string(),
3677 title: None,
3678 version: "2.0.0".to_string(),
3679 description: None,
3680 icons: Some(vec![Icon {
3681 src: "https://example.com/server.png".to_string(),
3682 mime_type: Some("image/png".to_string()),
3683 sizes: Some(vec!["48x48".to_string()]),
3684 }]),
3685 website_url: Some("https://docs.example.com".to_string()),
3686 },
3687 instructions: None,
3688 };
3689
3690 let json = serde_json::to_value(&init_result).unwrap();
3691 assert!(json["serverInfo"]["icons"].is_array());
3692 assert_eq!(
3693 json["serverInfo"]["icons"][0]["src"],
3694 "https://example.com/server.png"
3695 );
3696 assert_eq!(json["serverInfo"]["icons"][0]["sizes"][0], "48x48");
3697 assert_eq!(json["serverInfo"]["websiteUrl"], "https://docs.example.com");
3698 }
3699
3700 #[test]
3701 fn test_elicitation_deserialization_untagged() {
3702 let json_data_without_tag = json!({
3704 "message": "Please provide more details.",
3705 "requestedSchema": {
3706 "title": "User Details",
3707 "type": "object",
3708 "properties": {
3709 "name": { "type": "string" },
3710 "age": { "type": "integer" }
3711 },
3712 "required": ["name", "age"]
3713 }
3714 });
3715 let elicitation: CreateElicitationRequestParams =
3716 serde_json::from_value(json_data_without_tag).expect("Deserialization failed");
3717 if let CreateElicitationRequestParams::FormElicitationParams {
3718 meta,
3719 message,
3720 requested_schema,
3721 } = elicitation
3722 {
3723 assert_eq!(meta, None);
3724 assert_eq!(message, "Please provide more details.");
3725 assert_eq!(requested_schema.title, Some(Cow::from("User Details")));
3726 assert_eq!(requested_schema.type_, ObjectTypeConst);
3727 } else {
3728 panic!("Expected FormElicitationParam");
3729 }
3730 }
3731
3732 #[test]
3733 fn test_elicitation_deserialization() {
3734 let json_data_form = json!({
3735 "_meta": { "meta_form_key_1": "meta form value 1" },
3736 "mode": "form",
3737 "message": "Please provide more details.",
3738 "requestedSchema": {
3739 "title": "User Details",
3740 "type": "object",
3741 "properties": {
3742 "name": { "type": "string" },
3743 "age": { "type": "integer" }
3744 },
3745 "required": ["name", "age"]
3746 }
3747 });
3748 let elicitation_form: CreateElicitationRequestParams =
3749 serde_json::from_value(json_data_form).expect("Deserialization failed");
3750 if let CreateElicitationRequestParams::FormElicitationParams {
3751 meta,
3752 message,
3753 requested_schema,
3754 } = elicitation_form
3755 {
3756 assert_eq!(
3757 meta,
3758 Some(Meta(object!({ "meta_form_key_1": "meta form value 1" })))
3759 );
3760 assert_eq!(message, "Please provide more details.");
3761 assert_eq!(requested_schema.title, Some(Cow::from("User Details")));
3762 assert_eq!(requested_schema.type_, ObjectTypeConst);
3763 } else {
3764 panic!("Expected FormElicitationParam");
3765 }
3766
3767 let json_data_url = json!({
3768 "_meta": { "meta_url_key_1": "meta url value 1" },
3769 "mode": "url",
3770 "message": "Please fill out the form at the following URL.",
3771 "url": "https://example.com/form",
3772 "elicitationId": "elicitation-123"
3773 });
3774 let elicitation_url: CreateElicitationRequestParams =
3775 serde_json::from_value(json_data_url).expect("Deserialization failed");
3776 if let CreateElicitationRequestParams::UrlElicitationParams {
3777 meta,
3778 message,
3779 url,
3780 elicitation_id,
3781 } = elicitation_url
3782 {
3783 assert_eq!(
3784 meta,
3785 Some(Meta(object!({ "meta_url_key_1": "meta url value 1" })))
3786 );
3787 assert_eq!(message, "Please fill out the form at the following URL.");
3788 assert_eq!(url, "https://example.com/form");
3789 assert_eq!(elicitation_id, "elicitation-123");
3790 } else {
3791 panic!("Expected UrlElicitationParam");
3792 }
3793 }
3794
3795 #[test]
3796 fn test_elicitation_serialization() {
3797 let form_elicitation = CreateElicitationRequestParams::FormElicitationParams {
3798 meta: Some(Meta(object!({ "meta_form_key_1": "meta form value 1" }))),
3799 message: "Please provide more details.".to_string(),
3800 requested_schema: ElicitationSchema::builder()
3801 .title("User Details")
3802 .string_property("name", |s| s)
3803 .build()
3804 .expect("Valid schema"),
3805 };
3806 let json_form = serde_json::to_value(&form_elicitation).expect("Serialization failed");
3807 let expected_form_json = json!({
3808 "_meta": { "meta_form_key_1": "meta form value 1" },
3809 "mode": "form",
3810 "message": "Please provide more details.",
3811 "requestedSchema": {
3812 "title":"User Details",
3813 "type":"object",
3814 "properties":{
3815 "name": { "type": "string" },
3816 },
3817 }
3818 });
3819 assert_eq!(json_form, expected_form_json);
3820
3821 let url_elicitation = CreateElicitationRequestParams::UrlElicitationParams {
3822 meta: Some(Meta(object!({ "meta_url_key_1": "meta url value 1" }))),
3823 message: "Please fill out the form at the following URL.".to_string(),
3824 url: "https://example.com/form".to_string(),
3825 elicitation_id: "elicitation-123".to_string(),
3826 };
3827 let json_url = serde_json::to_value(&url_elicitation).expect("Serialization failed");
3828 let expected_url_json = json!({
3829 "_meta": { "meta_url_key_1": "meta url value 1" },
3830 "mode": "url",
3831 "message": "Please fill out the form at the following URL.",
3832 "url": "https://example.com/form",
3833 "elicitationId": "elicitation-123"
3834 });
3835 assert_eq!(json_url, expected_url_json);
3836 }
3837
3838 #[test]
3839 fn notification_without_params_should_deserialize_as_bare_jsonrpc_message() {
3840 let payload = b"{\"method\":\"notifications/initialized\",\"jsonrpc\":\"2.0\"}";
3841 let result: Result<JsonRpcMessage, _> = serde_json::from_slice(payload);
3842 assert!(
3843 matches!(result, Ok(JsonRpcMessage::Notification(_))),
3844 "Expected Ok(Notification), got: {:?}",
3845 result
3846 );
3847 }
3848}