mcp_protocol_sdk/protocol/
types.rs

1//! Complete MCP Protocol Types for 2025-03-26 Specification
2//!
3//! This module contains all the core types defined by the Model Context Protocol
4//! specification version 2025-03-26, including all new features and capabilities.
5
6use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8
9// ============================================================================
10// Core Protocol Constants
11// ============================================================================
12
13/// MCP Protocol version (2025-03-26)
14pub const LATEST_PROTOCOL_VERSION: &str = "2025-03-26";
15pub const JSONRPC_VERSION: &str = "2.0";
16
17// Legacy constant for compatibility
18pub const PROTOCOL_VERSION: &str = LATEST_PROTOCOL_VERSION;
19
20// ============================================================================
21// Type Aliases
22// ============================================================================
23
24/// Progress token for associating notifications with requests
25pub type ProgressToken = serde_json::Value; // string | number
26
27/// Cursor for pagination
28pub type Cursor = String;
29
30/// Request ID for JSON-RPC correlation
31pub type RequestId = serde_json::Value; // string | number | null
32
33/// JSON-RPC ID type for better type safety
34#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
35#[serde(untagged)]
36pub enum JsonRpcId {
37    String(String),
38    Number(i64),
39    Null,
40}
41
42impl From<i64> for JsonRpcId {
43    fn from(value: i64) -> Self {
44        JsonRpcId::Number(value)
45    }
46}
47
48impl From<String> for JsonRpcId {
49    fn from(value: String) -> Self {
50        JsonRpcId::String(value)
51    }
52}
53
54impl From<&str> for JsonRpcId {
55    fn from(value: &str) -> Self {
56        JsonRpcId::String(value.to_string())
57    }
58}
59
60// ============================================================================
61// Core Implementation Info
62// ============================================================================
63
64/// Information about an MCP implementation
65#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
66pub struct Implementation {
67    /// Name of the implementation
68    pub name: String,
69    /// Version of the implementation
70    pub version: String,
71}
72
73// Type aliases for compatibility
74pub type ServerInfo = Implementation;
75pub type ClientInfo = Implementation;
76
77// ============================================================================
78// Capabilities (2025-03-26)
79// ============================================================================
80
81/// Server capabilities for 2025-03-26
82#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
83pub struct ServerCapabilities {
84    /// Prompt-related capabilities
85    #[serde(skip_serializing_if = "Option::is_none")]
86    pub prompts: Option<PromptsCapability>,
87    /// Resource-related capabilities
88    #[serde(skip_serializing_if = "Option::is_none")]
89    pub resources: Option<ResourcesCapability>,
90    /// Tool-related capabilities
91    #[serde(skip_serializing_if = "Option::is_none")]
92    pub tools: Option<ToolsCapability>,
93    /// Sampling-related capabilities
94    #[serde(skip_serializing_if = "Option::is_none")]
95    pub sampling: Option<SamplingCapability>,
96    /// Logging capabilities (2025-03-26)
97    #[serde(skip_serializing_if = "Option::is_none")]
98    pub logging: Option<LoggingCapability>,
99    /// Autocompletion capabilities (2025-03-26)
100    #[serde(skip_serializing_if = "Option::is_none")]
101    pub completions: Option<CompletionsCapability>,
102    /// Experimental capabilities (2025-03-26)
103    #[serde(skip_serializing_if = "Option::is_none")]
104    pub experimental: Option<HashMap<String, serde_json::Value>>,
105}
106
107/// Client capabilities for 2025-03-26
108#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
109pub struct ClientCapabilities {
110    /// Sampling-related capabilities
111    #[serde(skip_serializing_if = "Option::is_none")]
112    pub sampling: Option<SamplingCapability>,
113    /// Roots listing capabilities (2025-03-26)
114    #[serde(skip_serializing_if = "Option::is_none")]
115    pub roots: Option<RootsCapability>,
116    /// Experimental capabilities (2025-03-26)
117    #[serde(skip_serializing_if = "Option::is_none")]
118    pub experimental: Option<HashMap<String, serde_json::Value>>,
119}
120
121/// Prompt-related server capabilities
122#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
123pub struct PromptsCapability {
124    /// Whether the server supports prompt list change notifications
125    #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
126    pub list_changed: Option<bool>,
127}
128
129/// Resource-related server capabilities
130#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
131pub struct ResourcesCapability {
132    /// Whether the server supports resource subscriptions
133    #[serde(skip_serializing_if = "Option::is_none")]
134    pub subscribe: Option<bool>,
135    /// Whether the server supports resource list change notifications
136    #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
137    pub list_changed: Option<bool>,
138}
139
140/// Tool-related server capabilities
141#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
142pub struct ToolsCapability {
143    /// Whether the server supports tool list change notifications
144    #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
145    pub list_changed: Option<bool>,
146}
147
148/// Sampling-related capabilities
149#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
150pub struct SamplingCapability {
151    /// Additional properties
152    #[serde(flatten)]
153    pub additional_properties: HashMap<String, serde_json::Value>,
154}
155
156/// Logging capabilities (2025-03-26)
157#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
158pub struct LoggingCapability {
159    /// Additional properties
160    #[serde(flatten)]
161    pub additional_properties: HashMap<String, serde_json::Value>,
162}
163
164/// Autocompletion capabilities (2025-03-26)
165#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
166pub struct CompletionsCapability {
167    /// Additional properties
168    #[serde(flatten)]
169    pub additional_properties: HashMap<String, serde_json::Value>,
170}
171
172/// Roots capability for clients (2025-03-26)
173#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
174pub struct RootsCapability {
175    /// Whether the client supports notifications for changes to the roots list
176    #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
177    pub list_changed: Option<bool>,
178}
179
180// ============================================================================
181// Annotations (2025-03-26 NEW)
182// ============================================================================
183
184/// Tool behavior annotations (2025-03-26)
185#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
186pub struct Annotations {
187    /// Target audience for this tool
188    #[serde(skip_serializing_if = "Option::is_none")]
189    pub audience: Option<Vec<AnnotationAudience>>,
190    /// Danger level of this tool
191    #[serde(skip_serializing_if = "Option::is_none")]
192    pub danger: Option<DangerLevel>,
193    /// Whether this tool performs destructive operations
194    #[serde(skip_serializing_if = "Option::is_none")]
195    pub destructive: Option<bool>,
196    /// Whether this tool is read-only (no side effects)
197    #[serde(rename = "readOnly", skip_serializing_if = "Option::is_none")]
198    pub read_only: Option<bool>,
199}
200
201/// Target audience for tool usage
202#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
203#[serde(rename_all = "lowercase")]
204pub enum AnnotationAudience {
205    /// For general users
206    User,
207    /// For developers and technical users
208    Developer,
209    /// For administrative operations
210    Admin,
211}
212
213/// Danger level classification for tools
214#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
215#[serde(rename_all = "lowercase")]
216pub enum DangerLevel {
217    /// Safe operations with no risk
218    Safe,
219    /// Low risk operations
220    Low,
221    /// Medium risk operations
222    Medium,
223    /// High risk operations
224    High,
225    /// Critical operations
226    Critical,
227}
228
229// ============================================================================
230// Content Types (2025-03-26 with Audio Support)
231// ============================================================================
232
233/// Text content
234#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
235pub struct TextContent {
236    /// Content type identifier
237    #[serde(rename = "type")]
238    pub content_type: String, // "text"
239    /// The text content
240    pub text: String,
241    /// Content annotations (2025-03-26)
242    #[serde(skip_serializing_if = "Option::is_none")]
243    pub annotations: Option<Annotations>,
244}
245
246/// Image content
247#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
248pub struct ImageContent {
249    /// Content type identifier
250    #[serde(rename = "type")]
251    pub content_type: String, // "image"
252    /// Base64-encoded image data
253    pub data: String,
254    /// MIME type of the image
255    #[serde(rename = "mimeType")]
256    pub mime_type: String,
257    /// Content annotations (2025-03-26)
258    #[serde(skip_serializing_if = "Option::is_none")]
259    pub annotations: Option<Annotations>,
260}
261
262/// Audio content (2025-03-26 NEW)
263#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
264pub struct AudioContent {
265    /// Content type identifier
266    #[serde(rename = "type")]
267    pub content_type: String, // "audio"
268    /// Base64-encoded audio data
269    pub data: String,
270    /// MIME type of the audio
271    #[serde(rename = "mimeType")]
272    pub mime_type: String,
273    /// Content annotations (2025-03-26)
274    #[serde(skip_serializing_if = "Option::is_none")]
275    pub annotations: Option<Annotations>,
276}
277
278/// Embedded resource content (2025-03-26)
279#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
280pub struct EmbeddedResource {
281    /// Content type identifier
282    #[serde(rename = "type")]
283    pub content_type: String, // "resource"
284    /// Resource reference
285    pub resource: ResourceReference,
286    /// Content annotations (2025-03-26)
287    #[serde(skip_serializing_if = "Option::is_none")]
288    pub annotations: Option<Annotations>,
289}
290
291/// Resource reference for embedded resources
292#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
293pub struct ResourceReference {
294    /// URI of the resource
295    pub uri: String,
296}
297
298/// Unified content type (2025-03-26 complete)
299#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
300#[serde(tag = "type")]
301pub enum Content {
302    /// Text content
303    #[serde(rename = "text")]
304    Text {
305        /// The text content
306        text: String,
307        /// Content annotations (2025-03-26)
308        #[serde(skip_serializing_if = "Option::is_none")]
309        annotations: Option<Annotations>,
310    },
311    /// Image content
312    #[serde(rename = "image")]
313    Image {
314        /// Base64-encoded image data
315        data: String,
316        /// MIME type of the image
317        #[serde(rename = "mimeType")]
318        mime_type: String,
319        /// Content annotations (2025-03-26)
320        #[serde(skip_serializing_if = "Option::is_none")]
321        annotations: Option<Annotations>,
322    },
323    /// Audio content (2025-03-26 NEW)
324    #[serde(rename = "audio")]
325    Audio {
326        /// Base64-encoded audio data
327        data: String,
328        /// MIME type of the audio
329        #[serde(rename = "mimeType")]
330        mime_type: String,
331        /// Content annotations (2025-03-26)
332        #[serde(skip_serializing_if = "Option::is_none")]
333        annotations: Option<Annotations>,
334    },
335    /// Embedded resource content (2025-03-26 NEW)
336    #[serde(rename = "resource")]
337    Resource {
338        /// Resource reference
339        resource: ResourceReference,
340        /// Content annotations (2025-03-26)
341        #[serde(skip_serializing_if = "Option::is_none")]
342        annotations: Option<Annotations>,
343    },
344}
345
346// ============================================================================
347// Tool Types (2025-03-26 with Annotations)
348// ============================================================================
349
350/// Tool definition with annotations (2025-03-26)
351#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
352pub struct Tool {
353    /// Name of the tool
354    pub name: String,
355    /// Description of what the tool does
356    #[serde(skip_serializing_if = "Option::is_none")]
357    pub description: Option<String>,
358    /// JSON Schema describing the tool's input parameters
359    #[serde(rename = "inputSchema")]
360    pub input_schema: ToolInputSchema,
361    /// Tool behavior annotations (2025-03-26 NEW)
362    #[serde(skip_serializing_if = "Option::is_none")]
363    pub annotations: Option<Annotations>,
364}
365
366/// Tool input schema
367#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
368pub struct ToolInputSchema {
369    /// Schema type (always "object")
370    #[serde(rename = "type")]
371    pub schema_type: String,
372    /// Schema properties
373    #[serde(skip_serializing_if = "Option::is_none")]
374    pub properties: Option<HashMap<String, serde_json::Value>>,
375    /// Required properties
376    #[serde(skip_serializing_if = "Option::is_none")]
377    pub required: Option<Vec<String>>,
378    /// Additional schema properties
379    #[serde(flatten)]
380    pub additional_properties: HashMap<String, serde_json::Value>,
381}
382
383/// Result of a tool execution (2025-03-26 with metadata)
384#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
385pub struct CallToolResult {
386    /// Content returned by the tool
387    pub content: Vec<Content>,
388    /// Whether this result represents an error
389    #[serde(rename = "isError", skip_serializing_if = "Option::is_none")]
390    pub is_error: Option<bool>,
391    /// Result metadata (2025-03-26 NEW)
392    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
393    pub meta: Option<HashMap<String, serde_json::Value>>,
394}
395
396// Re-export types with legacy names for compatibility
397pub type ToolInfo = Tool;
398pub type ToolResult = CallToolResult;
399
400// ============================================================================
401// Resource Types (2025-03-26)
402// ============================================================================
403
404/// Resource definition
405#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
406pub struct Resource {
407    /// URI of the resource
408    pub uri: String,
409    /// Human-readable name of the resource
410    #[serde(skip_serializing_if = "Option::is_none")]
411    pub name: Option<String>,
412    /// Description of the resource
413    #[serde(skip_serializing_if = "Option::is_none")]
414    pub description: Option<String>,
415    /// MIME type of the resource
416    #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
417    pub mime_type: Option<String>,
418    /// Resource annotations (2025-03-26)
419    #[serde(skip_serializing_if = "Option::is_none")]
420    pub annotations: Option<Annotations>,
421    /// Resource size in bytes (2025-03-26)
422    #[serde(skip_serializing_if = "Option::is_none")]
423    pub size: Option<u64>,
424}
425
426/// Resource template for URI patterns
427#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
428pub struct ResourceTemplate {
429    /// URI template with variables
430    #[serde(rename = "uriTemplate")]
431    pub uri_template: String,
432    /// Human-readable name
433    #[serde(skip_serializing_if = "Option::is_none")]
434    pub name: Option<String>,
435    /// Description of the resource template
436    #[serde(skip_serializing_if = "Option::is_none")]
437    pub description: Option<String>,
438    /// MIME type of resources from this template
439    #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
440    pub mime_type: Option<String>,
441}
442
443/// Content of a resource
444#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
445#[serde(untagged)]
446pub enum ResourceContents {
447    /// Text resource content
448    Text {
449        /// URI of the resource
450        uri: String,
451        /// MIME type
452        #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
453        mime_type: Option<String>,
454        /// Text content
455        text: String,
456    },
457    /// Binary resource content
458    Blob {
459        /// URI of the resource
460        uri: String,
461        /// MIME type
462        #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
463        mime_type: Option<String>,
464        /// Base64-encoded binary data
465        blob: String,
466    },
467}
468
469// Legacy type aliases for compatibility
470pub type ResourceInfo = Resource;
471
472// ============================================================================
473// Prompt Types (2025-03-26)
474// ============================================================================
475
476/// Prompt definition
477#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
478pub struct Prompt {
479    /// Name of the prompt
480    pub name: String,
481    /// Description of what the prompt does
482    #[serde(skip_serializing_if = "Option::is_none")]
483    pub description: Option<String>,
484    /// Arguments that the prompt accepts
485    #[serde(skip_serializing_if = "Option::is_none")]
486    pub arguments: Option<Vec<PromptArgument>>,
487}
488
489/// Argument for a prompt
490#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
491pub struct PromptArgument {
492    /// Name of the argument
493    pub name: String,
494    /// Description of the argument
495    #[serde(skip_serializing_if = "Option::is_none")]
496    pub description: Option<String>,
497    /// Whether this argument is required
498    #[serde(skip_serializing_if = "Option::is_none")]
499    pub required: Option<bool>,
500}
501
502/// Message role
503#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
504#[serde(rename_all = "lowercase")]
505pub enum Role {
506    User,
507    Assistant,
508}
509
510/// Message in a prompt result (2025-03-26 with audio support)
511#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
512pub struct PromptMessage {
513    /// Role of the message
514    pub role: Role,
515    /// Content of the message (supports all content types)
516    pub content: Content,
517}
518
519/// Result of prompt execution (2025-03-26 with metadata)
520#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
521pub struct GetPromptResult {
522    /// Description of the prompt result
523    #[serde(skip_serializing_if = "Option::is_none")]
524    pub description: Option<String>,
525    /// Messages generated by the prompt
526    pub messages: Vec<PromptMessage>,
527    /// Result metadata (2025-03-26 NEW)
528    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
529    pub meta: Option<HashMap<String, serde_json::Value>>,
530}
531
532// Legacy type aliases for compatibility
533pub type PromptInfo = Prompt;
534pub type PromptResult = GetPromptResult;
535
536// ============================================================================
537// Sampling Types (2025-03-26)
538// ============================================================================
539
540/// A message in a sampling conversation (2025-03-26 with audio)
541#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
542pub struct SamplingMessage {
543    /// Role of the message
544    pub role: Role,
545    /// Content of the message (text, image, or audio)
546    pub content: Content,
547}
548
549/// Model preferences for sampling
550#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
551pub struct ModelPreferences {
552    /// Hints about cost constraints
553    #[serde(rename = "costPriority", skip_serializing_if = "Option::is_none")]
554    pub cost_priority: Option<f32>,
555    /// Hints about speed constraints
556    #[serde(rename = "speedPriority", skip_serializing_if = "Option::is_none")]
557    pub speed_priority: Option<f32>,
558    /// Hints about quality constraints
559    #[serde(rename = "qualityPriority", skip_serializing_if = "Option::is_none")]
560    pub quality_priority: Option<f32>,
561}
562
563/// Result of sampling/createMessage (2025-03-26)
564#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
565pub struct CreateMessageResult {
566    /// Role of the generated message
567    pub role: Role,
568    /// Content of the generated message
569    pub content: Content,
570    /// Model used for generation
571    pub model: String,
572    /// Stop reason
573    #[serde(rename = "stopReason", skip_serializing_if = "Option::is_none")]
574    pub stop_reason: Option<StopReason>,
575    /// Result metadata (2025-03-26 NEW)
576    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
577    pub meta: Option<HashMap<String, serde_json::Value>>,
578}
579
580/// Reasons why sampling stopped
581#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
582#[serde(rename_all = "camelCase")]
583pub enum StopReason {
584    EndTurn,
585    StopSequence,
586    MaxTokens,
587    #[serde(untagged)]
588    Other(String),
589}
590
591// ============================================================================
592// Logging Types (2025-03-26)
593// ============================================================================
594
595/// Logging level enumeration (2025-03-26)
596#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
597#[serde(rename_all = "lowercase")]
598pub enum LoggingLevel {
599    Debug,
600    Info,
601    Notice,
602    Warning,
603    Error,
604    Critical,
605    Alert,
606    Emergency,
607}
608
609// ============================================================================
610// JSON-RPC Types (2025-03-26 with Batching)
611// ============================================================================
612
613/// JSON-RPC request message
614#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
615pub struct JsonRpcRequest {
616    /// JSON-RPC version (always "2.0")
617    pub jsonrpc: String,
618    /// Request ID for correlation
619    pub id: RequestId,
620    /// Method name being called
621    pub method: String,
622    /// Method parameters
623    #[serde(skip_serializing_if = "Option::is_none")]
624    pub params: Option<serde_json::Value>,
625}
626
627/// JSON-RPC response message
628#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
629pub struct JsonRpcResponse {
630    /// JSON-RPC version (always "2.0")
631    pub jsonrpc: String,
632    /// Request ID for correlation
633    pub id: RequestId,
634    /// Result of the method call
635    #[serde(skip_serializing_if = "Option::is_none")]
636    pub result: Option<serde_json::Value>,
637}
638
639/// JSON-RPC error message
640#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
641pub struct JsonRpcError {
642    /// JSON-RPC version (always "2.0")
643    pub jsonrpc: String,
644    /// Request ID for correlation
645    pub id: RequestId,
646    /// Error information
647    pub error: ErrorObject,
648}
649
650/// Error object
651#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
652pub struct ErrorObject {
653    /// Error code
654    pub code: i32,
655    /// Error message
656    pub message: String,
657    /// Additional error data
658    #[serde(skip_serializing_if = "Option::is_none")]
659    pub data: Option<serde_json::Value>,
660}
661
662/// JSON-RPC notification message
663#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
664pub struct JsonRpcNotification {
665    /// JSON-RPC version (always "2.0")
666    pub jsonrpc: String,
667    /// Method name being called
668    pub method: String,
669    /// Method parameters
670    #[serde(skip_serializing_if = "Option::is_none")]
671    pub params: Option<serde_json::Value>,
672}
673
674/// JSON-RPC batch request (2025-03-26 NEW)
675pub type JsonRpcBatchRequest = Vec<JsonRpcRequestOrNotification>;
676
677/// JSON-RPC batch response (2025-03-26 NEW)
678pub type JsonRpcBatchResponse = Vec<JsonRpcResponseOrError>;
679
680/// Items in a batch request
681#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
682#[serde(untagged)]
683pub enum JsonRpcRequestOrNotification {
684    Request(JsonRpcRequest),
685    Notification(JsonRpcNotification),
686}
687
688/// Items in a batch response
689#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
690#[serde(untagged)]
691pub enum JsonRpcResponseOrError {
692    Response(JsonRpcResponse),
693    Error(JsonRpcError),
694}
695
696/// Complete JSON-RPC message types (2025-03-26)
697#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
698#[serde(untagged)]
699pub enum JsonRpcMessage {
700    Request(JsonRpcRequest),
701    Response(JsonRpcResponse),
702    Error(JsonRpcError),
703    Notification(JsonRpcNotification),
704    BatchRequest(JsonRpcBatchRequest),
705    BatchResponse(JsonRpcBatchResponse),
706}
707
708// ============================================================================
709// Request/Response Metadata (2025-03-26 NEW)
710// ============================================================================
711
712/// Base request with metadata support
713#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
714pub struct Request {
715    /// Method name
716    pub method: String,
717    /// Parameters with metadata support
718    #[serde(skip_serializing_if = "Option::is_none")]
719    pub params: Option<RequestParams>,
720}
721
722/// Request parameters with metadata
723#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
724pub struct RequestParams {
725    /// Request metadata (2025-03-26 NEW)
726    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
727    pub meta: Option<RequestMeta>,
728    /// Additional parameters
729    #[serde(flatten)]
730    pub params: HashMap<String, serde_json::Value>,
731}
732
733/// Request metadata
734#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
735pub struct RequestMeta {
736    /// Progress token for out-of-band progress notifications
737    #[serde(rename = "progressToken", skip_serializing_if = "Option::is_none")]
738    pub progress_token: Option<ProgressToken>,
739}
740
741/// Base notification with metadata support
742#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
743pub struct Notification {
744    /// Method name
745    pub method: String,
746    /// Parameters with metadata support
747    #[serde(skip_serializing_if = "Option::is_none")]
748    pub params: Option<NotificationParams>,
749}
750
751/// Notification parameters with metadata
752#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
753pub struct NotificationParams {
754    /// Notification metadata (2025-03-26 NEW)
755    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
756    pub meta: Option<HashMap<String, serde_json::Value>>,
757    /// Additional parameters
758    #[serde(flatten)]
759    pub params: HashMap<String, serde_json::Value>,
760}
761
762// ============================================================================
763// Pagination Support
764// ============================================================================
765
766/// Base for paginated requests
767#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
768pub struct PaginatedRequest {
769    /// Cursor for pagination
770    #[serde(skip_serializing_if = "Option::is_none")]
771    pub cursor: Option<Cursor>,
772}
773
774/// Base for paginated results
775#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
776pub struct PaginatedResult {
777    /// Cursor for next page
778    #[serde(rename = "nextCursor", skip_serializing_if = "Option::is_none")]
779    pub next_cursor: Option<Cursor>,
780}
781
782// ============================================================================
783// Helper Constructors
784// ============================================================================
785
786impl Content {
787    /// Create text content
788    pub fn text<S: Into<String>>(text: S) -> Self {
789        Self::Text {
790            text: text.into(),
791            annotations: None,
792        }
793    }
794
795    /// Create image content
796    pub fn image<S: Into<String>>(data: S, mime_type: S) -> Self {
797        Self::Image {
798            data: data.into(),
799            mime_type: mime_type.into(),
800            annotations: None,
801        }
802    }
803
804    /// Create audio content (2025-03-26 NEW)
805    pub fn audio<S: Into<String>>(data: S, mime_type: S) -> Self {
806        Self::Audio {
807            data: data.into(),
808            mime_type: mime_type.into(),
809            annotations: None,
810        }
811    }
812
813    /// Create embedded resource content (2025-03-26 NEW)
814    pub fn resource<S: Into<String>>(uri: S) -> Self {
815        Self::Resource {
816            resource: ResourceReference { uri: uri.into() },
817            annotations: None,
818        }
819    }
820}
821
822impl Annotations {
823    /// Create new annotations
824    pub fn new() -> Self {
825        Self {
826            audience: None,
827            danger: None,
828            destructive: None,
829            read_only: None,
830        }
831    }
832
833    /// Mark as read-only tool
834    pub fn read_only(mut self) -> Self {
835        self.read_only = Some(true);
836        self.destructive = Some(false);
837        self
838    }
839
840    /// Mark as destructive tool
841    pub fn destructive(mut self, danger: DangerLevel) -> Self {
842        self.destructive = Some(true);
843        self.read_only = Some(false);
844        self.danger = Some(danger);
845        self
846    }
847
848    /// Set audience
849    pub fn for_audience(mut self, audience: Vec<AnnotationAudience>) -> Self {
850        self.audience = Some(audience);
851        self
852    }
853
854    /// Set danger level
855    pub fn with_danger_level(mut self, danger: DangerLevel) -> Self {
856        self.danger = Some(danger);
857        self
858    }
859}
860
861impl Tool {
862    /// Create a new tool
863    pub fn new<S: Into<String>>(name: S, description: S) -> Self {
864        Self {
865            name: name.into(),
866            description: Some(description.into()),
867            input_schema: ToolInputSchema {
868                schema_type: "object".to_string(),
869                properties: None,
870                required: None,
871                additional_properties: HashMap::new(),
872            },
873            annotations: None,
874        }
875    }
876
877    /// Add annotations to the tool
878    pub fn with_annotations(mut self, annotations: Annotations) -> Self {
879        self.annotations = Some(annotations);
880        self
881    }
882}
883
884impl JsonRpcRequest {
885    /// Create a new JSON-RPC request
886    pub fn new<T: Serialize>(
887        id: RequestId,
888        method: String,
889        params: Option<T>,
890    ) -> std::result::Result<Self, serde_json::Error> {
891        let params = match params {
892            Some(p) => Some(serde_json::to_value(p)?),
893            None => None,
894        };
895
896        Ok(Self {
897            jsonrpc: JSONRPC_VERSION.to_string(),
898            id,
899            method,
900            params,
901        })
902    }
903}
904
905impl JsonRpcResponse {
906    /// Create a successful JSON-RPC response
907    pub fn success<T: Serialize>(
908        id: RequestId,
909        result: T,
910    ) -> std::result::Result<Self, serde_json::Error> {
911        Ok(Self {
912            jsonrpc: JSONRPC_VERSION.to_string(),
913            id,
914            result: Some(serde_json::to_value(result)?),
915        })
916    }
917}
918
919impl JsonRpcError {
920    /// Create an error JSON-RPC response
921    pub fn error(
922        id: RequestId,
923        code: i32,
924        message: String,
925        data: Option<serde_json::Value>,
926    ) -> Self {
927        Self {
928            jsonrpc: JSONRPC_VERSION.to_string(),
929            id,
930            error: ErrorObject {
931                code,
932                message,
933                data,
934            },
935        }
936    }
937}
938
939impl JsonRpcNotification {
940    /// Create a new JSON-RPC notification
941    pub fn new<T: Serialize>(
942        method: String,
943        params: Option<T>,
944    ) -> std::result::Result<Self, serde_json::Error> {
945        let params = match params {
946            Some(p) => Some(serde_json::to_value(p)?),
947            None => None,
948        };
949
950        Ok(Self {
951            jsonrpc: JSONRPC_VERSION.to_string(),
952            method,
953            params,
954        })
955    }
956}
957
958impl SamplingMessage {
959    /// Create a user text message
960    pub fn user_text<S: Into<String>>(text: S) -> Self {
961        Self {
962            role: Role::User,
963            content: Content::text(text),
964        }
965    }
966
967    /// Create an assistant text message
968    pub fn assistant_text<S: Into<String>>(text: S) -> Self {
969        Self {
970            role: Role::Assistant,
971            content: Content::text(text),
972        }
973    }
974}
975
976// ============================================================================
977// Error Codes
978// ============================================================================
979
980/// Standard JSON-RPC error codes
981pub mod error_codes {
982    /// Invalid JSON was received
983    pub const PARSE_ERROR: i32 = -32700;
984    /// The JSON sent is not a valid Request object
985    pub const INVALID_REQUEST: i32 = -32600;
986    /// The method does not exist / is not available
987    pub const METHOD_NOT_FOUND: i32 = -32601;
988    /// Invalid method parameter(s)
989    pub const INVALID_PARAMS: i32 = -32602;
990    /// Internal JSON-RPC error
991    pub const INTERNAL_ERROR: i32 = -32603;
992
993    /// MCP-specific error codes
994    pub const TOOL_NOT_FOUND: i32 = -32000;
995    pub const RESOURCE_NOT_FOUND: i32 = -32001;
996    pub const PROMPT_NOT_FOUND: i32 = -32002;
997}
998
999#[cfg(test)]
1000mod tests {
1001    use super::*;
1002    use serde_json::json;
1003
1004    #[test]
1005    fn test_protocol_version() {
1006        assert_eq!(LATEST_PROTOCOL_VERSION, "2025-03-26");
1007        assert_eq!(JSONRPC_VERSION, "2.0");
1008    }
1009
1010    #[test]
1011    fn test_content_types() {
1012        // Test text content
1013        let text = Content::text("Hello, world!");
1014        let json = serde_json::to_value(&text).unwrap();
1015        assert_eq!(json["type"], "text");
1016        assert_eq!(json["text"], "Hello, world!");
1017
1018        // Test audio content (new in 2025-03-26)
1019        let audio = Content::audio("base64data", "audio/wav");
1020        let json = serde_json::to_value(&audio).unwrap();
1021        assert_eq!(json["type"], "audio");
1022        assert_eq!(json["data"], "base64data");
1023        assert_eq!(json["mimeType"], "audio/wav");
1024
1025        // Test resource content (new in 2025-03-26)
1026        let resource = Content::resource("file:///test.txt");
1027        let json = serde_json::to_value(&resource).unwrap();
1028        assert_eq!(json["type"], "resource");
1029        assert_eq!(json["resource"]["uri"], "file:///test.txt");
1030    }
1031
1032    #[test]
1033    fn test_annotations() {
1034        let annotations = Annotations::new()
1035            .read_only()
1036            .for_audience(vec![AnnotationAudience::Developer])
1037            .with_danger_level(DangerLevel::Safe);
1038
1039        assert_eq!(annotations.read_only, Some(true));
1040        assert_eq!(annotations.destructive, Some(false));
1041        assert_eq!(annotations.danger, Some(DangerLevel::Safe));
1042        assert_eq!(
1043            annotations.audience,
1044            Some(vec![AnnotationAudience::Developer])
1045        );
1046    }
1047
1048    #[test]
1049    fn test_tool_with_annotations() {
1050        let tool = Tool::new("safe_reader", "Read file safely")
1051            .with_annotations(Annotations::new().read_only());
1052
1053        assert_eq!(tool.name, "safe_reader");
1054        assert!(tool.annotations.is_some());
1055        assert_eq!(tool.annotations.unwrap().read_only, Some(true));
1056    }
1057
1058    #[test]
1059    fn test_jsonrpc_batching() {
1060        let req1 = JsonRpcRequest::new(json!(1), "method1".to_string(), Some(json!({}))).unwrap();
1061        let req2 = JsonRpcRequest::new::<serde_json::Value>(json!(2), "method2".to_string(), None)
1062            .unwrap();
1063
1064        let batch: JsonRpcBatchRequest = vec![
1065            JsonRpcRequestOrNotification::Request(req1),
1066            JsonRpcRequestOrNotification::Request(req2),
1067        ];
1068
1069        let json = serde_json::to_value(&batch).unwrap();
1070        assert!(json.is_array());
1071        assert_eq!(json.as_array().unwrap().len(), 2);
1072    }
1073
1074    #[test]
1075    fn test_server_capabilities_2025() {
1076        let caps = ServerCapabilities {
1077            tools: Some(ToolsCapability {
1078                list_changed: Some(true),
1079            }),
1080            completions: Some(CompletionsCapability::default()),
1081            logging: Some(LoggingCapability::default()),
1082            experimental: Some(HashMap::new()),
1083            ..Default::default()
1084        };
1085
1086        let json = serde_json::to_value(&caps).unwrap();
1087        assert!(json["tools"]["listChanged"].as_bool().unwrap());
1088        assert!(json["completions"].is_object());
1089        assert!(json["logging"].is_object());
1090        assert!(json["experimental"].is_object());
1091    }
1092}