1use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8use turbomcp_core::MessageId;
9
10pub type ProtocolVersion = String;
12
13pub type RequestId = MessageId;
15
16pub type ProgressToken = String;
18
19pub type Uri = String;
21
22pub type MimeType = String;
24
25pub type Base64String = String;
27
28pub mod error_codes {
34 pub const PARSE_ERROR: i32 = -32700;
36 pub const INVALID_REQUEST: i32 = -32600;
38 pub const METHOD_NOT_FOUND: i32 = -32601;
40 pub const INVALID_PARAMS: i32 = -32602;
42 pub const INTERNAL_ERROR: i32 = -32603;
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
48pub struct JsonRpcError {
49 pub code: i32,
51 pub message: String,
53 #[serde(skip_serializing_if = "Option::is_none")]
55 pub data: Option<serde_json::Value>,
56}
57
58impl JsonRpcError {
59 pub fn new(code: i32, message: String) -> Self {
61 Self {
62 code,
63 message,
64 data: None,
65 }
66 }
67
68 pub fn with_data(code: i32, message: String, data: serde_json::Value) -> Self {
70 Self {
71 code,
72 message,
73 data: Some(data),
74 }
75 }
76
77 pub fn parse_error() -> Self {
79 Self::new(error_codes::PARSE_ERROR, "Parse error".to_string())
80 }
81
82 pub fn invalid_request() -> Self {
84 Self::new(error_codes::INVALID_REQUEST, "Invalid Request".to_string())
85 }
86
87 pub fn method_not_found(method: &str) -> Self {
89 Self::new(
90 error_codes::METHOD_NOT_FOUND,
91 format!("Method not found: {method}"),
92 )
93 }
94
95 pub fn invalid_params(details: &str) -> Self {
97 Self::new(
98 error_codes::INVALID_PARAMS,
99 format!("Invalid params: {details}"),
100 )
101 }
102
103 pub fn internal_error(details: &str) -> Self {
105 Self::new(
106 error_codes::INTERNAL_ERROR,
107 format!("Internal error: {details}"),
108 )
109 }
110}
111
112pub type Cursor = String;
114
115#[derive(Debug, Clone, Serialize, Deserialize)]
122pub struct BaseMetadata {
123 pub name: String,
125
126 #[serde(skip_serializing_if = "Option::is_none")]
132 pub title: Option<String>,
133}
134
135#[derive(Debug, Clone, Serialize, Deserialize)]
137pub struct Implementation {
138 pub name: String,
140 #[serde(skip_serializing_if = "Option::is_none")]
142 pub title: Option<String>,
143 pub version: String,
145}
146
147#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
149pub struct Annotations {
150 #[serde(skip_serializing_if = "Option::is_none")]
152 pub audience: Option<Vec<String>>,
153 #[serde(skip_serializing_if = "Option::is_none")]
155 pub priority: Option<f64>,
156 #[serde(skip_serializing_if = "Option::is_none")]
158 #[serde(rename = "lastModified")]
159 pub last_modified: Option<String>,
160 #[serde(flatten)]
162 pub custom: HashMap<String, serde_json::Value>,
163}
164
165#[derive(Debug, Clone, Serialize, Deserialize)]
171#[serde(tag = "method")]
172pub enum ClientRequest {
173 #[serde(rename = "initialize")]
175 Initialize(InitializeRequest),
176
177 #[serde(rename = "tools/list")]
179 ListTools(ListToolsRequest),
180
181 #[serde(rename = "tools/call")]
183 CallTool(CallToolRequest),
184
185 #[serde(rename = "prompts/list")]
187 ListPrompts(ListPromptsRequest),
188
189 #[serde(rename = "prompts/get")]
191 GetPrompt(GetPromptRequest),
192
193 #[serde(rename = "resources/list")]
195 ListResources(ListResourcesRequest),
196
197 #[serde(rename = "resources/templates/list")]
199 ListResourceTemplates(ListResourceTemplatesRequest),
200
201 #[serde(rename = "resources/read")]
203 ReadResource(ReadResourceRequest),
204
205 #[serde(rename = "resources/subscribe")]
207 Subscribe(SubscribeRequest),
208
209 #[serde(rename = "resources/unsubscribe")]
211 Unsubscribe(UnsubscribeRequest),
212
213 #[serde(rename = "logging/setLevel")]
215 SetLevel(SetLevelRequest),
216
217 #[serde(rename = "completion/complete")]
219 Complete(CompleteRequestParams),
220
221 #[serde(rename = "ping")]
223 Ping(PingParams),
224}
225
226#[derive(Debug, Clone, Serialize, Deserialize)]
228#[serde(tag = "method")]
229pub enum ServerRequest {
230 #[serde(rename = "ping")]
232 Ping(PingParams),
233
234 #[serde(rename = "sampling/createMessage")]
236 CreateMessage(CreateMessageRequest),
237
238 #[serde(rename = "roots/list")]
240 ListRoots(ListRootsRequest),
241
242 #[serde(rename = "elicitation/create")]
244 ElicitationCreate(ElicitRequestParams),
245}
246
247#[derive(Debug, Clone, Serialize, Deserialize)]
249#[serde(tag = "method")]
250pub enum ClientNotification {
251 #[serde(rename = "notifications/initialized")]
253 Initialized(InitializedNotification),
254
255 #[serde(rename = "notifications/progress")]
257 Progress(ProgressNotification),
258
259 #[serde(rename = "notifications/roots/list_changed")]
261 RootsListChanged(RootsListChangedNotification),
262}
263
264#[derive(Debug, Clone, Serialize, Deserialize)]
266#[serde(tag = "method")]
267pub enum ServerNotification {
268 #[serde(rename = "notifications/message")]
270 Message(LoggingNotification),
271
272 #[serde(rename = "notifications/resources/updated")]
274 ResourceUpdated(ResourceUpdatedNotification),
275
276 #[serde(rename = "notifications/resources/list_changed")]
278 ResourceListChanged,
279
280 #[serde(rename = "notifications/progress")]
282 Progress(ProgressNotification),
283
284 #[serde(rename = "notifications/cancelled")]
286 Cancelled(CancelledNotification),
287
288 #[serde(rename = "notifications/prompts/list_changed")]
290 PromptsListChanged,
291
292 #[serde(rename = "notifications/tools/list_changed")]
294 ToolsListChanged,
295
296 #[serde(rename = "notifications/roots/list_changed")]
298 RootsListChanged,
299}
300
301#[derive(Debug, Clone, Serialize, Deserialize)]
307pub struct InitializeRequest {
308 #[serde(rename = "protocolVersion")]
310 pub protocol_version: ProtocolVersion,
311 pub capabilities: ClientCapabilities,
313 #[serde(rename = "clientInfo")]
315 pub client_info: Implementation,
316}
317
318#[derive(Debug, Clone, Serialize, Deserialize)]
320pub struct InitializeResult {
321 #[serde(rename = "protocolVersion")]
323 pub protocol_version: ProtocolVersion,
324 pub capabilities: ServerCapabilities,
326 #[serde(rename = "serverInfo")]
328 pub server_info: Implementation,
329 #[serde(skip_serializing_if = "Option::is_none")]
331 pub instructions: Option<String>,
332}
333
334#[derive(Debug, Clone, Serialize, Deserialize)]
336pub struct InitializedNotification;
337
338#[derive(Debug, Clone, Serialize, Deserialize, Default)]
344pub struct ClientCapabilities {
345 #[serde(skip_serializing_if = "Option::is_none")]
347 pub experimental: Option<HashMap<String, serde_json::Value>>,
348
349 #[serde(skip_serializing_if = "Option::is_none")]
351 pub roots: Option<RootsCapabilities>,
352
353 #[serde(skip_serializing_if = "Option::is_none")]
355 pub sampling: Option<SamplingCapabilities>,
356
357 #[serde(skip_serializing_if = "Option::is_none")]
359 pub elicitation: Option<ElicitationCapabilities>,
360}
361
362#[derive(Debug, Clone, Serialize, Deserialize, Default)]
364pub struct ServerCapabilities {
365 #[serde(skip_serializing_if = "Option::is_none")]
367 pub experimental: Option<HashMap<String, serde_json::Value>>,
368
369 #[serde(skip_serializing_if = "Option::is_none")]
371 pub logging: Option<LoggingCapabilities>,
372
373 #[serde(skip_serializing_if = "Option::is_none")]
375 pub completions: Option<CompletionCapabilities>,
376
377 #[serde(skip_serializing_if = "Option::is_none")]
379 pub prompts: Option<PromptsCapabilities>,
380
381 #[serde(skip_serializing_if = "Option::is_none")]
383 pub resources: Option<ResourcesCapabilities>,
384
385 #[serde(skip_serializing_if = "Option::is_none")]
387 pub tools: Option<ToolsCapabilities>,
388}
389
390#[derive(Debug, Clone, Serialize, Deserialize, Default)]
392pub struct SamplingCapabilities;
393
394#[derive(Debug, Clone, Serialize, Deserialize, Default)]
396pub struct ElicitationCapabilities;
397
398#[derive(Debug, Clone, Serialize, Deserialize, Default)]
400pub struct CompletionCapabilities;
401
402#[derive(Debug, Clone, Serialize, Deserialize, Default)]
404pub struct RootsCapabilities {
405 #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
407 pub list_changed: Option<bool>,
408}
409
410#[derive(Debug, Clone, Serialize, Deserialize, Default)]
412pub struct LoggingCapabilities;
413
414#[derive(Debug, Clone, Serialize, Deserialize, Default)]
416pub struct PromptsCapabilities {
417 #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
419 pub list_changed: Option<bool>,
420}
421
422#[derive(Debug, Clone, Serialize, Deserialize, Default)]
424pub struct ResourcesCapabilities {
425 #[serde(skip_serializing_if = "Option::is_none")]
427 pub subscribe: Option<bool>,
428
429 #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
431 pub list_changed: Option<bool>,
432}
433
434#[derive(Debug, Clone, Serialize, Deserialize, Default)]
436pub struct ToolsCapabilities {
437 #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
439 pub list_changed: Option<bool>,
440}
441
442#[derive(Debug, Clone, Serialize, Deserialize)]
448#[serde(tag = "type")]
449pub enum ContentBlock {
450 #[serde(rename = "text")]
452 Text(TextContent),
453 #[serde(rename = "image")]
455 Image(ImageContent),
456 #[serde(rename = "audio")]
458 Audio(AudioContent),
459 #[serde(rename = "resource_link")]
461 ResourceLink(ResourceLink),
462 #[serde(rename = "resource")]
464 Resource(EmbeddedResource),
465}
466
467pub type Content = ContentBlock;
469
470#[derive(Debug, Clone, Serialize, Deserialize)]
472pub struct TextContent {
473 pub text: String,
475 #[serde(skip_serializing_if = "Option::is_none")]
477 pub annotations: Option<Annotations>,
478 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
480 pub meta: Option<HashMap<String, serde_json::Value>>,
481}
482
483#[derive(Debug, Clone, Serialize, Deserialize)]
485pub struct ImageContent {
486 pub data: String,
488 #[serde(rename = "mimeType")]
490 pub mime_type: String,
491 #[serde(skip_serializing_if = "Option::is_none")]
493 pub annotations: Option<Annotations>,
494 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
496 pub meta: Option<HashMap<String, serde_json::Value>>,
497}
498
499#[derive(Debug, Clone, Serialize, Deserialize)]
501pub struct AudioContent {
502 pub data: String,
504 #[serde(rename = "mimeType")]
506 pub mime_type: String,
507 #[serde(skip_serializing_if = "Option::is_none")]
509 pub annotations: Option<Annotations>,
510 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
512 pub meta: Option<HashMap<String, serde_json::Value>>,
513}
514
515#[derive(Debug, Clone, Serialize, Deserialize)]
517pub struct ResourceLink {
518 pub name: String,
520 #[serde(skip_serializing_if = "Option::is_none")]
522 pub title: Option<String>,
523 pub uri: String,
525 #[serde(skip_serializing_if = "Option::is_none")]
527 pub description: Option<String>,
528 #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
530 pub mime_type: Option<String>,
531 #[serde(skip_serializing_if = "Option::is_none")]
533 pub annotations: Option<Annotations>,
534 #[serde(skip_serializing_if = "Option::is_none")]
536 pub size: Option<u64>,
537 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
539 pub meta: Option<HashMap<String, serde_json::Value>>,
540}
541
542#[derive(Debug, Clone, Serialize, Deserialize)]
544pub struct EmbeddedResource {
545 pub resource: ResourceContent,
547 #[serde(skip_serializing_if = "Option::is_none")]
549 pub annotations: Option<Annotations>,
550 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
552 pub meta: Option<HashMap<String, serde_json::Value>>,
553}
554
555#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
557#[serde(rename_all = "lowercase")]
558pub enum Role {
559 User,
561 Assistant,
563}
564
565#[derive(Debug, Clone, Serialize, Deserialize, Default)]
571pub struct ToolAnnotations {
572 #[serde(skip_serializing_if = "Option::is_none")]
574 pub title: Option<String>,
575 #[serde(skip_serializing_if = "Option::is_none")]
577 pub audience: Option<Vec<String>>,
578 #[serde(skip_serializing_if = "Option::is_none")]
580 pub priority: Option<f64>,
581 #[serde(skip_serializing_if = "Option::is_none")]
583 #[serde(rename = "destructiveHint")]
584 pub destructive_hint: Option<bool>,
585 #[serde(skip_serializing_if = "Option::is_none")]
587 #[serde(rename = "idempotentHint")]
588 pub idempotent_hint: Option<bool>,
589 #[serde(skip_serializing_if = "Option::is_none")]
591 #[serde(rename = "openWorldHint")]
592 pub open_world_hint: Option<bool>,
593 #[serde(skip_serializing_if = "Option::is_none")]
595 #[serde(rename = "readOnlyHint")]
596 pub read_only_hint: Option<bool>,
597 #[serde(flatten)]
599 pub custom: HashMap<String, serde_json::Value>,
600}
601
602#[derive(Debug, Clone, Serialize, Deserialize)]
604pub struct Tool {
605 pub name: String,
607
608 #[serde(skip_serializing_if = "Option::is_none")]
610 pub title: Option<String>,
611
612 #[serde(skip_serializing_if = "Option::is_none")]
615 pub description: Option<String>,
616
617 #[serde(rename = "inputSchema")]
619 pub input_schema: ToolInputSchema,
620
621 #[serde(rename = "outputSchema", skip_serializing_if = "Option::is_none")]
624 pub output_schema: Option<ToolOutputSchema>,
625
626 #[serde(skip_serializing_if = "Option::is_none")]
629 pub annotations: Option<ToolAnnotations>,
630
631 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
633 pub meta: Option<HashMap<String, serde_json::Value>>,
634}
635
636#[derive(Debug, Clone, Serialize, Deserialize)]
638pub struct ToolInputSchema {
639 #[serde(rename = "type")]
641 pub schema_type: String,
642 #[serde(skip_serializing_if = "Option::is_none")]
644 pub properties: Option<HashMap<String, serde_json::Value>>,
645 #[serde(skip_serializing_if = "Option::is_none")]
647 pub required: Option<Vec<String>>,
648 #[serde(
650 rename = "additionalProperties",
651 skip_serializing_if = "Option::is_none"
652 )]
653 pub additional_properties: Option<bool>,
654}
655
656#[derive(Debug, Clone, Serialize, Deserialize)]
658pub struct ToolOutputSchema {
659 #[serde(rename = "type")]
661 pub schema_type: String,
662 #[serde(skip_serializing_if = "Option::is_none")]
664 pub properties: Option<HashMap<String, serde_json::Value>>,
665 #[serde(skip_serializing_if = "Option::is_none")]
667 pub required: Option<Vec<String>>,
668 #[serde(
670 rename = "additionalProperties",
671 skip_serializing_if = "Option::is_none"
672 )]
673 pub additional_properties: Option<bool>,
674}
675
676#[derive(Debug, Clone, Serialize, Deserialize)]
678pub struct ListToolsRequest;
679
680#[derive(Debug, Clone, Serialize, Deserialize)]
682pub struct ListToolsResult {
683 pub tools: Vec<Tool>,
685 #[serde(rename = "nextCursor", skip_serializing_if = "Option::is_none")]
687 pub next_cursor: Option<String>,
688}
689
690#[derive(Debug, Clone, Serialize, Deserialize)]
692pub struct CallToolRequest {
693 pub name: String,
695 #[serde(skip_serializing_if = "Option::is_none")]
697 pub arguments: Option<HashMap<String, serde_json::Value>>,
698}
699
700#[derive(Debug, Clone, Serialize, Deserialize)]
702pub struct CallToolResult {
703 pub content: Vec<ContentBlock>,
705 #[serde(rename = "isError", skip_serializing_if = "Option::is_none")]
707 pub is_error: Option<bool>,
708}
709
710#[derive(Debug, Clone, Serialize, Deserialize)]
716pub struct Prompt {
717 pub name: String,
719
720 #[serde(skip_serializing_if = "Option::is_none")]
722 pub title: Option<String>,
723
724 #[serde(skip_serializing_if = "Option::is_none")]
726 pub description: Option<String>,
727
728 #[serde(skip_serializing_if = "Option::is_none")]
730 pub arguments: Option<Vec<PromptArgument>>,
731
732 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
734 pub meta: Option<HashMap<String, serde_json::Value>>,
735}
736
737#[derive(Debug, Clone, Serialize, Deserialize)]
739pub struct PromptArgument {
740 pub name: String,
742
743 #[serde(skip_serializing_if = "Option::is_none")]
745 pub title: Option<String>,
746
747 #[serde(skip_serializing_if = "Option::is_none")]
749 pub description: Option<String>,
750
751 #[serde(skip_serializing_if = "Option::is_none")]
753 pub required: Option<bool>,
754}
755
756pub type PromptInput = HashMap<String, serde_json::Value>;
758
759#[derive(Debug, Clone, Serialize, Deserialize)]
761pub struct ListPromptsRequest;
762
763#[derive(Debug, Clone, Serialize, Deserialize)]
765pub struct ListPromptsResult {
766 pub prompts: Vec<Prompt>,
768 #[serde(rename = "nextCursor", skip_serializing_if = "Option::is_none")]
770 pub next_cursor: Option<String>,
771}
772
773#[derive(Debug, Clone, Serialize, Deserialize)]
775pub struct GetPromptRequest {
776 pub name: String,
778 #[serde(skip_serializing_if = "Option::is_none")]
780 pub arguments: Option<PromptInput>,
781}
782
783#[derive(Debug, Clone, Serialize, Deserialize)]
785pub struct GetPromptResult {
786 #[serde(skip_serializing_if = "Option::is_none")]
788 pub description: Option<String>,
789 pub messages: Vec<PromptMessage>,
791}
792
793#[derive(Debug, Clone, Serialize, Deserialize)]
795pub struct PromptMessage {
796 pub role: Role,
798 pub content: Content,
800}
801
802#[derive(Debug, Clone, Serialize, Deserialize)]
808pub struct Resource {
809 pub name: String,
811
812 #[serde(skip_serializing_if = "Option::is_none")]
814 pub title: Option<String>,
815
816 pub uri: String,
818
819 #[serde(skip_serializing_if = "Option::is_none")]
822 pub description: Option<String>,
823
824 #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
826 pub mime_type: Option<String>,
827
828 #[serde(skip_serializing_if = "Option::is_none")]
830 pub annotations: Option<Annotations>,
831
832 #[serde(skip_serializing_if = "Option::is_none")]
835 pub size: Option<u64>,
836
837 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
839 pub meta: Option<HashMap<String, serde_json::Value>>,
840}
841
842#[derive(Debug, Clone, Serialize, Deserialize)]
844pub struct ResourceContents {
845 pub uri: String,
847 #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
849 pub mime_type: Option<String>,
850 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
852 pub meta: Option<HashMap<String, serde_json::Value>>,
853}
854
855#[derive(Debug, Clone, Serialize, Deserialize)]
857pub struct TextResourceContents {
858 pub uri: String,
860 #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
862 pub mime_type: Option<String>,
863 pub text: String,
865 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
867 pub meta: Option<HashMap<String, serde_json::Value>>,
868}
869
870#[derive(Debug, Clone, Serialize, Deserialize)]
872pub struct BlobResourceContents {
873 pub uri: String,
875 #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
877 pub mime_type: Option<String>,
878 pub blob: String,
880 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
882 pub meta: Option<HashMap<String, serde_json::Value>>,
883}
884
885#[derive(Debug, Clone, Serialize, Deserialize)]
887#[serde(untagged)]
888pub enum ResourceContent {
889 Text(TextResourceContents),
891 Blob(BlobResourceContents),
893}
894
895#[derive(Debug, Clone, Serialize, Deserialize)]
897pub struct ListResourcesRequest {
898 #[serde(skip_serializing_if = "Option::is_none")]
900 pub cursor: Option<String>,
901}
902
903#[derive(Debug, Clone, Serialize, Deserialize)]
905pub struct ListResourcesResult {
906 pub resources: Vec<Resource>,
908 #[serde(rename = "nextCursor", skip_serializing_if = "Option::is_none")]
910 pub next_cursor: Option<String>,
911}
912
913#[derive(Debug, Clone, Serialize, Deserialize)]
915pub struct ReadResourceRequest {
916 pub uri: Uri,
918}
919
920#[derive(Debug, Clone, Serialize, Deserialize)]
922pub struct ReadResourceResult {
923 pub contents: Vec<ResourceContent>,
925}
926
927#[derive(Debug, Clone, Serialize, Deserialize)]
929pub struct SubscribeRequest {
930 pub uri: Uri,
932}
933
934#[derive(Debug, Clone, Serialize, Deserialize)]
936pub struct UnsubscribeRequest {
937 pub uri: Uri,
939}
940
941#[derive(Debug, Clone, Serialize, Deserialize)]
943pub struct ResourceUpdatedNotification {
944 pub uri: Uri,
946}
947
948#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
954#[serde(rename_all = "lowercase")]
955pub enum LogLevel {
956 Debug,
958 Info,
960 Notice,
962 Warning,
964 Error,
966 Critical,
968 Alert,
970 Emergency,
972}
973
974#[derive(Debug, Clone, Serialize, Deserialize)]
976pub struct SetLevelRequest {
977 pub level: LogLevel,
979}
980
981#[derive(Debug, Clone, Serialize, Deserialize)]
983pub struct SetLevelResult;
984
985#[derive(Debug, Clone, Serialize, Deserialize)]
987pub struct LoggingNotification {
988 pub level: LogLevel,
990 pub data: serde_json::Value,
992 #[serde(skip_serializing_if = "Option::is_none")]
994 pub logger: Option<String>,
995}
996
997#[derive(Debug, Clone, Serialize, Deserialize)]
1003pub struct ProgressNotification {
1004 #[serde(rename = "progressToken")]
1007 pub progress_token: ProgressToken,
1008 pub progress: f64,
1011 #[serde(skip_serializing_if = "Option::is_none")]
1013 pub total: Option<f64>,
1014 #[serde(skip_serializing_if = "Option::is_none")]
1016 pub message: Option<String>,
1017}
1018
1019#[derive(Debug, Clone, Serialize, Deserialize)]
1021pub struct CancelledNotification {
1022 #[serde(rename = "requestId")]
1025 pub request_id: RequestId,
1026 #[serde(skip_serializing_if = "Option::is_none")]
1029 pub reason: Option<String>,
1030}
1031
1032#[derive(Debug, Clone, Serialize, Deserialize)]
1038pub struct CreateMessageRequest {
1039 pub messages: Vec<SamplingMessage>,
1041 #[serde(rename = "modelPreferences", skip_serializing_if = "Option::is_none")]
1043 pub model_preferences: Option<ModelPreferences>,
1044 #[serde(rename = "systemPrompt", skip_serializing_if = "Option::is_none")]
1046 pub system_prompt: Option<String>,
1047 #[serde(rename = "includeContext", skip_serializing_if = "Option::is_none")]
1049 pub include_context: Option<IncludeContext>,
1050 #[serde(skip_serializing_if = "Option::is_none")]
1052 pub temperature: Option<f64>,
1053 #[serde(rename = "maxTokens")]
1055 pub max_tokens: u32,
1056 #[serde(rename = "stopSequences", skip_serializing_if = "Option::is_none")]
1058 pub stop_sequences: Option<Vec<String>>,
1059 #[serde(skip_serializing_if = "Option::is_none")]
1061 pub metadata: Option<HashMap<String, serde_json::Value>>,
1062}
1063
1064#[derive(Debug, Clone, Serialize, Deserialize)]
1066pub struct ModelPreferences {
1067 #[serde(skip_serializing_if = "Option::is_none")]
1069 pub hints: Option<Vec<ModelHint>>,
1070 #[serde(rename = "costPriority", skip_serializing_if = "Option::is_none")]
1072 pub cost_priority: Option<f64>,
1073 #[serde(rename = "speedPriority", skip_serializing_if = "Option::is_none")]
1075 pub speed_priority: Option<f64>,
1076 #[serde(
1078 rename = "intelligencePriority",
1079 skip_serializing_if = "Option::is_none"
1080 )]
1081 pub intelligence_priority: Option<f64>,
1082}
1083
1084#[derive(Debug, Clone, Serialize, Deserialize)]
1086pub struct ModelHint {
1087 pub name: String,
1089}
1090
1091#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1093#[serde(rename_all = "lowercase")]
1094pub enum IncludeContext {
1095 None,
1097 ThisServer,
1099 AllServers,
1101}
1102
1103#[derive(Debug, Clone, Serialize, Deserialize)]
1105pub struct SamplingMessage {
1106 pub role: Role,
1108 pub content: Content,
1110}
1111
1112#[derive(Debug, Clone, Serialize, Deserialize)]
1114pub struct CreateMessageResult {
1115 pub role: Role,
1117 pub content: Content,
1119 #[serde(skip_serializing_if = "Option::is_none")]
1121 pub model: Option<String>,
1122 #[serde(rename = "stopReason", skip_serializing_if = "Option::is_none")]
1124 pub stop_reason: Option<String>,
1125}
1126
1127#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1134#[serde(tag = "type")]
1135pub enum PrimitiveSchemaDefinition {
1136 #[serde(rename = "string")]
1138 String {
1139 #[serde(skip_serializing_if = "Option::is_none")]
1141 title: Option<String>,
1142 #[serde(skip_serializing_if = "Option::is_none")]
1144 description: Option<String>,
1145 #[serde(skip_serializing_if = "Option::is_none")]
1147 format: Option<String>,
1148 #[serde(skip_serializing_if = "Option::is_none")]
1150 #[serde(rename = "minLength")]
1151 min_length: Option<u32>,
1152 #[serde(skip_serializing_if = "Option::is_none")]
1154 #[serde(rename = "maxLength")]
1155 max_length: Option<u32>,
1156 #[serde(skip_serializing_if = "Option::is_none")]
1158 #[serde(rename = "enum")]
1159 enum_values: Option<Vec<String>>,
1160 #[serde(skip_serializing_if = "Option::is_none")]
1162 #[serde(rename = "enumNames")]
1163 enum_names: Option<Vec<String>>,
1164 },
1165 #[serde(rename = "number")]
1167 Number {
1168 #[serde(skip_serializing_if = "Option::is_none")]
1170 title: Option<String>,
1171 #[serde(skip_serializing_if = "Option::is_none")]
1173 description: Option<String>,
1174 #[serde(skip_serializing_if = "Option::is_none")]
1176 minimum: Option<f64>,
1177 #[serde(skip_serializing_if = "Option::is_none")]
1179 maximum: Option<f64>,
1180 },
1181 #[serde(rename = "integer")]
1183 Integer {
1184 #[serde(skip_serializing_if = "Option::is_none")]
1186 title: Option<String>,
1187 #[serde(skip_serializing_if = "Option::is_none")]
1189 description: Option<String>,
1190 #[serde(skip_serializing_if = "Option::is_none")]
1192 minimum: Option<i64>,
1193 #[serde(skip_serializing_if = "Option::is_none")]
1195 maximum: Option<i64>,
1196 },
1197 #[serde(rename = "boolean")]
1199 Boolean {
1200 #[serde(skip_serializing_if = "Option::is_none")]
1202 title: Option<String>,
1203 #[serde(skip_serializing_if = "Option::is_none")]
1205 description: Option<String>,
1206 #[serde(skip_serializing_if = "Option::is_none")]
1208 default: Option<bool>,
1209 },
1210}
1211
1212#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1214pub struct ElicitationSchema {
1215 #[serde(rename = "type")]
1217 pub schema_type: String,
1218 pub properties: std::collections::HashMap<String, PrimitiveSchemaDefinition>,
1220 #[serde(skip_serializing_if = "Option::is_none")]
1222 pub required: Option<Vec<String>>,
1223}
1224
1225impl ElicitationSchema {
1226 pub fn new() -> Self {
1228 Self {
1229 schema_type: "object".to_string(),
1230 properties: std::collections::HashMap::new(),
1231 required: None,
1232 }
1233 }
1234
1235 pub fn add_string_property<K: Into<String>>(
1237 mut self,
1238 name: K,
1239 required: bool,
1240 description: Option<String>,
1241 ) -> Self {
1242 let property = PrimitiveSchemaDefinition::String {
1243 title: None,
1244 description,
1245 format: None,
1246 min_length: None,
1247 max_length: None,
1248 enum_values: None,
1249 enum_names: None,
1250 };
1251
1252 let name = name.into();
1253 self.properties.insert(name.clone(), property);
1254
1255 if required {
1256 self.required.get_or_insert_with(Vec::new).push(name);
1257 }
1258
1259 self
1260 }
1261
1262 pub fn add_number_property<K: Into<String>>(
1264 mut self,
1265 name: K,
1266 required: bool,
1267 description: Option<String>,
1268 min: Option<f64>,
1269 max: Option<f64>,
1270 ) -> Self {
1271 let property = PrimitiveSchemaDefinition::Number {
1272 title: None,
1273 description,
1274 minimum: min,
1275 maximum: max,
1276 };
1277
1278 let name = name.into();
1279 self.properties.insert(name.clone(), property);
1280
1281 if required {
1282 self.required.get_or_insert_with(Vec::new).push(name);
1283 }
1284
1285 self
1286 }
1287
1288 pub fn add_boolean_property<K: Into<String>>(
1290 mut self,
1291 name: K,
1292 required: bool,
1293 description: Option<String>,
1294 default: Option<bool>,
1295 ) -> Self {
1296 let property = PrimitiveSchemaDefinition::Boolean {
1297 title: None,
1298 description,
1299 default,
1300 };
1301
1302 let name = name.into();
1303 self.properties.insert(name.clone(), property);
1304
1305 if required {
1306 self.required.get_or_insert_with(Vec::new).push(name);
1307 }
1308
1309 self
1310 }
1311
1312 pub fn add_enum_property<K: Into<String>>(
1314 mut self,
1315 name: K,
1316 required: bool,
1317 description: Option<String>,
1318 values: Vec<String>,
1319 names: Option<Vec<String>>,
1320 ) -> Self {
1321 let property = PrimitiveSchemaDefinition::String {
1322 title: None,
1323 description,
1324 format: None,
1325 min_length: None,
1326 max_length: None,
1327 enum_values: Some(values),
1328 enum_names: names,
1329 };
1330
1331 let name = name.into();
1332 self.properties.insert(name.clone(), property);
1333
1334 if required {
1335 self.required.get_or_insert_with(Vec::new).push(name);
1336 }
1337
1338 self
1339 }
1340}
1341
1342impl Default for ElicitationSchema {
1343 fn default() -> Self {
1344 Self::new()
1345 }
1346}
1347
1348#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1350#[serde(rename_all = "camelCase")]
1351pub struct ElicitRequestParams {
1352 pub message: String,
1354 pub requested_schema: ElicitationSchema,
1356}
1357
1358#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1360pub struct ElicitRequest {
1361 pub method: String,
1363 pub params: ElicitRequestParams,
1365}
1366
1367impl ElicitRequest {
1368 pub fn new<M: Into<String>>(message: M, schema: ElicitationSchema) -> Self {
1370 Self {
1371 method: "elicitation/create".to_string(),
1372 params: ElicitRequestParams {
1373 message: message.into(),
1374 requested_schema: schema,
1375 },
1376 }
1377 }
1378}
1379
1380#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1382#[serde(rename_all = "lowercase")]
1383pub enum ElicitationAction {
1384 Accept,
1386 Decline,
1388 Cancel,
1390}
1391
1392#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1394pub struct ElicitResult {
1395 pub action: ElicitationAction,
1397 #[serde(skip_serializing_if = "Option::is_none")]
1400 pub content: Option<std::collections::HashMap<String, serde_json::Value>>,
1401 #[serde(skip_serializing_if = "Option::is_none")]
1403 pub _meta: Option<serde_json::Value>,
1404}
1405
1406impl ElicitResult {
1407 pub fn accept(content: std::collections::HashMap<String, serde_json::Value>) -> Self {
1409 Self {
1410 action: ElicitationAction::Accept,
1411 content: Some(content),
1412 _meta: None,
1413 }
1414 }
1415
1416 pub fn decline() -> Self {
1418 Self {
1419 action: ElicitationAction::Decline,
1420 content: None,
1421 _meta: None,
1422 }
1423 }
1424
1425 pub fn cancel() -> Self {
1427 Self {
1428 action: ElicitationAction::Cancel,
1429 content: None,
1430 _meta: None,
1431 }
1432 }
1433
1434 pub fn with_meta(mut self, meta: serde_json::Value) -> Self {
1436 self._meta = Some(meta);
1437 self
1438 }
1439}
1440
1441#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1447pub struct ArgumentInfo {
1448 pub name: String,
1450 pub value: String,
1452}
1453
1454#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1456pub struct CompletionContext {
1457 #[serde(skip_serializing_if = "Option::is_none")]
1459 pub arguments: Option<std::collections::HashMap<String, String>>,
1460}
1461
1462#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1464pub struct PromptReference {
1465 #[serde(rename = "type")]
1467 pub ref_type: String,
1468 pub name: String,
1470 #[serde(skip_serializing_if = "Option::is_none")]
1472 pub title: Option<String>,
1473}
1474
1475impl PromptReference {
1476 pub fn new<N: Into<String>>(name: N) -> Self {
1478 Self {
1479 ref_type: "ref/prompt".to_string(),
1480 name: name.into(),
1481 title: None,
1482 }
1483 }
1484
1485 pub fn with_title<T: Into<String>>(mut self, title: T) -> Self {
1487 self.title = Some(title.into());
1488 self
1489 }
1490}
1491
1492#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1494pub struct ResourceTemplateReference {
1495 #[serde(rename = "type")]
1497 pub ref_type: String,
1498 pub uri: String,
1500}
1501
1502impl ResourceTemplateReference {
1503 pub fn new<U: Into<String>>(uri: U) -> Self {
1505 Self {
1506 ref_type: "ref/resource".to_string(),
1507 uri: uri.into(),
1508 }
1509 }
1510}
1511
1512#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1514#[serde(tag = "type")]
1515pub enum CompletionReference {
1516 #[serde(rename = "ref/prompt")]
1518 Prompt(PromptReferenceData),
1519 #[serde(rename = "ref/resource")]
1521 ResourceTemplate(ResourceTemplateReferenceData),
1522}
1523
1524#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1526pub struct PromptReferenceData {
1527 pub name: String,
1529 #[serde(skip_serializing_if = "Option::is_none")]
1531 pub title: Option<String>,
1532}
1533
1534#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1536pub struct ResourceTemplateReferenceData {
1537 pub uri: String,
1539}
1540
1541#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1543pub struct CompleteRequestParams {
1544 pub argument: ArgumentInfo,
1546 #[serde(rename = "ref")]
1548 pub reference: CompletionReference,
1549 #[serde(skip_serializing_if = "Option::is_none")]
1551 pub context: Option<CompletionContext>,
1552}
1553
1554#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1556pub struct CompleteRequest {
1557 pub method: String,
1559 pub params: CompleteRequestParams,
1561}
1562
1563impl CompleteRequest {
1564 pub fn new(argument: ArgumentInfo, reference: CompletionReference) -> Self {
1566 Self {
1567 method: "completion/complete".to_string(),
1568 params: CompleteRequestParams {
1569 argument,
1570 reference,
1571 context: None,
1572 },
1573 }
1574 }
1575
1576 pub fn with_context(mut self, context: CompletionContext) -> Self {
1578 self.params.context = Some(context);
1579 self
1580 }
1581}
1582
1583#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1585#[serde(rename_all = "camelCase")]
1586pub struct CompletionResponse {
1587 pub values: Vec<String>,
1589 #[serde(skip_serializing_if = "Option::is_none")]
1591 pub total: Option<u32>,
1592 #[serde(skip_serializing_if = "Option::is_none")]
1594 pub has_more: Option<bool>,
1595}
1596
1597impl CompletionResponse {
1598 pub fn new(values: Vec<String>) -> Self {
1600 Self {
1601 values,
1602 total: None,
1603 has_more: None,
1604 }
1605 }
1606
1607 pub fn with_total(mut self, total: u32) -> Self {
1609 self.total = Some(total);
1610 self
1611 }
1612
1613 pub fn with_has_more(mut self, has_more: bool) -> Self {
1615 self.has_more = Some(has_more);
1616 self
1617 }
1618
1619 pub fn paginated(values: Vec<String>, total: u32, has_more: bool) -> Self {
1621 Self {
1622 values,
1623 total: Some(total),
1624 has_more: Some(has_more),
1625 }
1626 }
1627}
1628
1629#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1631pub struct CompleteResult {
1632 pub completion: CompletionResponse,
1634 #[serde(skip_serializing_if = "Option::is_none")]
1636 pub _meta: Option<serde_json::Value>,
1637}
1638
1639impl CompleteResult {
1640 pub fn new(completion: CompletionResponse) -> Self {
1642 Self {
1643 completion,
1644 _meta: None,
1645 }
1646 }
1647
1648 pub fn with_meta(mut self, meta: serde_json::Value) -> Self {
1650 self._meta = Some(meta);
1651 self
1652 }
1653}
1654
1655#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1662#[serde(rename_all = "camelCase")]
1663pub struct ResourceTemplate {
1664 pub name: String,
1666 pub uri_template: String,
1668 #[serde(skip_serializing_if = "Option::is_none")]
1670 pub title: Option<String>,
1671 #[serde(skip_serializing_if = "Option::is_none")]
1673 pub description: Option<String>,
1674 #[serde(skip_serializing_if = "Option::is_none")]
1676 pub mime_type: Option<String>,
1677 #[serde(skip_serializing_if = "Option::is_none")]
1679 pub annotations: Option<Annotations>,
1680 #[serde(skip_serializing_if = "Option::is_none")]
1682 pub _meta: Option<serde_json::Value>,
1683}
1684
1685impl ResourceTemplate {
1686 pub fn new<N: Into<String>, U: Into<String>>(name: N, uri_template: U) -> Self {
1688 Self {
1689 name: name.into(),
1690 uri_template: uri_template.into(),
1691 title: None,
1692 description: None,
1693 mime_type: None,
1694 annotations: None,
1695 _meta: None,
1696 }
1697 }
1698
1699 pub fn with_title<T: Into<String>>(mut self, title: T) -> Self {
1701 self.title = Some(title.into());
1702 self
1703 }
1704
1705 pub fn with_description<D: Into<String>>(mut self, description: D) -> Self {
1707 self.description = Some(description.into());
1708 self
1709 }
1710
1711 pub fn with_mime_type<M: Into<String>>(mut self, mime_type: M) -> Self {
1713 self.mime_type = Some(mime_type.into());
1714 self
1715 }
1716
1717 pub fn with_annotations(mut self, annotations: Annotations) -> Self {
1719 self.annotations = Some(annotations);
1720 self
1721 }
1722
1723 pub fn with_meta(mut self, meta: serde_json::Value) -> Self {
1725 self._meta = Some(meta);
1726 self
1727 }
1728
1729 pub fn file_system<N: Into<String>>(name: N, base_path: &str) -> Self {
1731 Self::new(name, format!("file://{}/{{path}}", base_path))
1732 .with_title("File System Access")
1733 .with_description("Access files within the specified directory")
1734 }
1735
1736 pub fn api_endpoint<N: Into<String>>(name: N, base_url: &str) -> Self {
1738 Self::new(name, format!("{}/{{endpoint}}", base_url))
1739 .with_mime_type("application/json")
1740 .with_title("API Endpoint Access")
1741 .with_description("Access API endpoints")
1742 }
1743
1744 pub fn database_query<N: Into<String>>(name: N) -> Self {
1746 Self::new(name, "db://query/{table}?{query*}")
1747 .with_title("Database Query")
1748 .with_description("Execute database queries")
1749 }
1750}
1751
1752#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
1754pub struct ListResourceTemplatesParams {
1755 #[serde(skip_serializing_if = "Option::is_none")]
1757 pub cursor: Option<String>,
1758}
1759
1760#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1762pub struct ListResourceTemplatesRequest {
1763 #[serde(skip_serializing_if = "Option::is_none")]
1765 pub params: Option<ListResourceTemplatesParams>,
1766}
1767
1768impl ListResourceTemplatesRequest {
1769 pub fn new() -> Self {
1771 Self { params: None }
1772 }
1773
1774 pub fn with_cursor<C: Into<String>>(cursor: C) -> Self {
1776 Self {
1777 params: Some(ListResourceTemplatesParams {
1778 cursor: Some(cursor.into()),
1779 }),
1780 }
1781 }
1782}
1783
1784impl Default for ListResourceTemplatesRequest {
1785 fn default() -> Self {
1786 Self::new()
1787 }
1788}
1789
1790#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1792#[serde(rename_all = "camelCase")]
1793pub struct ListResourceTemplatesResult {
1794 pub resource_templates: Vec<ResourceTemplate>,
1796 #[serde(skip_serializing_if = "Option::is_none")]
1798 pub next_cursor: Option<String>,
1799 #[serde(skip_serializing_if = "Option::is_none")]
1801 pub _meta: Option<serde_json::Value>,
1802}
1803
1804impl ListResourceTemplatesResult {
1805 pub fn new(templates: Vec<ResourceTemplate>) -> Self {
1807 Self {
1808 resource_templates: templates,
1809 next_cursor: None,
1810 _meta: None,
1811 }
1812 }
1813
1814 pub fn paginated(templates: Vec<ResourceTemplate>, next_cursor: String) -> Self {
1816 Self {
1817 resource_templates: templates,
1818 next_cursor: Some(next_cursor),
1819 _meta: None,
1820 }
1821 }
1822
1823 pub fn with_meta(mut self, meta: serde_json::Value) -> Self {
1825 self._meta = Some(meta);
1826 self
1827 }
1828}
1829
1830#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
1836pub struct PingParams {
1837 #[serde(skip_serializing_if = "Option::is_none")]
1839 pub _meta: Option<serde_json::Value>,
1840}
1841
1842impl PingParams {
1843 pub fn new() -> Self {
1845 Self { _meta: None }
1846 }
1847
1848 pub fn with_meta(mut self, meta: serde_json::Value) -> Self {
1850 self._meta = Some(meta);
1851 self
1852 }
1853}
1854
1855#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1857pub struct PingRequest {
1858 pub method: String,
1860 #[serde(skip_serializing_if = "Option::is_none")]
1862 pub params: Option<PingParams>,
1863}
1864
1865impl PingRequest {
1866 pub fn new() -> Self {
1868 Self {
1869 method: "ping".to_string(),
1870 params: None,
1871 }
1872 }
1873
1874 pub fn with_meta(meta: serde_json::Value) -> Self {
1876 Self {
1877 method: "ping".to_string(),
1878 params: Some(PingParams::new().with_meta(meta)),
1879 }
1880 }
1881}
1882
1883impl Default for PingRequest {
1884 fn default() -> Self {
1885 Self::new()
1886 }
1887}
1888
1889#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1891pub struct PingResult {
1892 #[serde(skip_serializing_if = "Option::is_none")]
1894 pub _meta: Option<serde_json::Value>,
1895}
1896
1897impl PingResult {
1898 pub fn new() -> Self {
1900 Self { _meta: None }
1901 }
1902
1903 pub fn with_meta(meta: serde_json::Value) -> Self {
1905 Self { _meta: Some(meta) }
1906 }
1907}
1908
1909impl Default for PingResult {
1910 fn default() -> Self {
1911 Self::new()
1912 }
1913}
1914
1915#[derive(Debug, Clone, Serialize, Deserialize)]
1921pub struct Root {
1922 pub uri: Uri,
1924 #[serde(skip_serializing_if = "Option::is_none")]
1926 pub name: Option<String>,
1927}
1928
1929#[derive(Debug, Clone, Serialize, Deserialize)]
1931pub struct ListRootsRequest;
1932
1933#[derive(Debug, Clone, Serialize, Deserialize)]
1935pub struct ListRootsResult {
1936 pub roots: Vec<Root>,
1938}
1939
1940#[derive(Debug, Clone, Serialize, Deserialize)]
1942pub struct RootsListChangedNotification;
1943
1944#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1946pub struct EmptyResult {}
1947
1948#[cfg(test)]
1949mod tests {
1950 use super::*;
1951
1952 #[test]
1953 fn test_serialize_deserialize() {
1954 let tool = Tool {
1955 name: "test_tool".to_string(),
1956 title: Some("Test Tool".to_string()),
1957 description: Some("A test tool".to_string()),
1958 input_schema: ToolInputSchema {
1959 schema_type: "object".to_string(),
1960 properties: None,
1961 required: None,
1962 additional_properties: None,
1963 },
1964 output_schema: None,
1965 annotations: None,
1966 meta: None,
1967 };
1968
1969 let json = serde_json::to_string(&tool).unwrap();
1970 let deserialized: Tool = serde_json::from_str(&json).unwrap();
1971 assert_eq!(tool.name, deserialized.name);
1972 }
1973
1974 #[test]
1975 fn test_content_types() {
1976 let text_content = ContentBlock::Text(TextContent {
1977 text: "Hello, World!".to_string(),
1978 annotations: None,
1979 meta: None,
1980 });
1981
1982 let json = serde_json::to_string(&text_content).unwrap();
1983 let _deserialized: ContentBlock = serde_json::from_str(&json).unwrap();
1984
1985 let _compatible: Content = text_content;
1987 }
1988
1989 #[test]
1990 fn test_elicitation_schema_builder() {
1991 let schema = ElicitationSchema::new()
1992 .add_string_property("username", true, Some("Your username".to_string()))
1993 .add_number_property(
1994 "age",
1995 false,
1996 Some("Your age".to_string()),
1997 Some(0.0),
1998 Some(150.0),
1999 )
2000 .add_boolean_property(
2001 "subscribe",
2002 true,
2003 Some("Subscribe to newsletter".to_string()),
2004 Some(false),
2005 )
2006 .add_enum_property(
2007 "role",
2008 true,
2009 Some("Your role".to_string()),
2010 vec!["admin".to_string(), "user".to_string(), "guest".to_string()],
2011 None,
2012 );
2013
2014 assert_eq!(schema.schema_type, "object");
2015 assert_eq!(schema.properties.len(), 4);
2016 assert_eq!(schema.required.as_ref().unwrap().len(), 3);
2017
2018 let username_prop = &schema.properties["username"];
2020 match username_prop {
2021 PrimitiveSchemaDefinition::String { description, .. } => {
2022 assert_eq!(description.as_ref().unwrap(), "Your username");
2023 }
2024 _ => panic!("Expected string property"),
2025 }
2026
2027 let age_prop = &schema.properties["age"];
2029 match age_prop {
2030 PrimitiveSchemaDefinition::Number {
2031 minimum, maximum, ..
2032 } => {
2033 assert_eq!(*minimum, Some(0.0));
2034 assert_eq!(*maximum, Some(150.0));
2035 }
2036 _ => panic!("Expected number property"),
2037 }
2038 }
2039
2040 #[test]
2041 fn test_elicit_request_serialization() {
2042 let schema = ElicitationSchema::new()
2043 .add_string_property("name", true, Some("Your name".to_string()))
2044 .add_boolean_property("confirm", true, None, Some(false));
2045
2046 let request = ElicitRequest::new("Please provide your details", schema);
2047
2048 let json = serde_json::to_string(&request).unwrap();
2050
2051 assert!(json.contains("elicitation/create"));
2053 assert!(json.contains("Please provide your details"));
2054 assert!(json.contains("requestedSchema"));
2055
2056 let deserialized: ElicitRequest = serde_json::from_str(&json).unwrap();
2058 assert_eq!(deserialized.method, "elicitation/create");
2059 assert_eq!(deserialized.params.message, "Please provide your details");
2060 }
2061
2062 #[test]
2063 fn test_elicit_result_actions() {
2064 let mut content = std::collections::HashMap::new();
2066 content.insert(
2067 "name".to_string(),
2068 serde_json::Value::String("John".to_string()),
2069 );
2070 content.insert(
2071 "age".to_string(),
2072 serde_json::Value::Number(serde_json::Number::from(30)),
2073 );
2074
2075 let accept_result = ElicitResult::accept(content);
2076 assert_eq!(accept_result.action, ElicitationAction::Accept);
2077 assert!(accept_result.content.is_some());
2078
2079 let decline_result = ElicitResult::decline();
2081 assert_eq!(decline_result.action, ElicitationAction::Decline);
2082 assert!(decline_result.content.is_none());
2083
2084 let cancel_result = ElicitResult::cancel();
2086 assert_eq!(cancel_result.action, ElicitationAction::Cancel);
2087 assert!(cancel_result.content.is_none());
2088 }
2089
2090 #[test]
2091 fn test_elicit_result_serialization_compliance() {
2092 let mut content = std::collections::HashMap::new();
2094 content.insert(
2095 "field1".to_string(),
2096 serde_json::Value::String("value1".to_string()),
2097 );
2098
2099 let result = ElicitResult::accept(content);
2100 let json = serde_json::to_string(&result).unwrap();
2101
2102 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2104
2105 assert_eq!(parsed["action"].as_str().unwrap(), "accept");
2107
2108 assert!(parsed["content"].is_object());
2110 assert_eq!(parsed["content"]["field1"].as_str().unwrap(), "value1");
2111 }
2112
2113 #[test]
2114 fn test_primitive_schema_serialization() {
2115 let string_schema = PrimitiveSchemaDefinition::String {
2117 title: Some("Title".to_string()),
2118 description: Some("Description".to_string()),
2119 format: Some("email".to_string()),
2120 min_length: Some(1),
2121 max_length: Some(100),
2122 enum_values: None,
2123 enum_names: None,
2124 };
2125
2126 let json = serde_json::to_string(&string_schema).unwrap();
2127 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2128
2129 assert_eq!(parsed["type"].as_str().unwrap(), "string");
2130 assert_eq!(parsed["format"].as_str().unwrap(), "email");
2131 assert_eq!(parsed["minLength"].as_u64().unwrap(), 1);
2132 assert_eq!(parsed["maxLength"].as_u64().unwrap(), 100);
2133
2134 let enum_schema = PrimitiveSchemaDefinition::String {
2136 title: None,
2137 description: Some("Select option".to_string()),
2138 format: None,
2139 min_length: None,
2140 max_length: None,
2141 enum_values: Some(vec!["option1".to_string(), "option2".to_string()]),
2142 enum_names: Some(vec!["Option 1".to_string(), "Option 2".to_string()]),
2143 };
2144
2145 let enum_json = serde_json::to_string(&enum_schema).unwrap();
2146 let enum_parsed: serde_json::Value = serde_json::from_str(&enum_json).unwrap();
2147
2148 assert_eq!(enum_parsed["type"].as_str().unwrap(), "string");
2149 assert_eq!(enum_parsed["enum"].as_array().unwrap().len(), 2);
2150 assert_eq!(enum_parsed["enumNames"].as_array().unwrap().len(), 2);
2151 }
2152
2153 #[test]
2154 fn test_server_request_with_elicitation() {
2155 let schema = ElicitationSchema::new().add_string_property(
2156 "email",
2157 true,
2158 Some("Your email address".to_string()),
2159 );
2160
2161 let request_params = ElicitRequestParams {
2162 message: "Please provide your email".to_string(),
2163 requested_schema: schema,
2164 };
2165
2166 let server_request = ServerRequest::ElicitationCreate(request_params);
2167
2168 let json = serde_json::to_string(&server_request).unwrap();
2170 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2171
2172 assert_eq!(parsed["method"].as_str().unwrap(), "elicitation/create");
2173 assert!(parsed["message"].is_string());
2174 assert!(parsed["requestedSchema"].is_object());
2175 }
2176
2177 #[test]
2178 fn test_completion_request_serialization() {
2179 let argument = ArgumentInfo {
2180 name: "file_path".to_string(),
2181 value: "/home/user/doc".to_string(),
2182 };
2183
2184 let reference = CompletionReference::ResourceTemplate(ResourceTemplateReferenceData {
2185 uri: "/files/{path}".to_string(),
2186 });
2187
2188 let request = CompleteRequest::new(argument, reference);
2189
2190 let json = serde_json::to_string(&request).unwrap();
2192 assert!(json.contains("completion/complete"));
2193 assert!(json.contains("file_path"));
2194 assert!(json.contains("/home/user/doc"));
2195
2196 let deserialized: CompleteRequest = serde_json::from_str(&json).unwrap();
2198 assert_eq!(deserialized.method, "completion/complete");
2199 assert_eq!(deserialized.params.argument.name, "file_path");
2200 }
2201
2202 #[test]
2203 fn test_completion_reference_types() {
2204 let prompt_ref = CompletionReference::Prompt(PromptReferenceData {
2206 name: "code_review".to_string(),
2207 title: Some("Code Review Assistant".to_string()),
2208 });
2209
2210 let json = serde_json::to_string(&prompt_ref).unwrap();
2211 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2212 assert_eq!(parsed["type"].as_str().unwrap(), "ref/prompt");
2213 assert_eq!(parsed["name"].as_str().unwrap(), "code_review");
2214
2215 let resource_ref = CompletionReference::ResourceTemplate(ResourceTemplateReferenceData {
2217 uri: "/api/{endpoint}".to_string(),
2218 });
2219
2220 let json = serde_json::to_string(&resource_ref).unwrap();
2221 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2222 assert_eq!(parsed["type"].as_str().unwrap(), "ref/resource");
2223 assert_eq!(parsed["uri"].as_str().unwrap(), "/api/{endpoint}");
2224 }
2225
2226 #[test]
2227 fn test_completion_response_with_pagination() {
2228 let simple =
2230 CompletionResponse::new(vec!["file1.txt".to_string(), "file2.txt".to_string()]);
2231 assert_eq!(simple.values.len(), 2);
2232 assert!(simple.total.is_none());
2233
2234 let paginated = CompletionResponse::paginated(
2236 vec!["item1".to_string(), "item2".to_string()],
2237 100,
2238 true,
2239 );
2240 assert_eq!(paginated.values.len(), 2);
2241 assert_eq!(paginated.total, Some(100));
2242 assert_eq!(paginated.has_more, Some(true));
2243
2244 let json = serde_json::to_string(&paginated).unwrap();
2246 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2247 assert_eq!(parsed["total"].as_u64().unwrap(), 100);
2248 assert!(parsed["hasMore"].as_bool().unwrap());
2249 assert_eq!(parsed["values"].as_array().unwrap().len(), 2);
2250 }
2251
2252 #[test]
2253 fn test_complete_result_structure() {
2254 let completion = CompletionResponse::paginated(
2255 vec!["option1".to_string(), "option2".to_string()],
2256 50,
2257 false,
2258 );
2259
2260 let result = CompleteResult::new(completion);
2261
2262 let json = serde_json::to_string(&result).unwrap();
2264 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2265
2266 assert!(parsed["completion"].is_object());
2268 assert!(parsed["completion"]["values"].is_array());
2269 assert_eq!(parsed["completion"]["total"].as_u64().unwrap(), 50);
2270 assert!(!parsed["completion"]["hasMore"].as_bool().unwrap());
2271
2272 let deserialized: CompleteResult = serde_json::from_str(&json).unwrap();
2274 assert_eq!(deserialized.completion.values.len(), 2);
2275 assert_eq!(deserialized.completion.total, Some(50));
2276 }
2277
2278 #[test]
2279 fn test_completion_context() {
2280 let mut context_args = std::collections::HashMap::new();
2281 context_args.insert("user_id".to_string(), "12345".to_string());
2282 context_args.insert("project".to_string(), "main".to_string());
2283
2284 let context = CompletionContext {
2285 arguments: Some(context_args),
2286 };
2287
2288 let argument = ArgumentInfo {
2289 name: "endpoint".to_string(),
2290 value: "api".to_string(),
2291 };
2292
2293 let reference = CompletionReference::ResourceTemplate(ResourceTemplateReferenceData {
2294 uri: "/projects/{project}/endpoints/{endpoint}".to_string(),
2295 });
2296
2297 let request = CompleteRequest::new(argument, reference).with_context(context);
2298
2299 let json = serde_json::to_string(&request).unwrap();
2301 assert!(json.contains("user_id"));
2302 assert!(json.contains("12345"));
2303 assert!(json.contains("project"));
2304 assert!(json.contains("main"));
2305 }
2306
2307 #[test]
2308 fn test_client_request_with_completion() {
2309 let argument = ArgumentInfo {
2310 name: "query".to_string(),
2311 value: "hello".to_string(),
2312 };
2313
2314 let reference = CompletionReference::Prompt(PromptReferenceData {
2315 name: "greeting".to_string(),
2316 title: None,
2317 });
2318
2319 let complete_params = CompleteRequestParams {
2320 argument,
2321 reference,
2322 context: None,
2323 };
2324
2325 let client_request = ClientRequest::Complete(complete_params);
2326
2327 let json = serde_json::to_string(&client_request).unwrap();
2329 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2330
2331 assert_eq!(parsed["method"].as_str().unwrap(), "completion/complete");
2332 assert_eq!(parsed["argument"]["name"].as_str().unwrap(), "query");
2333 assert_eq!(parsed["ref"]["type"].as_str().unwrap(), "ref/prompt");
2334 }
2335
2336 #[test]
2337 fn test_resource_template_creation() {
2338 let template = ResourceTemplate::new("file_access", "/files/{path}");
2340 assert_eq!(template.name, "file_access");
2341 assert_eq!(template.uri_template, "/files/{path}");
2342
2343 let enhanced_template = ResourceTemplate::new("api_access", "/api/{endpoint}")
2345 .with_title("API Access")
2346 .with_description("Access to REST API endpoints")
2347 .with_mime_type("application/json");
2348
2349 assert_eq!(enhanced_template.title, Some("API Access".to_string()));
2350 assert_eq!(
2351 enhanced_template.description,
2352 Some("Access to REST API endpoints".to_string())
2353 );
2354 assert_eq!(
2355 enhanced_template.mime_type,
2356 Some("application/json".to_string())
2357 );
2358 }
2359
2360 #[test]
2361 fn test_resource_template_presets() {
2362 let fs_template = ResourceTemplate::file_system("files", "/home/user");
2364 assert_eq!(fs_template.name, "files");
2365 assert_eq!(fs_template.uri_template, "file:///home/user/{path}");
2366 assert_eq!(fs_template.title, Some("File System Access".to_string()));
2367
2368 let api_template = ResourceTemplate::api_endpoint("api", "https://api.example.com");
2370 assert_eq!(
2371 api_template.uri_template,
2372 "https://api.example.com/{endpoint}"
2373 );
2374 assert_eq!(api_template.mime_type, Some("application/json".to_string()));
2375
2376 let db_template = ResourceTemplate::database_query("queries");
2378 assert_eq!(db_template.uri_template, "db://query/{table}?{query*}");
2379 assert_eq!(db_template.title, Some("Database Query".to_string()));
2380 }
2381
2382 #[test]
2383 fn test_resource_template_serialization() {
2384 let template = ResourceTemplate::new("test_template", "/test/{id}")
2385 .with_title("Test Template")
2386 .with_description("A template for testing")
2387 .with_mime_type("text/plain");
2388
2389 let json = serde_json::to_string(&template).unwrap();
2390 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2391
2392 assert_eq!(parsed["name"].as_str().unwrap(), "test_template");
2393 assert_eq!(parsed["uriTemplate"].as_str().unwrap(), "/test/{id}");
2394 assert_eq!(parsed["title"].as_str().unwrap(), "Test Template");
2395 assert_eq!(
2396 parsed["description"].as_str().unwrap(),
2397 "A template for testing"
2398 );
2399 assert_eq!(parsed["mimeType"].as_str().unwrap(), "text/plain");
2400
2401 let deserialized: ResourceTemplate = serde_json::from_str(&json).unwrap();
2403 assert_eq!(deserialized.name, "test_template");
2404 assert_eq!(deserialized.uri_template, "/test/{id}");
2405 }
2406
2407 #[test]
2408 fn test_list_resource_templates_request() {
2409 let request = ListResourceTemplatesRequest::new();
2411 assert!(request.params.is_none());
2412
2413 let paginated_request = ListResourceTemplatesRequest::with_cursor("cursor123");
2415 assert!(paginated_request.params.is_some());
2416 assert_eq!(
2417 paginated_request.params.unwrap().cursor,
2418 Some("cursor123".to_string())
2419 );
2420
2421 let json = serde_json::to_string(&request).unwrap();
2423 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2424
2425 assert!(parsed.as_object().unwrap().is_empty());
2427 }
2428
2429 #[test]
2430 fn test_list_resource_templates_result() {
2431 let templates = vec![
2432 ResourceTemplate::new("template1", "/api/{endpoint}"),
2433 ResourceTemplate::new("template2", "/files/{path}"),
2434 ];
2435
2436 let result = ListResourceTemplatesResult::new(templates.clone());
2438 assert_eq!(result.resource_templates.len(), 2);
2439 assert!(result.next_cursor.is_none());
2440
2441 let paginated_result =
2443 ListResourceTemplatesResult::paginated(templates, "next_cursor".to_string());
2444 assert_eq!(paginated_result.resource_templates.len(), 2);
2445 assert_eq!(
2446 paginated_result.next_cursor,
2447 Some("next_cursor".to_string())
2448 );
2449
2450 let json = serde_json::to_string(&paginated_result).unwrap();
2452 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2453
2454 assert!(parsed["resourceTemplates"].is_array());
2455 assert_eq!(parsed["resourceTemplates"].as_array().unwrap().len(), 2);
2456 assert_eq!(parsed["nextCursor"].as_str().unwrap(), "next_cursor");
2457
2458 let deserialized: ListResourceTemplatesResult = serde_json::from_str(&json).unwrap();
2460 assert_eq!(deserialized.resource_templates.len(), 2);
2461 assert_eq!(deserialized.next_cursor, Some("next_cursor".to_string()));
2462 }
2463
2464 #[test]
2465 fn test_client_request_with_resource_templates() {
2466 let request = ListResourceTemplatesRequest::with_cursor("abc123");
2467 let client_request = ClientRequest::ListResourceTemplates(request);
2468
2469 let json = serde_json::to_string(&client_request).unwrap();
2471 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2472
2473 assert_eq!(
2474 parsed["method"].as_str().unwrap(),
2475 "resources/templates/list"
2476 );
2477 assert_eq!(parsed["params"]["cursor"].as_str().unwrap(), "abc123");
2478 }
2479
2480 #[test]
2481 fn test_complex_uri_templates() {
2482 let complex_templates = vec![
2484 ResourceTemplate::new(
2485 "github",
2486 "https://api.github.com/repos/{owner}/{repo}/contents/{+path}",
2487 ),
2488 ResourceTemplate::new("search", "/search{?q,type,sort,order}"),
2489 ResourceTemplate::new("matrix", "/matrix{;x,y}/data"),
2490 ResourceTemplate::new("fragment", "/documents/{id}{#section}"),
2491 ];
2492
2493 for template in complex_templates {
2494 let json = serde_json::to_string(&template).unwrap();
2495 let deserialized: ResourceTemplate = serde_json::from_str(&json).unwrap();
2496 assert_eq!(template.uri_template, deserialized.uri_template);
2497 }
2498 }
2499
2500 #[test]
2501 fn test_resource_template_with_annotations() {
2502 let annotations = Annotations {
2503 priority: Some(1.0),
2504 ..Default::default()
2505 };
2506
2507 let template =
2508 ResourceTemplate::new("important", "/critical/{id}").with_annotations(annotations);
2509
2510 assert!(template.annotations.is_some());
2511 assert_eq!(template.annotations.unwrap().priority, Some(1.0));
2512 }
2513
2514 #[test]
2515 fn test_ping_request_creation() {
2516 let ping = PingRequest::new();
2518 assert_eq!(ping.method, "ping");
2519 assert!(ping.params.is_none());
2520
2521 let meta_value = serde_json::json!({"timestamp": "2025-08-29T12:00:00Z"});
2523 let ping_with_meta = PingRequest::with_meta(meta_value.clone());
2524 assert_eq!(ping_with_meta.method, "ping");
2525 assert!(ping_with_meta.params.is_some());
2526 assert_eq!(ping_with_meta.params.unwrap()._meta, Some(meta_value));
2527 }
2528
2529 #[test]
2530 fn test_ping_serialization() {
2531 let ping = PingRequest::new();
2533 let json = serde_json::to_string(&ping).unwrap();
2534 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2535 assert_eq!(parsed["method"].as_str().unwrap(), "ping");
2536
2537 let deserialized: PingRequest = serde_json::from_str(&json).unwrap();
2539 assert_eq!(deserialized.method, "ping");
2540
2541 let meta_value = serde_json::json!({"client": "test", "version": "1.0"});
2543 let ping_with_meta = PingRequest::with_meta(meta_value.clone());
2544 let json_with_meta = serde_json::to_string(&ping_with_meta).unwrap();
2545 let parsed_meta: serde_json::Value = serde_json::from_str(&json_with_meta).unwrap();
2546
2547 assert!(parsed_meta["params"].is_object());
2548 assert_eq!(
2549 parsed_meta["params"]["_meta"]["client"].as_str().unwrap(),
2550 "test"
2551 );
2552 }
2553
2554 #[test]
2555 fn test_ping_result() {
2556 let result = PingResult::new();
2558 assert!(result._meta.is_none());
2559
2560 let meta = serde_json::json!({"latency_ms": 42});
2562 let result_with_meta = PingResult::with_meta(meta.clone());
2563 assert_eq!(result_with_meta._meta, Some(meta));
2564
2565 let json = serde_json::to_string(&result).unwrap();
2567 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2568 assert!(parsed.as_object().unwrap().is_empty());
2570
2571 let deserialized: PingResult = serde_json::from_str(&json).unwrap();
2573 assert!(deserialized._meta.is_none());
2574 }
2575
2576 #[test]
2577 fn test_ping_params() {
2578 let params = PingParams::new();
2580 assert!(params._meta.is_none());
2581
2582 let meta = serde_json::json!({"timeout": 5000});
2584 let params_with_meta = PingParams::new().with_meta(meta.clone());
2585 assert_eq!(params_with_meta._meta, Some(meta));
2586
2587 let json = serde_json::to_string(¶ms).unwrap();
2589 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2590 assert!(parsed.as_object().unwrap().is_empty());
2591 }
2592
2593 #[test]
2594 fn test_server_request_with_ping() {
2595 let ping_params = PingParams::new();
2596 let server_request = ServerRequest::Ping(ping_params);
2597
2598 let json = serde_json::to_string(&server_request).unwrap();
2600 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2601
2602 assert_eq!(parsed["method"].as_str().unwrap(), "ping");
2603 }
2604
2605 #[test]
2606 fn test_client_request_with_ping() {
2607 let ping_params = PingParams::new();
2608 let client_request = ClientRequest::Ping(ping_params);
2609
2610 let json = serde_json::to_string(&client_request).unwrap();
2612 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2613
2614 assert_eq!(parsed["method"].as_str().unwrap(), "ping");
2615 }
2616
2617 #[test]
2618 fn test_ping_protocol_bidirectional() {
2619 let meta = serde_json::json!({"source": "test"});
2621
2622 let client_ping = ClientRequest::Ping(PingParams::new().with_meta(meta.clone()));
2624 let client_json = serde_json::to_string(&client_ping).unwrap();
2625
2626 let server_ping = ServerRequest::Ping(PingParams::new().with_meta(meta.clone()));
2628 let server_json = serde_json::to_string(&server_ping).unwrap();
2629
2630 let client_parsed: serde_json::Value = serde_json::from_str(&client_json).unwrap();
2632 let server_parsed: serde_json::Value = serde_json::from_str(&server_json).unwrap();
2633
2634 assert_eq!(client_parsed["method"], server_parsed["method"]);
2635 assert_eq!(
2636 client_parsed["_meta"]["source"],
2637 server_parsed["_meta"]["source"]
2638 );
2639 }
2640}