1use crate::Error;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct Request {
10 pub jsonrpc: String,
12 pub method: String,
14 #[serde(default = "serde_json::Value::default")]
16 pub params: serde_json::Value,
17 #[serde(default = "default_null")]
19 pub id: serde_json::Value,
20}
21
22fn default_null() -> serde_json::Value {
23 serde_json::Value::Null
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize)]
28pub struct Response {
29 pub jsonrpc: String,
31 #[serde(skip_serializing_if = "Option::is_none")]
33 pub result: Option<serde_json::Value>,
34 #[serde(skip_serializing_if = "Option::is_none")]
36 pub error: Option<Error>,
37 pub id: serde_json::Value,
39}
40
41#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct ProtocolVersion {
44 pub major: u32,
45 pub minor: u32,
46 pub patch: u32,
47}
48
49impl Default for ProtocolVersion {
50 fn default() -> Self {
51 Self {
52 major: 2025,
53 minor: 6,
54 patch: 18,
55 }
56 }
57}
58
59impl std::fmt::Display for ProtocolVersion {
60 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61 write!(f, "{:04}-{:02}-{:02}", self.major, self.minor, self.patch)
62 }
63}
64
65#[derive(Debug, Clone, Serialize, Deserialize)]
67pub struct Implementation {
68 pub name: String,
69 pub version: String,
70}
71
72#[derive(Debug, Clone, Serialize, Deserialize, Default)]
74pub struct ServerCapabilities {
75 #[serde(skip_serializing_if = "Option::is_none")]
76 pub tools: Option<ToolsCapability>,
77 #[serde(skip_serializing_if = "Option::is_none")]
78 pub resources: Option<ResourcesCapability>,
79 #[serde(skip_serializing_if = "Option::is_none")]
80 pub prompts: Option<PromptsCapability>,
81 #[serde(skip_serializing_if = "Option::is_none")]
82 pub logging: Option<LoggingCapability>,
83 #[serde(skip_serializing_if = "Option::is_none")]
84 pub sampling: Option<SamplingCapability>,
85 #[serde(skip_serializing_if = "Option::is_none")]
86 pub elicitation: Option<ElicitationCapability>,
87}
88
89#[derive(Debug, Clone, Serialize, Deserialize, Default)]
90pub struct ToolsCapability {
91 #[serde(skip_serializing_if = "Option::is_none")]
92 pub list_changed: Option<bool>,
93}
94
95#[derive(Debug, Clone, Serialize, Deserialize, Default)]
96pub struct ResourcesCapability {
97 #[serde(skip_serializing_if = "Option::is_none")]
98 pub subscribe: Option<bool>,
99 #[serde(skip_serializing_if = "Option::is_none")]
100 pub list_changed: Option<bool>,
101}
102
103#[derive(Debug, Clone, Serialize, Deserialize, Default)]
104pub struct PromptsCapability {
105 #[serde(skip_serializing_if = "Option::is_none")]
106 pub list_changed: Option<bool>,
107}
108
109#[derive(Debug, Clone, Serialize, Deserialize, Default)]
110pub struct LoggingCapability {
111 #[serde(skip_serializing_if = "Option::is_none")]
112 pub level: Option<String>,
113}
114
115#[derive(Debug, Clone, Serialize, Deserialize, Default)]
116pub struct SamplingCapability {}
117
118#[derive(Debug, Clone, Serialize, Deserialize, Default)]
119pub struct ElicitationCapability {}
120
121impl ServerCapabilities {
122 pub fn builder() -> ServerCapabilitiesBuilder {
123 ServerCapabilitiesBuilder::default()
124 }
125}
126
127#[derive(Default)]
128pub struct ServerCapabilitiesBuilder {
129 capabilities: ServerCapabilities,
130}
131
132impl ServerCapabilitiesBuilder {
133 #[must_use]
134 pub fn enable_tools(mut self) -> Self {
135 self.capabilities.tools = Some(ToolsCapability {
136 list_changed: Some(true),
137 });
138 self
139 }
140
141 #[must_use]
142 pub fn enable_resources(mut self) -> Self {
143 self.capabilities.resources = Some(ResourcesCapability {
144 subscribe: Some(true),
145 list_changed: Some(true),
146 });
147 self
148 }
149
150 #[must_use]
151 pub fn enable_prompts(mut self) -> Self {
152 self.capabilities.prompts = Some(PromptsCapability {
153 list_changed: Some(true),
154 });
155 self
156 }
157
158 #[must_use]
159 pub fn enable_logging(mut self) -> Self {
160 self.capabilities.logging = Some(LoggingCapability {
161 level: Some("info".to_string()),
162 });
163 self
164 }
165
166 #[must_use]
167 pub fn enable_sampling(mut self) -> Self {
168 self.capabilities.sampling = Some(SamplingCapability {});
169 self
170 }
171
172 #[must_use]
173 pub fn enable_elicitation(mut self) -> Self {
174 self.capabilities.elicitation = Some(ElicitationCapability {});
175 self
176 }
177
178 pub fn build(self) -> ServerCapabilities {
179 self.capabilities
180 }
181}
182
183#[derive(Debug, Clone, Serialize, Deserialize)]
185pub struct ServerInfo {
186 pub protocol_version: ProtocolVersion,
187 pub capabilities: ServerCapabilities,
188 pub server_info: Implementation,
189 pub instructions: Option<String>,
190}
191
192#[derive(Debug, Clone, Serialize, Deserialize)]
194#[serde(rename_all = "camelCase")]
195pub struct Tool {
196 pub name: String,
197 pub description: String,
198 pub input_schema: serde_json::Value,
199 #[serde(skip_serializing_if = "Option::is_none")]
200 pub output_schema: Option<serde_json::Value>,
201}
202
203#[derive(Debug, Clone, Serialize, Deserialize)]
205#[serde(rename_all = "camelCase")]
206pub struct ListToolsResult {
207 pub tools: Vec<Tool>,
208 #[serde(skip_serializing_if = "Option::is_none")]
209 pub next_cursor: Option<String>,
210}
211
212#[derive(Debug, Clone, Serialize, Deserialize)]
214pub struct PaginatedRequestParam {
215 pub cursor: Option<String>,
216}
217
218#[derive(Debug, Clone, Serialize, Deserialize)]
220pub struct CallToolRequestParam {
221 pub name: String,
222 pub arguments: Option<serde_json::Value>,
223}
224
225#[derive(Debug, Clone, Serialize, Deserialize)]
227#[serde(tag = "type")]
228pub enum Content {
229 #[serde(rename = "text")]
230 Text { text: String },
231 #[serde(rename = "image")]
232 Image { data: String, mime_type: String },
233 #[serde(rename = "resource")]
234 Resource {
235 resource: String,
236 text: Option<String>,
237 },
238}
239
240impl Content {
241 pub fn text(text: impl Into<String>) -> Self {
242 Self::Text { text: text.into() }
243 }
244
245 pub fn image(data: impl Into<String>, mime_type: impl Into<String>) -> Self {
246 Self::Image {
247 data: data.into(),
248 mime_type: mime_type.into(),
249 }
250 }
251
252 pub fn resource(resource: impl Into<String>, text: Option<String>) -> Self {
253 Self::Resource {
254 resource: resource.into(),
255 text,
256 }
257 }
258
259 pub fn as_text(&self) -> Option<&Self> {
261 match self {
262 Self::Text { .. } => Some(self),
263 _ => None,
264 }
265 }
266}
267
268pub struct TextContent {
270 pub text: String,
271}
272
273impl Content {
274 pub fn as_text_content(&self) -> Option<TextContent> {
276 match self {
277 Self::Text { text } => Some(TextContent { text: text.clone() }),
278 _ => None,
279 }
280 }
281}
282
283#[derive(Debug, Clone, Serialize, Deserialize)]
285#[serde(rename_all = "camelCase")]
286pub struct CallToolResult {
287 pub content: Vec<Content>,
288 pub is_error: Option<bool>,
289 #[serde(skip_serializing_if = "Option::is_none")]
290 pub structured_content: Option<serde_json::Value>,
291}
292
293impl CallToolResult {
294 pub fn success(content: Vec<Content>) -> Self {
295 Self {
296 content,
297 is_error: Some(false),
298 structured_content: None,
299 }
300 }
301
302 pub fn error(content: Vec<Content>) -> Self {
303 Self {
304 content,
305 is_error: Some(true),
306 structured_content: None,
307 }
308 }
309
310 pub fn text(text: impl Into<String>) -> Self {
311 Self::success(vec![Content::text(text)])
312 }
313
314 pub fn error_text(text: impl Into<String>) -> Self {
315 Self::error(vec![Content::text(text)])
316 }
317
318 pub fn structured(content: Vec<Content>, structured_content: serde_json::Value) -> Self {
320 Self {
321 content,
322 is_error: Some(false),
323 structured_content: Some(structured_content),
324 }
325 }
326
327 pub fn structured_error(content: Vec<Content>, structured_content: serde_json::Value) -> Self {
329 Self {
330 content,
331 is_error: Some(true),
332 structured_content: Some(structured_content),
333 }
334 }
335
336 pub fn text_with_structured(
338 text: impl Into<String>,
339 structured_content: serde_json::Value,
340 ) -> Self {
341 Self::structured(vec![Content::text(text)], structured_content)
342 }
343
344 pub fn validate_structured_content(
350 &self,
351 output_schema: &serde_json::Value,
352 ) -> crate::Result<()> {
353 use crate::validation::Validator;
354
355 if let Some(structured_content) = &self.structured_content {
356 Validator::validate_structured_content(structured_content, output_schema)?;
357 }
358 Ok(())
359 }
360}
361
362#[derive(Debug, Clone, Serialize, Deserialize)]
364pub struct Resource {
365 pub uri: String,
366 pub name: String,
367 pub description: Option<String>,
368 pub mime_type: Option<String>,
369 pub annotations: Option<Annotations>,
370 #[serde(skip_serializing_if = "Option::is_none")]
371 pub raw: Option<RawResource>,
372}
373
374#[derive(Debug, Clone, Serialize, Deserialize, Default)]
376pub struct Annotations {
377 pub audience: Option<Vec<String>>,
378 pub priority: Option<f32>,
379}
380
381#[derive(Debug, Clone, Serialize, Deserialize)]
383pub struct ListResourcesResult {
384 pub resources: Vec<Resource>,
385 #[serde(skip_serializing_if = "Option::is_none")]
386 pub next_cursor: Option<String>,
387}
388
389#[derive(Debug, Clone, Serialize, Deserialize)]
391pub struct ReadResourceRequestParam {
392 pub uri: String,
393}
394
395#[derive(Debug, Clone, Serialize, Deserialize)]
397pub struct ResourceContents {
398 pub uri: String,
399 pub mime_type: Option<String>,
400 pub text: Option<String>,
401 pub blob: Option<String>,
402}
403
404#[derive(Debug, Clone, Serialize, Deserialize)]
406pub struct ReadResourceResult {
407 pub contents: Vec<ResourceContents>,
408}
409
410#[derive(Debug, Clone, Serialize, Deserialize)]
412pub struct RawResource {
413 pub uri: String,
414 pub data: Vec<u8>,
415 pub mime_type: Option<String>,
416 pub name: Option<String>,
417 pub description: Option<String>,
418 pub size: Option<usize>,
419}
420
421impl PromptMessage {
422 pub fn new_text(role: PromptMessageRole, text: impl Into<String>) -> Self {
424 Self {
425 role,
426 content: PromptMessageContent::Text { text: text.into() },
427 }
428 }
429
430 pub fn new_image(
432 role: PromptMessageRole,
433 data: impl Into<String>,
434 mime_type: impl Into<String>,
435 ) -> Self {
436 Self {
437 role,
438 content: PromptMessageContent::Image {
439 data: data.into(),
440 mime_type: mime_type.into(),
441 },
442 }
443 }
444}
445
446impl CompleteResult {
447 pub fn simple(completion: impl Into<String>) -> Self {
449 Self {
450 completion: vec![CompletionInfo {
451 completion: completion.into(),
452 has_more: Some(false),
453 }],
454 }
455 }
456}
457
458#[derive(Debug, Clone, Serialize, Deserialize)]
460pub struct Prompt {
461 pub name: String,
462 pub description: Option<String>,
463 pub arguments: Option<Vec<PromptArgument>>,
464}
465
466#[derive(Debug, Clone, Serialize, Deserialize)]
468pub struct PromptArgument {
469 pub name: String,
470 pub description: Option<String>,
471 pub required: Option<bool>,
472}
473
474#[derive(Debug, Clone, Serialize, Deserialize)]
476pub struct ListPromptsResult {
477 pub prompts: Vec<Prompt>,
478 #[serde(skip_serializing_if = "Option::is_none")]
479 pub next_cursor: Option<String>,
480}
481
482#[derive(Debug, Clone, Serialize, Deserialize)]
484pub struct GetPromptRequestParam {
485 pub name: String,
486 pub arguments: Option<HashMap<String, String>>,
487}
488
489#[derive(Debug, Clone, Serialize, Deserialize)]
491#[serde(rename_all = "lowercase")]
492pub enum PromptMessageRole {
493 User,
494 Assistant,
495 System,
496}
497
498#[derive(Debug, Clone, Serialize, Deserialize)]
500#[serde(tag = "type")]
501pub enum PromptMessageContent {
502 #[serde(rename = "text")]
503 Text { text: String },
504 #[serde(rename = "image")]
505 Image { data: String, mime_type: String },
506}
507
508#[derive(Debug, Clone, Serialize, Deserialize)]
510pub struct PromptMessage {
511 pub role: PromptMessageRole,
512 pub content: PromptMessageContent,
513}
514
515#[derive(Debug, Clone, Serialize, Deserialize)]
517pub struct GetPromptResult {
518 pub description: Option<String>,
519 pub messages: Vec<PromptMessage>,
520}
521
522#[derive(Debug, Clone, Serialize, Deserialize)]
524pub struct InitializeRequestParam {
525 #[serde(rename = "protocolVersion")]
526 pub protocol_version: String,
527 pub capabilities: serde_json::Value,
528 #[serde(rename = "clientInfo")]
529 pub client_info: Implementation,
530}
531
532#[derive(Debug, Clone, Serialize, Deserialize)]
534pub struct InitializeResult {
535 #[serde(rename = "protocolVersion")]
536 pub protocol_version: String,
537 pub capabilities: ServerCapabilities,
538 #[serde(rename = "serverInfo")]
539 pub server_info: Implementation,
540 #[serde(skip_serializing_if = "Option::is_none")]
541 pub instructions: Option<String>,
542}
543
544#[derive(Debug, Clone, Serialize, Deserialize)]
546pub struct CompleteRequestParam {
547 pub ref_: String,
548 pub argument: serde_json::Value,
549}
550
551#[derive(Debug, Clone, Serialize, Deserialize)]
553pub struct CompletionInfo {
554 pub completion: String,
555 pub has_more: Option<bool>,
556}
557
558#[derive(Debug, Clone, Serialize, Deserialize)]
560pub struct CompleteResult {
561 pub completion: Vec<CompletionInfo>,
562}
563
564#[derive(Debug, Clone, Serialize, Deserialize)]
566pub struct SetLevelRequestParam {
567 pub level: String,
568}
569
570#[derive(Debug, Clone, Serialize, Deserialize)]
572pub struct ResourceTemplate {
573 #[serde(rename = "uriTemplate")]
574 pub uri_template: String,
575 pub name: String,
576 pub description: Option<String>,
577 #[serde(rename = "mimeType")]
578 pub mime_type: Option<String>,
579}
580
581#[derive(Debug, Clone, Serialize, Deserialize)]
583pub struct ListResourceTemplatesResult {
584 #[serde(rename = "resourceTemplates")]
585 pub resource_templates: Vec<ResourceTemplate>,
586 #[serde(rename = "nextCursor", skip_serializing_if = "Option::is_none")]
587 pub next_cursor: Option<String>,
588}
589
590#[derive(Debug, Clone, Serialize, Deserialize)]
592pub struct SubscribeRequestParam {
593 pub uri: String,
594}
595
596#[derive(Debug, Clone, Serialize, Deserialize)]
598pub struct UnsubscribeRequestParam {
599 pub uri: String,
600}
601
602#[derive(Debug, Clone, Serialize, Deserialize)]
604pub struct ElicitationRequestParam {
605 pub message: String,
606 #[serde(rename = "requestedSchema")]
607 pub requested_schema: serde_json::Value,
608}
609
610#[derive(Debug, Clone, Serialize, Deserialize)]
612#[serde(rename_all = "lowercase")]
613pub enum ElicitationAction {
614 Accept,
615 Decline,
616 Cancel,
617}
618
619#[derive(Debug, Clone, Serialize, Deserialize)]
621pub struct ElicitationResponse {
622 pub action: ElicitationAction,
623 #[serde(skip_serializing_if = "Option::is_none")]
624 pub data: Option<serde_json::Value>,
625}
626
627#[derive(Debug, Clone, Serialize, Deserialize)]
629pub struct ElicitationResult {
630 pub response: ElicitationResponse,
631}
632
633impl ElicitationResult {
634 pub fn accept(data: serde_json::Value) -> Self {
636 Self {
637 response: ElicitationResponse {
638 action: ElicitationAction::Accept,
639 data: Some(data),
640 },
641 }
642 }
643
644 pub fn decline() -> Self {
646 Self {
647 response: ElicitationResponse {
648 action: ElicitationAction::Decline,
649 data: None,
650 },
651 }
652 }
653
654 pub fn cancel() -> Self {
656 Self {
657 response: ElicitationResponse {
658 action: ElicitationAction::Cancel,
659 data: None,
660 },
661 }
662 }
663}