1use std::{borrow::Cow, sync::Arc};
2mod annotated;
3mod capabilities;
4mod content;
5mod extension;
6mod meta;
7mod prompt;
8mod resource;
9mod serde_impl;
10mod tool;
11pub use annotated::*;
12pub use capabilities::*;
13pub use content::*;
14pub use extension::*;
15pub use meta::*;
16pub use prompt::*;
17pub use resource::*;
18use serde::{Deserialize, Serialize};
19use serde_json::Value;
20pub use tool::*;
21
22pub type JsonObject<F = Value> = serde_json::Map<String, F>;
24
25pub fn object(value: serde_json::Value) -> JsonObject {
30 debug_assert!(value.is_object());
31 match value {
32 serde_json::Value::Object(map) => map,
33 _ => JsonObject::default(),
34 }
35}
36
37#[cfg(feature = "macros")]
39#[cfg_attr(docsrs, doc(cfg(feature = "macros")))]
40#[macro_export]
41macro_rules! object {
42 ({$($tt:tt)*}) => {
43 $crate::model::object(serde_json::json! {
44 {$($tt)*}
45 })
46 };
47}
48#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy, Eq)]
49#[cfg_attr(feature = "server", derive(schemars::JsonSchema))]
50pub struct EmptyObject {}
51
52pub trait ConstString: Default {
53 const VALUE: &str;
54}
55#[macro_export]
56macro_rules! const_string {
57 ($name:ident = $value:literal) => {
58 #[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
59 pub struct $name;
60
61 impl ConstString for $name {
62 const VALUE: &str = $value;
63 }
64
65 impl serde::Serialize for $name {
66 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
67 where
68 S: serde::Serializer,
69 {
70 $value.serialize(serializer)
71 }
72 }
73
74 impl<'de> serde::Deserialize<'de> for $name {
75 fn deserialize<D>(deserializer: D) -> Result<$name, D::Error>
76 where
77 D: serde::Deserializer<'de>,
78 {
79 let s: String = serde::Deserialize::deserialize(deserializer)?;
80 if s == $value {
81 Ok($name)
82 } else {
83 Err(serde::de::Error::custom(format!(concat!(
84 "expect const string value \"",
85 $value,
86 "\""
87 ))))
88 }
89 }
90 }
91
92 #[cfg(feature = "schemars")]
93 impl schemars::JsonSchema for $name {
94 fn schema_name() -> String {
95 stringify!($name).to_string()
96 }
97
98 fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::schema::Schema {
99 schemars::schema::Schema::Object(schemars::schema::SchemaObject {
101 instance_type: Some(schemars::schema::InstanceType::String.into()),
102 format: Some("const".to_string()),
103 const_value: Some(serde_json::Value::String($value.into())),
104 ..Default::default()
105 })
106 }
107 }
108 };
109}
110
111const_string!(JsonRpcVersion2_0 = "2.0");
112
113#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd)]
114#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
115pub struct ProtocolVersion(Cow<'static, str>);
116
117impl Default for ProtocolVersion {
118 fn default() -> Self {
119 Self::LATEST
120 }
121}
122
123impl std::fmt::Display for ProtocolVersion {
124 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
125 self.0.fmt(f)
126 }
127}
128
129impl ProtocolVersion {
130 pub const V_2025_03_26: Self = Self(Cow::Borrowed("2025-03-26"));
131 pub const V_2024_11_05: Self = Self(Cow::Borrowed("2024-11-05"));
132 pub const LATEST: Self = Self::V_2025_03_26;
133}
134
135impl Serialize for ProtocolVersion {
136 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
137 where
138 S: serde::Serializer,
139 {
140 self.0.serialize(serializer)
141 }
142}
143
144impl<'de> Deserialize<'de> for ProtocolVersion {
145 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
146 where
147 D: serde::Deserializer<'de>,
148 {
149 let s: String = Deserialize::deserialize(deserializer)?;
150 #[allow(clippy::single_match)]
151 match s.as_str() {
152 "2024-11-05" => return Ok(ProtocolVersion::V_2024_11_05),
153 "2025-03-26" => return Ok(ProtocolVersion::V_2025_03_26),
154 _ => {}
155 }
156 Ok(ProtocolVersion(Cow::Owned(s)))
157 }
158}
159
160#[derive(Debug, Clone, Eq, PartialEq, Hash)]
161pub enum NumberOrString {
162 Number(u32),
163 String(Arc<str>),
164}
165
166impl NumberOrString {
167 pub fn into_json_value(self) -> Value {
168 match self {
169 NumberOrString::Number(n) => Value::Number(serde_json::Number::from(n)),
170 NumberOrString::String(s) => Value::String(s.to_string()),
171 }
172 }
173}
174
175impl std::fmt::Display for NumberOrString {
176 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
177 match self {
178 NumberOrString::Number(n) => n.fmt(f),
179 NumberOrString::String(s) => s.fmt(f),
180 }
181 }
182}
183
184impl Serialize for NumberOrString {
185 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
186 where
187 S: serde::Serializer,
188 {
189 match self {
190 NumberOrString::Number(n) => n.serialize(serializer),
191 NumberOrString::String(s) => s.serialize(serializer),
192 }
193 }
194}
195
196impl<'de> Deserialize<'de> for NumberOrString {
197 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
198 where
199 D: serde::Deserializer<'de>,
200 {
201 let value: Value = Deserialize::deserialize(deserializer)?;
202 match value {
203 Value::Number(n) => Ok(NumberOrString::Number(
204 n.as_u64()
205 .ok_or(serde::de::Error::custom("Expect an integer"))? as u32,
206 )),
207 Value::String(s) => Ok(NumberOrString::String(s.into())),
208 _ => Err(serde::de::Error::custom("Expect number or string")),
209 }
210 }
211}
212
213#[cfg(feature = "schemars")]
214impl schemars::JsonSchema for NumberOrString {
215 fn schema_name() -> String {
216 "NumberOrString".to_string()
217 }
218
219 fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::schema::Schema {
220 schemars::schema::Schema::Object(schemars::schema::SchemaObject {
221 subschemas: Some(Box::new(schemars::schema::SubschemaValidation {
222 one_of: Some(vec![
223 schemars::schema::Schema::Object(schemars::schema::SchemaObject {
224 instance_type: Some(schemars::schema::InstanceType::Number.into()),
225 ..Default::default()
226 }),
227 schemars::schema::Schema::Object(schemars::schema::SchemaObject {
228 instance_type: Some(schemars::schema::InstanceType::String.into()),
229 ..Default::default()
230 }),
231 ]),
232 ..Default::default()
233 })),
234 ..Default::default()
235 })
236 }
237}
238
239pub type RequestId = NumberOrString;
240
241#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Hash, Eq)]
242#[serde(transparent)]
243#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
244pub struct ProgressToken(pub NumberOrString);
245#[derive(Debug, Clone)]
246#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
247pub struct Request<M = String, P = JsonObject> {
248 pub method: M,
249 pub params: P,
251 #[cfg_attr(feature = "schemars", schemars(skip))]
255 pub extensions: Extensions,
256}
257
258impl<M, P> GetExtensions for Request<M, P> {
259 fn extensions(&self) -> &Extensions {
260 &self.extensions
261 }
262 fn extensions_mut(&mut self) -> &mut Extensions {
263 &mut self.extensions
264 }
265}
266
267#[derive(Debug, Clone)]
268#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
269pub struct RequestOptionalParam<M = String, P = JsonObject> {
270 pub method: M,
271 pub params: Option<P>,
273 #[cfg_attr(feature = "schemars", schemars(skip))]
277 pub extensions: Extensions,
278}
279
280#[derive(Debug, Clone)]
281#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
282pub struct RequestNoParam<M = String> {
283 pub method: M,
284 #[cfg_attr(feature = "schemars", schemars(skip))]
288 pub extensions: Extensions,
289}
290
291impl<M> GetExtensions for RequestNoParam<M> {
292 fn extensions(&self) -> &Extensions {
293 &self.extensions
294 }
295 fn extensions_mut(&mut self) -> &mut Extensions {
296 &mut self.extensions
297 }
298}
299#[derive(Debug, Clone)]
300#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
301pub struct Notification<M = String, P = JsonObject> {
302 pub method: M,
303 pub params: P,
304 #[cfg_attr(feature = "schemars", schemars(skip))]
308 pub extensions: Extensions,
309}
310
311#[derive(Debug, Clone)]
312#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
313pub struct NotificationNoParam<M = String> {
314 pub method: M,
315 #[cfg_attr(feature = "schemars", schemars(skip))]
319 pub extensions: Extensions,
320}
321
322#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
323#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
324pub struct JsonRpcRequest<R = Request> {
325 pub jsonrpc: JsonRpcVersion2_0,
326 pub id: RequestId,
327 #[serde(flatten)]
328 pub request: R,
329}
330
331type DefaultResponse = JsonObject;
332#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
333#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
334pub struct JsonRpcResponse<R = JsonObject> {
335 pub jsonrpc: JsonRpcVersion2_0,
336 pub id: RequestId,
337 pub result: R,
338}
339
340#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
341#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
342pub struct JsonRpcError {
343 pub jsonrpc: JsonRpcVersion2_0,
344 pub id: RequestId,
345 pub error: ErrorData,
346}
347
348#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
349#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
350pub struct JsonRpcNotification<N = Notification> {
351 pub jsonrpc: JsonRpcVersion2_0,
352 #[serde(flatten)]
353 pub notification: N,
354}
355
356#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
358#[serde(transparent)]
359#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
360pub struct ErrorCode(pub i32);
361
362impl ErrorCode {
363 pub const RESOURCE_NOT_FOUND: Self = Self(-32002);
364 pub const INVALID_REQUEST: Self = Self(-32600);
365 pub const METHOD_NOT_FOUND: Self = Self(-32601);
366 pub const INVALID_PARAMS: Self = Self(-32602);
367 pub const INTERNAL_ERROR: Self = Self(-32603);
368 pub const PARSE_ERROR: Self = Self(-32700);
369}
370
371#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
373#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
374pub struct ErrorData {
375 pub code: ErrorCode,
377
378 pub message: Cow<'static, str>,
380
381 #[serde(skip_serializing_if = "Option::is_none")]
384 pub data: Option<Value>,
385}
386
387impl ErrorData {
388 pub fn new(
389 code: ErrorCode,
390 message: impl Into<Cow<'static, str>>,
391 data: Option<Value>,
392 ) -> Self {
393 Self {
394 code,
395 message: message.into(),
396 data,
397 }
398 }
399 pub fn resource_not_found(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
400 Self::new(ErrorCode::RESOURCE_NOT_FOUND, message, data)
401 }
402 pub fn parse_error(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
403 Self::new(ErrorCode::PARSE_ERROR, message, data)
404 }
405 pub fn invalid_request(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
406 Self::new(ErrorCode::INVALID_REQUEST, message, data)
407 }
408 pub fn method_not_found<M: ConstString>() -> Self {
409 Self::new(ErrorCode::METHOD_NOT_FOUND, M::VALUE, None)
410 }
411 pub fn invalid_params(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
412 Self::new(ErrorCode::INVALID_PARAMS, message, data)
413 }
414 pub fn internal_error(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
415 Self::new(ErrorCode::INTERNAL_ERROR, message, data)
416 }
417}
418
419#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
420#[serde(untagged)]
421#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
422pub enum JsonRpcBatchRequestItem<Req, Not> {
423 Request(JsonRpcRequest<Req>),
424 Notification(JsonRpcNotification<Not>),
425}
426
427impl<Req, Not> JsonRpcBatchRequestItem<Req, Not> {
428 pub fn into_non_batch_message<Resp>(self) -> JsonRpcMessage<Req, Resp, Not> {
429 match self {
430 JsonRpcBatchRequestItem::Request(r) => JsonRpcMessage::Request(r),
431 JsonRpcBatchRequestItem::Notification(n) => JsonRpcMessage::Notification(n),
432 }
433 }
434}
435
436#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
437#[serde(untagged)]
438#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
439pub enum JsonRpcBatchResponseItem<Resp> {
440 Response(JsonRpcResponse<Resp>),
441 Error(JsonRpcError),
442}
443
444impl<Resp> JsonRpcBatchResponseItem<Resp> {
445 pub fn into_non_batch_message<Req, Not>(self) -> JsonRpcMessage<Req, Resp, Not> {
446 match self {
447 JsonRpcBatchResponseItem::Response(r) => JsonRpcMessage::Response(r),
448 JsonRpcBatchResponseItem::Error(e) => JsonRpcMessage::Error(e),
449 }
450 }
451}
452
453#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
454#[serde(untagged)]
455#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
456pub enum JsonRpcMessage<Req = Request, Resp = DefaultResponse, Noti = Notification> {
457 Request(JsonRpcRequest<Req>),
458 Response(JsonRpcResponse<Resp>),
459 Notification(JsonRpcNotification<Noti>),
460 BatchRequest(Vec<JsonRpcBatchRequestItem<Req, Noti>>),
461 BatchResponse(Vec<JsonRpcBatchResponseItem<Resp>>),
462 Error(JsonRpcError),
463}
464
465impl<Req, Resp, Not> JsonRpcMessage<Req, Resp, Not> {
466 #[inline]
467 pub const fn request(request: Req, id: RequestId) -> Self {
468 JsonRpcMessage::Request(JsonRpcRequest {
469 jsonrpc: JsonRpcVersion2_0,
470 id,
471 request,
472 })
473 }
474 #[inline]
475 pub const fn response(response: Resp, id: RequestId) -> Self {
476 JsonRpcMessage::Response(JsonRpcResponse {
477 jsonrpc: JsonRpcVersion2_0,
478 id,
479 result: response,
480 })
481 }
482 #[inline]
483 pub const fn error(error: ErrorData, id: RequestId) -> Self {
484 JsonRpcMessage::Error(JsonRpcError {
485 jsonrpc: JsonRpcVersion2_0,
486 id,
487 error,
488 })
489 }
490 #[inline]
491 pub const fn notification(notification: Not) -> Self {
492 JsonRpcMessage::Notification(JsonRpcNotification {
493 jsonrpc: JsonRpcVersion2_0,
494 notification,
495 })
496 }
497 pub fn into_request(self) -> Option<(Req, RequestId)> {
498 match self {
499 JsonRpcMessage::Request(r) => Some((r.request, r.id)),
500 _ => None,
501 }
502 }
503 pub fn into_response(self) -> Option<(Resp, RequestId)> {
504 match self {
505 JsonRpcMessage::Response(r) => Some((r.result, r.id)),
506 _ => None,
507 }
508 }
509 pub fn into_notification(self) -> Option<Not> {
510 match self {
511 JsonRpcMessage::Notification(n) => Some(n.notification),
512 _ => None,
513 }
514 }
515 pub fn into_error(self) -> Option<(ErrorData, RequestId)> {
516 match self {
517 JsonRpcMessage::Error(e) => Some((e.error, e.id)),
518 _ => None,
519 }
520 }
521 pub fn into_result(self) -> Option<(Result<Resp, ErrorData>, RequestId)> {
522 match self {
523 JsonRpcMessage::Response(r) => Some((Ok(r.result), r.id)),
524 JsonRpcMessage::Error(e) => Some((Err(e.error), e.id)),
525
526 _ => None,
527 }
528 }
529}
530
531pub type EmptyResult = EmptyObject;
534
535impl From<()> for EmptyResult {
536 fn from(_value: ()) -> Self {
537 EmptyResult {}
538 }
539}
540
541impl From<EmptyResult> for () {
542 fn from(_value: EmptyResult) {}
543}
544
545#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
546#[serde(rename_all = "camelCase")]
547#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
548pub struct CancelledNotificationParam {
549 pub request_id: RequestId,
550 pub reason: Option<String>,
551}
552
553const_string!(CancelledNotificationMethod = "notifications/cancelled");
554
555pub type CancelledNotification =
564 Notification<CancelledNotificationMethod, CancelledNotificationParam>;
565
566const_string!(InitializeResultMethod = "initialize");
567pub type InitializeRequest = Request<InitializeResultMethod, InitializeRequestParam>;
570
571const_string!(InitializedNotificationMethod = "notifications/initialized");
572pub type InitializedNotification = NotificationNoParam<InitializedNotificationMethod>;
574#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
575#[serde(rename_all = "camelCase")]
576#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
577pub struct InitializeRequestParam {
578 pub protocol_version: ProtocolVersion,
579 pub capabilities: ClientCapabilities,
580 pub client_info: Implementation,
581}
582
583#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
584#[serde(rename_all = "camelCase")]
585#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
586pub struct InitializeResult {
587 pub protocol_version: ProtocolVersion,
588 pub capabilities: ServerCapabilities,
589 pub server_info: Implementation,
590 #[serde(skip_serializing_if = "Option::is_none")]
591 pub instructions: Option<String>,
592}
593
594pub type ServerInfo = InitializeResult;
595pub type ClientInfo = InitializeRequestParam;
596
597impl Default for ServerInfo {
598 fn default() -> Self {
599 ServerInfo {
600 protocol_version: ProtocolVersion::default(),
601 capabilities: ServerCapabilities::default(),
602 server_info: Implementation::from_build_env(),
603 instructions: None,
604 }
605 }
606}
607
608impl Default for ClientInfo {
609 fn default() -> Self {
610 ClientInfo {
611 protocol_version: ProtocolVersion::default(),
612 capabilities: ClientCapabilities::default(),
613 client_info: Implementation::from_build_env(),
614 }
615 }
616}
617
618#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
619#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
620pub struct Implementation {
621 pub name: String,
622 pub version: String,
623}
624
625impl Default for Implementation {
626 fn default() -> Self {
627 Self::from_build_env()
628 }
629}
630
631impl Implementation {
632 pub fn from_build_env() -> Self {
633 Implementation {
634 name: env!("CARGO_CRATE_NAME").to_owned(),
635 version: env!("CARGO_PKG_VERSION").to_owned(),
636 }
637 }
638}
639
640#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
641#[serde(rename_all = "camelCase")]
642#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
643pub struct PaginatedRequestParam {
644 #[serde(skip_serializing_if = "Option::is_none")]
645 pub cursor: Option<String>,
646}
647const_string!(PingRequestMethod = "ping");
648pub type PingRequest = RequestNoParam<PingRequestMethod>;
649
650const_string!(ProgressNotificationMethod = "notifications/progress");
651#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
652#[serde(rename_all = "camelCase")]
653#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
654pub struct ProgressNotificationParam {
655 pub progress_token: ProgressToken,
656 pub progress: u32,
658 #[serde(skip_serializing_if = "Option::is_none")]
660 pub total: Option<u32>,
661 #[serde(skip_serializing_if = "Option::is_none")]
663 pub message: Option<String>,
664}
665
666pub type ProgressNotification = Notification<ProgressNotificationMethod, ProgressNotificationParam>;
667
668pub type Cursor = String;
669
670macro_rules! paginated_result {
671 ($t:ident {
672 $i_item: ident: $t_item: ty
673 }) => {
674 #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
675 #[serde(rename_all = "camelCase")]
676 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
677 pub struct $t {
678 #[serde(skip_serializing_if = "Option::is_none")]
679 pub next_cursor: Option<Cursor>,
680 pub $i_item: $t_item,
681 }
682
683 impl $t {
684 pub fn with_all_items(
685 items: $t_item,
686 ) -> Self {
687 Self {
688 next_cursor: None,
689 $i_item: items,
690 }
691 }
692 }
693 };
694}
695
696const_string!(ListResourcesRequestMethod = "resources/list");
697pub type ListResourcesRequest =
698 RequestOptionalParam<ListResourcesRequestMethod, PaginatedRequestParam>;
699paginated_result!(ListResourcesResult {
700 resources: Vec<Resource>
701});
702
703const_string!(ListResourceTemplatesRequestMethod = "resources/templates/list");
704pub type ListResourceTemplatesRequest =
705 RequestOptionalParam<ListResourceTemplatesRequestMethod, PaginatedRequestParam>;
706paginated_result!(ListResourceTemplatesResult {
707 resource_templates: Vec<ResourceTemplate>
708});
709
710const_string!(ReadResourceRequestMethod = "resources/read");
711#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
712#[serde(rename_all = "camelCase")]
713#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
714pub struct ReadResourceRequestParam {
715 pub uri: String,
716}
717
718#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
719#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
720pub struct ReadResourceResult {
721 pub contents: Vec<ResourceContents>,
722}
723
724pub type ReadResourceRequest = Request<ReadResourceRequestMethod, ReadResourceRequestParam>;
725
726const_string!(ResourceListChangedNotificationMethod = "notifications/resources/list_changed");
727pub type ResourceListChangedNotification =
728 NotificationNoParam<ResourceListChangedNotificationMethod>;
729
730const_string!(SubscribeRequestMethod = "resources/subscribe");
731#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
732#[serde(rename_all = "camelCase")]
733#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
734pub struct SubscribeRequestParam {
735 pub uri: String,
736}
737pub type SubscribeRequest = Request<SubscribeRequestMethod, SubscribeRequestParam>;
738
739const_string!(UnsubscribeRequestMethod = "resources/unsubscribe");
740#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
741#[serde(rename_all = "camelCase")]
742#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
743pub struct UnsubscribeRequestParam {
744 pub uri: String,
745}
746pub type UnsubscribeRequest = Request<UnsubscribeRequestMethod, UnsubscribeRequestParam>;
747
748const_string!(ResourceUpdatedNotificationMethod = "notifications/resources/updated");
749#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
750#[serde(rename_all = "camelCase")]
751#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
752pub struct ResourceUpdatedNotificationParam {
753 pub uri: String,
754}
755pub type ResourceUpdatedNotification =
756 Notification<ResourceUpdatedNotificationMethod, ResourceUpdatedNotificationParam>;
757
758const_string!(ListPromptsRequestMethod = "prompts/list");
759pub type ListPromptsRequest = RequestOptionalParam<ListPromptsRequestMethod, PaginatedRequestParam>;
760paginated_result!(ListPromptsResult {
761 prompts: Vec<Prompt>
762});
763
764const_string!(GetPromptRequestMethod = "prompts/get");
765#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
766#[serde(rename_all = "camelCase")]
767#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
768pub struct GetPromptRequestParam {
769 pub name: String,
770 #[serde(skip_serializing_if = "Option::is_none")]
771 pub arguments: Option<JsonObject>,
772}
773pub type GetPromptRequest = Request<GetPromptRequestMethod, GetPromptRequestParam>;
774
775const_string!(PromptListChangedNotificationMethod = "notifications/prompts/list_changed");
776pub type PromptListChangedNotification = NotificationNoParam<PromptListChangedNotificationMethod>;
777
778const_string!(ToolListChangedNotificationMethod = "notifications/tools/list_changed");
779pub type ToolListChangedNotification = NotificationNoParam<ToolListChangedNotificationMethod>;
780#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
782#[serde(rename_all = "lowercase")] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
784pub enum LoggingLevel {
785 Debug,
786 Info,
787 Notice,
788 Warning,
789 Error,
790 Critical,
791 Alert,
792 Emergency,
793}
794
795const_string!(SetLevelRequestMethod = "logging/setLevel");
796#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
797#[serde(rename_all = "camelCase")]
798#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
799pub struct SetLevelRequestParam {
800 pub level: LoggingLevel,
801}
802pub type SetLevelRequest = Request<SetLevelRequestMethod, SetLevelRequestParam>;
803
804const_string!(LoggingMessageNotificationMethod = "notifications/message");
805#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
806#[serde(rename_all = "camelCase")]
807#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
808pub struct LoggingMessageNotificationParam {
809 pub level: LoggingLevel,
810 #[serde(skip_serializing_if = "Option::is_none")]
811 pub logger: Option<String>,
812 pub data: Value,
813}
814pub type LoggingMessageNotification =
815 Notification<LoggingMessageNotificationMethod, LoggingMessageNotificationParam>;
816
817const_string!(CreateMessageRequestMethod = "sampling/createMessage");
818pub type CreateMessageRequest = Request<CreateMessageRequestMethod, CreateMessageRequestParam>;
819
820#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
821#[serde(rename_all = "camelCase")]
822#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
823pub enum Role {
824 User,
825 Assistant,
826}
827
828#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
829#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
830pub struct SamplingMessage {
831 pub role: Role,
832 pub content: Content,
833}
834
835#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
836#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
837pub enum ContextInclusion {
838 #[serde(rename = "allServers")]
839 AllServers,
840 #[serde(rename = "none")]
841 None,
842 #[serde(rename = "thisServer")]
843 ThisServer,
844}
845
846#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
847#[serde(rename_all = "camelCase")]
848#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
849pub struct CreateMessageRequestParam {
850 pub messages: Vec<SamplingMessage>,
851 #[serde(skip_serializing_if = "Option::is_none")]
852 pub model_preferences: Option<ModelPreferences>,
853 #[serde(skip_serializing_if = "Option::is_none")]
854 pub system_prompt: Option<String>,
855 #[serde(skip_serializing_if = "Option::is_none")]
856 pub include_context: Option<ContextInclusion>,
857 #[serde(skip_serializing_if = "Option::is_none")]
858 pub temperature: Option<f32>,
859 pub max_tokens: u32,
860 #[serde(skip_serializing_if = "Option::is_none")]
861 pub stop_sequences: Option<Vec<String>>,
862 #[serde(skip_serializing_if = "Option::is_none")]
863 pub metadata: Option<Value>,
864}
865
866#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
867#[serde(rename_all = "camelCase")]
868#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
869pub struct ModelPreferences {
870 #[serde(skip_serializing_if = "Option::is_none")]
871 pub hints: Option<Vec<ModelHint>>,
872 #[serde(skip_serializing_if = "Option::is_none")]
873 pub cost_priority: Option<f32>,
874 #[serde(skip_serializing_if = "Option::is_none")]
875 pub speed_priority: Option<f32>,
876 #[serde(skip_serializing_if = "Option::is_none")]
877 pub intelligence_priority: Option<f32>,
878}
879
880#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
881#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
882pub struct ModelHint {
883 #[serde(skip_serializing_if = "Option::is_none")]
884 pub name: Option<String>,
885}
886
887#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
888#[serde(rename_all = "camelCase")]
889#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
890pub struct CompleteRequestParam {
891 pub r#ref: Reference,
892 pub argument: ArgumentInfo,
893}
894
895pub type CompleteRequest = Request<CompleteRequestMethod, CompleteRequestParam>;
896
897#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
898#[serde(rename_all = "camelCase")]
899#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
900pub struct CompletionInfo {
901 pub values: Vec<String>,
902 #[serde(skip_serializing_if = "Option::is_none")]
903 pub total: Option<u32>,
904 #[serde(skip_serializing_if = "Option::is_none")]
905 pub has_more: Option<bool>,
906}
907
908#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
909#[serde(rename_all = "camelCase")]
910#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
911pub struct CompleteResult {
912 pub completion: CompletionInfo,
913}
914
915#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
916#[serde(tag = "type")]
917#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
918pub enum Reference {
919 #[serde(rename = "ref/resource")]
920 Resource(ResourceReference),
921 #[serde(rename = "ref/prompt")]
922 Prompt(PromptReference),
923}
924
925#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
926#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
927pub struct ResourceReference {
928 pub uri: String,
929}
930
931#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
932#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
933pub struct PromptReference {
934 pub name: String,
935}
936
937const_string!(CompleteRequestMethod = "completion/complete");
938#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
939#[serde(rename_all = "camelCase")]
940#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
941pub struct ArgumentInfo {
942 pub name: String,
943 pub value: String,
944}
945
946#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
948#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
949pub struct Root {
950 pub uri: String,
951 #[serde(skip_serializing_if = "Option::is_none")]
952 pub name: Option<String>,
953}
954
955const_string!(ListRootsRequestMethod = "roots/list");
956pub type ListRootsRequest = RequestNoParam<ListRootsRequestMethod>;
957
958#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
959#[serde(rename_all = "camelCase")]
960#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
961pub struct ListRootsResult {
962 pub roots: Vec<Root>,
963}
964
965const_string!(RootsListChangedNotificationMethod = "notifications/roots/list_changed");
966pub type RootsListChangedNotification = NotificationNoParam<RootsListChangedNotificationMethod>;
967
968#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
969#[serde(rename_all = "camelCase")]
970#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
971pub struct CallToolResult {
972 pub content: Vec<Content>,
973 #[serde(skip_serializing_if = "Option::is_none")]
974 pub is_error: Option<bool>,
975}
976
977impl CallToolResult {
978 pub fn success(content: Vec<Content>) -> Self {
979 CallToolResult {
980 content,
981 is_error: Some(false),
982 }
983 }
984 pub fn error(content: Vec<Content>) -> Self {
985 CallToolResult {
986 content,
987 is_error: Some(true),
988 }
989 }
990}
991
992const_string!(ListToolsRequestMethod = "tools/list");
993pub type ListToolsRequest = RequestOptionalParam<ListToolsRequestMethod, PaginatedRequestParam>;
994paginated_result!(
995 ListToolsResult {
996 tools: Vec<Tool>
997 }
998);
999
1000const_string!(CallToolRequestMethod = "tools/call");
1001#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1002#[serde(rename_all = "camelCase")]
1003#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1004pub struct CallToolRequestParam {
1005 pub name: Cow<'static, str>,
1006 #[serde(skip_serializing_if = "Option::is_none")]
1007 pub arguments: Option<JsonObject>,
1008}
1009
1010pub type CallToolRequest = Request<CallToolRequestMethod, CallToolRequestParam>;
1011
1012#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1013#[serde(rename_all = "camelCase")]
1014#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1015pub struct CreateMessageResult {
1016 pub model: String,
1017 #[serde(skip_serializing_if = "Option::is_none")]
1018 pub stop_reason: Option<String>,
1019 #[serde(flatten)]
1020 pub message: SamplingMessage,
1021}
1022
1023impl CreateMessageResult {
1024 pub const STOP_REASON_END_TURN: &str = "endTurn";
1025 pub const STOP_REASON_END_SEQUENCE: &str = "stopSequence";
1026 pub const STOP_REASON_END_MAX_TOKEN: &str = "maxTokens";
1027}
1028
1029#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1030#[serde(rename_all = "camelCase")]
1031#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1032pub struct GetPromptResult {
1033 #[serde(skip_serializing_if = "Option::is_none")]
1034 pub description: Option<String>,
1035 pub messages: Vec<PromptMessage>,
1036}
1037
1038macro_rules! ts_union {
1039 (
1040 export type $U: ident =
1041 $(|)?$($V: ident)|*;
1042 ) => {
1043 #[derive(Debug, Serialize, Deserialize, Clone)]
1044 #[serde(untagged)]
1045 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1046 pub enum $U {
1047 $($V($V),)*
1048 }
1049 };
1050}
1051
1052ts_union!(
1053 export type ClientRequest =
1054 | PingRequest
1055 | InitializeRequest
1056 | CompleteRequest
1057 | SetLevelRequest
1058 | GetPromptRequest
1059 | ListPromptsRequest
1060 | ListResourcesRequest
1061 | ListResourceTemplatesRequest
1062 | ReadResourceRequest
1063 | SubscribeRequest
1064 | UnsubscribeRequest
1065 | CallToolRequest
1066 | ListToolsRequest;
1067);
1068
1069ts_union!(
1070 export type ClientNotification =
1071 | CancelledNotification
1072 | ProgressNotification
1073 | InitializedNotification
1074 | RootsListChangedNotification;
1075);
1076
1077ts_union!(
1078 export type ClientResult = CreateMessageResult | ListRootsResult | EmptyResult;
1079);
1080
1081impl ClientResult {
1082 pub fn empty(_: ()) -> ClientResult {
1083 ClientResult::EmptyResult(EmptyResult {})
1084 }
1085}
1086
1087pub type ClientJsonRpcMessage = JsonRpcMessage<ClientRequest, ClientResult, ClientNotification>;
1088
1089ts_union!(
1090 export type ServerRequest =
1091 | PingRequest
1092 | CreateMessageRequest
1093 | ListRootsRequest;
1094);
1095
1096ts_union!(
1097 export type ServerNotification =
1098 | CancelledNotification
1099 | ProgressNotification
1100 | LoggingMessageNotification
1101 | ResourceUpdatedNotification
1102 | ResourceListChangedNotification
1103 | ToolListChangedNotification
1104 | PromptListChangedNotification;
1105);
1106
1107ts_union!(
1108 export type ServerResult =
1109 | InitializeResult
1110 | CompleteResult
1111 | GetPromptResult
1112 | ListPromptsResult
1113 | ListResourcesResult
1114 | ListResourceTemplatesResult
1115 | ReadResourceResult
1116 | CallToolResult
1117 | ListToolsResult
1118 | EmptyResult
1119 ;
1120);
1121
1122impl ServerResult {
1123 pub fn empty(_: ()) -> ServerResult {
1124 ServerResult::EmptyResult(EmptyResult {})
1125 }
1126}
1127
1128pub type ServerJsonRpcMessage = JsonRpcMessage<ServerRequest, ServerResult, ServerNotification>;
1129
1130impl TryInto<CancelledNotification> for ServerNotification {
1131 type Error = ServerNotification;
1132 fn try_into(self) -> Result<CancelledNotification, Self::Error> {
1133 if let ServerNotification::CancelledNotification(t) = self {
1134 Ok(t)
1135 } else {
1136 Err(self)
1137 }
1138 }
1139}
1140
1141impl TryInto<CancelledNotification> for ClientNotification {
1142 type Error = ClientNotification;
1143 fn try_into(self) -> Result<CancelledNotification, Self::Error> {
1144 if let ClientNotification::CancelledNotification(t) = self {
1145 Ok(t)
1146 } else {
1147 Err(self)
1148 }
1149 }
1150}
1151impl From<CancelledNotification> for ServerNotification {
1152 fn from(value: CancelledNotification) -> Self {
1153 ServerNotification::CancelledNotification(value)
1154 }
1155}
1156
1157impl From<CancelledNotification> for ClientNotification {
1158 fn from(value: CancelledNotification) -> Self {
1159 ClientNotification::CancelledNotification(value)
1160 }
1161}
1162
1163#[cfg(test)]
1164mod tests {
1165 use serde_json::json;
1166
1167 use super::*;
1168
1169 #[test]
1170 fn test_notification_serde() {
1171 let raw = json!( {
1172 "jsonrpc": JsonRpcVersion2_0,
1173 "method": InitializedNotificationMethod,
1174 });
1175 let message: ClientJsonRpcMessage =
1176 serde_json::from_value(raw.clone()).expect("invalid notification");
1177 match &message {
1178 ClientJsonRpcMessage::Notification(JsonRpcNotification {
1179 notification: ClientNotification::InitializedNotification(_n),
1180 ..
1181 }) => {}
1182 _ => panic!("Expected Notification"),
1183 }
1184 let json = serde_json::to_value(message).expect("valid json");
1185 assert_eq!(json, raw);
1186 }
1187
1188 #[test]
1189 fn test_request_conversion() {
1190 let raw = json!( {
1191 "jsonrpc": JsonRpcVersion2_0,
1192 "id": 1,
1193 "method": "request",
1194 "params": {"key": "value"},
1195 });
1196 let message: JsonRpcMessage = serde_json::from_value(raw.clone()).expect("invalid request");
1197
1198 match &message {
1199 JsonRpcMessage::Request(r) => {
1200 assert_eq!(r.id, RequestId::Number(1));
1201 assert_eq!(r.request.method, "request");
1202 assert_eq!(
1203 &r.request.params,
1204 json!({"key": "value"})
1205 .as_object()
1206 .expect("should be an object")
1207 );
1208 }
1209 _ => panic!("Expected Request"),
1210 }
1211 let json = serde_json::to_value(&message).expect("valid json");
1212 assert_eq!(json, raw);
1213 }
1214
1215 #[test]
1216 fn test_initial_request_response_serde() {
1217 let request = json!({
1218 "jsonrpc": "2.0",
1219 "id": 1,
1220 "method": "initialize",
1221 "params": {
1222 "protocolVersion": "2024-11-05",
1223 "capabilities": {
1224 "roots": {
1225 "listChanged": true
1226 },
1227 "sampling": {}
1228 },
1229 "clientInfo": {
1230 "name": "ExampleClient",
1231 "version": "1.0.0"
1232 }
1233 }
1234 });
1235 let raw_response_json = json!({
1236 "jsonrpc": "2.0",
1237 "id": 1,
1238 "result": {
1239 "protocolVersion": "2024-11-05",
1240 "capabilities": {
1241 "logging": {},
1242 "prompts": {
1243 "listChanged": true
1244 },
1245 "resources": {
1246 "subscribe": true,
1247 "listChanged": true
1248 },
1249 "tools": {
1250 "listChanged": true
1251 }
1252 },
1253 "serverInfo": {
1254 "name": "ExampleServer",
1255 "version": "1.0.0"
1256 }
1257 }
1258 });
1259 let request: ClientJsonRpcMessage =
1260 serde_json::from_value(request.clone()).expect("invalid request");
1261 let (request, id) = request.into_request().expect("should be a request");
1262 assert_eq!(id, RequestId::Number(1));
1263 match request {
1264 ClientRequest::InitializeRequest(Request {
1265 method: _,
1266 params:
1267 InitializeRequestParam {
1268 protocol_version: _,
1269 capabilities,
1270 client_info,
1271 },
1272 ..
1273 }) => {
1274 assert_eq!(capabilities.roots.unwrap().list_changed, Some(true));
1275 assert_eq!(capabilities.sampling.unwrap().len(), 0);
1276 assert_eq!(client_info.name, "ExampleClient");
1277 assert_eq!(client_info.version, "1.0.0");
1278 }
1279 _ => panic!("Expected InitializeRequest"),
1280 }
1281 let server_response: ServerJsonRpcMessage =
1282 serde_json::from_value(raw_response_json.clone()).expect("invalid response");
1283 let (response, id) = server_response
1284 .clone()
1285 .into_response()
1286 .expect("expect response");
1287 assert_eq!(id, RequestId::Number(1));
1288 match response {
1289 ServerResult::InitializeResult(InitializeResult {
1290 protocol_version: _,
1291 capabilities,
1292 server_info,
1293 instructions,
1294 }) => {
1295 assert_eq!(capabilities.logging.unwrap().len(), 0);
1296 assert_eq!(capabilities.prompts.unwrap().list_changed, Some(true));
1297 assert_eq!(
1298 capabilities.resources.as_ref().unwrap().subscribe,
1299 Some(true)
1300 );
1301 assert_eq!(capabilities.resources.unwrap().list_changed, Some(true));
1302 assert_eq!(capabilities.tools.unwrap().list_changed, Some(true));
1303 assert_eq!(server_info.name, "ExampleServer");
1304 assert_eq!(server_info.version, "1.0.0");
1305 assert_eq!(instructions, None);
1306 }
1307 other => panic!("Expected InitializeResult, got {other:?}"),
1308 }
1309
1310 let server_response_json: Value = serde_json::to_value(&server_response).expect("msg");
1311
1312 assert_eq!(server_response_json, raw_response_json);
1313 }
1314
1315 #[test]
1316 fn test_protocol_version_order() {
1317 let v1 = ProtocolVersion::V_2024_11_05;
1318 let v2 = ProtocolVersion::V_2025_03_26;
1319 assert!(v1 < v2);
1320 }
1321}