1use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8use turbomcp_core::MessageId;
9
10pub type ProtocolVersion = String;
12
13pub type RequestId = MessageId;
15
16#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
21#[serde(untagged)]
22pub enum ProgressToken {
23 String(String),
25 Integer(i64),
27}
28
29impl ProgressToken {
30 pub fn from_string<S: Into<String>>(s: S) -> Self {
32 Self::String(s.into())
33 }
34
35 pub fn from_integer(i: i64) -> Self {
37 Self::Integer(i)
38 }
39
40 pub fn is_string(&self) -> bool {
42 matches!(self, Self::String(_))
43 }
44
45 pub fn is_integer(&self) -> bool {
47 matches!(self, Self::Integer(_))
48 }
49
50 pub fn as_string(&self) -> Option<&str> {
52 match self {
53 Self::String(s) => Some(s),
54 Self::Integer(_) => None,
55 }
56 }
57
58 pub fn as_integer(&self) -> Option<i64> {
60 match self {
61 Self::String(_) => None,
62 Self::Integer(i) => Some(*i),
63 }
64 }
65
66 pub fn to_display_string(&self) -> String {
68 match self {
69 Self::String(s) => s.clone(),
70 Self::Integer(i) => i.to_string(),
71 }
72 }
73}
74
75impl std::fmt::Display for ProgressToken {
76 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77 match self {
78 Self::String(s) => write!(f, "{}", s),
79 Self::Integer(i) => write!(f, "{}", i),
80 }
81 }
82}
83
84impl From<String> for ProgressToken {
85 fn from(s: String) -> Self {
86 Self::String(s)
87 }
88}
89
90impl From<&str> for ProgressToken {
91 fn from(s: &str) -> Self {
92 Self::String(s.to_string())
93 }
94}
95
96impl From<i64> for ProgressToken {
97 fn from(i: i64) -> Self {
98 Self::Integer(i)
99 }
100}
101
102impl From<i32> for ProgressToken {
103 fn from(i: i32) -> Self {
104 Self::Integer(i64::from(i))
105 }
106}
107
108impl From<u32> for ProgressToken {
109 fn from(i: u32) -> Self {
110 Self::Integer(i64::from(i))
111 }
112}
113
114pub type Uri = String;
116
117pub type MimeType = String;
119
120pub type Base64String = String;
122
123pub mod error_codes {
129 pub const PARSE_ERROR: i32 = -32700;
131 pub const INVALID_REQUEST: i32 = -32600;
133 pub const METHOD_NOT_FOUND: i32 = -32601;
135 pub const INVALID_PARAMS: i32 = -32602;
137 pub const INTERNAL_ERROR: i32 = -32603;
139}
140
141#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
143pub struct JsonRpcError {
144 pub code: i32,
146 pub message: String,
148 #[serde(skip_serializing_if = "Option::is_none")]
150 pub data: Option<serde_json::Value>,
151}
152
153impl JsonRpcError {
154 pub fn new(code: i32, message: String) -> Self {
156 Self {
157 code,
158 message,
159 data: None,
160 }
161 }
162
163 pub fn with_data(code: i32, message: String, data: serde_json::Value) -> Self {
165 Self {
166 code,
167 message,
168 data: Some(data),
169 }
170 }
171
172 pub fn parse_error() -> Self {
174 Self::new(error_codes::PARSE_ERROR, "Parse error".to_string())
175 }
176
177 pub fn invalid_request() -> Self {
179 Self::new(error_codes::INVALID_REQUEST, "Invalid Request".to_string())
180 }
181
182 pub fn method_not_found(method: &str) -> Self {
184 Self::new(
185 error_codes::METHOD_NOT_FOUND,
186 format!("Method not found: {method}"),
187 )
188 }
189
190 pub fn invalid_params(details: &str) -> Self {
192 Self::new(
193 error_codes::INVALID_PARAMS,
194 format!("Invalid params: {details}"),
195 )
196 }
197
198 pub fn internal_error(details: &str) -> Self {
200 Self::new(
201 error_codes::INTERNAL_ERROR,
202 format!("Internal error: {details}"),
203 )
204 }
205}
206
207pub type Cursor = String;
209
210#[derive(Debug, Clone, Serialize, Deserialize)]
217pub struct BaseMetadata {
218 pub name: String,
220
221 #[serde(skip_serializing_if = "Option::is_none")]
227 pub title: Option<String>,
228}
229
230#[derive(Debug, Clone, Serialize, Deserialize)]
232pub struct Implementation {
233 pub name: String,
235 #[serde(skip_serializing_if = "Option::is_none")]
237 pub title: Option<String>,
238 pub version: String,
240}
241
242#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
244pub struct Annotations {
245 #[serde(skip_serializing_if = "Option::is_none")]
247 pub audience: Option<Vec<String>>,
248 #[serde(skip_serializing_if = "Option::is_none")]
250 pub priority: Option<f64>,
251 #[serde(skip_serializing_if = "Option::is_none")]
253 #[serde(rename = "lastModified")]
254 pub last_modified: Option<String>,
255 #[serde(flatten)]
257 pub custom: HashMap<String, serde_json::Value>,
258}
259
260#[derive(Debug, Clone, Serialize, Deserialize)]
266#[serde(tag = "method")]
267pub enum ClientRequest {
268 #[serde(rename = "initialize")]
270 Initialize(InitializeRequest),
271
272 #[serde(rename = "tools/list")]
274 ListTools(ListToolsRequest),
275
276 #[serde(rename = "tools/call")]
278 CallTool(CallToolRequest),
279
280 #[serde(rename = "prompts/list")]
282 ListPrompts(ListPromptsRequest),
283
284 #[serde(rename = "prompts/get")]
286 GetPrompt(GetPromptRequest),
287
288 #[serde(rename = "resources/list")]
290 ListResources(ListResourcesRequest),
291
292 #[serde(rename = "resources/templates/list")]
294 ListResourceTemplates(ListResourceTemplatesRequest),
295
296 #[serde(rename = "resources/read")]
298 ReadResource(ReadResourceRequest),
299
300 #[serde(rename = "resources/subscribe")]
302 Subscribe(SubscribeRequest),
303
304 #[serde(rename = "resources/unsubscribe")]
306 Unsubscribe(UnsubscribeRequest),
307
308 #[serde(rename = "logging/setLevel")]
310 SetLevel(SetLevelRequest),
311
312 #[serde(rename = "completion/complete")]
314 Complete(CompleteRequestParams),
315
316 #[serde(rename = "ping")]
318 Ping(PingParams),
319}
320
321#[derive(Debug, Clone, Serialize, Deserialize)]
323#[serde(tag = "method")]
324pub enum ServerRequest {
325 #[serde(rename = "ping")]
327 Ping(PingParams),
328
329 #[serde(rename = "sampling/createMessage")]
331 CreateMessage(CreateMessageRequest),
332
333 #[serde(rename = "roots/list")]
335 ListRoots(ListRootsRequest),
336
337 #[serde(rename = "elicitation/create")]
339 ElicitationCreate(ElicitRequestParams),
340}
341
342#[derive(Debug, Clone, Serialize, Deserialize)]
344#[serde(tag = "method")]
345pub enum ClientNotification {
346 #[serde(rename = "notifications/initialized")]
348 Initialized(InitializedNotification),
349
350 #[serde(rename = "notifications/progress")]
352 Progress(ProgressNotification),
353
354 #[serde(rename = "notifications/roots/list_changed")]
356 RootsListChanged(RootsListChangedNotification),
357}
358
359#[derive(Debug, Clone, Serialize, Deserialize)]
361#[serde(tag = "method")]
362pub enum ServerNotification {
363 #[serde(rename = "notifications/message")]
365 Message(LoggingNotification),
366
367 #[serde(rename = "notifications/resources/updated")]
369 ResourceUpdated(ResourceUpdatedNotification),
370
371 #[serde(rename = "notifications/resources/list_changed")]
373 ResourceListChanged,
374
375 #[serde(rename = "notifications/progress")]
377 Progress(ProgressNotification),
378
379 #[serde(rename = "notifications/cancelled")]
381 Cancelled(CancelledNotification),
382
383 #[serde(rename = "notifications/prompts/list_changed")]
385 PromptsListChanged,
386
387 #[serde(rename = "notifications/tools/list_changed")]
389 ToolsListChanged,
390
391 #[serde(rename = "notifications/roots/list_changed")]
393 RootsListChanged,
394}
395
396#[derive(Debug, Clone, Serialize, Deserialize)]
402pub struct InitializeRequest {
403 #[serde(rename = "protocolVersion")]
405 pub protocol_version: ProtocolVersion,
406 pub capabilities: ClientCapabilities,
408 #[serde(rename = "clientInfo")]
410 pub client_info: Implementation,
411 #[serde(skip_serializing_if = "Option::is_none")]
413 pub _meta: Option<serde_json::Value>,
414}
415
416#[derive(Debug, Clone, Serialize, Deserialize)]
418pub struct InitializeResult {
419 #[serde(rename = "protocolVersion")]
421 pub protocol_version: ProtocolVersion,
422 pub capabilities: ServerCapabilities,
424 #[serde(rename = "serverInfo")]
426 pub server_info: Implementation,
427 #[serde(skip_serializing_if = "Option::is_none")]
429 pub instructions: Option<String>,
430 #[serde(skip_serializing_if = "Option::is_none")]
432 pub _meta: Option<serde_json::Value>,
433}
434
435#[derive(Debug, Clone, Serialize, Deserialize)]
437pub struct InitializedNotification;
438
439#[derive(Debug, Clone, Serialize, Deserialize, Default)]
445pub struct ClientCapabilities {
446 #[serde(skip_serializing_if = "Option::is_none")]
448 pub experimental: Option<HashMap<String, serde_json::Value>>,
449
450 #[serde(skip_serializing_if = "Option::is_none")]
452 pub roots: Option<RootsCapabilities>,
453
454 #[serde(skip_serializing_if = "Option::is_none")]
456 pub sampling: Option<SamplingCapabilities>,
457
458 #[serde(skip_serializing_if = "Option::is_none")]
460 pub elicitation: Option<ElicitationCapabilities>,
461}
462
463#[derive(Debug, Clone, Serialize, Deserialize, Default)]
465pub struct ServerCapabilities {
466 #[serde(skip_serializing_if = "Option::is_none")]
468 pub experimental: Option<HashMap<String, serde_json::Value>>,
469
470 #[serde(skip_serializing_if = "Option::is_none")]
472 pub logging: Option<LoggingCapabilities>,
473
474 #[serde(skip_serializing_if = "Option::is_none")]
476 pub completions: Option<CompletionCapabilities>,
477
478 #[serde(skip_serializing_if = "Option::is_none")]
480 pub prompts: Option<PromptsCapabilities>,
481
482 #[serde(skip_serializing_if = "Option::is_none")]
484 pub resources: Option<ResourcesCapabilities>,
485
486 #[serde(skip_serializing_if = "Option::is_none")]
488 pub tools: Option<ToolsCapabilities>,
489}
490
491#[derive(Debug, Clone, Serialize, Deserialize, Default)]
493pub struct SamplingCapabilities;
494
495#[derive(Debug, Clone, Serialize, Deserialize, Default)]
497pub struct ElicitationCapabilities;
498
499#[derive(Debug, Clone, Serialize, Deserialize, Default)]
501pub struct CompletionCapabilities;
502
503#[derive(Debug, Clone, Serialize, Deserialize, Default)]
505pub struct RootsCapabilities {
506 #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
508 pub list_changed: Option<bool>,
509}
510
511#[derive(Debug, Clone, Serialize, Deserialize, Default)]
513pub struct LoggingCapabilities;
514
515#[derive(Debug, Clone, Serialize, Deserialize, Default)]
517pub struct PromptsCapabilities {
518 #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
520 pub list_changed: Option<bool>,
521}
522
523#[derive(Debug, Clone, Serialize, Deserialize, Default)]
525pub struct ResourcesCapabilities {
526 #[serde(skip_serializing_if = "Option::is_none")]
528 pub subscribe: Option<bool>,
529
530 #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
532 pub list_changed: Option<bool>,
533}
534
535#[derive(Debug, Clone, Serialize, Deserialize, Default)]
537pub struct ToolsCapabilities {
538 #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
540 pub list_changed: Option<bool>,
541}
542
543#[derive(Debug, Clone, Serialize, Deserialize)]
549#[serde(tag = "type")]
550pub enum ContentBlock {
551 #[serde(rename = "text")]
553 Text(TextContent),
554 #[serde(rename = "image")]
556 Image(ImageContent),
557 #[serde(rename = "audio")]
559 Audio(AudioContent),
560 #[serde(rename = "resource_link")]
562 ResourceLink(ResourceLink),
563 #[serde(rename = "resource")]
565 Resource(EmbeddedResource),
566}
567
568pub type Content = ContentBlock;
570
571#[derive(Debug, Clone, Serialize, Deserialize)]
573pub struct TextContent {
574 pub text: String,
576 #[serde(skip_serializing_if = "Option::is_none")]
578 pub annotations: Option<Annotations>,
579 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
581 pub meta: Option<HashMap<String, serde_json::Value>>,
582}
583
584#[derive(Debug, Clone, Serialize, Deserialize)]
586pub struct ImageContent {
587 pub data: String,
589 #[serde(rename = "mimeType")]
591 pub mime_type: String,
592 #[serde(skip_serializing_if = "Option::is_none")]
594 pub annotations: Option<Annotations>,
595 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
597 pub meta: Option<HashMap<String, serde_json::Value>>,
598}
599
600#[derive(Debug, Clone, Serialize, Deserialize)]
602pub struct AudioContent {
603 pub data: String,
605 #[serde(rename = "mimeType")]
607 pub mime_type: String,
608 #[serde(skip_serializing_if = "Option::is_none")]
610 pub annotations: Option<Annotations>,
611 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
613 pub meta: Option<HashMap<String, serde_json::Value>>,
614}
615
616#[derive(Debug, Clone, Serialize, Deserialize)]
618pub struct ResourceLink {
619 pub name: String,
621 #[serde(skip_serializing_if = "Option::is_none")]
623 pub title: Option<String>,
624 pub uri: String,
626 #[serde(skip_serializing_if = "Option::is_none")]
628 pub description: Option<String>,
629 #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
631 pub mime_type: Option<String>,
632 #[serde(skip_serializing_if = "Option::is_none")]
634 pub annotations: Option<Annotations>,
635 #[serde(skip_serializing_if = "Option::is_none")]
637 pub size: Option<u64>,
638 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
640 pub meta: Option<HashMap<String, serde_json::Value>>,
641}
642
643#[derive(Debug, Clone, Serialize, Deserialize)]
645pub struct EmbeddedResource {
646 pub resource: ResourceContent,
648 #[serde(skip_serializing_if = "Option::is_none")]
650 pub annotations: Option<Annotations>,
651 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
653 pub meta: Option<HashMap<String, serde_json::Value>>,
654}
655
656#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
658#[serde(rename_all = "lowercase")]
659pub enum Role {
660 User,
662 Assistant,
664}
665
666#[derive(Debug, Clone, Serialize, Deserialize, Default)]
672pub struct ToolAnnotations {
673 #[serde(skip_serializing_if = "Option::is_none")]
675 pub title: Option<String>,
676 #[serde(skip_serializing_if = "Option::is_none")]
678 pub audience: Option<Vec<String>>,
679 #[serde(skip_serializing_if = "Option::is_none")]
681 pub priority: Option<f64>,
682 #[serde(skip_serializing_if = "Option::is_none")]
684 #[serde(rename = "destructiveHint")]
685 pub destructive_hint: Option<bool>,
686 #[serde(skip_serializing_if = "Option::is_none")]
688 #[serde(rename = "idempotentHint")]
689 pub idempotent_hint: Option<bool>,
690 #[serde(skip_serializing_if = "Option::is_none")]
692 #[serde(rename = "openWorldHint")]
693 pub open_world_hint: Option<bool>,
694 #[serde(skip_serializing_if = "Option::is_none")]
696 #[serde(rename = "readOnlyHint")]
697 pub read_only_hint: Option<bool>,
698 #[serde(flatten)]
700 pub custom: HashMap<String, serde_json::Value>,
701}
702
703#[derive(Debug, Clone, Serialize, Deserialize)]
705pub struct Tool {
706 pub name: String,
708
709 #[serde(skip_serializing_if = "Option::is_none")]
711 pub title: Option<String>,
712
713 #[serde(skip_serializing_if = "Option::is_none")]
716 pub description: Option<String>,
717
718 #[serde(rename = "inputSchema")]
720 pub input_schema: ToolInputSchema,
721
722 #[serde(rename = "outputSchema", skip_serializing_if = "Option::is_none")]
725 pub output_schema: Option<ToolOutputSchema>,
726
727 #[serde(skip_serializing_if = "Option::is_none")]
730 pub annotations: Option<ToolAnnotations>,
731
732 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
734 pub meta: Option<HashMap<String, serde_json::Value>>,
735}
736
737impl Default for Tool {
738 fn default() -> Self {
739 Self {
740 name: "unnamed_tool".to_string(), title: None,
742 description: None,
743 input_schema: ToolInputSchema::default(),
744 output_schema: None,
745 annotations: None,
746 meta: None,
747 }
748 }
749}
750
751impl Tool {
752 pub fn new(name: impl Into<String>) -> Self {
757 let name = name.into();
758 assert!(!name.trim().is_empty(), "Tool name cannot be empty");
759
760 Self {
761 name,
762 title: None,
763 description: None,
764 input_schema: ToolInputSchema::default(),
765 output_schema: None,
766 annotations: None,
767 meta: None,
768 }
769 }
770
771 pub fn with_description(name: impl Into<String>, description: impl Into<String>) -> Self {
776 let name = name.into();
777 assert!(!name.trim().is_empty(), "Tool name cannot be empty");
778
779 Self {
780 name,
781 title: None,
782 description: Some(description.into()),
783 input_schema: ToolInputSchema::default(),
784 output_schema: None,
785 annotations: None,
786 meta: None,
787 }
788 }
789}
790
791#[derive(Debug, Clone, Serialize, Deserialize)]
793pub struct ToolInputSchema {
794 #[serde(rename = "type")]
796 pub schema_type: String,
797 #[serde(skip_serializing_if = "Option::is_none")]
799 pub properties: Option<HashMap<String, serde_json::Value>>,
800 #[serde(skip_serializing_if = "Option::is_none")]
802 pub required: Option<Vec<String>>,
803 #[serde(
805 rename = "additionalProperties",
806 skip_serializing_if = "Option::is_none"
807 )]
808 pub additional_properties: Option<bool>,
809}
810
811impl Default for ToolInputSchema {
812 fn default() -> Self {
813 Self {
814 schema_type: "object".to_string(),
815 properties: None,
816 required: None,
817 additional_properties: None,
818 }
819 }
820}
821
822impl ToolInputSchema {
823 pub fn empty() -> Self {
825 Self::default()
826 }
827
828 pub fn with_properties(properties: HashMap<String, serde_json::Value>) -> Self {
830 Self {
831 schema_type: "object".to_string(),
832 properties: Some(properties),
833 required: None,
834 additional_properties: None,
835 }
836 }
837
838 pub fn with_required_properties(
840 properties: HashMap<String, serde_json::Value>,
841 required: Vec<String>,
842 ) -> Self {
843 Self {
844 schema_type: "object".to_string(),
845 properties: Some(properties),
846 required: Some(required),
847 additional_properties: None,
848 }
849 }
850}
851
852#[derive(Debug, Clone, Serialize, Deserialize)]
854pub struct ToolOutputSchema {
855 #[serde(rename = "type")]
857 pub schema_type: String,
858 #[serde(skip_serializing_if = "Option::is_none")]
860 pub properties: Option<HashMap<String, serde_json::Value>>,
861 #[serde(skip_serializing_if = "Option::is_none")]
863 pub required: Option<Vec<String>>,
864 #[serde(
866 rename = "additionalProperties",
867 skip_serializing_if = "Option::is_none"
868 )]
869 pub additional_properties: Option<bool>,
870}
871
872#[derive(Debug, Clone, Serialize, Deserialize)]
874pub struct ListToolsRequest;
875
876#[derive(Debug, Clone, Serialize, Deserialize)]
878pub struct ListToolsResult {
879 pub tools: Vec<Tool>,
881 #[serde(rename = "nextCursor", skip_serializing_if = "Option::is_none")]
883 pub next_cursor: Option<String>,
884 #[serde(skip_serializing_if = "Option::is_none")]
886 pub _meta: Option<serde_json::Value>,
887}
888
889#[derive(Debug, Clone, Serialize, Deserialize)]
891pub struct CallToolRequest {
892 pub name: String,
894 #[serde(skip_serializing_if = "Option::is_none")]
896 pub arguments: Option<HashMap<String, serde_json::Value>>,
897 #[serde(skip_serializing_if = "Option::is_none")]
899 pub _meta: Option<serde_json::Value>,
900}
901
902#[derive(Debug, Clone, Serialize, Deserialize)]
904pub struct CallToolResult {
905 pub content: Vec<ContentBlock>,
907 #[serde(rename = "isError", skip_serializing_if = "Option::is_none")]
909 pub is_error: Option<bool>,
910 #[serde(rename = "structuredContent", skip_serializing_if = "Option::is_none")]
912 pub structured_content: Option<serde_json::Value>,
913 #[serde(skip_serializing_if = "Option::is_none")]
915 pub _meta: Option<serde_json::Value>,
916}
917
918#[derive(Debug, Clone, Serialize, Deserialize)]
924pub struct Prompt {
925 pub name: String,
927
928 #[serde(skip_serializing_if = "Option::is_none")]
930 pub title: Option<String>,
931
932 #[serde(skip_serializing_if = "Option::is_none")]
934 pub description: Option<String>,
935
936 #[serde(skip_serializing_if = "Option::is_none")]
938 pub arguments: Option<Vec<PromptArgument>>,
939
940 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
942 pub meta: Option<HashMap<String, serde_json::Value>>,
943}
944
945#[derive(Debug, Clone, Serialize, Deserialize)]
947pub struct PromptArgument {
948 pub name: String,
950
951 #[serde(skip_serializing_if = "Option::is_none")]
953 pub title: Option<String>,
954
955 #[serde(skip_serializing_if = "Option::is_none")]
957 pub description: Option<String>,
958
959 #[serde(skip_serializing_if = "Option::is_none")]
961 pub required: Option<bool>,
962}
963
964pub type PromptInput = HashMap<String, serde_json::Value>;
966
967#[derive(Debug, Clone, Serialize, Deserialize)]
969pub struct ListPromptsRequest;
970
971#[derive(Debug, Clone, Serialize, Deserialize)]
973pub struct ListPromptsResult {
974 pub prompts: Vec<Prompt>,
976 #[serde(rename = "nextCursor", skip_serializing_if = "Option::is_none")]
978 pub next_cursor: Option<String>,
979 #[serde(skip_serializing_if = "Option::is_none")]
981 pub _meta: Option<serde_json::Value>,
982}
983
984#[derive(Debug, Clone, Serialize, Deserialize)]
986pub struct GetPromptRequest {
987 pub name: String,
989 #[serde(skip_serializing_if = "Option::is_none")]
991 pub arguments: Option<PromptInput>,
992 #[serde(skip_serializing_if = "Option::is_none")]
994 pub _meta: Option<serde_json::Value>,
995}
996
997#[derive(Debug, Clone, Serialize, Deserialize)]
999pub struct GetPromptResult {
1000 #[serde(skip_serializing_if = "Option::is_none")]
1002 pub description: Option<String>,
1003 pub messages: Vec<PromptMessage>,
1005 #[serde(skip_serializing_if = "Option::is_none")]
1007 pub _meta: Option<serde_json::Value>,
1008}
1009
1010#[derive(Debug, Clone, Serialize, Deserialize)]
1012pub struct PromptMessage {
1013 pub role: Role,
1015 pub content: Content,
1017}
1018
1019#[derive(Debug, Clone, Serialize, Deserialize)]
1025pub struct Resource {
1026 pub name: String,
1028
1029 #[serde(skip_serializing_if = "Option::is_none")]
1031 pub title: Option<String>,
1032
1033 pub uri: String,
1035
1036 #[serde(skip_serializing_if = "Option::is_none")]
1039 pub description: Option<String>,
1040
1041 #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
1043 pub mime_type: Option<String>,
1044
1045 #[serde(skip_serializing_if = "Option::is_none")]
1047 pub annotations: Option<Annotations>,
1048
1049 #[serde(skip_serializing_if = "Option::is_none")]
1052 pub size: Option<u64>,
1053
1054 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1056 pub meta: Option<HashMap<String, serde_json::Value>>,
1057}
1058
1059#[derive(Debug, Clone, Serialize, Deserialize)]
1061pub struct ResourceContents {
1062 pub uri: String,
1064 #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
1066 pub mime_type: Option<String>,
1067 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1069 pub meta: Option<HashMap<String, serde_json::Value>>,
1070}
1071
1072#[derive(Debug, Clone, Serialize, Deserialize)]
1074pub struct TextResourceContents {
1075 pub uri: String,
1077 #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
1079 pub mime_type: Option<String>,
1080 pub text: String,
1082 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1084 pub meta: Option<HashMap<String, serde_json::Value>>,
1085}
1086
1087#[derive(Debug, Clone, Serialize, Deserialize)]
1089pub struct BlobResourceContents {
1090 pub uri: String,
1092 #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
1094 pub mime_type: Option<String>,
1095 pub blob: String,
1097 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1099 pub meta: Option<HashMap<String, serde_json::Value>>,
1100}
1101
1102#[derive(Debug, Clone, Serialize, Deserialize)]
1104#[serde(untagged)]
1105pub enum ResourceContent {
1106 Text(TextResourceContents),
1108 Blob(BlobResourceContents),
1110}
1111
1112#[derive(Debug, Clone, Serialize, Deserialize)]
1114pub struct ListResourcesRequest {
1115 #[serde(skip_serializing_if = "Option::is_none")]
1117 pub cursor: Option<String>,
1118 #[serde(skip_serializing_if = "Option::is_none")]
1120 pub _meta: Option<serde_json::Value>,
1121}
1122
1123#[derive(Debug, Clone, Serialize, Deserialize)]
1125pub struct ListResourcesResult {
1126 pub resources: Vec<Resource>,
1128 #[serde(rename = "nextCursor", skip_serializing_if = "Option::is_none")]
1130 pub next_cursor: Option<String>,
1131 #[serde(skip_serializing_if = "Option::is_none")]
1133 pub _meta: Option<serde_json::Value>,
1134}
1135
1136#[derive(Debug, Clone, Serialize, Deserialize)]
1138pub struct ReadResourceRequest {
1139 pub uri: Uri,
1141 #[serde(skip_serializing_if = "Option::is_none")]
1143 pub _meta: Option<serde_json::Value>,
1144}
1145
1146#[derive(Debug, Clone, Serialize, Deserialize)]
1148pub struct ReadResourceResult {
1149 pub contents: Vec<ResourceContent>,
1151 #[serde(skip_serializing_if = "Option::is_none")]
1153 pub _meta: Option<serde_json::Value>,
1154}
1155
1156#[derive(Debug, Clone, Serialize, Deserialize)]
1158pub struct SubscribeRequest {
1159 pub uri: Uri,
1161}
1162
1163#[derive(Debug, Clone, Serialize, Deserialize)]
1165pub struct UnsubscribeRequest {
1166 pub uri: Uri,
1168}
1169
1170#[derive(Debug, Clone, Serialize, Deserialize)]
1172pub struct ResourceUpdatedNotification {
1173 pub uri: Uri,
1175}
1176
1177#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1183#[serde(rename_all = "lowercase")]
1184pub enum LogLevel {
1185 Debug,
1187 Info,
1189 Notice,
1191 Warning,
1193 Error,
1195 Critical,
1197 Alert,
1199 Emergency,
1201}
1202
1203#[derive(Debug, Clone, Serialize, Deserialize)]
1205pub struct SetLevelRequest {
1206 pub level: LogLevel,
1208}
1209
1210#[derive(Debug, Clone, Serialize, Deserialize)]
1212pub struct SetLevelResult;
1213
1214#[derive(Debug, Clone, Serialize, Deserialize)]
1216pub struct LoggingNotification {
1217 pub level: LogLevel,
1219 pub data: serde_json::Value,
1221 #[serde(skip_serializing_if = "Option::is_none")]
1223 pub logger: Option<String>,
1224}
1225
1226#[derive(Debug, Clone, Serialize, Deserialize)]
1232pub struct ProgressNotification {
1233 #[serde(rename = "progressToken")]
1236 pub progress_token: ProgressToken,
1237 pub progress: f64,
1240 #[serde(skip_serializing_if = "Option::is_none")]
1242 pub total: Option<f64>,
1243 #[serde(skip_serializing_if = "Option::is_none")]
1245 pub message: Option<String>,
1246}
1247
1248#[derive(Debug, Clone, Serialize, Deserialize)]
1250pub struct CancelledNotification {
1251 #[serde(rename = "requestId")]
1254 pub request_id: RequestId,
1255 #[serde(skip_serializing_if = "Option::is_none")]
1258 pub reason: Option<String>,
1259}
1260
1261#[derive(Debug, Clone, Serialize, Deserialize)]
1267pub struct CreateMessageRequest {
1268 pub messages: Vec<SamplingMessage>,
1270 #[serde(rename = "modelPreferences", skip_serializing_if = "Option::is_none")]
1272 pub model_preferences: Option<ModelPreferences>,
1273 #[serde(rename = "systemPrompt", skip_serializing_if = "Option::is_none")]
1275 pub system_prompt: Option<String>,
1276 #[serde(rename = "includeContext", skip_serializing_if = "Option::is_none")]
1278 pub include_context: Option<IncludeContext>,
1279 #[serde(skip_serializing_if = "Option::is_none")]
1281 pub temperature: Option<f64>,
1282 #[serde(rename = "maxTokens")]
1284 pub max_tokens: u32,
1285 #[serde(rename = "stopSequences", skip_serializing_if = "Option::is_none")]
1287 pub stop_sequences: Option<Vec<String>>,
1288 #[serde(skip_serializing_if = "Option::is_none")]
1290 pub metadata: Option<HashMap<String, serde_json::Value>>,
1291 #[serde(skip_serializing_if = "Option::is_none")]
1293 pub _meta: Option<serde_json::Value>,
1294}
1295
1296#[derive(Debug, Clone, Serialize, Deserialize)]
1298pub struct ModelPreferences {
1299 #[serde(skip_serializing_if = "Option::is_none")]
1301 pub hints: Option<Vec<ModelHint>>,
1302 #[serde(rename = "costPriority", skip_serializing_if = "Option::is_none")]
1304 pub cost_priority: Option<f64>,
1305 #[serde(rename = "speedPriority", skip_serializing_if = "Option::is_none")]
1307 pub speed_priority: Option<f64>,
1308 #[serde(
1310 rename = "intelligencePriority",
1311 skip_serializing_if = "Option::is_none"
1312 )]
1313 pub intelligence_priority: Option<f64>,
1314}
1315
1316#[derive(Debug, Clone, Serialize, Deserialize)]
1318pub struct ModelHint {
1319 pub name: String,
1321}
1322
1323#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1325#[serde(rename_all = "lowercase")]
1326pub enum IncludeContext {
1327 None,
1329 ThisServer,
1331 AllServers,
1333}
1334
1335#[derive(Debug, Clone, Serialize, Deserialize)]
1337pub struct SamplingMessage {
1338 pub role: Role,
1340 pub content: Content,
1342}
1343
1344#[derive(Debug, Clone, Serialize, Deserialize)]
1346pub struct CreateMessageResult {
1347 pub role: Role,
1349 pub content: Content,
1351 #[serde(skip_serializing_if = "Option::is_none")]
1353 pub model: Option<String>,
1354 #[serde(rename = "stopReason", skip_serializing_if = "Option::is_none")]
1356 pub stop_reason: Option<String>,
1357 #[serde(skip_serializing_if = "Option::is_none")]
1359 pub _meta: Option<serde_json::Value>,
1360}
1361
1362#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1369#[serde(tag = "type")]
1370pub enum PrimitiveSchemaDefinition {
1371 #[serde(rename = "string")]
1373 String {
1374 #[serde(skip_serializing_if = "Option::is_none")]
1376 title: Option<String>,
1377 #[serde(skip_serializing_if = "Option::is_none")]
1379 description: Option<String>,
1380 #[serde(skip_serializing_if = "Option::is_none")]
1382 format: Option<String>,
1383 #[serde(skip_serializing_if = "Option::is_none")]
1385 #[serde(rename = "minLength")]
1386 min_length: Option<u32>,
1387 #[serde(skip_serializing_if = "Option::is_none")]
1389 #[serde(rename = "maxLength")]
1390 max_length: Option<u32>,
1391 #[serde(skip_serializing_if = "Option::is_none")]
1393 #[serde(rename = "enum")]
1394 enum_values: Option<Vec<String>>,
1395 #[serde(skip_serializing_if = "Option::is_none")]
1397 #[serde(rename = "enumNames")]
1398 enum_names: Option<Vec<String>>,
1399 },
1400 #[serde(rename = "number")]
1402 Number {
1403 #[serde(skip_serializing_if = "Option::is_none")]
1405 title: Option<String>,
1406 #[serde(skip_serializing_if = "Option::is_none")]
1408 description: Option<String>,
1409 #[serde(skip_serializing_if = "Option::is_none")]
1411 minimum: Option<f64>,
1412 #[serde(skip_serializing_if = "Option::is_none")]
1414 maximum: Option<f64>,
1415 },
1416 #[serde(rename = "integer")]
1418 Integer {
1419 #[serde(skip_serializing_if = "Option::is_none")]
1421 title: Option<String>,
1422 #[serde(skip_serializing_if = "Option::is_none")]
1424 description: Option<String>,
1425 #[serde(skip_serializing_if = "Option::is_none")]
1427 minimum: Option<i64>,
1428 #[serde(skip_serializing_if = "Option::is_none")]
1430 maximum: Option<i64>,
1431 },
1432 #[serde(rename = "boolean")]
1434 Boolean {
1435 #[serde(skip_serializing_if = "Option::is_none")]
1437 title: Option<String>,
1438 #[serde(skip_serializing_if = "Option::is_none")]
1440 description: Option<String>,
1441 #[serde(skip_serializing_if = "Option::is_none")]
1443 default: Option<bool>,
1444 },
1445}
1446
1447#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1449pub struct ElicitationSchema {
1450 #[serde(rename = "type")]
1452 pub schema_type: String,
1453 pub properties: std::collections::HashMap<String, PrimitiveSchemaDefinition>,
1455 #[serde(skip_serializing_if = "Option::is_none")]
1457 pub required: Option<Vec<String>>,
1458}
1459
1460impl ElicitationSchema {
1461 pub fn new() -> Self {
1463 Self {
1464 schema_type: "object".to_string(),
1465 properties: std::collections::HashMap::new(),
1466 required: None,
1467 }
1468 }
1469
1470 pub fn add_string_property<K: Into<String>>(
1472 mut self,
1473 name: K,
1474 required: bool,
1475 description: Option<String>,
1476 ) -> Self {
1477 let property = PrimitiveSchemaDefinition::String {
1478 title: None,
1479 description,
1480 format: None,
1481 min_length: None,
1482 max_length: None,
1483 enum_values: None,
1484 enum_names: None,
1485 };
1486
1487 let name = name.into();
1488 self.properties.insert(name.clone(), property);
1489
1490 if required {
1491 self.required.get_or_insert_with(Vec::new).push(name);
1492 }
1493
1494 self
1495 }
1496
1497 pub fn add_number_property<K: Into<String>>(
1499 mut self,
1500 name: K,
1501 required: bool,
1502 description: Option<String>,
1503 min: Option<f64>,
1504 max: Option<f64>,
1505 ) -> Self {
1506 let property = PrimitiveSchemaDefinition::Number {
1507 title: None,
1508 description,
1509 minimum: min,
1510 maximum: max,
1511 };
1512
1513 let name = name.into();
1514 self.properties.insert(name.clone(), property);
1515
1516 if required {
1517 self.required.get_or_insert_with(Vec::new).push(name);
1518 }
1519
1520 self
1521 }
1522
1523 pub fn add_boolean_property<K: Into<String>>(
1525 mut self,
1526 name: K,
1527 required: bool,
1528 description: Option<String>,
1529 default: Option<bool>,
1530 ) -> Self {
1531 let property = PrimitiveSchemaDefinition::Boolean {
1532 title: None,
1533 description,
1534 default,
1535 };
1536
1537 let name = name.into();
1538 self.properties.insert(name.clone(), property);
1539
1540 if required {
1541 self.required.get_or_insert_with(Vec::new).push(name);
1542 }
1543
1544 self
1545 }
1546
1547 pub fn add_enum_property<K: Into<String>>(
1549 mut self,
1550 name: K,
1551 required: bool,
1552 description: Option<String>,
1553 values: Vec<String>,
1554 names: Option<Vec<String>>,
1555 ) -> Self {
1556 let property = PrimitiveSchemaDefinition::String {
1557 title: None,
1558 description,
1559 format: None,
1560 min_length: None,
1561 max_length: None,
1562 enum_values: Some(values),
1563 enum_names: names,
1564 };
1565
1566 let name = name.into();
1567 self.properties.insert(name.clone(), property);
1568
1569 if required {
1570 self.required.get_or_insert_with(Vec::new).push(name);
1571 }
1572
1573 self
1574 }
1575}
1576
1577impl Default for ElicitationSchema {
1578 fn default() -> Self {
1579 Self::new()
1580 }
1581}
1582
1583#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1585#[serde(rename_all = "camelCase")]
1586pub struct ElicitRequestParams {
1587 pub message: String,
1589 pub requested_schema: ElicitationSchema,
1591 #[serde(skip_serializing_if = "Option::is_none")]
1593 pub _meta: Option<serde_json::Value>,
1594}
1595
1596#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1598pub struct ElicitRequest {
1599 pub method: String,
1601 pub params: ElicitRequestParams,
1603}
1604
1605impl ElicitRequest {
1606 pub fn new<M: Into<String>>(message: M, schema: ElicitationSchema) -> Self {
1608 Self {
1609 method: "elicitation/create".to_string(),
1610 params: ElicitRequestParams {
1611 message: message.into(),
1612 requested_schema: schema,
1613 _meta: None,
1614 },
1615 }
1616 }
1617}
1618
1619#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1621#[serde(rename_all = "lowercase")]
1622pub enum ElicitationAction {
1623 Accept,
1625 Decline,
1627 Cancel,
1629}
1630
1631#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1633pub struct ElicitResult {
1634 pub action: ElicitationAction,
1636 #[serde(skip_serializing_if = "Option::is_none")]
1639 pub content: Option<std::collections::HashMap<String, serde_json::Value>>,
1640 #[serde(skip_serializing_if = "Option::is_none")]
1642 pub _meta: Option<serde_json::Value>,
1643}
1644
1645impl ElicitResult {
1646 pub fn accept(content: std::collections::HashMap<String, serde_json::Value>) -> Self {
1648 Self {
1649 action: ElicitationAction::Accept,
1650 content: Some(content),
1651 _meta: None,
1652 }
1653 }
1654
1655 pub fn decline() -> Self {
1657 Self {
1658 action: ElicitationAction::Decline,
1659 content: None,
1660 _meta: None,
1661 }
1662 }
1663
1664 pub fn cancel() -> Self {
1666 Self {
1667 action: ElicitationAction::Cancel,
1668 content: None,
1669 _meta: None,
1670 }
1671 }
1672
1673 pub fn with_meta(mut self, meta: serde_json::Value) -> Self {
1675 self._meta = Some(meta);
1676 self
1677 }
1678}
1679
1680#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1686pub struct ArgumentInfo {
1687 pub name: String,
1689 pub value: String,
1691}
1692
1693#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1695pub struct CompletionContext {
1696 #[serde(skip_serializing_if = "Option::is_none")]
1698 pub arguments: Option<std::collections::HashMap<String, String>>,
1699}
1700
1701#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1703pub struct PromptReference {
1704 #[serde(rename = "type")]
1706 pub ref_type: String,
1707 pub name: String,
1709 #[serde(skip_serializing_if = "Option::is_none")]
1711 pub title: Option<String>,
1712}
1713
1714impl PromptReference {
1715 pub fn new<N: Into<String>>(name: N) -> Self {
1717 Self {
1718 ref_type: "ref/prompt".to_string(),
1719 name: name.into(),
1720 title: None,
1721 }
1722 }
1723
1724 pub fn with_title<T: Into<String>>(mut self, title: T) -> Self {
1726 self.title = Some(title.into());
1727 self
1728 }
1729}
1730
1731#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1733pub struct ResourceTemplateReference {
1734 #[serde(rename = "type")]
1736 pub ref_type: String,
1737 pub uri: String,
1739}
1740
1741impl ResourceTemplateReference {
1742 pub fn new<U: Into<String>>(uri: U) -> Self {
1744 Self {
1745 ref_type: "ref/resource".to_string(),
1746 uri: uri.into(),
1747 }
1748 }
1749}
1750
1751#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1753#[serde(tag = "type")]
1754pub enum CompletionReference {
1755 #[serde(rename = "ref/prompt")]
1757 Prompt(PromptReferenceData),
1758 #[serde(rename = "ref/resource")]
1760 ResourceTemplate(ResourceTemplateReferenceData),
1761}
1762
1763#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1765pub struct PromptReferenceData {
1766 pub name: String,
1768 #[serde(skip_serializing_if = "Option::is_none")]
1770 pub title: Option<String>,
1771}
1772
1773#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1775pub struct ResourceTemplateReferenceData {
1776 pub uri: String,
1778}
1779
1780#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1782pub struct CompleteRequestParams {
1783 pub argument: ArgumentInfo,
1785 #[serde(rename = "ref")]
1787 pub reference: CompletionReference,
1788 #[serde(skip_serializing_if = "Option::is_none")]
1790 pub context: Option<CompletionContext>,
1791 #[serde(skip_serializing_if = "Option::is_none")]
1793 pub _meta: Option<serde_json::Value>,
1794}
1795
1796#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1798pub struct CompleteRequest {
1799 pub method: String,
1801 pub params: CompleteRequestParams,
1803}
1804
1805impl CompleteRequest {
1806 pub fn new(argument: ArgumentInfo, reference: CompletionReference) -> Self {
1808 Self {
1809 method: "completion/complete".to_string(),
1810 params: CompleteRequestParams {
1811 argument,
1812 reference,
1813 context: None,
1814 _meta: None,
1815 },
1816 }
1817 }
1818
1819 pub fn with_context(mut self, context: CompletionContext) -> Self {
1821 self.params.context = Some(context);
1822 self
1823 }
1824}
1825
1826#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1828#[serde(rename_all = "camelCase")]
1829pub struct CompletionResponse {
1830 pub values: Vec<String>,
1832 #[serde(skip_serializing_if = "Option::is_none")]
1834 pub total: Option<u32>,
1835 #[serde(skip_serializing_if = "Option::is_none")]
1837 pub has_more: Option<bool>,
1838}
1839
1840impl CompletionResponse {
1841 pub fn new(values: Vec<String>) -> Self {
1843 Self {
1844 values,
1845 total: None,
1846 has_more: None,
1847 }
1848 }
1849
1850 pub fn with_total(mut self, total: u32) -> Self {
1852 self.total = Some(total);
1853 self
1854 }
1855
1856 pub fn with_has_more(mut self, has_more: bool) -> Self {
1858 self.has_more = Some(has_more);
1859 self
1860 }
1861
1862 pub fn paginated(values: Vec<String>, total: u32, has_more: bool) -> Self {
1864 Self {
1865 values,
1866 total: Some(total),
1867 has_more: Some(has_more),
1868 }
1869 }
1870}
1871
1872#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1874pub struct CompleteResult {
1875 pub completion: CompletionResponse,
1877 #[serde(skip_serializing_if = "Option::is_none")]
1879 pub _meta: Option<serde_json::Value>,
1880}
1881
1882impl CompleteResult {
1883 pub fn new(completion: CompletionResponse) -> Self {
1885 Self {
1886 completion,
1887 _meta: None,
1888 }
1889 }
1890
1891 pub fn with_meta(mut self, meta: serde_json::Value) -> Self {
1893 self._meta = Some(meta);
1894 self
1895 }
1896}
1897
1898#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1905#[serde(rename_all = "camelCase")]
1906pub struct ResourceTemplate {
1907 pub name: String,
1909 pub uri_template: String,
1911 #[serde(skip_serializing_if = "Option::is_none")]
1913 pub title: Option<String>,
1914 #[serde(skip_serializing_if = "Option::is_none")]
1916 pub description: Option<String>,
1917 #[serde(skip_serializing_if = "Option::is_none")]
1919 pub mime_type: Option<String>,
1920 #[serde(skip_serializing_if = "Option::is_none")]
1922 pub annotations: Option<Annotations>,
1923 #[serde(skip_serializing_if = "Option::is_none")]
1925 pub _meta: Option<serde_json::Value>,
1926}
1927
1928impl ResourceTemplate {
1929 pub fn new<N: Into<String>, U: Into<String>>(name: N, uri_template: U) -> Self {
1931 Self {
1932 name: name.into(),
1933 uri_template: uri_template.into(),
1934 title: None,
1935 description: None,
1936 mime_type: None,
1937 annotations: None,
1938 _meta: None,
1939 }
1940 }
1941
1942 pub fn with_title<T: Into<String>>(mut self, title: T) -> Self {
1944 self.title = Some(title.into());
1945 self
1946 }
1947
1948 pub fn with_description<D: Into<String>>(mut self, description: D) -> Self {
1950 self.description = Some(description.into());
1951 self
1952 }
1953
1954 pub fn with_mime_type<M: Into<String>>(mut self, mime_type: M) -> Self {
1956 self.mime_type = Some(mime_type.into());
1957 self
1958 }
1959
1960 pub fn with_annotations(mut self, annotations: Annotations) -> Self {
1962 self.annotations = Some(annotations);
1963 self
1964 }
1965
1966 pub fn with_meta(mut self, meta: serde_json::Value) -> Self {
1968 self._meta = Some(meta);
1969 self
1970 }
1971
1972 pub fn file_system<N: Into<String>>(name: N, base_path: &str) -> Self {
1974 Self::new(name, format!("file://{}/{{path}}", base_path))
1975 .with_title("File System Access")
1976 .with_description("Access files within the specified directory")
1977 }
1978
1979 pub fn api_endpoint<N: Into<String>>(name: N, base_url: &str) -> Self {
1981 Self::new(name, format!("{}/{{endpoint}}", base_url))
1982 .with_mime_type("application/json")
1983 .with_title("API Endpoint Access")
1984 .with_description("Access API endpoints")
1985 }
1986
1987 pub fn database_query<N: Into<String>>(name: N) -> Self {
1989 Self::new(name, "db://query/{table}?{query*}")
1990 .with_title("Database Query")
1991 .with_description("Execute database queries")
1992 }
1993}
1994
1995#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
1997pub struct ListResourceTemplatesParams {
1998 #[serde(skip_serializing_if = "Option::is_none")]
2000 pub cursor: Option<String>,
2001}
2002
2003#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2005pub struct ListResourceTemplatesRequest {
2006 #[serde(skip_serializing_if = "Option::is_none")]
2008 pub params: Option<ListResourceTemplatesParams>,
2009}
2010
2011impl ListResourceTemplatesRequest {
2012 pub fn new() -> Self {
2014 Self { params: None }
2015 }
2016
2017 pub fn with_cursor<C: Into<String>>(cursor: C) -> Self {
2019 Self {
2020 params: Some(ListResourceTemplatesParams {
2021 cursor: Some(cursor.into()),
2022 }),
2023 }
2024 }
2025}
2026
2027impl Default for ListResourceTemplatesRequest {
2028 fn default() -> Self {
2029 Self::new()
2030 }
2031}
2032
2033#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2035#[serde(rename_all = "camelCase")]
2036pub struct ListResourceTemplatesResult {
2037 pub resource_templates: Vec<ResourceTemplate>,
2039 #[serde(skip_serializing_if = "Option::is_none")]
2041 pub next_cursor: Option<String>,
2042 #[serde(skip_serializing_if = "Option::is_none")]
2044 pub _meta: Option<serde_json::Value>,
2045}
2046
2047impl ListResourceTemplatesResult {
2048 pub fn new(templates: Vec<ResourceTemplate>) -> Self {
2050 Self {
2051 resource_templates: templates,
2052 next_cursor: None,
2053 _meta: None,
2054 }
2055 }
2056
2057 pub fn paginated(templates: Vec<ResourceTemplate>, next_cursor: String) -> Self {
2059 Self {
2060 resource_templates: templates,
2061 next_cursor: Some(next_cursor),
2062 _meta: None,
2063 }
2064 }
2065
2066 pub fn with_meta(mut self, meta: serde_json::Value) -> Self {
2068 self._meta = Some(meta);
2069 self
2070 }
2071}
2072
2073#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
2079pub struct PingParams {
2080 #[serde(skip_serializing_if = "Option::is_none")]
2082 pub _meta: Option<serde_json::Value>,
2083}
2084
2085impl PingParams {
2086 pub fn new() -> Self {
2088 Self { _meta: None }
2089 }
2090
2091 pub fn with_meta(mut self, meta: serde_json::Value) -> Self {
2093 self._meta = Some(meta);
2094 self
2095 }
2096}
2097
2098#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2100pub struct PingRequest {
2101 pub method: String,
2103 #[serde(skip_serializing_if = "Option::is_none")]
2105 pub params: Option<PingParams>,
2106}
2107
2108impl PingRequest {
2109 pub fn new() -> Self {
2111 Self {
2112 method: "ping".to_string(),
2113 params: None,
2114 }
2115 }
2116
2117 pub fn with_meta(meta: serde_json::Value) -> Self {
2119 Self {
2120 method: "ping".to_string(),
2121 params: Some(PingParams::new().with_meta(meta)),
2122 }
2123 }
2124}
2125
2126impl Default for PingRequest {
2127 fn default() -> Self {
2128 Self::new()
2129 }
2130}
2131
2132#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2134pub struct PingResult {
2135 #[serde(skip_serializing_if = "Option::is_none")]
2137 pub _meta: Option<serde_json::Value>,
2138}
2139
2140impl PingResult {
2141 pub fn new() -> Self {
2143 Self { _meta: None }
2144 }
2145
2146 pub fn with_meta(meta: serde_json::Value) -> Self {
2148 Self { _meta: Some(meta) }
2149 }
2150}
2151
2152impl Default for PingResult {
2153 fn default() -> Self {
2154 Self::new()
2155 }
2156}
2157
2158#[derive(Debug, Clone, Serialize, Deserialize)]
2164pub struct Root {
2165 pub uri: Uri,
2167 #[serde(skip_serializing_if = "Option::is_none")]
2169 pub name: Option<String>,
2170}
2171
2172#[derive(Debug, Clone, Serialize, Deserialize)]
2174pub struct ListRootsRequest;
2175
2176#[derive(Debug, Clone, Serialize, Deserialize)]
2178pub struct ListRootsResult {
2179 pub roots: Vec<Root>,
2181 #[serde(skip_serializing_if = "Option::is_none")]
2183 pub _meta: Option<serde_json::Value>,
2184}
2185
2186#[derive(Debug, Clone, Serialize, Deserialize)]
2188pub struct RootsListChangedNotification;
2189
2190#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2192pub struct EmptyResult {}
2193
2194#[cfg(test)]
2195mod tests {
2196 use super::*;
2197
2198 #[test]
2199 fn test_serialize_deserialize() {
2200 let tool = Tool {
2201 name: "test_tool".to_string(),
2202 title: Some("Test Tool".to_string()),
2203 description: Some("A test tool".to_string()),
2204 input_schema: ToolInputSchema {
2205 schema_type: "object".to_string(),
2206 properties: None,
2207 required: None,
2208 additional_properties: None,
2209 },
2210 output_schema: None,
2211 annotations: None,
2212 meta: None,
2213 };
2214
2215 let json = serde_json::to_string(&tool).unwrap();
2216 let deserialized: Tool = serde_json::from_str(&json).unwrap();
2217 assert_eq!(tool.name, deserialized.name);
2218 }
2219
2220 #[test]
2221 fn test_content_types() {
2222 let text_content = ContentBlock::Text(TextContent {
2223 text: "Hello, World!".to_string(),
2224 annotations: None,
2225 meta: None,
2226 });
2227
2228 let json = serde_json::to_string(&text_content).unwrap();
2229 let _deserialized: ContentBlock = serde_json::from_str(&json).unwrap();
2230
2231 let _compatible: Content = text_content;
2233 }
2234
2235 #[test]
2236 fn test_elicitation_schema_builder() {
2237 let schema = ElicitationSchema::new()
2238 .add_string_property("username", true, Some("Your username".to_string()))
2239 .add_number_property(
2240 "age",
2241 false,
2242 Some("Your age".to_string()),
2243 Some(0.0),
2244 Some(150.0),
2245 )
2246 .add_boolean_property(
2247 "subscribe",
2248 true,
2249 Some("Subscribe to newsletter".to_string()),
2250 Some(false),
2251 )
2252 .add_enum_property(
2253 "role",
2254 true,
2255 Some("Your role".to_string()),
2256 vec!["admin".to_string(), "user".to_string(), "guest".to_string()],
2257 None,
2258 );
2259
2260 assert_eq!(schema.schema_type, "object");
2261 assert_eq!(schema.properties.len(), 4);
2262 assert_eq!(schema.required.as_ref().unwrap().len(), 3);
2263
2264 let username_prop = &schema.properties["username"];
2266 match username_prop {
2267 PrimitiveSchemaDefinition::String { description, .. } => {
2268 assert_eq!(description.as_ref().unwrap(), "Your username");
2269 }
2270 _ => panic!("Expected string property"),
2271 }
2272
2273 let age_prop = &schema.properties["age"];
2275 match age_prop {
2276 PrimitiveSchemaDefinition::Number {
2277 minimum, maximum, ..
2278 } => {
2279 assert_eq!(*minimum, Some(0.0));
2280 assert_eq!(*maximum, Some(150.0));
2281 }
2282 _ => panic!("Expected number property"),
2283 }
2284 }
2285
2286 #[test]
2287 fn test_elicit_request_serialization() {
2288 let schema = ElicitationSchema::new()
2289 .add_string_property("name", true, Some("Your name".to_string()))
2290 .add_boolean_property("confirm", true, None, Some(false));
2291
2292 let request = ElicitRequest::new("Please provide your details", schema);
2293
2294 let json = serde_json::to_string(&request).unwrap();
2296
2297 assert!(json.contains("elicitation/create"));
2299 assert!(json.contains("Please provide your details"));
2300 assert!(json.contains("requestedSchema"));
2301
2302 let deserialized: ElicitRequest = serde_json::from_str(&json).unwrap();
2304 assert_eq!(deserialized.method, "elicitation/create");
2305 assert_eq!(deserialized.params.message, "Please provide your details");
2306 }
2307
2308 #[test]
2309 fn test_elicit_result_actions() {
2310 let mut content = std::collections::HashMap::new();
2312 content.insert(
2313 "name".to_string(),
2314 serde_json::Value::String("John".to_string()),
2315 );
2316 content.insert(
2317 "age".to_string(),
2318 serde_json::Value::Number(serde_json::Number::from(30)),
2319 );
2320
2321 let accept_result = ElicitResult::accept(content);
2322 assert_eq!(accept_result.action, ElicitationAction::Accept);
2323 assert!(accept_result.content.is_some());
2324
2325 let decline_result = ElicitResult::decline();
2327 assert_eq!(decline_result.action, ElicitationAction::Decline);
2328 assert!(decline_result.content.is_none());
2329
2330 let cancel_result = ElicitResult::cancel();
2332 assert_eq!(cancel_result.action, ElicitationAction::Cancel);
2333 assert!(cancel_result.content.is_none());
2334 }
2335
2336 #[test]
2337 fn test_elicit_result_serialization_compliance() {
2338 let mut content = std::collections::HashMap::new();
2340 content.insert(
2341 "field1".to_string(),
2342 serde_json::Value::String("value1".to_string()),
2343 );
2344
2345 let result = ElicitResult::accept(content);
2346 let json = serde_json::to_string(&result).unwrap();
2347
2348 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2350
2351 assert_eq!(parsed["action"].as_str().unwrap(), "accept");
2353
2354 assert!(parsed["content"].is_object());
2356 assert_eq!(parsed["content"]["field1"].as_str().unwrap(), "value1");
2357 }
2358
2359 #[test]
2360 fn test_primitive_schema_serialization() {
2361 let string_schema = PrimitiveSchemaDefinition::String {
2363 title: Some("Title".to_string()),
2364 description: Some("Description".to_string()),
2365 format: Some("email".to_string()),
2366 min_length: Some(1),
2367 max_length: Some(100),
2368 enum_values: None,
2369 enum_names: None,
2370 };
2371
2372 let json = serde_json::to_string(&string_schema).unwrap();
2373 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2374
2375 assert_eq!(parsed["type"].as_str().unwrap(), "string");
2376 assert_eq!(parsed["format"].as_str().unwrap(), "email");
2377 assert_eq!(parsed["minLength"].as_u64().unwrap(), 1);
2378 assert_eq!(parsed["maxLength"].as_u64().unwrap(), 100);
2379
2380 let enum_schema = PrimitiveSchemaDefinition::String {
2382 title: None,
2383 description: Some("Select option".to_string()),
2384 format: None,
2385 min_length: None,
2386 max_length: None,
2387 enum_values: Some(vec!["option1".to_string(), "option2".to_string()]),
2388 enum_names: Some(vec!["Option 1".to_string(), "Option 2".to_string()]),
2389 };
2390
2391 let enum_json = serde_json::to_string(&enum_schema).unwrap();
2392 let enum_parsed: serde_json::Value = serde_json::from_str(&enum_json).unwrap();
2393
2394 assert_eq!(enum_parsed["type"].as_str().unwrap(), "string");
2395 assert_eq!(enum_parsed["enum"].as_array().unwrap().len(), 2);
2396 assert_eq!(enum_parsed["enumNames"].as_array().unwrap().len(), 2);
2397 }
2398
2399 #[test]
2400 fn test_server_request_with_elicitation() {
2401 let schema = ElicitationSchema::new().add_string_property(
2402 "email",
2403 true,
2404 Some("Your email address".to_string()),
2405 );
2406
2407 let request_params = ElicitRequestParams {
2408 message: "Please provide your email".to_string(),
2409 requested_schema: schema,
2410 _meta: None,
2411 };
2412
2413 let server_request = ServerRequest::ElicitationCreate(request_params);
2414
2415 let json = serde_json::to_string(&server_request).unwrap();
2417 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2418
2419 assert_eq!(parsed["method"].as_str().unwrap(), "elicitation/create");
2420 assert!(parsed["message"].is_string());
2421 assert!(parsed["requestedSchema"].is_object());
2422 }
2423
2424 #[test]
2425 fn test_completion_request_serialization() {
2426 let argument = ArgumentInfo {
2427 name: "file_path".to_string(),
2428 value: "/home/user/doc".to_string(),
2429 };
2430
2431 let reference = CompletionReference::ResourceTemplate(ResourceTemplateReferenceData {
2432 uri: "/files/{path}".to_string(),
2433 });
2434
2435 let request = CompleteRequest::new(argument, reference);
2436
2437 let json = serde_json::to_string(&request).unwrap();
2439 assert!(json.contains("completion/complete"));
2440 assert!(json.contains("file_path"));
2441 assert!(json.contains("/home/user/doc"));
2442
2443 let deserialized: CompleteRequest = serde_json::from_str(&json).unwrap();
2445 assert_eq!(deserialized.method, "completion/complete");
2446 assert_eq!(deserialized.params.argument.name, "file_path");
2447 }
2448
2449 #[test]
2450 fn test_completion_reference_types() {
2451 let prompt_ref = CompletionReference::Prompt(PromptReferenceData {
2453 name: "code_review".to_string(),
2454 title: Some("Code Review Assistant".to_string()),
2455 });
2456
2457 let json = serde_json::to_string(&prompt_ref).unwrap();
2458 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2459 assert_eq!(parsed["type"].as_str().unwrap(), "ref/prompt");
2460 assert_eq!(parsed["name"].as_str().unwrap(), "code_review");
2461
2462 let resource_ref = CompletionReference::ResourceTemplate(ResourceTemplateReferenceData {
2464 uri: "/api/{endpoint}".to_string(),
2465 });
2466
2467 let json = serde_json::to_string(&resource_ref).unwrap();
2468 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2469 assert_eq!(parsed["type"].as_str().unwrap(), "ref/resource");
2470 assert_eq!(parsed["uri"].as_str().unwrap(), "/api/{endpoint}");
2471 }
2472
2473 #[test]
2474 fn test_completion_response_with_pagination() {
2475 let simple =
2477 CompletionResponse::new(vec!["file1.txt".to_string(), "file2.txt".to_string()]);
2478 assert_eq!(simple.values.len(), 2);
2479 assert!(simple.total.is_none());
2480
2481 let paginated = CompletionResponse::paginated(
2483 vec!["item1".to_string(), "item2".to_string()],
2484 100,
2485 true,
2486 );
2487 assert_eq!(paginated.values.len(), 2);
2488 assert_eq!(paginated.total, Some(100));
2489 assert_eq!(paginated.has_more, Some(true));
2490
2491 let json = serde_json::to_string(&paginated).unwrap();
2493 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2494 assert_eq!(parsed["total"].as_u64().unwrap(), 100);
2495 assert!(parsed["hasMore"].as_bool().unwrap());
2496 assert_eq!(parsed["values"].as_array().unwrap().len(), 2);
2497 }
2498
2499 #[test]
2500 fn test_complete_result_structure() {
2501 let completion = CompletionResponse::paginated(
2502 vec!["option1".to_string(), "option2".to_string()],
2503 50,
2504 false,
2505 );
2506
2507 let result = CompleteResult::new(completion);
2508
2509 let json = serde_json::to_string(&result).unwrap();
2511 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2512
2513 assert!(parsed["completion"].is_object());
2515 assert!(parsed["completion"]["values"].is_array());
2516 assert_eq!(parsed["completion"]["total"].as_u64().unwrap(), 50);
2517 assert!(!parsed["completion"]["hasMore"].as_bool().unwrap());
2518
2519 let deserialized: CompleteResult = serde_json::from_str(&json).unwrap();
2521 assert_eq!(deserialized.completion.values.len(), 2);
2522 assert_eq!(deserialized.completion.total, Some(50));
2523 }
2524
2525 #[test]
2526 fn test_completion_context() {
2527 let mut context_args = std::collections::HashMap::new();
2528 context_args.insert("user_id".to_string(), "12345".to_string());
2529 context_args.insert("project".to_string(), "main".to_string());
2530
2531 let context = CompletionContext {
2532 arguments: Some(context_args),
2533 };
2534
2535 let argument = ArgumentInfo {
2536 name: "endpoint".to_string(),
2537 value: "api".to_string(),
2538 };
2539
2540 let reference = CompletionReference::ResourceTemplate(ResourceTemplateReferenceData {
2541 uri: "/projects/{project}/endpoints/{endpoint}".to_string(),
2542 });
2543
2544 let request = CompleteRequest::new(argument, reference).with_context(context);
2545
2546 let json = serde_json::to_string(&request).unwrap();
2548 assert!(json.contains("user_id"));
2549 assert!(json.contains("12345"));
2550 assert!(json.contains("project"));
2551 assert!(json.contains("main"));
2552 }
2553
2554 #[test]
2555 fn test_client_request_with_completion() {
2556 let argument = ArgumentInfo {
2557 name: "query".to_string(),
2558 value: "hello".to_string(),
2559 };
2560
2561 let reference = CompletionReference::Prompt(PromptReferenceData {
2562 name: "greeting".to_string(),
2563 title: None,
2564 });
2565
2566 let complete_params = CompleteRequestParams {
2567 argument,
2568 reference,
2569 context: None,
2570 _meta: None,
2571 };
2572
2573 let client_request = ClientRequest::Complete(complete_params);
2574
2575 let json = serde_json::to_string(&client_request).unwrap();
2577 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2578
2579 assert_eq!(parsed["method"].as_str().unwrap(), "completion/complete");
2580 assert_eq!(parsed["argument"]["name"].as_str().unwrap(), "query");
2581 assert_eq!(parsed["ref"]["type"].as_str().unwrap(), "ref/prompt");
2582 }
2583
2584 #[test]
2585 fn test_resource_template_creation() {
2586 let template = ResourceTemplate::new("file_access", "/files/{path}");
2588 assert_eq!(template.name, "file_access");
2589 assert_eq!(template.uri_template, "/files/{path}");
2590
2591 let enhanced_template = ResourceTemplate::new("api_access", "/api/{endpoint}")
2593 .with_title("API Access")
2594 .with_description("Access to REST API endpoints")
2595 .with_mime_type("application/json");
2596
2597 assert_eq!(enhanced_template.title, Some("API Access".to_string()));
2598 assert_eq!(
2599 enhanced_template.description,
2600 Some("Access to REST API endpoints".to_string())
2601 );
2602 assert_eq!(
2603 enhanced_template.mime_type,
2604 Some("application/json".to_string())
2605 );
2606 }
2607
2608 #[test]
2609 fn test_resource_template_presets() {
2610 let fs_template = ResourceTemplate::file_system("files", "/home/user");
2612 assert_eq!(fs_template.name, "files");
2613 assert_eq!(fs_template.uri_template, "file:///home/user/{path}");
2614 assert_eq!(fs_template.title, Some("File System Access".to_string()));
2615
2616 let api_template = ResourceTemplate::api_endpoint("api", "https://api.example.com");
2618 assert_eq!(
2619 api_template.uri_template,
2620 "https://api.example.com/{endpoint}"
2621 );
2622 assert_eq!(api_template.mime_type, Some("application/json".to_string()));
2623
2624 let db_template = ResourceTemplate::database_query("queries");
2626 assert_eq!(db_template.uri_template, "db://query/{table}?{query*}");
2627 assert_eq!(db_template.title, Some("Database Query".to_string()));
2628 }
2629
2630 #[test]
2631 fn test_resource_template_serialization() {
2632 let template = ResourceTemplate::new("test_template", "/test/{id}")
2633 .with_title("Test Template")
2634 .with_description("A template for testing")
2635 .with_mime_type("text/plain");
2636
2637 let json = serde_json::to_string(&template).unwrap();
2638 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2639
2640 assert_eq!(parsed["name"].as_str().unwrap(), "test_template");
2641 assert_eq!(parsed["uriTemplate"].as_str().unwrap(), "/test/{id}");
2642 assert_eq!(parsed["title"].as_str().unwrap(), "Test Template");
2643 assert_eq!(
2644 parsed["description"].as_str().unwrap(),
2645 "A template for testing"
2646 );
2647 assert_eq!(parsed["mimeType"].as_str().unwrap(), "text/plain");
2648
2649 let deserialized: ResourceTemplate = serde_json::from_str(&json).unwrap();
2651 assert_eq!(deserialized.name, "test_template");
2652 assert_eq!(deserialized.uri_template, "/test/{id}");
2653 }
2654
2655 #[test]
2656 fn test_list_resource_templates_request() {
2657 let request = ListResourceTemplatesRequest::new();
2659 assert!(request.params.is_none());
2660
2661 let paginated_request = ListResourceTemplatesRequest::with_cursor("cursor123");
2663 assert!(paginated_request.params.is_some());
2664 assert_eq!(
2665 paginated_request.params.unwrap().cursor,
2666 Some("cursor123".to_string())
2667 );
2668
2669 let json = serde_json::to_string(&request).unwrap();
2671 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2672
2673 assert!(parsed.as_object().unwrap().is_empty());
2675 }
2676
2677 #[test]
2678 fn test_list_resource_templates_result() {
2679 let templates = vec![
2680 ResourceTemplate::new("template1", "/api/{endpoint}"),
2681 ResourceTemplate::new("template2", "/files/{path}"),
2682 ];
2683
2684 let result = ListResourceTemplatesResult::new(templates.clone());
2686 assert_eq!(result.resource_templates.len(), 2);
2687 assert!(result.next_cursor.is_none());
2688
2689 let paginated_result =
2691 ListResourceTemplatesResult::paginated(templates, "next_cursor".to_string());
2692 assert_eq!(paginated_result.resource_templates.len(), 2);
2693 assert_eq!(
2694 paginated_result.next_cursor,
2695 Some("next_cursor".to_string())
2696 );
2697
2698 let json = serde_json::to_string(&paginated_result).unwrap();
2700 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2701
2702 assert!(parsed["resourceTemplates"].is_array());
2703 assert_eq!(parsed["resourceTemplates"].as_array().unwrap().len(), 2);
2704 assert_eq!(parsed["nextCursor"].as_str().unwrap(), "next_cursor");
2705
2706 let deserialized: ListResourceTemplatesResult = serde_json::from_str(&json).unwrap();
2708 assert_eq!(deserialized.resource_templates.len(), 2);
2709 assert_eq!(deserialized.next_cursor, Some("next_cursor".to_string()));
2710 }
2711
2712 #[test]
2713 fn test_client_request_with_resource_templates() {
2714 let request = ListResourceTemplatesRequest::with_cursor("abc123");
2715 let client_request = ClientRequest::ListResourceTemplates(request);
2716
2717 let json = serde_json::to_string(&client_request).unwrap();
2719 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2720
2721 assert_eq!(
2722 parsed["method"].as_str().unwrap(),
2723 "resources/templates/list"
2724 );
2725 assert_eq!(parsed["params"]["cursor"].as_str().unwrap(), "abc123");
2726 }
2727
2728 #[test]
2729 fn test_complex_uri_templates() {
2730 let complex_templates = vec![
2732 ResourceTemplate::new(
2733 "github",
2734 "https://api.github.com/repos/{owner}/{repo}/contents/{+path}",
2735 ),
2736 ResourceTemplate::new("search", "/search{?q,type,sort,order}"),
2737 ResourceTemplate::new("matrix", "/matrix{;x,y}/data"),
2738 ResourceTemplate::new("fragment", "/documents/{id}{#section}"),
2739 ];
2740
2741 for template in complex_templates {
2742 let json = serde_json::to_string(&template).unwrap();
2743 let deserialized: ResourceTemplate = serde_json::from_str(&json).unwrap();
2744 assert_eq!(template.uri_template, deserialized.uri_template);
2745 }
2746 }
2747
2748 #[test]
2749 fn test_resource_template_with_annotations() {
2750 let annotations = Annotations {
2751 priority: Some(1.0),
2752 ..Default::default()
2753 };
2754
2755 let template =
2756 ResourceTemplate::new("important", "/critical/{id}").with_annotations(annotations);
2757
2758 assert!(template.annotations.is_some());
2759 assert_eq!(template.annotations.unwrap().priority, Some(1.0));
2760 }
2761
2762 #[test]
2763 fn test_ping_request_creation() {
2764 let ping = PingRequest::new();
2766 assert_eq!(ping.method, "ping");
2767 assert!(ping.params.is_none());
2768
2769 let meta_value = serde_json::json!({"timestamp": "2025-08-29T12:00:00Z"});
2771 let ping_with_meta = PingRequest::with_meta(meta_value.clone());
2772 assert_eq!(ping_with_meta.method, "ping");
2773 assert!(ping_with_meta.params.is_some());
2774 assert_eq!(ping_with_meta.params.unwrap()._meta, Some(meta_value));
2775 }
2776
2777 #[test]
2778 fn test_ping_serialization() {
2779 let ping = PingRequest::new();
2781 let json = serde_json::to_string(&ping).unwrap();
2782 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2783 assert_eq!(parsed["method"].as_str().unwrap(), "ping");
2784
2785 let deserialized: PingRequest = serde_json::from_str(&json).unwrap();
2787 assert_eq!(deserialized.method, "ping");
2788
2789 let meta_value = serde_json::json!({"client": "test", "version": "1.0"});
2791 let ping_with_meta = PingRequest::with_meta(meta_value.clone());
2792 let json_with_meta = serde_json::to_string(&ping_with_meta).unwrap();
2793 let parsed_meta: serde_json::Value = serde_json::from_str(&json_with_meta).unwrap();
2794
2795 assert!(parsed_meta["params"].is_object());
2796 assert_eq!(
2797 parsed_meta["params"]["_meta"]["client"].as_str().unwrap(),
2798 "test"
2799 );
2800 }
2801
2802 #[test]
2803 fn test_ping_result() {
2804 let result = PingResult::new();
2806 assert!(result._meta.is_none());
2807
2808 let meta = serde_json::json!({"latency_ms": 42});
2810 let result_with_meta = PingResult::with_meta(meta.clone());
2811 assert_eq!(result_with_meta._meta, Some(meta));
2812
2813 let json = serde_json::to_string(&result).unwrap();
2815 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2816 assert!(parsed.as_object().unwrap().is_empty());
2818
2819 let deserialized: PingResult = serde_json::from_str(&json).unwrap();
2821 assert!(deserialized._meta.is_none());
2822 }
2823
2824 #[test]
2825 fn test_ping_params() {
2826 let params = PingParams::new();
2828 assert!(params._meta.is_none());
2829
2830 let meta = serde_json::json!({"timeout": 5000});
2832 let params_with_meta = PingParams::new().with_meta(meta.clone());
2833 assert_eq!(params_with_meta._meta, Some(meta));
2834
2835 let json = serde_json::to_string(¶ms).unwrap();
2837 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2838 assert!(parsed.as_object().unwrap().is_empty());
2839 }
2840
2841 #[test]
2842 fn test_server_request_with_ping() {
2843 let ping_params = PingParams::new();
2844 let server_request = ServerRequest::Ping(ping_params);
2845
2846 let json = serde_json::to_string(&server_request).unwrap();
2848 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2849
2850 assert_eq!(parsed["method"].as_str().unwrap(), "ping");
2851 }
2852
2853 #[test]
2854 fn test_client_request_with_ping() {
2855 let ping_params = PingParams::new();
2856 let client_request = ClientRequest::Ping(ping_params);
2857
2858 let json = serde_json::to_string(&client_request).unwrap();
2860 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2861
2862 assert_eq!(parsed["method"].as_str().unwrap(), "ping");
2863 }
2864
2865 #[test]
2866 fn test_ping_protocol_bidirectional() {
2867 let meta = serde_json::json!({"source": "test"});
2869
2870 let client_ping = ClientRequest::Ping(PingParams::new().with_meta(meta.clone()));
2872 let client_json = serde_json::to_string(&client_ping).unwrap();
2873
2874 let server_ping = ServerRequest::Ping(PingParams::new().with_meta(meta.clone()));
2876 let server_json = serde_json::to_string(&server_ping).unwrap();
2877
2878 let client_parsed: serde_json::Value = serde_json::from_str(&client_json).unwrap();
2880 let server_parsed: serde_json::Value = serde_json::from_str(&server_json).unwrap();
2881
2882 assert_eq!(client_parsed["method"], server_parsed["method"]);
2883 assert_eq!(
2884 client_parsed["_meta"]["source"],
2885 server_parsed["_meta"]["source"]
2886 );
2887 }
2888}