1use collections::HashMap;
2use serde::de::DeserializeOwned;
3use serde::{Deserialize, Serialize};
4use url::Url;
5
6use crate::client::RequestId;
7
8pub const LATEST_PROTOCOL_VERSION: &str = "2025-03-26";
9pub const VERSION_2024_11_05: &str = "2024-11-05";
10
11pub mod requests {
12 use super::*;
13
14 macro_rules! request {
15 ($method:expr, $name:ident, $params:ty, $response:ty) => {
16 pub struct $name;
17
18 impl Request for $name {
19 type Params = $params;
20 type Response = $response;
21 const METHOD: &'static str = $method;
22 }
23 };
24 }
25
26 request!(
27 "initialize",
28 Initialize,
29 InitializeParams,
30 InitializeResponse
31 );
32 request!("tools/call", CallTool, CallToolParams, CallToolResponse);
33 request!(
34 "resources/unsubscribe",
35 ResourcesUnsubscribe,
36 ResourcesUnsubscribeParams,
37 ()
38 );
39 request!(
40 "resources/subscribe",
41 ResourcesSubscribe,
42 ResourcesSubscribeParams,
43 ()
44 );
45 request!(
46 "resources/read",
47 ResourcesRead,
48 ResourcesReadParams,
49 ResourcesReadResponse
50 );
51 request!("resources/list", ResourcesList, (), ResourcesListResponse);
52 request!(
53 "logging/setLevel",
54 LoggingSetLevel,
55 LoggingSetLevelParams,
56 ()
57 );
58 request!(
59 "prompts/get",
60 PromptsGet,
61 PromptsGetParams,
62 PromptsGetResponse
63 );
64 request!("prompts/list", PromptsList, (), PromptsListResponse);
65 request!(
66 "completion/complete",
67 CompletionComplete,
68 CompletionCompleteParams,
69 CompletionCompleteResponse
70 );
71 request!("ping", Ping, (), ());
72 request!("tools/list", ListTools, (), ListToolsResponse);
73 request!(
74 "resources/templates/list",
75 ListResourceTemplates,
76 (),
77 ListResourceTemplatesResponse
78 );
79 request!("roots/list", ListRoots, (), ListRootsResponse);
80}
81
82pub trait Request {
83 type Params: DeserializeOwned + Serialize + Send + Sync + 'static;
84 type Response: DeserializeOwned + Serialize + Send + Sync + 'static;
85 const METHOD: &'static str;
86}
87
88pub mod notifications {
89 use super::*;
90
91 macro_rules! notification {
92 ($method:expr, $name:ident, $params:ty) => {
93 pub struct $name;
94
95 impl Notification for $name {
96 type Params = $params;
97 const METHOD: &'static str = $method;
98 }
99 };
100 }
101
102 notification!("notifications/initialized", Initialized, ());
103 notification!("notifications/progress", Progress, ProgressParams);
104 notification!("notifications/message", Message, MessageParams);
105 notification!("notifications/cancelled", Cancelled, CancelledParams);
106 notification!(
107 "notifications/resources/updated",
108 ResourcesUpdated,
109 ResourcesUpdatedParams
110 );
111 notification!(
112 "notifications/resources/list_changed",
113 ResourcesListChanged,
114 ()
115 );
116 notification!("notifications/tools/list_changed", ToolsListChanged, ());
117 notification!("notifications/prompts/list_changed", PromptsListChanged, ());
118 notification!("notifications/roots/list_changed", RootsListChanged, ());
119}
120
121pub trait Notification {
122 type Params: DeserializeOwned + Serialize + Send + Sync + 'static;
123 const METHOD: &'static str;
124}
125
126#[derive(Debug, Serialize, Deserialize)]
127#[serde(rename_all = "camelCase")]
128pub struct MessageParams {
129 pub level: LoggingLevel,
130 pub logger: Option<String>,
131 pub data: serde_json::Value,
132}
133
134#[derive(Debug, Serialize, Deserialize)]
135#[serde(rename_all = "camelCase")]
136pub struct ResourcesUpdatedParams {
137 pub uri: String,
138}
139
140#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
141#[serde(transparent)]
142pub struct ProtocolVersion(pub String);
143
144#[derive(Debug, Serialize, Deserialize)]
145#[serde(rename_all = "camelCase")]
146pub struct InitializeParams {
147 pub protocol_version: ProtocolVersion,
148 pub capabilities: ClientCapabilities,
149 pub client_info: Implementation,
150 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
151 pub meta: Option<HashMap<String, serde_json::Value>>,
152}
153
154#[derive(Debug, Serialize, Deserialize)]
155#[serde(rename_all = "camelCase")]
156pub struct CallToolParams {
157 pub name: String,
158 #[serde(skip_serializing_if = "Option::is_none")]
159 pub arguments: Option<serde_json::Value>,
160 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
161 pub meta: Option<HashMap<String, serde_json::Value>>,
162}
163
164#[derive(Debug, Serialize, Deserialize)]
165#[serde(rename_all = "camelCase")]
166pub struct ResourcesUnsubscribeParams {
167 pub uri: Url,
168 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
169 pub meta: Option<HashMap<String, serde_json::Value>>,
170}
171
172#[derive(Debug, Serialize, Deserialize)]
173#[serde(rename_all = "camelCase")]
174pub struct ResourcesSubscribeParams {
175 pub uri: Url,
176 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
177 pub meta: Option<HashMap<String, serde_json::Value>>,
178}
179
180#[derive(Debug, Serialize, Deserialize)]
181#[serde(rename_all = "camelCase")]
182pub struct ResourcesReadParams {
183 pub uri: Url,
184 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
185 pub meta: Option<HashMap<String, serde_json::Value>>,
186}
187
188#[derive(Debug, Serialize, Deserialize)]
189#[serde(rename_all = "camelCase")]
190pub struct LoggingSetLevelParams {
191 pub level: LoggingLevel,
192 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
193 pub meta: Option<HashMap<String, serde_json::Value>>,
194}
195
196#[derive(Debug, Serialize, Deserialize)]
197#[serde(rename_all = "camelCase")]
198pub struct PromptsGetParams {
199 pub name: String,
200 #[serde(skip_serializing_if = "Option::is_none")]
201 pub arguments: Option<HashMap<String, String>>,
202 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
203 pub meta: Option<HashMap<String, serde_json::Value>>,
204}
205
206#[derive(Debug, Serialize, Deserialize)]
207#[serde(rename_all = "camelCase")]
208pub struct CompletionCompleteParams {
209 #[serde(rename = "ref")]
210 pub reference: CompletionReference,
211 pub argument: CompletionArgument,
212 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
213 pub meta: Option<HashMap<String, serde_json::Value>>,
214}
215
216#[derive(Debug, Serialize, Deserialize)]
217#[serde(untagged)]
218pub enum CompletionReference {
219 Prompt(PromptReference),
220 Resource(ResourceReference),
221}
222
223#[derive(Debug, Serialize, Deserialize)]
224#[serde(rename_all = "camelCase")]
225pub struct PromptReference {
226 #[serde(rename = "type")]
227 pub ty: PromptReferenceType,
228 pub name: String,
229}
230
231#[derive(Debug, Serialize, Deserialize)]
232#[serde(rename_all = "camelCase")]
233pub struct ResourceReference {
234 #[serde(rename = "type")]
235 pub ty: PromptReferenceType,
236 pub uri: Url,
237}
238
239#[derive(Debug, Serialize, Deserialize)]
240#[serde(rename_all = "snake_case")]
241pub enum PromptReferenceType {
242 #[serde(rename = "ref/prompt")]
243 Prompt,
244 #[serde(rename = "ref/resource")]
245 Resource,
246}
247
248#[derive(Debug, Serialize, Deserialize)]
249#[serde(rename_all = "camelCase")]
250pub struct CompletionArgument {
251 pub name: String,
252 pub value: String,
253}
254
255#[derive(Debug, Serialize, Deserialize)]
256#[serde(rename_all = "camelCase")]
257pub struct InitializeResponse {
258 pub protocol_version: ProtocolVersion,
259 pub capabilities: ServerCapabilities,
260 pub server_info: Implementation,
261 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
262 pub meta: Option<HashMap<String, serde_json::Value>>,
263}
264
265#[derive(Debug, Serialize, Deserialize)]
266#[serde(rename_all = "camelCase")]
267pub struct ResourcesReadResponse {
268 pub contents: Vec<ResourceContentsType>,
269 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
270 pub meta: Option<HashMap<String, serde_json::Value>>,
271}
272
273#[derive(Debug, Serialize, Deserialize)]
274#[serde(untagged)]
275pub enum ResourceContentsType {
276 Text(TextResourceContents),
277 Blob(BlobResourceContents),
278}
279
280#[derive(Debug, Serialize, Deserialize)]
281#[serde(rename_all = "camelCase")]
282pub struct ResourcesListResponse {
283 pub resources: Vec<Resource>,
284 #[serde(skip_serializing_if = "Option::is_none")]
285 pub next_cursor: Option<String>,
286 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
287 pub meta: Option<HashMap<String, serde_json::Value>>,
288}
289
290#[derive(Debug, Serialize, Deserialize)]
291#[serde(rename_all = "camelCase")]
292pub struct SamplingMessage {
293 pub role: Role,
294 pub content: MessageContent,
295}
296
297#[derive(Debug, Serialize, Deserialize)]
298#[serde(rename_all = "camelCase")]
299pub struct CreateMessageRequest {
300 pub messages: Vec<SamplingMessage>,
301 #[serde(skip_serializing_if = "Option::is_none")]
302 pub model_preferences: Option<ModelPreferences>,
303 #[serde(skip_serializing_if = "Option::is_none")]
304 pub system_prompt: Option<String>,
305 #[serde(skip_serializing_if = "Option::is_none")]
306 pub include_context: Option<String>,
307 #[serde(skip_serializing_if = "Option::is_none")]
308 pub temperature: Option<f64>,
309 pub max_tokens: u32,
310 #[serde(skip_serializing_if = "Option::is_none")]
311 pub stop_sequences: Option<Vec<String>>,
312 #[serde(skip_serializing_if = "Option::is_none")]
313 pub metadata: Option<serde_json::Value>,
314}
315
316#[derive(Debug, Deserialize)]
317#[serde(rename_all = "camelCase")]
318pub struct CreateMessageResult {
319 pub role: Role,
320 pub content: MessageContent,
321 pub model: String,
322 #[serde(skip_serializing_if = "Option::is_none")]
323 pub stop_reason: Option<String>,
324}
325
326#[derive(Debug, Serialize, Deserialize)]
327#[serde(rename_all = "camelCase")]
328pub struct PromptMessage {
329 pub role: Role,
330 pub content: MessageContent,
331}
332
333#[derive(Debug, Serialize, Deserialize)]
334#[serde(rename_all = "lowercase")]
335pub enum Role {
336 User,
337 Assistant,
338}
339
340#[derive(Debug, Serialize, Deserialize)]
341#[serde(tag = "type")]
342pub enum MessageContent {
343 #[serde(rename = "text")]
344 Text {
345 text: String,
346 #[serde(skip_serializing_if = "Option::is_none")]
347 annotations: Option<MessageAnnotations>,
348 },
349 #[serde(rename = "image", rename_all = "camelCase")]
350 Image {
351 data: String,
352 mime_type: String,
353 #[serde(skip_serializing_if = "Option::is_none")]
354 annotations: Option<MessageAnnotations>,
355 },
356 #[serde(rename = "audio", rename_all = "camelCase")]
357 Audio {
358 data: String,
359 mime_type: String,
360 #[serde(skip_serializing_if = "Option::is_none")]
361 annotations: Option<MessageAnnotations>,
362 },
363 #[serde(rename = "resource")]
364 Resource {
365 resource: ResourceContents,
366 #[serde(skip_serializing_if = "Option::is_none")]
367 annotations: Option<MessageAnnotations>,
368 },
369}
370
371#[derive(Debug, Serialize, Deserialize)]
372#[serde(rename_all = "camelCase")]
373pub struct MessageAnnotations {
374 #[serde(skip_serializing_if = "Option::is_none")]
375 pub audience: Option<Vec<Role>>,
376 #[serde(skip_serializing_if = "Option::is_none")]
377 pub priority: Option<f64>,
378}
379
380#[derive(Debug, Serialize, Deserialize)]
381#[serde(rename_all = "camelCase")]
382pub struct PromptsGetResponse {
383 #[serde(skip_serializing_if = "Option::is_none")]
384 pub description: Option<String>,
385 pub messages: Vec<PromptMessage>,
386 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
387 pub meta: Option<HashMap<String, serde_json::Value>>,
388}
389
390#[derive(Debug, Serialize, Deserialize)]
391#[serde(rename_all = "camelCase")]
392pub struct PromptsListResponse {
393 pub prompts: Vec<Prompt>,
394 #[serde(skip_serializing_if = "Option::is_none")]
395 pub next_cursor: Option<String>,
396 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
397 pub meta: Option<HashMap<String, serde_json::Value>>,
398}
399
400#[derive(Debug, Serialize, Deserialize)]
401#[serde(rename_all = "camelCase")]
402pub struct CompletionCompleteResponse {
403 pub completion: CompletionResult,
404 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
405 pub meta: Option<HashMap<String, serde_json::Value>>,
406}
407
408#[derive(Debug, Serialize, Deserialize)]
409#[serde(rename_all = "camelCase")]
410pub struct CompletionResult {
411 pub values: Vec<String>,
412 #[serde(skip_serializing_if = "Option::is_none")]
413 pub total: Option<u32>,
414 #[serde(skip_serializing_if = "Option::is_none")]
415 pub has_more: Option<bool>,
416 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
417 pub meta: Option<HashMap<String, serde_json::Value>>,
418}
419
420#[derive(Debug, Serialize, Deserialize)]
421#[serde(rename_all = "camelCase")]
422pub struct Prompt {
423 pub name: String,
424 #[serde(skip_serializing_if = "Option::is_none")]
425 pub description: Option<String>,
426 #[serde(skip_serializing_if = "Option::is_none")]
427 pub arguments: Option<Vec<PromptArgument>>,
428}
429
430#[derive(Debug, Serialize, Deserialize)]
431#[serde(rename_all = "camelCase")]
432pub struct PromptArgument {
433 pub name: String,
434 #[serde(skip_serializing_if = "Option::is_none")]
435 pub description: Option<String>,
436 #[serde(skip_serializing_if = "Option::is_none")]
437 pub required: Option<bool>,
438}
439
440#[derive(Debug, Serialize, Deserialize)]
441#[serde(rename_all = "camelCase")]
442pub struct ClientCapabilities {
443 #[serde(skip_serializing_if = "Option::is_none")]
444 pub experimental: Option<HashMap<String, serde_json::Value>>,
445 #[serde(skip_serializing_if = "Option::is_none")]
446 pub sampling: Option<serde_json::Value>,
447 #[serde(skip_serializing_if = "Option::is_none")]
448 pub roots: Option<RootsCapabilities>,
449}
450
451#[derive(Default, Debug, Serialize, Deserialize)]
452#[serde(rename_all = "camelCase")]
453pub struct ServerCapabilities {
454 #[serde(skip_serializing_if = "Option::is_none")]
455 pub experimental: Option<HashMap<String, serde_json::Value>>,
456 #[serde(skip_serializing_if = "Option::is_none")]
457 pub logging: Option<serde_json::Value>,
458 #[serde(skip_serializing_if = "Option::is_none")]
459 pub completions: Option<serde_json::Value>,
460 #[serde(skip_serializing_if = "Option::is_none")]
461 pub prompts: Option<PromptsCapabilities>,
462 #[serde(skip_serializing_if = "Option::is_none")]
463 pub resources: Option<ResourcesCapabilities>,
464 #[serde(skip_serializing_if = "Option::is_none")]
465 pub tools: Option<ToolsCapabilities>,
466}
467
468#[derive(Debug, Serialize, Deserialize)]
469#[serde(rename_all = "camelCase")]
470pub struct PromptsCapabilities {
471 #[serde(skip_serializing_if = "Option::is_none")]
472 pub list_changed: Option<bool>,
473}
474
475#[derive(Debug, Serialize, Deserialize)]
476#[serde(rename_all = "camelCase")]
477pub struct ResourcesCapabilities {
478 #[serde(skip_serializing_if = "Option::is_none")]
479 pub subscribe: Option<bool>,
480 #[serde(skip_serializing_if = "Option::is_none")]
481 pub list_changed: Option<bool>,
482}
483
484#[derive(Debug, Serialize, Deserialize)]
485#[serde(rename_all = "camelCase")]
486pub struct ToolsCapabilities {
487 #[serde(skip_serializing_if = "Option::is_none")]
488 pub list_changed: Option<bool>,
489}
490
491#[derive(Debug, Serialize, Deserialize)]
492#[serde(rename_all = "camelCase")]
493pub struct RootsCapabilities {
494 #[serde(skip_serializing_if = "Option::is_none")]
495 pub list_changed: Option<bool>,
496}
497
498#[derive(Clone, Debug, Serialize, Deserialize)]
499#[serde(rename_all = "camelCase")]
500pub struct Tool {
501 pub name: String,
502 #[serde(skip_serializing_if = "Option::is_none")]
503 pub description: Option<String>,
504 pub input_schema: serde_json::Value,
505 #[serde(default, skip_serializing_if = "Option::is_none")]
506 pub output_schema: Option<serde_json::Value>,
507 #[serde(skip_serializing_if = "Option::is_none")]
508 pub annotations: Option<ToolAnnotations>,
509}
510
511#[derive(Clone, Debug, Serialize, Deserialize)]
512#[serde(rename_all = "camelCase")]
513pub struct ToolAnnotations {
514 /// A human-readable title for the tool.
515 #[serde(skip_serializing_if = "Option::is_none")]
516 pub title: Option<String>,
517 /// If true, the tool does not modify its environment.
518 #[serde(skip_serializing_if = "Option::is_none")]
519 pub read_only_hint: Option<bool>,
520 /// If true, the tool may perform destructive updates to its environment.
521 #[serde(skip_serializing_if = "Option::is_none")]
522 pub destructive_hint: Option<bool>,
523 /// If true, calling the tool repeatedly with the same arguments will have no additional effect on its environment.
524 #[serde(skip_serializing_if = "Option::is_none")]
525 pub idempotent_hint: Option<bool>,
526 /// If true, this tool may interact with an "open world" of external entities.
527 #[serde(skip_serializing_if = "Option::is_none")]
528 pub open_world_hint: Option<bool>,
529}
530
531#[derive(Debug, Serialize, Deserialize)]
532#[serde(rename_all = "camelCase")]
533pub struct Implementation {
534 pub name: String,
535 pub version: String,
536}
537
538#[derive(Debug, Serialize, Deserialize)]
539#[serde(rename_all = "camelCase")]
540pub struct Resource {
541 pub uri: Url,
542 pub name: String,
543 #[serde(skip_serializing_if = "Option::is_none")]
544 pub description: Option<String>,
545 #[serde(skip_serializing_if = "Option::is_none")]
546 pub mime_type: Option<String>,
547}
548
549#[derive(Debug, Serialize, Deserialize)]
550#[serde(rename_all = "camelCase")]
551pub struct ResourceContents {
552 pub uri: Url,
553 #[serde(skip_serializing_if = "Option::is_none")]
554 pub mime_type: Option<String>,
555}
556
557#[derive(Debug, Serialize, Deserialize)]
558#[serde(rename_all = "camelCase")]
559pub struct TextResourceContents {
560 pub uri: Url,
561 #[serde(skip_serializing_if = "Option::is_none")]
562 pub mime_type: Option<String>,
563 pub text: String,
564}
565
566#[derive(Debug, Serialize, Deserialize)]
567#[serde(rename_all = "camelCase")]
568pub struct BlobResourceContents {
569 pub uri: Url,
570 #[serde(skip_serializing_if = "Option::is_none")]
571 pub mime_type: Option<String>,
572 pub blob: String,
573}
574
575#[derive(Debug, Serialize, Deserialize)]
576#[serde(rename_all = "camelCase")]
577pub struct ResourceTemplate {
578 pub uri_template: String,
579 pub name: String,
580 #[serde(skip_serializing_if = "Option::is_none")]
581 pub description: Option<String>,
582 #[serde(skip_serializing_if = "Option::is_none")]
583 pub mime_type: Option<String>,
584}
585
586#[derive(Debug, Serialize, Deserialize)]
587#[serde(rename_all = "lowercase")]
588pub enum LoggingLevel {
589 Debug,
590 Info,
591 Notice,
592 Warning,
593 Error,
594 Critical,
595 Alert,
596 Emergency,
597}
598
599#[derive(Debug, Serialize, Deserialize)]
600#[serde(rename_all = "camelCase")]
601pub struct ModelPreferences {
602 #[serde(skip_serializing_if = "Option::is_none")]
603 pub hints: Option<Vec<ModelHint>>,
604 #[serde(skip_serializing_if = "Option::is_none")]
605 pub cost_priority: Option<f64>,
606 #[serde(skip_serializing_if = "Option::is_none")]
607 pub speed_priority: Option<f64>,
608 #[serde(skip_serializing_if = "Option::is_none")]
609 pub intelligence_priority: Option<f64>,
610}
611
612#[derive(Debug, Serialize, Deserialize)]
613#[serde(rename_all = "camelCase")]
614pub struct ModelHint {
615 #[serde(skip_serializing_if = "Option::is_none")]
616 pub name: Option<String>,
617}
618
619#[derive(Debug, Serialize)]
620#[serde(untagged)]
621pub enum ClientNotification {
622 Initialized,
623 Progress(ProgressParams),
624 RootsListChanged,
625 Cancelled(CancelledParams),
626}
627
628#[derive(Debug, Serialize, Deserialize)]
629#[serde(rename_all = "camelCase")]
630pub struct CancelledParams {
631 pub request_id: RequestId,
632 #[serde(skip_serializing_if = "Option::is_none")]
633 pub reason: Option<String>,
634}
635
636#[derive(Debug, Serialize, Deserialize)]
637#[serde(untagged)]
638pub enum ProgressToken {
639 String(String),
640 Number(f64),
641}
642
643#[derive(Debug, Serialize, Deserialize)]
644#[serde(rename_all = "camelCase")]
645pub struct ProgressParams {
646 pub progress_token: ProgressToken,
647 pub progress: f64,
648 #[serde(skip_serializing_if = "Option::is_none")]
649 pub message: Option<String>,
650 #[serde(skip_serializing_if = "Option::is_none")]
651 pub total: Option<f64>,
652 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
653 pub meta: Option<HashMap<String, serde_json::Value>>,
654}
655
656pub enum CompletionTotal {
657 Exact(u32),
658 HasMore,
659 Unknown,
660}
661
662impl CompletionTotal {
663 pub fn from_options(has_more: Option<bool>, total: Option<u32>) -> Self {
664 match (has_more, total) {
665 (_, Some(count)) => CompletionTotal::Exact(count),
666 (Some(true), _) => CompletionTotal::HasMore,
667 _ => CompletionTotal::Unknown,
668 }
669 }
670}
671
672pub struct Completion {
673 pub values: Vec<String>,
674 pub total: CompletionTotal,
675}
676
677#[derive(Debug, Serialize, Deserialize)]
678#[serde(rename_all = "camelCase")]
679pub struct CallToolResponse {
680 pub content: Vec<ToolResponseContent>,
681 #[serde(skip_serializing_if = "Option::is_none")]
682 pub is_error: Option<bool>,
683 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
684 pub meta: Option<HashMap<String, serde_json::Value>>,
685 #[serde(default, skip_serializing_if = "Option::is_none")]
686 pub structured_content: Option<serde_json::Value>,
687}
688
689impl CallToolResponse {
690 pub fn text_contents(&self) -> String {
691 let mut text = String::new();
692 for chunk in &self.content {
693 if let ToolResponseContent::Text { text: chunk } = chunk {
694 text.push_str(chunk)
695 };
696 }
697 text
698 }
699}
700
701#[derive(Debug, Serialize, Deserialize)]
702#[serde(tag = "type")]
703pub enum ToolResponseContent {
704 #[serde(rename = "text")]
705 Text { text: String },
706 #[serde(rename = "image", rename_all = "camelCase")]
707 Image { data: String, mime_type: String },
708 #[serde(rename = "audio", rename_all = "camelCase")]
709 Audio { data: String, mime_type: String },
710 #[serde(rename = "resource")]
711 Resource { resource: ResourceContents },
712}
713
714impl ToolResponseContent {
715 pub fn text(&self) -> Option<&str> {
716 if let ToolResponseContent::Text { text } = self {
717 Some(text)
718 } else {
719 None
720 }
721 }
722}
723
724#[derive(Debug, Serialize, Deserialize)]
725#[serde(rename_all = "camelCase")]
726pub struct ListToolsResponse {
727 pub tools: Vec<Tool>,
728 #[serde(skip_serializing_if = "Option::is_none")]
729 pub next_cursor: Option<String>,
730 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
731 pub meta: Option<HashMap<String, serde_json::Value>>,
732}
733
734#[derive(Debug, Serialize, Deserialize)]
735#[serde(rename_all = "camelCase")]
736pub struct ListResourceTemplatesResponse {
737 pub resource_templates: Vec<ResourceTemplate>,
738 #[serde(skip_serializing_if = "Option::is_none")]
739 pub next_cursor: Option<String>,
740 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
741 pub meta: Option<HashMap<String, serde_json::Value>>,
742}
743
744#[derive(Debug, Serialize, Deserialize)]
745#[serde(rename_all = "camelCase")]
746pub struct ListRootsResponse {
747 pub roots: Vec<Root>,
748 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
749 pub meta: Option<HashMap<String, serde_json::Value>>,
750}
751
752#[derive(Debug, Serialize, Deserialize)]
753#[serde(rename_all = "camelCase")]
754pub struct Root {
755 pub uri: Url,
756 #[serde(skip_serializing_if = "Option::is_none")]
757 pub name: Option<String>,
758}