1use crate::Error;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6use std::sync::Arc;
7
8pub mod mime_types {
10 pub const HTML_MCP: &str = "text/html+mcp";
12
13 pub const HTML: &str = "text/html";
15
16 pub const JSON: &str = "application/json";
18
19 pub const TEXT: &str = "text/plain";
21
22 pub const OCTET_STREAM: &str = "application/octet-stream";
24}
25
26pub mod uri_schemes {
28 pub const UI: &str = "ui://";
30
31 pub const FILE: &str = "file://";
33
34 pub const HTTP: &str = "http://";
36
37 pub const HTTPS: &str = "https://";
39}
40
41#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct Meta {
44 #[serde(rename = "progressToken", skip_serializing_if = "Option::is_none")]
46 pub progress_token: Option<String>,
47}
48
49#[derive(Debug, Clone, Eq, PartialEq, Hash)]
51pub enum NumberOrString {
52 Number(i64),
53 String(Arc<str>),
54}
55
56impl NumberOrString {
57 pub fn into_json_value(self) -> serde_json::Value {
58 match self {
59 NumberOrString::Number(n) => serde_json::Value::Number(serde_json::Number::from(n)),
60 NumberOrString::String(s) => serde_json::Value::String(s.to_string()),
61 }
62 }
63
64 pub fn from_json_value(value: serde_json::Value) -> Option<Self> {
65 match value {
66 serde_json::Value::Number(n) => n.as_i64().map(NumberOrString::Number),
67 serde_json::Value::String(s) => Some(NumberOrString::String(Arc::from(s.as_str()))),
68 _ => None,
69 }
70 }
71}
72
73impl std::fmt::Display for NumberOrString {
74 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75 match self {
76 NumberOrString::Number(n) => write!(f, "{n}"),
77 NumberOrString::String(s) => write!(f, "{s}"),
78 }
79 }
80}
81
82impl Serialize for NumberOrString {
83 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
84 where
85 S: serde::Serializer,
86 {
87 match self {
88 NumberOrString::Number(n) => serializer.serialize_i64(*n),
89 NumberOrString::String(s) => serializer.serialize_str(s),
90 }
91 }
92}
93
94impl<'de> Deserialize<'de> for NumberOrString {
95 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
96 where
97 D: serde::Deserializer<'de>,
98 {
99 struct NumberOrStringVisitor;
100
101 impl<'de> serde::de::Visitor<'de> for NumberOrStringVisitor {
102 type Value = NumberOrString;
103
104 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
105 formatter.write_str("a number or string")
106 }
107
108 fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
109 where
110 E: serde::de::Error,
111 {
112 Ok(NumberOrString::Number(value))
113 }
114
115 fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
116 where
117 E: serde::de::Error,
118 {
119 Ok(NumberOrString::Number(value as i64))
120 }
121
122 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
123 where
124 E: serde::de::Error,
125 {
126 Ok(NumberOrString::String(Arc::from(value)))
127 }
128
129 fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
130 where
131 E: serde::de::Error,
132 {
133 Ok(NumberOrString::String(Arc::from(value.as_str())))
134 }
135 }
136
137 deserializer.deserialize_any(NumberOrStringVisitor)
138 }
139}
140
141#[derive(Debug, Clone, Serialize, Deserialize)]
143pub struct Request {
144 pub jsonrpc: String,
146 pub method: String,
148 #[serde(default = "serde_json::Value::default")]
150 pub params: serde_json::Value,
151 #[serde(skip_serializing_if = "Option::is_none")]
153 pub id: Option<NumberOrString>,
154}
155
156#[derive(Debug, Clone, Serialize, Deserialize)]
158pub struct Response {
159 pub jsonrpc: String,
161 #[serde(skip_serializing_if = "Option::is_none")]
163 pub result: Option<serde_json::Value>,
164 #[serde(skip_serializing_if = "Option::is_none")]
166 pub error: Option<Error>,
167 #[serde(skip_serializing_if = "Option::is_none")]
169 pub id: Option<NumberOrString>,
170}
171
172#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Serialize, Deserialize)]
174pub struct ProtocolVersion(std::borrow::Cow<'static, str>);
175
176impl Default for ProtocolVersion {
177 fn default() -> Self {
178 Self::LATEST
179 }
180}
181
182impl std::fmt::Display for ProtocolVersion {
183 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
184 self.0.fmt(f)
185 }
186}
187
188impl ProtocolVersion {
189 pub const V_2025_11_25: Self = Self(std::borrow::Cow::Borrowed("2025-11-25"));
190 pub const V_2025_06_18: Self = Self(std::borrow::Cow::Borrowed("2025-06-18"));
191 pub const V_2025_03_26: Self = Self(std::borrow::Cow::Borrowed("2025-03-26"));
192 pub const V_2024_11_05: Self = Self(std::borrow::Cow::Borrowed("2024-11-05"));
193 pub const LATEST: Self = Self::V_2025_11_25;
194
195 pub fn new(version: impl Into<std::borrow::Cow<'static, str>>) -> Self {
196 Self(version.into())
197 }
198}
199
200#[derive(Debug, Clone, Serialize, Deserialize)]
202pub struct Implementation {
203 pub name: String,
204 pub version: String,
205 #[serde(skip_serializing_if = "Option::is_none")]
207 #[serde(default)]
208 pub description: Option<String>,
209}
210
211impl Implementation {
212 pub fn new(name: impl Into<String>, version: impl Into<String>) -> Self {
214 Self {
215 name: name.into(),
216 version: version.into(),
217 description: None,
218 }
219 }
220
221 pub fn with_description(
223 name: impl Into<String>,
224 version: impl Into<String>,
225 description: impl Into<String>,
226 ) -> Self {
227 Self {
228 name: name.into(),
229 version: version.into(),
230 description: Some(description.into()),
231 }
232 }
233}
234
235#[derive(Debug, Clone, Serialize, Deserialize, Default)]
237pub struct ServerCapabilities {
238 #[serde(skip_serializing_if = "Option::is_none")]
239 pub tools: Option<ToolsCapability>,
240 #[serde(skip_serializing_if = "Option::is_none")]
241 pub resources: Option<ResourcesCapability>,
242 #[serde(skip_serializing_if = "Option::is_none")]
243 pub prompts: Option<PromptsCapability>,
244 #[serde(skip_serializing_if = "Option::is_none")]
245 pub logging: Option<LoggingCapability>,
246 #[serde(skip_serializing_if = "Option::is_none")]
247 pub sampling: Option<SamplingCapability>,
248 #[serde(skip_serializing_if = "Option::is_none")]
249 pub elicitation: Option<ElicitationCapability>,
250 #[serde(skip_serializing_if = "Option::is_none")]
252 pub tasks: Option<TasksCapability>,
253}
254
255#[derive(Debug, Clone, Serialize, Deserialize, Default)]
256pub struct ToolsCapability {
257 #[serde(skip_serializing_if = "Option::is_none")]
258 pub list_changed: Option<bool>,
259}
260
261#[derive(Debug, Clone, Serialize, Deserialize, Default)]
262pub struct ResourcesCapability {
263 #[serde(skip_serializing_if = "Option::is_none")]
264 pub subscribe: Option<bool>,
265 #[serde(skip_serializing_if = "Option::is_none")]
266 pub list_changed: Option<bool>,
267}
268
269#[derive(Debug, Clone, Serialize, Deserialize, Default)]
270pub struct PromptsCapability {
271 #[serde(skip_serializing_if = "Option::is_none")]
272 pub list_changed: Option<bool>,
273}
274
275#[derive(Debug, Clone, Serialize, Deserialize, Default)]
276pub struct LoggingCapability {
277 #[serde(skip_serializing_if = "Option::is_none")]
278 pub level: Option<String>,
279}
280
281#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
283#[serde(rename_all = "lowercase")]
284pub enum LogLevel {
285 Emergency,
286 Alert,
287 Critical,
288 Error,
289 Warning,
290 Notice,
291 Info,
292 Debug,
293}
294
295impl LogLevel {
296 pub fn as_str(&self) -> &'static str {
297 match self {
298 LogLevel::Emergency => "emergency",
299 LogLevel::Alert => "alert",
300 LogLevel::Critical => "critical",
301 LogLevel::Error => "error",
302 LogLevel::Warning => "warning",
303 LogLevel::Notice => "notice",
304 LogLevel::Info => "info",
305 LogLevel::Debug => "debug",
306 }
307 }
308}
309
310impl std::str::FromStr for LogLevel {
311 type Err = String;
312
313 fn from_str(s: &str) -> Result<Self, Self::Err> {
314 match s.to_lowercase().as_str() {
315 "emergency" => Ok(LogLevel::Emergency),
316 "alert" => Ok(LogLevel::Alert),
317 "critical" => Ok(LogLevel::Critical),
318 "error" => Ok(LogLevel::Error),
319 "warning" => Ok(LogLevel::Warning),
320 "notice" => Ok(LogLevel::Notice),
321 "info" => Ok(LogLevel::Info),
322 "debug" => Ok(LogLevel::Debug),
323 _ => Err(format!("Invalid log level: {s}")),
324 }
325 }
326}
327
328impl std::fmt::Display for LogLevel {
329 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
330 write!(f, "{}", self.as_str())
331 }
332}
333
334#[derive(Debug, Clone, Serialize, Deserialize, Default)]
336pub struct SamplingCapability {
337 #[serde(skip_serializing_if = "Option::is_none")]
339 pub tools: Option<SamplingToolsCapability>,
340 #[serde(skip_serializing_if = "Option::is_none")]
342 pub context: Option<SamplingContextCapability>,
343}
344
345#[derive(Debug, Clone, Serialize, Deserialize, Default)]
347pub struct SamplingToolsCapability {}
348
349#[derive(Debug, Clone, Serialize, Deserialize, Default)]
351pub struct SamplingContextCapability {}
352
353#[derive(Debug, Clone, Serialize, Deserialize, Default)]
359pub struct ElicitationCapability {
360 #[serde(skip_serializing_if = "Option::is_none")]
362 pub form: Option<FormElicitationCapability>,
363 #[serde(skip_serializing_if = "Option::is_none")]
365 pub url: Option<UrlElicitationCapability>,
366}
367
368#[derive(Debug, Clone, Serialize, Deserialize, Default)]
370pub struct FormElicitationCapability {}
371
372#[derive(Debug, Clone, Serialize, Deserialize, Default)]
374pub struct UrlElicitationCapability {}
375
376impl ServerCapabilities {
377 pub fn builder() -> ServerCapabilitiesBuilder {
378 ServerCapabilitiesBuilder::default()
379 }
380}
381
382#[derive(Default)]
383pub struct ServerCapabilitiesBuilder {
384 capabilities: ServerCapabilities,
385}
386
387impl ServerCapabilitiesBuilder {
388 #[must_use]
389 pub fn enable_tools(mut self) -> Self {
390 self.capabilities.tools = Some(ToolsCapability {
391 list_changed: Some(true),
392 });
393 self
394 }
395
396 #[must_use]
397 pub fn enable_resources(mut self) -> Self {
398 self.capabilities.resources = Some(ResourcesCapability {
399 subscribe: Some(true),
400 list_changed: Some(true),
401 });
402 self
403 }
404
405 #[must_use]
406 pub fn enable_prompts(mut self) -> Self {
407 self.capabilities.prompts = Some(PromptsCapability {
408 list_changed: Some(true),
409 });
410 self
411 }
412
413 #[must_use]
414 pub fn enable_logging(mut self) -> Self {
415 self.capabilities.logging = Some(LoggingCapability {
416 level: Some("info".to_string()),
417 });
418 self
419 }
420
421 #[must_use]
422 pub fn enable_sampling(mut self) -> Self {
423 self.capabilities.sampling = Some(SamplingCapability::default());
424 self
425 }
426
427 #[must_use]
429 pub fn enable_sampling_with_tools(mut self) -> Self {
430 self.capabilities.sampling = Some(SamplingCapability {
431 tools: Some(SamplingToolsCapability {}),
432 context: Some(SamplingContextCapability {}),
433 });
434 self
435 }
436
437 #[must_use]
439 pub fn enable_elicitation(mut self) -> Self {
440 self.capabilities.elicitation = Some(ElicitationCapability {
441 form: Some(FormElicitationCapability {}),
442 url: None,
443 });
444 self
445 }
446
447 #[must_use]
449 pub fn enable_elicitation_modes(mut self, form: bool, url: bool) -> Self {
450 self.capabilities.elicitation = Some(ElicitationCapability {
451 form: if form {
452 Some(FormElicitationCapability {})
453 } else {
454 None
455 },
456 url: if url {
457 Some(UrlElicitationCapability {})
458 } else {
459 None
460 },
461 });
462 self
463 }
464
465 #[must_use]
467 pub fn enable_tasks(mut self) -> Self {
468 self.capabilities.tasks = Some(TasksCapability {
469 cancel: Some(TaskCancelCapability {}),
470 list: Some(TaskListCapability {}),
471 requests: Some(TaskRequestsCapability {
472 sampling: Some(TaskSamplingCapability {
473 create_message: Some(TaskMethodCapability {}),
474 }),
475 elicitation: Some(TaskElicitationCapability {
476 create: Some(TaskMethodCapability {}),
477 }),
478 tools: Some(TaskToolsCapability {
479 call: Some(TaskMethodCapability {}),
480 }),
481 }),
482 });
483 self
484 }
485
486 #[must_use]
488 pub fn enable_tasks_basic(mut self) -> Self {
489 self.capabilities.tasks = Some(TasksCapability {
490 cancel: Some(TaskCancelCapability {}),
491 list: Some(TaskListCapability {}),
492 requests: None,
493 });
494 self
495 }
496
497 pub fn build(self) -> ServerCapabilities {
498 self.capabilities
499 }
500}
501
502#[derive(Debug, Clone, Serialize, Deserialize)]
504pub struct ServerInfo {
505 pub protocol_version: ProtocolVersion,
506 pub capabilities: ServerCapabilities,
507 pub server_info: Implementation,
508 pub instructions: Option<String>,
509}
510
511#[derive(Debug, Clone, Serialize, Deserialize)]
513#[serde(rename_all = "camelCase")]
514pub struct Tool {
515 pub name: String,
516 #[serde(skip_serializing_if = "Option::is_none")]
517 pub title: Option<String>,
518 pub description: String,
519 pub input_schema: serde_json::Value,
520 #[serde(skip_serializing_if = "Option::is_none")]
521 pub output_schema: Option<serde_json::Value>,
522 #[serde(skip_serializing_if = "Option::is_none")]
523 pub annotations: Option<ToolAnnotations>,
524 #[serde(skip_serializing_if = "Option::is_none")]
525 pub icons: Option<Vec<Icon>>,
526 #[serde(skip_serializing_if = "Option::is_none")]
528 pub execution: Option<ToolExecution>,
529 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
531 pub _meta: Option<ToolMeta>,
532}
533
534#[derive(Debug, Clone, Serialize, Deserialize, Default)]
536pub struct ToolAnnotations {
537 #[serde(skip_serializing_if = "Option::is_none")]
538 pub read_only_hint: Option<bool>,
539 #[serde(skip_serializing_if = "Option::is_none")]
540 pub destructive_hint: Option<bool>,
541 #[serde(skip_serializing_if = "Option::is_none")]
542 pub idempotent_hint: Option<bool>,
543 #[serde(skip_serializing_if = "Option::is_none")]
544 pub open_world_hint: Option<bool>,
545}
546
547#[derive(Debug, Clone, Serialize, Deserialize, Default)]
552pub struct ToolMeta {
553 #[serde(rename = "ui/resourceUri", skip_serializing_if = "Option::is_none")]
561 pub ui_resource_uri: Option<String>,
562}
563
564impl ToolMeta {
565 pub fn with_ui_resource(uri: impl Into<String>) -> Self {
567 Self {
568 ui_resource_uri: Some(uri.into()),
569 }
570 }
571}
572
573#[derive(Debug, Clone, Serialize, Deserialize)]
575pub struct Icon {
576 pub uri: String,
577 #[serde(skip_serializing_if = "Option::is_none")]
578 pub mime_type: Option<String>,
579}
580
581#[derive(Debug, Clone, Serialize, Deserialize)]
583#[serde(rename_all = "camelCase")]
584pub struct ListToolsResult {
585 pub tools: Vec<Tool>,
586 #[serde(skip_serializing_if = "Option::is_none")]
587 pub next_cursor: Option<String>,
588}
589
590#[derive(Debug, Clone, Serialize, Deserialize)]
592pub struct PaginatedRequestParam {
593 pub cursor: Option<String>,
594}
595
596#[derive(Debug, Clone, Serialize, Deserialize)]
598pub struct CallToolRequestParam {
599 pub name: String,
600 pub arguments: Option<serde_json::Value>,
601}
602
603#[derive(Debug, Clone, Serialize, Deserialize)]
605#[serde(tag = "type")]
606pub enum Content {
607 #[serde(rename = "text")]
608 Text {
609 text: String,
610 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
611 _meta: Option<Meta>,
612 },
613 #[serde(rename = "image")]
614 Image {
615 data: String,
616 #[serde(rename = "mimeType")]
617 mime_type: String,
618 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
619 _meta: Option<Meta>,
620 },
621 #[serde(rename = "audio")]
623 Audio {
624 data: String,
626 #[serde(rename = "mimeType")]
628 mime_type: String,
629 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
630 _meta: Option<Meta>,
631 },
632 #[serde(rename = "resource")]
633 Resource {
634 resource: EmbeddedResourceContents,
636 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
637 _meta: Option<Meta>,
638 },
639 #[serde(rename = "tool_use")]
641 ToolUse {
642 id: String,
644 name: String,
646 input: serde_json::Value,
648 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
649 _meta: Option<Meta>,
650 },
651 #[serde(rename = "tool_result")]
653 ToolResult {
654 #[serde(rename = "toolUseId")]
656 tool_use_id: String,
657 content: Vec<ToolResultContent>,
659 #[serde(rename = "isError", skip_serializing_if = "Option::is_none")]
661 is_error: Option<bool>,
662 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
663 _meta: Option<Meta>,
664 },
665}
666
667#[derive(Debug, Clone, Serialize, Deserialize)]
669#[serde(tag = "type")]
670pub enum ToolResultContent {
671 #[serde(rename = "text")]
672 Text { text: String },
673 #[serde(rename = "image")]
674 Image {
675 data: String,
676 #[serde(rename = "mimeType")]
677 mime_type: String,
678 },
679}
680
681impl Content {
682 pub fn text(text: impl Into<String>) -> Self {
683 Self::Text {
684 text: text.into(),
685 _meta: None,
686 }
687 }
688
689 pub fn image(data: impl Into<String>, mime_type: impl Into<String>) -> Self {
690 Self::Image {
691 data: data.into(),
692 mime_type: mime_type.into(),
693 _meta: None,
694 }
695 }
696
697 pub fn audio(data: impl Into<String>, mime_type: impl Into<String>) -> Self {
699 Self::Audio {
700 data: data.into(),
701 mime_type: mime_type.into(),
702 _meta: None,
703 }
704 }
705
706 pub fn resource(
708 uri: impl Into<String>,
709 mime_type: Option<String>,
710 text: Option<String>,
711 ) -> Self {
712 Self::Resource {
713 resource: EmbeddedResourceContents {
714 uri: uri.into(),
715 mime_type,
716 text,
717 blob: None,
718 _meta: None,
719 },
720 _meta: None,
721 }
722 }
723
724 pub fn from_resource_contents(contents: ResourceContents) -> Self {
726 Self::Resource {
727 resource: contents,
728 _meta: None,
729 }
730 }
731
732 pub fn tool_use(
736 id: impl Into<String>,
737 name: impl Into<String>,
738 input: serde_json::Value,
739 ) -> Self {
740 Self::ToolUse {
741 id: id.into(),
742 name: name.into(),
743 input,
744 _meta: None,
745 }
746 }
747
748 pub fn tool_result(
752 tool_use_id: impl Into<String>,
753 content: Vec<ToolResultContent>,
754 is_error: Option<bool>,
755 ) -> Self {
756 Self::ToolResult {
757 tool_use_id: tool_use_id.into(),
758 content,
759 is_error,
760 _meta: None,
761 }
762 }
763
764 pub fn tool_result_text(tool_use_id: impl Into<String>, text: impl Into<String>) -> Self {
766 Self::tool_result(
767 tool_use_id,
768 vec![ToolResultContent::Text { text: text.into() }],
769 Some(false),
770 )
771 }
772
773 pub fn tool_result_error(
775 tool_use_id: impl Into<String>,
776 error_message: impl Into<String>,
777 ) -> Self {
778 Self::tool_result(
779 tool_use_id,
780 vec![ToolResultContent::Text {
781 text: error_message.into(),
782 }],
783 Some(true),
784 )
785 }
786
787 pub fn ui_html(uri: impl Into<String>, html: impl Into<String>) -> Self {
816 Self::resource(uri, Some("text/html".to_string()), Some(html.into()))
817 }
818
819 pub fn ui_resource(
836 uri: impl Into<String>,
837 mime_type: impl Into<String>,
838 content: impl Into<String>,
839 ) -> Self {
840 Self::resource(uri, Some(mime_type.into()), Some(content.into()))
841 }
842
843 pub fn as_text(&self) -> Option<&Self> {
845 match self {
846 Self::Text { .. } => Some(self),
847 _ => None,
848 }
849 }
850}
851
852pub struct TextContent {
854 pub text: String,
855}
856
857impl Content {
858 pub fn as_text_content(&self) -> Option<TextContent> {
860 match self {
861 Self::Text { text, .. } => Some(TextContent { text: text.clone() }),
862 _ => None,
863 }
864 }
865}
866
867#[derive(Debug, Clone, Serialize, Deserialize)]
869#[serde(rename_all = "camelCase")]
870pub struct CallToolResult {
871 pub content: Vec<Content>,
872 pub is_error: Option<bool>,
873 #[serde(skip_serializing_if = "Option::is_none")]
874 pub structured_content: Option<serde_json::Value>,
875 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
876 pub _meta: Option<Meta>,
877}
878
879impl CallToolResult {
880 pub fn success(content: Vec<Content>) -> Self {
881 Self {
882 content,
883 is_error: Some(false),
884 structured_content: None,
885 _meta: None,
886 }
887 }
888
889 pub fn error(content: Vec<Content>) -> Self {
890 Self {
891 content,
892 is_error: Some(true),
893 structured_content: None,
894 _meta: None,
895 }
896 }
897
898 pub fn text(text: impl Into<String>) -> Self {
899 Self::success(vec![Content::text(text)])
900 }
901
902 pub fn error_text(text: impl Into<String>) -> Self {
903 Self::error(vec![Content::text(text)])
904 }
905
906 pub fn input_validation_error(field: impl Into<String>, message: impl Into<String>) -> Self {
923 let error_msg = format!(
924 "Input validation error for '{}': {}",
925 field.into(),
926 message.into()
927 );
928 Self::error(vec![Content::text(error_msg)])
929 }
930
931 pub fn structured(content: Vec<Content>, structured_content: serde_json::Value) -> Self {
933 Self {
934 content,
935 is_error: Some(false),
936 structured_content: Some(structured_content),
937 _meta: None,
938 }
939 }
940
941 pub fn structured_error(content: Vec<Content>, structured_content: serde_json::Value) -> Self {
943 Self {
944 content,
945 is_error: Some(true),
946 structured_content: Some(structured_content),
947 _meta: None,
948 }
949 }
950
951 pub fn text_with_structured(
953 text: impl Into<String>,
954 structured_content: serde_json::Value,
955 ) -> Self {
956 Self::structured(vec![Content::text(text)], structured_content)
957 }
958
959 pub fn validate_structured_content(
965 &self,
966 output_schema: &serde_json::Value,
967 ) -> crate::Result<()> {
968 use crate::validation::Validator;
969
970 if let Some(structured_content) = &self.structured_content {
971 Validator::validate_structured_content(structured_content, output_schema)?;
972 }
973 Ok(())
974 }
975}
976
977#[derive(Debug, Clone, Serialize, Deserialize)]
979pub struct Resource {
980 pub uri: String,
981 pub name: String,
982 #[serde(skip_serializing_if = "Option::is_none")]
983 pub title: Option<String>,
984 pub description: Option<String>,
985 pub mime_type: Option<String>,
986 pub annotations: Option<Annotations>,
987 #[serde(skip_serializing_if = "Option::is_none")]
988 pub icons: Option<Vec<Icon>>,
989 #[serde(skip_serializing_if = "Option::is_none")]
990 pub raw: Option<RawResource>,
991 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
993 pub _meta: Option<ResourceMeta>,
994}
995
996#[derive(Debug, Clone, Serialize, Deserialize, Default)]
998pub struct ResourceMeta {
999 #[serde(rename = "ui", skip_serializing_if = "Option::is_none")]
1001 pub ui: Option<UiResourceMeta>,
1002}
1003
1004#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1006pub struct UiResourceMeta {
1007 #[serde(skip_serializing_if = "Option::is_none")]
1009 pub csp: Option<CspConfig>,
1010
1011 #[serde(skip_serializing_if = "Option::is_none")]
1013 pub domain: Option<String>,
1014
1015 #[serde(rename = "prefersBorder", skip_serializing_if = "Option::is_none")]
1017 pub prefers_border: Option<bool>,
1018}
1019
1020#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1022pub struct CspConfig {
1023 #[serde(rename = "connectDomains", skip_serializing_if = "Option::is_none")]
1025 pub connect_domains: Option<Vec<String>>,
1026
1027 #[serde(rename = "resourceDomains", skip_serializing_if = "Option::is_none")]
1029 pub resource_domains: Option<Vec<String>>,
1030}
1031
1032#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1034pub struct Annotations {
1035 pub audience: Option<Vec<String>>,
1036 pub priority: Option<f32>,
1037}
1038
1039impl Resource {
1040 pub fn ui_resource(
1057 uri: impl Into<String>,
1058 name: impl Into<String>,
1059 description: impl Into<String>,
1060 ) -> Self {
1061 Self {
1062 uri: uri.into(),
1063 name: name.into(),
1064 title: None,
1065 description: Some(description.into()),
1066 mime_type: Some(mime_types::HTML_MCP.to_string()),
1067 annotations: None,
1068 icons: None,
1069 raw: None,
1070 _meta: None,
1071 }
1072 }
1073
1074 pub fn ui_resource_with_csp(
1076 uri: impl Into<String>,
1077 name: impl Into<String>,
1078 description: impl Into<String>,
1079 csp: CspConfig,
1080 ) -> Self {
1081 Self {
1082 uri: uri.into(),
1083 name: name.into(),
1084 title: None,
1085 description: Some(description.into()),
1086 mime_type: Some(mime_types::HTML_MCP.to_string()),
1087 annotations: None,
1088 icons: None,
1089 raw: None,
1090 _meta: Some(ResourceMeta {
1091 ui: Some(UiResourceMeta {
1092 csp: Some(csp),
1093 domain: None,
1094 prefers_border: None,
1095 }),
1096 }),
1097 }
1098 }
1099
1100 pub fn is_ui_resource(&self) -> bool {
1102 self.uri.starts_with(uri_schemes::UI)
1103 }
1104
1105 pub fn uri_scheme(&self) -> Option<&str> {
1107 self.uri.split_once("://").map(|(scheme, _)| scheme)
1108 }
1109}
1110
1111impl ResourceContents {
1112 pub fn html_ui(uri: impl Into<String>, html: impl Into<String>) -> Self {
1114 Self {
1115 uri: uri.into(),
1116 mime_type: Some(mime_types::HTML_MCP.to_string()),
1117 text: Some(html.into()),
1118 blob: None,
1119 _meta: None,
1120 }
1121 }
1122
1123 pub fn json(uri: impl Into<String>, json: impl Into<String>) -> Self {
1125 Self {
1126 uri: uri.into(),
1127 mime_type: Some(mime_types::JSON.to_string()),
1128 text: Some(json.into()),
1129 blob: None,
1130 _meta: None,
1131 }
1132 }
1133
1134 pub fn text(uri: impl Into<String>, text: impl Into<String>) -> Self {
1136 Self {
1137 uri: uri.into(),
1138 mime_type: Some(mime_types::TEXT.to_string()),
1139 text: Some(text.into()),
1140 blob: None,
1141 _meta: None,
1142 }
1143 }
1144}
1145
1146#[derive(Debug, Clone, Serialize, Deserialize)]
1148pub struct ListResourcesResult {
1149 pub resources: Vec<Resource>,
1150 #[serde(skip_serializing_if = "Option::is_none")]
1151 pub next_cursor: Option<String>,
1152}
1153
1154#[derive(Debug, Clone, Serialize, Deserialize)]
1156pub struct ReadResourceRequestParam {
1157 pub uri: String,
1158}
1159
1160#[derive(Debug, Clone, Serialize, Deserialize)]
1162pub struct ResourceContents {
1163 pub uri: String,
1164 #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
1165 pub mime_type: Option<String>,
1166 #[serde(skip_serializing_if = "Option::is_none")]
1167 pub text: Option<String>,
1168 #[serde(skip_serializing_if = "Option::is_none")]
1169 pub blob: Option<String>,
1170 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1171 pub _meta: Option<Meta>,
1172}
1173
1174#[derive(Debug, Clone, Serialize, Deserialize)]
1176pub struct ReadResourceResult {
1177 pub contents: Vec<ResourceContents>,
1178}
1179
1180pub type EmbeddedResourceContents = ResourceContents;
1182
1183#[derive(Debug, Clone, Serialize, Deserialize)]
1185pub struct RawResource {
1186 pub uri: String,
1187 pub data: Vec<u8>,
1188 pub mime_type: Option<String>,
1189 pub name: Option<String>,
1190 pub description: Option<String>,
1191 pub size: Option<usize>,
1192}
1193
1194impl PromptMessage {
1195 pub fn new_text(role: PromptMessageRole, text: impl Into<String>) -> Self {
1197 Self {
1198 role,
1199 content: PromptMessageContent::Text { text: text.into() },
1200 }
1201 }
1202
1203 pub fn new_image(
1205 role: PromptMessageRole,
1206 data: impl Into<String>,
1207 mime_type: impl Into<String>,
1208 ) -> Self {
1209 Self {
1210 role,
1211 content: PromptMessageContent::Image {
1212 data: data.into(),
1213 mime_type: mime_type.into(),
1214 },
1215 }
1216 }
1217
1218 pub fn new_resource(
1220 role: PromptMessageRole,
1221 uri: impl Into<String>,
1222 mime_type: Option<String>,
1223 text: Option<String>,
1224 ) -> Self {
1225 Self {
1226 role,
1227 content: PromptMessageContent::Resource {
1228 resource: EmbeddedResourceContents {
1229 uri: uri.into(),
1230 mime_type,
1231 text,
1232 blob: None,
1233 _meta: None,
1234 },
1235 },
1236 }
1237 }
1238}
1239
1240impl CompleteResult {
1241 pub fn simple(value: impl Into<String>) -> Self {
1243 Self {
1244 completion: CompletionValues {
1245 values: vec![value.into()],
1246 total: None,
1247 has_more: Some(false),
1248 },
1249 }
1250 }
1251
1252 pub fn with_values(values: Vec<String>) -> Self {
1254 let total = values.len() as u64;
1255 Self {
1256 completion: CompletionValues {
1257 values,
1258 total: Some(total),
1259 has_more: Some(false),
1260 },
1261 }
1262 }
1263}
1264
1265#[derive(Debug, Clone, Serialize, Deserialize)]
1267pub struct Prompt {
1268 pub name: String,
1269 #[serde(skip_serializing_if = "Option::is_none")]
1270 pub title: Option<String>,
1271 #[serde(skip_serializing_if = "Option::is_none")]
1272 pub description: Option<String>,
1273 #[serde(skip_serializing_if = "Option::is_none")]
1274 pub arguments: Option<Vec<PromptArgument>>,
1275 #[serde(skip_serializing_if = "Option::is_none")]
1276 pub icons: Option<Vec<Icon>>,
1277}
1278
1279#[derive(Debug, Clone, Serialize, Deserialize)]
1281pub struct PromptArgument {
1282 pub name: String,
1283 pub description: Option<String>,
1284 pub required: Option<bool>,
1285}
1286
1287#[derive(Debug, Clone, Serialize, Deserialize)]
1289pub struct ListPromptsResult {
1290 pub prompts: Vec<Prompt>,
1291 #[serde(skip_serializing_if = "Option::is_none")]
1292 pub next_cursor: Option<String>,
1293}
1294
1295#[derive(Debug, Clone, Serialize, Deserialize)]
1297pub struct GetPromptRequestParam {
1298 pub name: String,
1299 pub arguments: Option<HashMap<String, String>>,
1300}
1301
1302#[derive(Debug, Clone, Serialize, Deserialize)]
1304#[serde(rename_all = "lowercase")]
1305pub enum PromptMessageRole {
1306 User,
1307 Assistant,
1308 System,
1309}
1310
1311#[derive(Debug, Clone, Serialize, Deserialize)]
1313#[serde(tag = "type")]
1314pub enum PromptMessageContent {
1315 #[serde(rename = "text")]
1316 Text { text: String },
1317 #[serde(rename = "image")]
1318 Image {
1319 data: String,
1320 #[serde(rename = "mimeType")]
1321 mime_type: String,
1322 },
1323 #[serde(rename = "resource")]
1325 Resource {
1326 resource: EmbeddedResourceContents,
1328 },
1329}
1330
1331#[derive(Debug, Clone, Serialize, Deserialize)]
1333pub struct PromptMessage {
1334 pub role: PromptMessageRole,
1335 pub content: PromptMessageContent,
1336}
1337
1338#[derive(Debug, Clone, Serialize, Deserialize)]
1340pub struct GetPromptResult {
1341 pub description: Option<String>,
1342 pub messages: Vec<PromptMessage>,
1343}
1344
1345#[derive(Debug, Clone, Serialize, Deserialize)]
1347pub struct InitializeRequestParam {
1348 #[serde(rename = "protocolVersion")]
1349 pub protocol_version: String,
1350 pub capabilities: serde_json::Value,
1351 #[serde(rename = "clientInfo")]
1352 pub client_info: Implementation,
1353}
1354
1355#[derive(Debug, Clone, Serialize, Deserialize)]
1357pub struct InitializeResult {
1358 #[serde(rename = "protocolVersion")]
1359 pub protocol_version: String,
1360 pub capabilities: ServerCapabilities,
1361 #[serde(rename = "serverInfo")]
1362 pub server_info: Implementation,
1363 #[serde(skip_serializing_if = "Option::is_none")]
1364 pub instructions: Option<String>,
1365}
1366
1367#[derive(Debug, Clone, Serialize, Deserialize)]
1369#[serde(rename_all = "camelCase")]
1370pub struct CompletionContext {
1371 pub argument_names: Vec<String>,
1373 pub values: HashMap<String, serde_json::Value>,
1375}
1376
1377impl CompletionContext {
1378 pub fn new(argument_names: Vec<String>, values: HashMap<String, serde_json::Value>) -> Self {
1380 Self {
1381 argument_names,
1382 values,
1383 }
1384 }
1385
1386 pub fn argument_names_iter(&self) -> impl Iterator<Item = &String> {
1388 self.argument_names.iter()
1389 }
1390}
1391
1392#[derive(Debug, Clone, Serialize, Deserialize)]
1394#[serde(tag = "type")]
1395pub enum CompletionRef {
1396 #[serde(rename = "ref/prompt")]
1398 Prompt { name: String },
1399 #[serde(rename = "ref/resource")]
1401 Resource { uri: String },
1402}
1403
1404#[derive(Debug, Clone, Serialize, Deserialize)]
1406pub struct CompletionArgument {
1407 pub name: String,
1408 pub value: String,
1409}
1410
1411#[derive(Debug, Clone, Serialize, Deserialize)]
1413pub struct CompleteRequestParam {
1414 #[serde(rename = "ref")]
1415 pub ref_: CompletionRef,
1416 pub argument: CompletionArgument,
1417 #[serde(skip_serializing_if = "Option::is_none")]
1419 pub context: Option<CompletionContext>,
1420}
1421
1422#[derive(Debug, Clone, Serialize, Deserialize)]
1424pub struct CompletionValues {
1425 pub values: Vec<String>,
1427 #[serde(skip_serializing_if = "Option::is_none")]
1429 pub total: Option<u64>,
1430 #[serde(rename = "hasMore", skip_serializing_if = "Option::is_none")]
1432 pub has_more: Option<bool>,
1433}
1434
1435#[derive(Debug, Clone, Serialize, Deserialize)]
1437pub struct CompleteResult {
1438 pub completion: CompletionValues,
1440}
1441
1442#[deprecated(note = "Use CompletionValues instead")]
1444pub type CompletionInfo = CompletionValues;
1445
1446#[derive(Debug, Clone, Serialize, Deserialize)]
1448pub struct SetLevelRequestParam {
1449 pub level: LogLevel,
1450}
1451
1452#[derive(Debug, Clone, Serialize, Deserialize)]
1454pub struct ResourceTemplate {
1455 #[serde(rename = "uriTemplate")]
1456 pub uri_template: String,
1457 pub name: String,
1458 pub description: Option<String>,
1459 #[serde(rename = "mimeType")]
1460 pub mime_type: Option<String>,
1461}
1462
1463#[derive(Debug, Clone, Serialize, Deserialize)]
1465pub struct ListResourceTemplatesResult {
1466 #[serde(rename = "resourceTemplates")]
1467 pub resource_templates: Vec<ResourceTemplate>,
1468 #[serde(rename = "nextCursor", skip_serializing_if = "Option::is_none")]
1469 pub next_cursor: Option<String>,
1470}
1471
1472#[derive(Debug, Clone, Serialize, Deserialize)]
1474pub struct SubscribeRequestParam {
1475 pub uri: String,
1476}
1477
1478#[derive(Debug, Clone, Serialize, Deserialize)]
1480pub struct UnsubscribeRequestParam {
1481 pub uri: String,
1482}
1483
1484#[derive(Debug, Clone, Serialize, Deserialize)]
1487pub struct ResourceUpdatedNotification {
1488 pub uri: String,
1490}
1491
1492#[derive(Debug, Clone, Serialize, Deserialize)]
1497pub struct ElicitationCompleteNotification {
1498 #[serde(rename = "elicitationId")]
1500 pub elicitation_id: String,
1501}
1502
1503#[derive(Debug, Clone, Serialize, Deserialize)]
1508pub struct UrlElicitationRequiredData {
1509 pub elicitations: Vec<UrlElicitationInfo>,
1511}
1512
1513#[derive(Debug, Clone, Serialize, Deserialize)]
1515pub struct UrlElicitationInfo {
1516 pub mode: ElicitationMode,
1518 #[serde(rename = "elicitationId")]
1520 pub elicitation_id: String,
1521 pub url: String,
1523 pub message: String,
1525}
1526
1527impl UrlElicitationInfo {
1528 pub fn new(
1530 elicitation_id: impl Into<String>,
1531 url: impl Into<String>,
1532 message: impl Into<String>,
1533 ) -> Self {
1534 Self {
1535 mode: ElicitationMode::Url,
1536 elicitation_id: elicitation_id.into(),
1537 url: url.into(),
1538 message: message.into(),
1539 }
1540 }
1541}
1542
1543#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1545#[serde(rename_all = "lowercase")]
1546pub enum ElicitationMode {
1547 Form,
1549 Url,
1551}
1552
1553impl Default for ElicitationMode {
1554 fn default() -> Self {
1555 Self::Form
1556 }
1557}
1558
1559#[derive(Debug, Clone, Serialize, Deserialize)]
1565pub struct ElicitationRequestParam {
1566 #[serde(default, skip_serializing_if = "is_form_mode")]
1568 pub mode: ElicitationMode,
1569 #[serde(rename = "elicitationId", skip_serializing_if = "Option::is_none")]
1571 pub elicitation_id: Option<String>,
1572 pub message: String,
1574 #[serde(rename = "requestedSchema", skip_serializing_if = "Option::is_none")]
1576 pub requested_schema: Option<serde_json::Value>,
1577 #[serde(skip_serializing_if = "Option::is_none")]
1579 pub url: Option<String>,
1580}
1581
1582fn is_form_mode(mode: &ElicitationMode) -> bool {
1583 *mode == ElicitationMode::Form
1584}
1585
1586impl ElicitationRequestParam {
1587 pub fn form(message: impl Into<String>, schema: serde_json::Value) -> Self {
1589 Self {
1590 mode: ElicitationMode::Form,
1591 elicitation_id: None,
1592 message: message.into(),
1593 requested_schema: Some(schema),
1594 url: None,
1595 }
1596 }
1597
1598 pub fn url(
1600 elicitation_id: impl Into<String>,
1601 url: impl Into<String>,
1602 message: impl Into<String>,
1603 ) -> Self {
1604 Self {
1605 mode: ElicitationMode::Url,
1606 elicitation_id: Some(elicitation_id.into()),
1607 message: message.into(),
1608 requested_schema: None,
1609 url: Some(url.into()),
1610 }
1611 }
1612}
1613
1614#[derive(Debug, Clone, Serialize, Deserialize)]
1616#[serde(rename_all = "lowercase")]
1617pub enum ElicitationAction {
1618 Accept,
1619 Decline,
1620 Cancel,
1621}
1622
1623#[derive(Debug, Clone, Serialize, Deserialize)]
1625pub struct ElicitationResponse {
1626 pub action: ElicitationAction,
1627 #[serde(skip_serializing_if = "Option::is_none")]
1628 pub data: Option<serde_json::Value>,
1629}
1630
1631#[derive(Debug, Clone, Serialize, Deserialize)]
1633pub struct ElicitationResult {
1634 pub response: ElicitationResponse,
1635}
1636
1637impl ElicitationResult {
1638 pub fn accept(data: serde_json::Value) -> Self {
1640 Self {
1641 response: ElicitationResponse {
1642 action: ElicitationAction::Accept,
1643 data: Some(data),
1644 },
1645 }
1646 }
1647
1648 pub fn decline() -> Self {
1650 Self {
1651 response: ElicitationResponse {
1652 action: ElicitationAction::Decline,
1653 data: None,
1654 },
1655 }
1656 }
1657
1658 pub fn cancel() -> Self {
1660 Self {
1661 response: ElicitationResponse {
1662 action: ElicitationAction::Cancel,
1663 data: None,
1664 },
1665 }
1666 }
1667}
1668
1669#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1673#[serde(rename_all = "lowercase")]
1674pub enum SamplingRole {
1675 User,
1676 Assistant,
1677}
1678
1679#[derive(Debug, Clone, Serialize, Deserialize)]
1681pub struct SamplingMessage {
1682 pub role: SamplingRole,
1684 pub content: SamplingContent,
1686}
1687
1688impl SamplingMessage {
1689 pub fn user_text(text: impl Into<String>) -> Self {
1691 Self {
1692 role: SamplingRole::User,
1693 content: SamplingContent::Text { text: text.into() },
1694 }
1695 }
1696
1697 pub fn assistant_text(text: impl Into<String>) -> Self {
1699 Self {
1700 role: SamplingRole::Assistant,
1701 content: SamplingContent::Text { text: text.into() },
1702 }
1703 }
1704}
1705
1706#[derive(Debug, Clone, Serialize, Deserialize)]
1708#[serde(tag = "type")]
1709pub enum SamplingContent {
1710 #[serde(rename = "text")]
1711 Text { text: String },
1712 #[serde(rename = "image")]
1713 Image { data: String, mime_type: String },
1714}
1715
1716#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1718#[serde(rename_all = "camelCase")]
1719pub struct ModelPreferences {
1720 #[serde(skip_serializing_if = "Option::is_none")]
1722 pub hints: Option<Vec<ModelHint>>,
1723 #[serde(skip_serializing_if = "Option::is_none")]
1725 pub cost_priority: Option<f32>,
1726 #[serde(skip_serializing_if = "Option::is_none")]
1728 pub speed_priority: Option<f32>,
1729 #[serde(skip_serializing_if = "Option::is_none")]
1731 pub intelligence_priority: Option<f32>,
1732}
1733
1734#[derive(Debug, Clone, Serialize, Deserialize)]
1736pub struct ModelHint {
1737 #[serde(skip_serializing_if = "Option::is_none")]
1739 pub name: Option<String>,
1740}
1741
1742#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1744#[serde(rename_all = "camelCase")]
1745pub enum ContextInclusion {
1746 AllServers,
1748 ThisServer,
1750 None,
1752}
1753
1754#[derive(Debug, Clone, Serialize, Deserialize)]
1756pub struct ToolChoice {
1757 pub mode: ToolChoiceMode,
1759}
1760
1761impl ToolChoice {
1762 pub fn auto() -> Self {
1764 Self {
1765 mode: ToolChoiceMode::Auto,
1766 }
1767 }
1768
1769 pub fn required() -> Self {
1771 Self {
1772 mode: ToolChoiceMode::Required,
1773 }
1774 }
1775
1776 pub fn none() -> Self {
1778 Self {
1779 mode: ToolChoiceMode::None,
1780 }
1781 }
1782}
1783
1784impl Default for ToolChoice {
1785 fn default() -> Self {
1786 Self::auto()
1787 }
1788}
1789
1790#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1792#[serde(rename_all = "lowercase")]
1793pub enum ToolChoiceMode {
1794 Auto,
1796 Required,
1798 None,
1800}
1801
1802#[derive(Debug, Clone, Serialize, Deserialize)]
1806#[serde(rename_all = "camelCase")]
1807pub struct CreateMessageRequestParam {
1808 pub max_tokens: u32,
1810 pub messages: Vec<SamplingMessage>,
1812 #[serde(skip_serializing_if = "Option::is_none")]
1814 pub system_prompt: Option<String>,
1815 #[serde(skip_serializing_if = "Option::is_none")]
1817 pub temperature: Option<f32>,
1818 #[serde(skip_serializing_if = "Option::is_none")]
1820 pub stop_sequences: Option<Vec<String>>,
1821 #[serde(skip_serializing_if = "Option::is_none")]
1823 pub model_preferences: Option<ModelPreferences>,
1824 #[serde(skip_serializing_if = "Option::is_none")]
1826 pub include_context: Option<ContextInclusion>,
1827 #[serde(skip_serializing_if = "Option::is_none")]
1829 pub tools: Option<Vec<Tool>>,
1830 #[serde(skip_serializing_if = "Option::is_none")]
1832 pub tool_choice: Option<ToolChoice>,
1833 #[serde(skip_serializing_if = "Option::is_none")]
1835 pub metadata: Option<serde_json::Value>,
1836}
1837
1838impl CreateMessageRequestParam {
1839 pub fn simple(max_tokens: u32, user_message: impl Into<String>) -> Self {
1841 Self {
1842 max_tokens,
1843 messages: vec![SamplingMessage::user_text(user_message)],
1844 system_prompt: None,
1845 temperature: None,
1846 stop_sequences: None,
1847 model_preferences: None,
1848 include_context: None,
1849 tools: None,
1850 tool_choice: None,
1851 metadata: None,
1852 }
1853 }
1854
1855 pub fn with_tools(max_tokens: u32, messages: Vec<SamplingMessage>, tools: Vec<Tool>) -> Self {
1857 Self {
1858 max_tokens,
1859 messages,
1860 system_prompt: None,
1861 temperature: None,
1862 stop_sequences: None,
1863 model_preferences: None,
1864 include_context: None,
1865 tools: Some(tools),
1866 tool_choice: Some(ToolChoice::auto()),
1867 metadata: None,
1868 }
1869 }
1870}
1871
1872#[derive(Debug, Clone, Serialize, Deserialize)]
1876#[serde(rename_all = "camelCase")]
1877pub struct CreateMessageResult {
1878 pub model: String,
1880 #[serde(skip_serializing_if = "Option::is_none")]
1882 pub stop_reason: Option<String>,
1883 pub message: SamplingMessage,
1885}
1886
1887impl CreateMessageResult {
1888 pub fn is_tool_use(&self) -> bool {
1890 self.stop_reason.as_deref() == Some("tool_use")
1891 }
1892
1893 pub fn is_end_turn(&self) -> bool {
1895 self.stop_reason.as_deref() == Some("end_turn")
1896 }
1897
1898 pub fn is_max_tokens(&self) -> bool {
1900 self.stop_reason.as_deref() == Some("max_tokens")
1901 }
1902}
1903
1904pub mod stop_reasons {
1906 pub const END_TURN: &str = "end_turn";
1908 pub const STOP_SEQUENCE: &str = "stop_sequence";
1910 pub const MAX_TOKENS: &str = "max_tokens";
1912 pub const TOOL_USE: &str = "tool_use";
1914}
1915
1916#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1920#[serde(rename_all = "kebab-case")]
1921pub enum TaskStatus {
1922 Working,
1924 InputRequired,
1926 Completed,
1928 Failed,
1930 Cancelled,
1932}
1933
1934impl std::fmt::Display for TaskStatus {
1935 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1936 let s = match self {
1937 TaskStatus::Working => "working",
1938 TaskStatus::InputRequired => "input-required",
1939 TaskStatus::Completed => "completed",
1940 TaskStatus::Failed => "failed",
1941 TaskStatus::Cancelled => "cancelled",
1942 };
1943 write!(f, "{s}")
1944 }
1945}
1946
1947#[derive(Debug, Clone, Serialize, Deserialize)]
1952#[serde(rename_all = "camelCase")]
1953pub struct Task {
1954 pub task_id: String,
1956 pub status: TaskStatus,
1958 #[serde(skip_serializing_if = "Option::is_none")]
1960 pub status_message: Option<String>,
1961 #[serde(skip_serializing_if = "Option::is_none")]
1963 pub created_at: Option<String>,
1964 #[serde(skip_serializing_if = "Option::is_none")]
1966 pub last_updated_at: Option<String>,
1967 #[serde(skip_serializing_if = "Option::is_none")]
1969 pub ttl: Option<u64>,
1970 #[serde(skip_serializing_if = "Option::is_none")]
1972 pub poll_interval: Option<u64>,
1973}
1974
1975impl Task {
1976 pub fn new(task_id: impl Into<String>) -> Self {
1978 Self {
1979 task_id: task_id.into(),
1980 status: TaskStatus::Working,
1981 status_message: None,
1982 created_at: None,
1983 last_updated_at: None,
1984 ttl: None,
1985 poll_interval: None,
1986 }
1987 }
1988
1989 pub fn with_timestamps(task_id: impl Into<String>, created_at: impl Into<String>) -> Self {
1991 let ts = created_at.into();
1992 Self {
1993 task_id: task_id.into(),
1994 status: TaskStatus::Working,
1995 status_message: None,
1996 created_at: Some(ts.clone()),
1997 last_updated_at: Some(ts),
1998 ttl: None,
1999 poll_interval: None,
2000 }
2001 }
2002
2003 pub fn is_terminal(&self) -> bool {
2005 matches!(
2006 self.status,
2007 TaskStatus::Completed | TaskStatus::Failed | TaskStatus::Cancelled
2008 )
2009 }
2010
2011 pub fn is_running(&self) -> bool {
2013 matches!(self.status, TaskStatus::Working | TaskStatus::InputRequired)
2014 }
2015}
2016
2017#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2019pub struct TasksCapability {
2020 #[serde(skip_serializing_if = "Option::is_none")]
2022 pub cancel: Option<TaskCancelCapability>,
2023 #[serde(skip_serializing_if = "Option::is_none")]
2025 pub list: Option<TaskListCapability>,
2026 #[serde(skip_serializing_if = "Option::is_none")]
2028 pub requests: Option<TaskRequestsCapability>,
2029}
2030
2031#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2033pub struct TaskCancelCapability {}
2034
2035#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2037pub struct TaskListCapability {}
2038
2039#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2041pub struct TaskRequestsCapability {
2042 #[serde(skip_serializing_if = "Option::is_none")]
2044 pub sampling: Option<TaskSamplingCapability>,
2045 #[serde(skip_serializing_if = "Option::is_none")]
2047 pub elicitation: Option<TaskElicitationCapability>,
2048 #[serde(skip_serializing_if = "Option::is_none")]
2050 pub tools: Option<TaskToolsCapability>,
2051}
2052
2053#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2055pub struct TaskSamplingCapability {
2056 #[serde(rename = "createMessage", skip_serializing_if = "Option::is_none")]
2058 pub create_message: Option<TaskMethodCapability>,
2059}
2060
2061#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2063pub struct TaskElicitationCapability {
2064 #[serde(skip_serializing_if = "Option::is_none")]
2066 pub create: Option<TaskMethodCapability>,
2067}
2068
2069#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2071pub struct TaskToolsCapability {
2072 #[serde(skip_serializing_if = "Option::is_none")]
2074 pub call: Option<TaskMethodCapability>,
2075}
2076
2077#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2079pub struct TaskMethodCapability {}
2080
2081#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2086#[serde(rename_all = "camelCase")]
2087pub struct TaskMetadata {
2088 #[serde(skip_serializing_if = "Option::is_none")]
2090 pub ttl: Option<u64>,
2091 #[serde(skip_serializing_if = "Option::is_none")]
2093 pub poll_interval: Option<u64>,
2094}
2095
2096#[derive(Debug, Clone, Serialize, Deserialize)]
2098#[serde(rename_all = "camelCase")]
2099pub struct CreateTaskResult {
2100 pub task: Task,
2102}
2103
2104#[derive(Debug, Clone, Serialize, Deserialize)]
2106#[serde(rename_all = "camelCase")]
2107pub struct GetTaskRequestParam {
2108 pub task_id: String,
2110}
2111
2112#[derive(Debug, Clone, Serialize, Deserialize)]
2114pub struct GetTaskResult {
2115 pub task: Task,
2117}
2118
2119#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2121pub struct ListTasksRequestParam {
2122 #[serde(skip_serializing_if = "Option::is_none")]
2124 pub cursor: Option<String>,
2125}
2126
2127#[derive(Debug, Clone, Serialize, Deserialize)]
2129#[serde(rename_all = "camelCase")]
2130pub struct ListTasksResult {
2131 pub tasks: Vec<Task>,
2133 #[serde(skip_serializing_if = "Option::is_none")]
2135 pub next_cursor: Option<String>,
2136}
2137
2138#[derive(Debug, Clone, Serialize, Deserialize)]
2143#[serde(rename_all = "camelCase")]
2144pub struct GetTaskResultRequestParam {
2145 pub task_id: String,
2147}
2148
2149#[derive(Debug, Clone, Serialize, Deserialize)]
2151#[serde(rename_all = "camelCase")]
2152pub struct CancelTaskRequestParam {
2153 pub task_id: String,
2155}
2156
2157#[derive(Debug, Clone, Serialize, Deserialize)]
2159pub struct CancelTaskResult {
2160 pub task: Task,
2162}
2163
2164#[derive(Debug, Clone, Serialize, Deserialize)]
2168#[serde(rename_all = "camelCase")]
2169pub struct TaskStatusNotification {
2170 pub task_id: String,
2172 pub status: TaskStatus,
2174 #[serde(skip_serializing_if = "Option::is_none")]
2176 pub status_message: Option<String>,
2177 #[serde(skip_serializing_if = "Option::is_none")]
2179 pub last_updated_at: Option<String>,
2180}
2181
2182impl TaskStatusNotification {
2183 pub fn new(task_id: impl Into<String>, status: TaskStatus) -> Self {
2185 Self {
2186 task_id: task_id.into(),
2187 status,
2188 status_message: None,
2189 last_updated_at: None,
2190 }
2191 }
2192
2193 pub fn with_message(
2195 task_id: impl Into<String>,
2196 status: TaskStatus,
2197 message: impl Into<String>,
2198 ) -> Self {
2199 Self {
2200 task_id: task_id.into(),
2201 status,
2202 status_message: Some(message.into()),
2203 last_updated_at: None,
2204 }
2205 }
2206}
2207
2208#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2212#[serde(rename_all = "camelCase")]
2213pub struct ToolExecution {
2214 #[serde(skip_serializing_if = "Option::is_none")]
2216 pub task_support: Option<TaskSupport>,
2217}
2218
2219#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2221#[serde(rename_all = "lowercase")]
2222pub enum TaskSupport {
2223 Forbidden,
2225 Optional,
2227 Required,
2229}
2230
2231impl Default for TaskSupport {
2232 fn default() -> Self {
2233 Self::Optional
2234 }
2235}