turbomcp_protocol/
types.rs

1//! # MCP Protocol Types
2//!
3//! This module contains all the type definitions for the Model Context Protocol
4//! according to the 2025-06-18 specification.
5
6use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8use turbomcp_core::MessageId;
9
10/// Protocol version string
11pub type ProtocolVersion = String;
12
13/// JSON-RPC request identifier
14pub type RequestId = MessageId;
15
16/// Progress token for tracking long-running operations
17///
18/// Per MCP 2025-06-18 specification, progress tokens can be either strings or integers
19/// to provide flexibility in how clients and servers track long-running operations.
20#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
21#[serde(untagged)]
22pub enum ProgressToken {
23    /// String-based progress token
24    String(String),
25    /// Integer-based progress token
26    Integer(i64),
27}
28
29impl ProgressToken {
30    /// Create a new string-based progress token
31    pub fn from_string<S: Into<String>>(s: S) -> Self {
32        Self::String(s.into())
33    }
34
35    /// Create a new integer-based progress token
36    pub fn from_integer(i: i64) -> Self {
37        Self::Integer(i)
38    }
39
40    /// Check if this is a string token
41    pub fn is_string(&self) -> bool {
42        matches!(self, Self::String(_))
43    }
44
45    /// Check if this is an integer token
46    pub fn is_integer(&self) -> bool {
47        matches!(self, Self::Integer(_))
48    }
49
50    /// Get the string value if this is a string token
51    pub fn as_string(&self) -> Option<&str> {
52        match self {
53            Self::String(s) => Some(s),
54            Self::Integer(_) => None,
55        }
56    }
57
58    /// Get the integer value if this is an integer token
59    pub fn as_integer(&self) -> Option<i64> {
60        match self {
61            Self::String(_) => None,
62            Self::Integer(i) => Some(*i),
63        }
64    }
65
66    /// Convert to a string representation for display/logging
67    pub fn to_display_string(&self) -> String {
68        match self {
69            Self::String(s) => s.clone(),
70            Self::Integer(i) => i.to_string(),
71        }
72    }
73}
74
75impl std::fmt::Display for ProgressToken {
76    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77        match self {
78            Self::String(s) => write!(f, "{}", s),
79            Self::Integer(i) => write!(f, "{}", i),
80        }
81    }
82}
83
84impl From<String> for ProgressToken {
85    fn from(s: String) -> Self {
86        Self::String(s)
87    }
88}
89
90impl From<&str> for ProgressToken {
91    fn from(s: &str) -> Self {
92        Self::String(s.to_string())
93    }
94}
95
96impl From<i64> for ProgressToken {
97    fn from(i: i64) -> Self {
98        Self::Integer(i)
99    }
100}
101
102impl From<i32> for ProgressToken {
103    fn from(i: i32) -> Self {
104        Self::Integer(i64::from(i))
105    }
106}
107
108impl From<u32> for ProgressToken {
109    fn from(i: u32) -> Self {
110        Self::Integer(i64::from(i))
111    }
112}
113
114/// URI string
115pub type Uri = String;
116
117/// MIME type
118pub type MimeType = String;
119
120/// Base64 encoded data
121pub type Base64String = String;
122
123// ============================================================================
124// JSON-RPC Error Codes
125// ============================================================================
126
127/// Standard JSON-RPC error codes per specification
128pub mod error_codes {
129    /// Parse error - Invalid JSON was received by the server
130    pub const PARSE_ERROR: i32 = -32700;
131    /// Invalid Request - The JSON sent is not a valid Request object
132    pub const INVALID_REQUEST: i32 = -32600;
133    /// Method not found - The method does not exist / is not available
134    pub const METHOD_NOT_FOUND: i32 = -32601;
135    /// Invalid params - Invalid method parameter(s)
136    pub const INVALID_PARAMS: i32 = -32602;
137    /// Internal error - Internal JSON-RPC error
138    pub const INTERNAL_ERROR: i32 = -32603;
139}
140
141/// JSON-RPC error structure per MCP 2025-06-18 specification
142#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
143pub struct JsonRpcError {
144    /// The error type that occurred
145    pub code: i32,
146    /// A short description of the error (should be limited to a concise single sentence)
147    pub message: String,
148    /// Additional information about the error (detailed error information, nested errors, etc.)
149    #[serde(skip_serializing_if = "Option::is_none")]
150    pub data: Option<serde_json::Value>,
151}
152
153impl JsonRpcError {
154    /// Create a new JSON-RPC error
155    pub fn new(code: i32, message: String) -> Self {
156        Self {
157            code,
158            message,
159            data: None,
160        }
161    }
162
163    /// Create a new JSON-RPC error with additional data
164    pub fn with_data(code: i32, message: String, data: serde_json::Value) -> Self {
165        Self {
166            code,
167            message,
168            data: Some(data),
169        }
170    }
171
172    /// Create a parse error
173    pub fn parse_error() -> Self {
174        Self::new(error_codes::PARSE_ERROR, "Parse error".to_string())
175    }
176
177    /// Create an invalid request error
178    pub fn invalid_request() -> Self {
179        Self::new(error_codes::INVALID_REQUEST, "Invalid Request".to_string())
180    }
181
182    /// Create a method not found error
183    pub fn method_not_found(method: &str) -> Self {
184        Self::new(
185            error_codes::METHOD_NOT_FOUND,
186            format!("Method not found: {method}"),
187        )
188    }
189
190    /// Create an invalid params error
191    pub fn invalid_params(details: &str) -> Self {
192        Self::new(
193            error_codes::INVALID_PARAMS,
194            format!("Invalid params: {details}"),
195        )
196    }
197
198    /// Create an internal error
199    pub fn internal_error(details: &str) -> Self {
200        Self::new(
201            error_codes::INTERNAL_ERROR,
202            format!("Internal error: {details}"),
203        )
204    }
205}
206
207/// Cursor for pagination
208pub type Cursor = String;
209
210// ============================================================================
211// Base Metadata Interface
212// ============================================================================
213
214/// Base interface for metadata with name (identifier) and title (display name) properties.
215/// Per MCP specification 2025-06-18, this is the foundation for Tool, Resource, and Prompt metadata.
216#[derive(Debug, Clone, Serialize, Deserialize)]
217pub struct BaseMetadata {
218    /// Intended for programmatic or logical use, but used as a display name in past specs or fallback (if title isn't present).
219    pub name: String,
220
221    /// Intended for UI and end-user contexts — optimized to be human-readable and easily understood,
222    /// even by those unfamiliar with domain-specific terminology.
223    ///
224    /// If not provided, the name should be used for display (except for Tool,
225    /// where `annotations.title` should be given precedence over using `name`, if present).
226    #[serde(skip_serializing_if = "Option::is_none")]
227    pub title: Option<String>,
228}
229
230/// Implementation information for MCP clients and servers
231#[derive(Debug, Clone, Serialize, Deserialize)]
232pub struct Implementation {
233    /// Implementation name
234    pub name: String,
235    /// Implementation display title
236    #[serde(skip_serializing_if = "Option::is_none")]
237    pub title: Option<String>,
238    /// Implementation version
239    pub version: String,
240}
241
242/// General annotations that can be attached to various MCP objects
243#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
244pub struct Annotations {
245    /// Audience-specific hints or information
246    #[serde(skip_serializing_if = "Option::is_none")]
247    pub audience: Option<Vec<String>>,
248    /// Priority level for ordering or importance
249    #[serde(skip_serializing_if = "Option::is_none")]
250    pub priority: Option<f64>,
251    /// The moment the resource was last modified, as an ISO 8601 formatted string
252    #[serde(skip_serializing_if = "Option::is_none")]
253    #[serde(rename = "lastModified")]
254    pub last_modified: Option<String>,
255    /// Additional custom annotations
256    #[serde(flatten)]
257    pub custom: HashMap<String, serde_json::Value>,
258}
259
260// ============================================================================
261// Core Protocol Types
262// ============================================================================
263
264/// Client-initiated request
265#[derive(Debug, Clone, Serialize, Deserialize)]
266#[serde(tag = "method")]
267pub enum ClientRequest {
268    /// Initialize the connection
269    #[serde(rename = "initialize")]
270    Initialize(InitializeRequest),
271
272    /// List available tools
273    #[serde(rename = "tools/list")]
274    ListTools(ListToolsRequest),
275
276    /// Call a tool
277    #[serde(rename = "tools/call")]
278    CallTool(CallToolRequest),
279
280    /// List available prompts
281    #[serde(rename = "prompts/list")]
282    ListPrompts(ListPromptsRequest),
283
284    /// Get a specific prompt
285    #[serde(rename = "prompts/get")]
286    GetPrompt(GetPromptRequest),
287
288    /// List available resources
289    #[serde(rename = "resources/list")]
290    ListResources(ListResourcesRequest),
291
292    /// List resource templates
293    #[serde(rename = "resources/templates/list")]
294    ListResourceTemplates(ListResourceTemplatesRequest),
295
296    /// Read a resource
297    #[serde(rename = "resources/read")]
298    ReadResource(ReadResourceRequest),
299
300    /// Subscribe to resource updates
301    #[serde(rename = "resources/subscribe")]
302    Subscribe(SubscribeRequest),
303
304    /// Unsubscribe from resource updates
305    #[serde(rename = "resources/unsubscribe")]
306    Unsubscribe(UnsubscribeRequest),
307
308    /// Set logging level
309    #[serde(rename = "logging/setLevel")]
310    SetLevel(SetLevelRequest),
311
312    /// Complete argument
313    #[serde(rename = "completion/complete")]
314    Complete(CompleteRequestParams),
315
316    /// Ping to check connection
317    #[serde(rename = "ping")]
318    Ping(PingParams),
319}
320
321/// Server-initiated request
322#[derive(Debug, Clone, Serialize, Deserialize)]
323#[serde(tag = "method")]
324pub enum ServerRequest {
325    /// Ping to check connection
326    #[serde(rename = "ping")]
327    Ping(PingParams),
328
329    /// Create a message (sampling) - server requests LLM sampling from client
330    #[serde(rename = "sampling/createMessage")]
331    CreateMessage(CreateMessageRequest),
332
333    /// List filesystem roots - server requests root URIs from client
334    #[serde(rename = "roots/list")]
335    ListRoots(ListRootsRequest),
336
337    /// Elicit user input
338    #[serde(rename = "elicitation/create")]
339    ElicitationCreate(ElicitRequestParams),
340}
341
342/// Client-initiated notification
343#[derive(Debug, Clone, Serialize, Deserialize)]
344#[serde(tag = "method")]
345pub enum ClientNotification {
346    /// Connection initialized
347    #[serde(rename = "notifications/initialized")]
348    Initialized(InitializedNotification),
349
350    /// Progress update
351    #[serde(rename = "notifications/progress")]
352    Progress(ProgressNotification),
353
354    /// Roots list changed
355    #[serde(rename = "notifications/roots/list_changed")]
356    RootsListChanged(RootsListChangedNotification),
357}
358
359/// Server-initiated notification
360#[derive(Debug, Clone, Serialize, Deserialize)]
361#[serde(tag = "method")]
362pub enum ServerNotification {
363    /// Log message
364    #[serde(rename = "notifications/message")]
365    Message(LoggingNotification),
366
367    /// Resource updated
368    #[serde(rename = "notifications/resources/updated")]
369    ResourceUpdated(ResourceUpdatedNotification),
370
371    /// Resource list changed
372    #[serde(rename = "notifications/resources/list_changed")]
373    ResourceListChanged,
374
375    /// Progress update
376    #[serde(rename = "notifications/progress")]
377    Progress(ProgressNotification),
378
379    /// Request cancellation
380    #[serde(rename = "notifications/cancelled")]
381    Cancelled(CancelledNotification),
382
383    /// Prompts list changed
384    #[serde(rename = "notifications/prompts/list_changed")]
385    PromptsListChanged,
386
387    /// Tools list changed
388    #[serde(rename = "notifications/tools/list_changed")]
389    ToolsListChanged,
390
391    /// Roots list changed
392    #[serde(rename = "notifications/roots/list_changed")]
393    RootsListChanged,
394}
395
396// ============================================================================
397// Initialization
398// ============================================================================
399
400/// Initialize request
401#[derive(Debug, Clone, Serialize, Deserialize)]
402pub struct InitializeRequest {
403    /// Protocol version
404    #[serde(rename = "protocolVersion")]
405    pub protocol_version: ProtocolVersion,
406    /// Client capabilities
407    pub capabilities: ClientCapabilities,
408    /// Client implementation info
409    #[serde(rename = "clientInfo")]
410    pub client_info: Implementation,
411    /// Optional metadata per MCP 2025-06-18 specification
412    #[serde(skip_serializing_if = "Option::is_none")]
413    pub _meta: Option<serde_json::Value>,
414}
415
416/// Initialize result
417#[derive(Debug, Clone, Serialize, Deserialize)]
418pub struct InitializeResult {
419    /// Protocol version
420    #[serde(rename = "protocolVersion")]
421    pub protocol_version: ProtocolVersion,
422    /// Server capabilities
423    pub capabilities: ServerCapabilities,
424    /// Server implementation info
425    #[serde(rename = "serverInfo")]
426    pub server_info: Implementation,
427    /// Additional instructions for the client
428    #[serde(skip_serializing_if = "Option::is_none")]
429    pub instructions: Option<String>,
430    /// Optional metadata per MCP 2025-06-18 specification
431    #[serde(skip_serializing_if = "Option::is_none")]
432    pub _meta: Option<serde_json::Value>,
433}
434
435/// Initialized notification (no parameters)
436#[derive(Debug, Clone, Serialize, Deserialize)]
437pub struct InitializedNotification;
438
439// ============================================================================
440// Capabilities
441// ============================================================================
442
443/// Client capabilities per MCP 2025-06-18 specification
444#[derive(Debug, Clone, Serialize, Deserialize, Default)]
445pub struct ClientCapabilities {
446    /// Experimental, non-standard capabilities that the client supports
447    #[serde(skip_serializing_if = "Option::is_none")]
448    pub experimental: Option<HashMap<String, serde_json::Value>>,
449
450    /// Present if the client supports listing roots
451    #[serde(skip_serializing_if = "Option::is_none")]
452    pub roots: Option<RootsCapabilities>,
453
454    /// Present if the client supports sampling from an LLM
455    #[serde(skip_serializing_if = "Option::is_none")]
456    pub sampling: Option<SamplingCapabilities>,
457
458    /// Present if the client supports elicitation from the server
459    #[serde(skip_serializing_if = "Option::is_none")]
460    pub elicitation: Option<ElicitationCapabilities>,
461}
462
463/// Server capabilities per MCP 2025-06-18 specification
464#[derive(Debug, Clone, Serialize, Deserialize, Default)]
465pub struct ServerCapabilities {
466    /// Experimental, non-standard capabilities that the server supports
467    #[serde(skip_serializing_if = "Option::is_none")]
468    pub experimental: Option<HashMap<String, serde_json::Value>>,
469
470    /// Present if the server supports sending log messages to the client
471    #[serde(skip_serializing_if = "Option::is_none")]
472    pub logging: Option<LoggingCapabilities>,
473
474    /// Present if the server supports argument autocompletion suggestions
475    #[serde(skip_serializing_if = "Option::is_none")]
476    pub completions: Option<CompletionCapabilities>,
477
478    /// Present if the server offers any prompt templates
479    #[serde(skip_serializing_if = "Option::is_none")]
480    pub prompts: Option<PromptsCapabilities>,
481
482    /// Present if the server offers any resources to read
483    #[serde(skip_serializing_if = "Option::is_none")]
484    pub resources: Option<ResourcesCapabilities>,
485
486    /// Present if the server offers any tools to call
487    #[serde(skip_serializing_if = "Option::is_none")]
488    pub tools: Option<ToolsCapabilities>,
489}
490
491/// Sampling capabilities
492#[derive(Debug, Clone, Serialize, Deserialize, Default)]
493pub struct SamplingCapabilities;
494
495/// Elicitation capabilities
496#[derive(Debug, Clone, Serialize, Deserialize, Default)]
497pub struct ElicitationCapabilities;
498
499/// Completion capabilities
500#[derive(Debug, Clone, Serialize, Deserialize, Default)]
501pub struct CompletionCapabilities;
502
503/// Roots capabilities
504#[derive(Debug, Clone, Serialize, Deserialize, Default)]
505pub struct RootsCapabilities {
506    /// Whether list can change
507    #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
508    pub list_changed: Option<bool>,
509}
510
511/// Logging capabilities
512#[derive(Debug, Clone, Serialize, Deserialize, Default)]
513pub struct LoggingCapabilities;
514
515/// Prompts capabilities
516#[derive(Debug, Clone, Serialize, Deserialize, Default)]
517pub struct PromptsCapabilities {
518    /// Whether list can change
519    #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
520    pub list_changed: Option<bool>,
521}
522
523/// Resources capabilities
524#[derive(Debug, Clone, Serialize, Deserialize, Default)]
525pub struct ResourcesCapabilities {
526    /// Whether subscribe is supported
527    #[serde(skip_serializing_if = "Option::is_none")]
528    pub subscribe: Option<bool>,
529
530    /// Whether list can change
531    #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
532    pub list_changed: Option<bool>,
533}
534
535/// Tools capabilities
536#[derive(Debug, Clone, Serialize, Deserialize, Default)]
537pub struct ToolsCapabilities {
538    /// Whether list can change
539    #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
540    pub list_changed: Option<bool>,
541}
542
543// ============================================================================
544// Content Types
545// ============================================================================
546
547/// Content block union type per MCP 2025-06-18 specification
548#[derive(Debug, Clone, Serialize, Deserialize)]
549#[serde(tag = "type")]
550pub enum ContentBlock {
551    /// Text content
552    #[serde(rename = "text")]
553    Text(TextContent),
554    /// Image content
555    #[serde(rename = "image")]
556    Image(ImageContent),
557    /// Audio content
558    #[serde(rename = "audio")]
559    Audio(AudioContent),
560    /// Resource link
561    #[serde(rename = "resource_link")]
562    ResourceLink(ResourceLink),
563    /// Embedded resource
564    #[serde(rename = "resource")]
565    Resource(EmbeddedResource),
566}
567
568/// Compatibility alias for the old Content enum
569pub type Content = ContentBlock;
570
571/// Text content per MCP 2025-06-18 specification
572#[derive(Debug, Clone, Serialize, Deserialize)]
573pub struct TextContent {
574    /// The text content of the message
575    pub text: String,
576    /// Optional annotations for the client
577    #[serde(skip_serializing_if = "Option::is_none")]
578    pub annotations: Option<Annotations>,
579    /// General metadata field for extensions and custom data
580    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
581    pub meta: Option<HashMap<String, serde_json::Value>>,
582}
583
584/// Image content per MCP 2025-06-18 specification
585#[derive(Debug, Clone, Serialize, Deserialize)]
586pub struct ImageContent {
587    /// The base64-encoded image data
588    pub data: String,
589    /// The MIME type of the image. Different providers may support different image types
590    #[serde(rename = "mimeType")]
591    pub mime_type: String,
592    /// Optional annotations for the client
593    #[serde(skip_serializing_if = "Option::is_none")]
594    pub annotations: Option<Annotations>,
595    /// General metadata field for extensions and custom data
596    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
597    pub meta: Option<HashMap<String, serde_json::Value>>,
598}
599
600/// Audio content per MCP 2025-06-18 specification
601#[derive(Debug, Clone, Serialize, Deserialize)]
602pub struct AudioContent {
603    /// The base64-encoded audio data
604    pub data: String,
605    /// The MIME type of the audio. Different providers may support different audio types
606    #[serde(rename = "mimeType")]
607    pub mime_type: String,
608    /// Optional annotations for the client
609    #[serde(skip_serializing_if = "Option::is_none")]
610    pub annotations: Option<Annotations>,
611    /// General metadata field for extensions and custom data
612    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
613    pub meta: Option<HashMap<String, serde_json::Value>>,
614}
615
616/// Resource link per MCP 2025-06-18 specification
617#[derive(Debug, Clone, Serialize, Deserialize)]
618pub struct ResourceLink {
619    /// Resource name (programmatic identifier)
620    pub name: String,
621    /// Display title for UI contexts (optional, falls back to name if not provided)
622    #[serde(skip_serializing_if = "Option::is_none")]
623    pub title: Option<String>,
624    /// The URI of this resource
625    pub uri: String,
626    /// A description of what this resource represents
627    #[serde(skip_serializing_if = "Option::is_none")]
628    pub description: Option<String>,
629    /// The MIME type of this resource, if known
630    #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
631    pub mime_type: Option<String>,
632    /// Optional annotations for the client
633    #[serde(skip_serializing_if = "Option::is_none")]
634    pub annotations: Option<Annotations>,
635    /// The size of the raw resource content, if known
636    #[serde(skip_serializing_if = "Option::is_none")]
637    pub size: Option<u64>,
638    /// General metadata field for extensions and custom data
639    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
640    pub meta: Option<HashMap<String, serde_json::Value>>,
641}
642
643/// Embedded resource content per MCP 2025-06-18 specification
644#[derive(Debug, Clone, Serialize, Deserialize)]
645pub struct EmbeddedResource {
646    /// The embedded resource content (text or binary)
647    pub resource: ResourceContent,
648    /// Optional annotations for the client
649    #[serde(skip_serializing_if = "Option::is_none")]
650    pub annotations: Option<Annotations>,
651    /// General metadata field for extensions and custom data
652    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
653    pub meta: Option<HashMap<String, serde_json::Value>>,
654}
655
656/// Role in conversation
657#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
658#[serde(rename_all = "lowercase")]
659pub enum Role {
660    /// User role
661    User,
662    /// Assistant role
663    Assistant,
664}
665
666// ============================================================================
667// Tool Types
668// ============================================================================
669
670/// Tool-specific annotations for additional tool information
671#[derive(Debug, Clone, Serialize, Deserialize, Default)]
672pub struct ToolAnnotations {
673    /// Title for display purposes - takes precedence over name for UI
674    #[serde(skip_serializing_if = "Option::is_none")]
675    pub title: Option<String>,
676    /// Audience-specific information
677    #[serde(skip_serializing_if = "Option::is_none")]
678    pub audience: Option<Vec<String>>,
679    /// Priority for ordering
680    #[serde(skip_serializing_if = "Option::is_none")]
681    pub priority: Option<f64>,
682    /// If true, the tool may perform destructive updates to its environment
683    #[serde(skip_serializing_if = "Option::is_none")]
684    #[serde(rename = "destructiveHint")]
685    pub destructive_hint: Option<bool>,
686    /// If true, calling the tool repeatedly with same arguments has no additional effect
687    #[serde(skip_serializing_if = "Option::is_none")]
688    #[serde(rename = "idempotentHint")]
689    pub idempotent_hint: Option<bool>,
690    /// If true, this tool may interact with an "open world" of external entities
691    #[serde(skip_serializing_if = "Option::is_none")]
692    #[serde(rename = "openWorldHint")]
693    pub open_world_hint: Option<bool>,
694    /// If true, the tool does not modify its environment
695    #[serde(skip_serializing_if = "Option::is_none")]
696    #[serde(rename = "readOnlyHint")]
697    pub read_only_hint: Option<bool>,
698    /// Additional custom annotations
699    #[serde(flatten)]
700    pub custom: HashMap<String, serde_json::Value>,
701}
702
703/// Tool definition per MCP 2025-06-18 specification
704#[derive(Debug, Clone, Serialize, Deserialize)]
705pub struct Tool {
706    /// Tool name (programmatic identifier)
707    pub name: String,
708
709    /// Display title for UI contexts (optional, falls back to name if not provided)
710    #[serde(skip_serializing_if = "Option::is_none")]
711    pub title: Option<String>,
712
713    /// Human-readable description of the tool
714    /// This can be used by clients to improve the LLM's understanding of available tools
715    #[serde(skip_serializing_if = "Option::is_none")]
716    pub description: Option<String>,
717
718    /// JSON Schema object defining the expected parameters for the tool
719    #[serde(rename = "inputSchema")]
720    pub input_schema: ToolInputSchema,
721
722    /// Optional JSON Schema object defining the structure of the tool's output
723    /// returned in the structuredContent field of a CallToolResult
724    #[serde(rename = "outputSchema", skip_serializing_if = "Option::is_none")]
725    pub output_schema: Option<ToolOutputSchema>,
726
727    /// Optional additional tool information
728    /// Display name precedence order is: title, annotations.title, then name
729    #[serde(skip_serializing_if = "Option::is_none")]
730    pub annotations: Option<ToolAnnotations>,
731
732    /// General metadata field for extensions and custom data
733    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
734    pub meta: Option<HashMap<String, serde_json::Value>>,
735}
736
737impl Default for Tool {
738    fn default() -> Self {
739        Self {
740            name: "unnamed_tool".to_string(), // Must have a valid name for MCP compliance
741            title: None,
742            description: None,
743            input_schema: ToolInputSchema::default(),
744            output_schema: None,
745            annotations: None,
746            meta: None,
747        }
748    }
749}
750
751impl Tool {
752    /// Create a new tool with just a name and minimal schema
753    ///
754    /// # Panics
755    /// Panics if the name is empty, as this would create an invalid tool.
756    pub fn new(name: impl Into<String>) -> Self {
757        let name = name.into();
758        assert!(!name.trim().is_empty(), "Tool name cannot be empty");
759
760        Self {
761            name,
762            title: None,
763            description: None,
764            input_schema: ToolInputSchema::default(),
765            output_schema: None,
766            annotations: None,
767            meta: None,
768        }
769    }
770
771    /// Create a new tool with name and description
772    ///
773    /// # Panics
774    /// Panics if the name is empty, as this would create an invalid tool.
775    pub fn with_description(name: impl Into<String>, description: impl Into<String>) -> Self {
776        let name = name.into();
777        assert!(!name.trim().is_empty(), "Tool name cannot be empty");
778
779        Self {
780            name,
781            title: None,
782            description: Some(description.into()),
783            input_schema: ToolInputSchema::default(),
784            output_schema: None,
785            annotations: None,
786            meta: None,
787        }
788    }
789}
790
791/// Tool input schema definition
792#[derive(Debug, Clone, Serialize, Deserialize)]
793pub struct ToolInputSchema {
794    /// Must be "object" for tool input schemas
795    #[serde(rename = "type")]
796    pub schema_type: String,
797    /// Schema properties defining the tool parameters
798    #[serde(skip_serializing_if = "Option::is_none")]
799    pub properties: Option<HashMap<String, serde_json::Value>>,
800    /// List of required property names
801    #[serde(skip_serializing_if = "Option::is_none")]
802    pub required: Option<Vec<String>>,
803    /// Whether additional properties are allowed
804    #[serde(
805        rename = "additionalProperties",
806        skip_serializing_if = "Option::is_none"
807    )]
808    pub additional_properties: Option<bool>,
809}
810
811impl Default for ToolInputSchema {
812    fn default() -> Self {
813        Self {
814            schema_type: "object".to_string(),
815            properties: None,
816            required: None,
817            additional_properties: None,
818        }
819    }
820}
821
822impl ToolInputSchema {
823    /// Create a simple input schema with no properties
824    pub fn empty() -> Self {
825        Self::default()
826    }
827
828    /// Create an input schema with properties
829    pub fn with_properties(properties: HashMap<String, serde_json::Value>) -> Self {
830        Self {
831            schema_type: "object".to_string(),
832            properties: Some(properties),
833            required: None,
834            additional_properties: None,
835        }
836    }
837
838    /// Create an input schema with properties and required fields
839    pub fn with_required_properties(
840        properties: HashMap<String, serde_json::Value>,
841        required: Vec<String>,
842    ) -> Self {
843        Self {
844            schema_type: "object".to_string(),
845            properties: Some(properties),
846            required: Some(required),
847            additional_properties: None,
848        }
849    }
850}
851
852/// Tool output schema definition
853#[derive(Debug, Clone, Serialize, Deserialize)]
854pub struct ToolOutputSchema {
855    /// Must be "object" for tool output schemas
856    #[serde(rename = "type")]
857    pub schema_type: String,
858    /// Schema properties defining the tool output structure
859    #[serde(skip_serializing_if = "Option::is_none")]
860    pub properties: Option<HashMap<String, serde_json::Value>>,
861    /// List of required property names
862    #[serde(skip_serializing_if = "Option::is_none")]
863    pub required: Option<Vec<String>>,
864    /// Whether additional properties are allowed
865    #[serde(
866        rename = "additionalProperties",
867        skip_serializing_if = "Option::is_none"
868    )]
869    pub additional_properties: Option<bool>,
870}
871
872/// List tools request (no parameters)
873#[derive(Debug, Clone, Serialize, Deserialize)]
874pub struct ListToolsRequest;
875
876/// List tools result
877#[derive(Debug, Clone, Serialize, Deserialize)]
878pub struct ListToolsResult {
879    /// Available tools
880    pub tools: Vec<Tool>,
881    /// Optional continuation token
882    #[serde(rename = "nextCursor", skip_serializing_if = "Option::is_none")]
883    pub next_cursor: Option<String>,
884    /// Optional metadata per MCP 2025-06-18 specification
885    #[serde(skip_serializing_if = "Option::is_none")]
886    pub _meta: Option<serde_json::Value>,
887}
888
889/// Call tool request
890#[derive(Debug, Clone, Serialize, Deserialize)]
891pub struct CallToolRequest {
892    /// Tool name
893    pub name: String,
894    /// Tool arguments
895    #[serde(skip_serializing_if = "Option::is_none")]
896    pub arguments: Option<HashMap<String, serde_json::Value>>,
897    /// Optional metadata per MCP 2025-06-18 specification
898    #[serde(skip_serializing_if = "Option::is_none")]
899    pub _meta: Option<serde_json::Value>,
900}
901
902/// Call tool result
903#[derive(Debug, Clone, Serialize, Deserialize)]
904pub struct CallToolResult {
905    /// Result content (required)
906    pub content: Vec<ContentBlock>,
907    /// Whether the operation failed
908    #[serde(rename = "isError", skip_serializing_if = "Option::is_none")]
909    pub is_error: Option<bool>,
910    /// Optional structured result of the tool call per MCP 2025-06-18 specification
911    #[serde(rename = "structuredContent", skip_serializing_if = "Option::is_none")]
912    pub structured_content: Option<serde_json::Value>,
913    /// Optional metadata per MCP 2025-06-18 specification
914    #[serde(skip_serializing_if = "Option::is_none")]
915    pub _meta: Option<serde_json::Value>,
916}
917
918// ============================================================================
919// Prompt Types
920// ============================================================================
921
922/// Prompt definition per MCP 2025-06-18 specification
923#[derive(Debug, Clone, Serialize, Deserialize)]
924pub struct Prompt {
925    /// Prompt name (programmatic identifier)
926    pub name: String,
927
928    /// Display title for UI contexts (optional, falls back to name if not provided)
929    #[serde(skip_serializing_if = "Option::is_none")]
930    pub title: Option<String>,
931
932    /// An optional description of what this prompt provides
933    #[serde(skip_serializing_if = "Option::is_none")]
934    pub description: Option<String>,
935
936    /// A list of arguments to use for templating the prompt
937    #[serde(skip_serializing_if = "Option::is_none")]
938    pub arguments: Option<Vec<PromptArgument>>,
939
940    /// General metadata field for extensions and custom data
941    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
942    pub meta: Option<HashMap<String, serde_json::Value>>,
943}
944
945/// Prompt argument definition per MCP 2025-06-18 specification
946#[derive(Debug, Clone, Serialize, Deserialize)]
947pub struct PromptArgument {
948    /// Argument name (programmatic identifier)
949    pub name: String,
950
951    /// Display title for UI contexts (optional, falls back to name if not provided)
952    #[serde(skip_serializing_if = "Option::is_none")]
953    pub title: Option<String>,
954
955    /// A human-readable description of the argument
956    #[serde(skip_serializing_if = "Option::is_none")]
957    pub description: Option<String>,
958
959    /// Whether this argument must be provided
960    #[serde(skip_serializing_if = "Option::is_none")]
961    pub required: Option<bool>,
962}
963
964/// Prompt input parameters
965pub type PromptInput = HashMap<String, serde_json::Value>;
966
967/// List prompts request (no parameters)
968#[derive(Debug, Clone, Serialize, Deserialize)]
969pub struct ListPromptsRequest;
970
971/// List prompts result
972#[derive(Debug, Clone, Serialize, Deserialize)]
973pub struct ListPromptsResult {
974    /// Available prompts
975    pub prompts: Vec<Prompt>,
976    /// Optional continuation token
977    #[serde(rename = "nextCursor", skip_serializing_if = "Option::is_none")]
978    pub next_cursor: Option<String>,
979    /// Optional metadata per MCP 2025-06-18 specification
980    #[serde(skip_serializing_if = "Option::is_none")]
981    pub _meta: Option<serde_json::Value>,
982}
983
984/// Get prompt request
985#[derive(Debug, Clone, Serialize, Deserialize)]
986pub struct GetPromptRequest {
987    /// Prompt name
988    pub name: String,
989    /// Prompt arguments
990    #[serde(skip_serializing_if = "Option::is_none")]
991    pub arguments: Option<PromptInput>,
992    /// Optional metadata per MCP 2025-06-18 specification
993    #[serde(skip_serializing_if = "Option::is_none")]
994    pub _meta: Option<serde_json::Value>,
995}
996
997/// Get prompt result
998#[derive(Debug, Clone, Serialize, Deserialize)]
999pub struct GetPromptResult {
1000    /// Prompt description
1001    #[serde(skip_serializing_if = "Option::is_none")]
1002    pub description: Option<String>,
1003    /// Prompt messages
1004    pub messages: Vec<PromptMessage>,
1005    /// Optional metadata per MCP 2025-06-18 specification
1006    #[serde(skip_serializing_if = "Option::is_none")]
1007    pub _meta: Option<serde_json::Value>,
1008}
1009
1010/// Prompt message
1011#[derive(Debug, Clone, Serialize, Deserialize)]
1012pub struct PromptMessage {
1013    /// Message role
1014    pub role: Role,
1015    /// Message content
1016    pub content: Content,
1017}
1018
1019// ============================================================================
1020// Resource Types
1021// ============================================================================
1022
1023/// Resource definition per MCP 2025-06-18 specification
1024#[derive(Debug, Clone, Serialize, Deserialize)]
1025pub struct Resource {
1026    /// Resource name (programmatic identifier)
1027    pub name: String,
1028
1029    /// Display title for UI contexts (optional, falls back to name if not provided)
1030    #[serde(skip_serializing_if = "Option::is_none")]
1031    pub title: Option<String>,
1032
1033    /// The URI of this resource
1034    pub uri: String,
1035
1036    /// A description of what this resource represents
1037    /// This can be used by clients to improve the LLM's understanding of available resources
1038    #[serde(skip_serializing_if = "Option::is_none")]
1039    pub description: Option<String>,
1040
1041    /// The MIME type of this resource, if known
1042    #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
1043    pub mime_type: Option<String>,
1044
1045    /// Optional annotations for the client
1046    #[serde(skip_serializing_if = "Option::is_none")]
1047    pub annotations: Option<Annotations>,
1048
1049    /// The size of the raw resource content, in bytes (before base64 encoding or tokenization), if known
1050    /// This can be used by Hosts to display file sizes and estimate context window usage
1051    #[serde(skip_serializing_if = "Option::is_none")]
1052    pub size: Option<u64>,
1053
1054    /// General metadata field for extensions and custom data
1055    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1056    pub meta: Option<HashMap<String, serde_json::Value>>,
1057}
1058
1059/// Base resource contents interface
1060#[derive(Debug, Clone, Serialize, Deserialize)]
1061pub struct ResourceContents {
1062    /// The URI of this resource
1063    pub uri: String,
1064    /// The MIME type of this resource, if known
1065    #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
1066    pub mime_type: Option<String>,
1067    /// General metadata field for extensions and custom data
1068    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1069    pub meta: Option<HashMap<String, serde_json::Value>>,
1070}
1071
1072/// Text resource contents
1073#[derive(Debug, Clone, Serialize, Deserialize)]
1074pub struct TextResourceContents {
1075    /// The URI of this resource
1076    pub uri: String,
1077    /// The MIME type of this resource, if known
1078    #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
1079    pub mime_type: Option<String>,
1080    /// The text content (must only be set for text-representable data)
1081    pub text: String,
1082    /// General metadata field for extensions and custom data
1083    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1084    pub meta: Option<HashMap<String, serde_json::Value>>,
1085}
1086
1087/// Binary resource contents
1088#[derive(Debug, Clone, Serialize, Deserialize)]
1089pub struct BlobResourceContents {
1090    /// The URI of this resource
1091    pub uri: String,
1092    /// The MIME type of this resource, if known
1093    #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
1094    pub mime_type: Option<String>,
1095    /// Base64-encoded binary data
1096    pub blob: String,
1097    /// General metadata field for extensions and custom data
1098    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1099    pub meta: Option<HashMap<String, serde_json::Value>>,
1100}
1101
1102/// Union type for resource contents (text or binary)
1103#[derive(Debug, Clone, Serialize, Deserialize)]
1104#[serde(untagged)]
1105pub enum ResourceContent {
1106    /// Text resource content
1107    Text(TextResourceContents),
1108    /// Binary resource content
1109    Blob(BlobResourceContents),
1110}
1111
1112/// List resources request
1113#[derive(Debug, Clone, Serialize, Deserialize)]
1114pub struct ListResourcesRequest {
1115    /// Optional cursor for pagination
1116    #[serde(skip_serializing_if = "Option::is_none")]
1117    pub cursor: Option<String>,
1118    /// Optional metadata per MCP 2025-06-18 specification
1119    #[serde(skip_serializing_if = "Option::is_none")]
1120    pub _meta: Option<serde_json::Value>,
1121}
1122
1123/// List resources result
1124#[derive(Debug, Clone, Serialize, Deserialize)]
1125pub struct ListResourcesResult {
1126    /// Available resources
1127    pub resources: Vec<Resource>,
1128    /// Optional continuation token
1129    #[serde(rename = "nextCursor", skip_serializing_if = "Option::is_none")]
1130    pub next_cursor: Option<String>,
1131    /// Optional metadata per MCP 2025-06-18 specification
1132    #[serde(skip_serializing_if = "Option::is_none")]
1133    pub _meta: Option<serde_json::Value>,
1134}
1135
1136/// Read resource request
1137#[derive(Debug, Clone, Serialize, Deserialize)]
1138pub struct ReadResourceRequest {
1139    /// Resource URI
1140    pub uri: Uri,
1141    /// Optional metadata per MCP 2025-06-18 specification
1142    #[serde(skip_serializing_if = "Option::is_none")]
1143    pub _meta: Option<serde_json::Value>,
1144}
1145
1146/// Read resource result
1147#[derive(Debug, Clone, Serialize, Deserialize)]
1148pub struct ReadResourceResult {
1149    /// Resource contents (can be text or binary)
1150    pub contents: Vec<ResourceContent>,
1151    /// Optional metadata per MCP 2025-06-18 specification
1152    #[serde(skip_serializing_if = "Option::is_none")]
1153    pub _meta: Option<serde_json::Value>,
1154}
1155
1156/// Subscribe to resource request
1157#[derive(Debug, Clone, Serialize, Deserialize)]
1158pub struct SubscribeRequest {
1159    /// Resource URI
1160    pub uri: Uri,
1161}
1162
1163/// Unsubscribe from resource request
1164#[derive(Debug, Clone, Serialize, Deserialize)]
1165pub struct UnsubscribeRequest {
1166    /// Resource URI
1167    pub uri: Uri,
1168}
1169
1170/// Resource updated notification
1171#[derive(Debug, Clone, Serialize, Deserialize)]
1172pub struct ResourceUpdatedNotification {
1173    /// Resource URI
1174    pub uri: Uri,
1175}
1176
1177// ============================================================================
1178// Logging Types
1179// ============================================================================
1180
1181/// Log level
1182#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1183#[serde(rename_all = "lowercase")]
1184pub enum LogLevel {
1185    /// Debug level
1186    Debug,
1187    /// Info level
1188    Info,
1189    /// Notice level
1190    Notice,
1191    /// Warning level
1192    Warning,
1193    /// Error level
1194    Error,
1195    /// Critical level
1196    Critical,
1197    /// Alert level
1198    Alert,
1199    /// Emergency level
1200    Emergency,
1201}
1202
1203/// Set log level request
1204#[derive(Debug, Clone, Serialize, Deserialize)]
1205pub struct SetLevelRequest {
1206    /// Log level to set
1207    pub level: LogLevel,
1208}
1209
1210/// Set log level result (no data)
1211#[derive(Debug, Clone, Serialize, Deserialize)]
1212pub struct SetLevelResult;
1213
1214/// Logging notification
1215#[derive(Debug, Clone, Serialize, Deserialize)]
1216pub struct LoggingNotification {
1217    /// Log level
1218    pub level: LogLevel,
1219    /// Log data
1220    pub data: serde_json::Value,
1221    /// Optional logger name
1222    #[serde(skip_serializing_if = "Option::is_none")]
1223    pub logger: Option<String>,
1224}
1225
1226// ============================================================================
1227// Progress Types
1228// ============================================================================
1229
1230/// Progress notification per MCP 2025-06-18 specification
1231#[derive(Debug, Clone, Serialize, Deserialize)]
1232pub struct ProgressNotification {
1233    /// The progress token which was given in the initial request
1234    /// Used to associate this notification with the request that is proceeding
1235    #[serde(rename = "progressToken")]
1236    pub progress_token: ProgressToken,
1237    /// The progress thus far. This should increase every time progress is made,
1238    /// even if the total is unknown
1239    pub progress: f64,
1240    /// Total number of items to process (or total progress required), if known
1241    #[serde(skip_serializing_if = "Option::is_none")]
1242    pub total: Option<f64>,
1243    /// An optional message describing the current progress
1244    #[serde(skip_serializing_if = "Option::is_none")]
1245    pub message: Option<String>,
1246}
1247
1248/// Cancellation notification per MCP 2025-06-18 specification
1249#[derive(Debug, Clone, Serialize, Deserialize)]
1250pub struct CancelledNotification {
1251    /// The ID of the request to cancel
1252    /// This MUST correspond to the ID of a request previously issued in the same direction
1253    #[serde(rename = "requestId")]
1254    pub request_id: RequestId,
1255    /// An optional string describing the reason for the cancellation
1256    /// This MAY be logged or presented to the user
1257    #[serde(skip_serializing_if = "Option::is_none")]
1258    pub reason: Option<String>,
1259}
1260
1261// ============================================================================
1262// Sampling Types
1263// ============================================================================
1264
1265/// Create message request
1266#[derive(Debug, Clone, Serialize, Deserialize)]
1267pub struct CreateMessageRequest {
1268    /// Messages to include
1269    pub messages: Vec<SamplingMessage>,
1270    /// Model preferences
1271    #[serde(rename = "modelPreferences", skip_serializing_if = "Option::is_none")]
1272    pub model_preferences: Option<ModelPreferences>,
1273    /// System prompt
1274    #[serde(rename = "systemPrompt", skip_serializing_if = "Option::is_none")]
1275    pub system_prompt: Option<String>,
1276    /// Include context
1277    #[serde(rename = "includeContext", skip_serializing_if = "Option::is_none")]
1278    pub include_context: Option<IncludeContext>,
1279    /// Temperature
1280    #[serde(skip_serializing_if = "Option::is_none")]
1281    pub temperature: Option<f64>,
1282    /// Max tokens (required by MCP 2025-06-18 spec)
1283    #[serde(rename = "maxTokens")]
1284    pub max_tokens: u32,
1285    /// Stop sequences
1286    #[serde(rename = "stopSequences", skip_serializing_if = "Option::is_none")]
1287    pub stop_sequences: Option<Vec<String>>,
1288    /// Metadata
1289    #[serde(skip_serializing_if = "Option::is_none")]
1290    pub metadata: Option<HashMap<String, serde_json::Value>>,
1291    /// Optional metadata per MCP 2025-06-18 specification
1292    #[serde(skip_serializing_if = "Option::is_none")]
1293    pub _meta: Option<serde_json::Value>,
1294}
1295
1296/// Model preferences
1297#[derive(Debug, Clone, Serialize, Deserialize)]
1298pub struct ModelPreferences {
1299    /// Preferred hints
1300    #[serde(skip_serializing_if = "Option::is_none")]
1301    pub hints: Option<Vec<ModelHint>>,
1302    /// Cost priority
1303    #[serde(rename = "costPriority", skip_serializing_if = "Option::is_none")]
1304    pub cost_priority: Option<f64>,
1305    /// Speed priority
1306    #[serde(rename = "speedPriority", skip_serializing_if = "Option::is_none")]
1307    pub speed_priority: Option<f64>,
1308    /// Intelligence priority
1309    #[serde(
1310        rename = "intelligencePriority",
1311        skip_serializing_if = "Option::is_none"
1312    )]
1313    pub intelligence_priority: Option<f64>,
1314}
1315
1316/// Model hint
1317#[derive(Debug, Clone, Serialize, Deserialize)]
1318pub struct ModelHint {
1319    /// Hint name (required by MCP 2025-06-18 spec)
1320    pub name: String,
1321}
1322
1323/// Include context options
1324#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1325#[serde(rename_all = "lowercase")]
1326pub enum IncludeContext {
1327    /// No context
1328    None,
1329    /// This server only
1330    ThisServer,
1331    /// All servers
1332    AllServers,
1333}
1334
1335/// Sampling message
1336#[derive(Debug, Clone, Serialize, Deserialize)]
1337pub struct SamplingMessage {
1338    /// Message role
1339    pub role: Role,
1340    /// Message content
1341    pub content: Content,
1342}
1343
1344/// Create message result
1345#[derive(Debug, Clone, Serialize, Deserialize)]
1346pub struct CreateMessageResult {
1347    /// Role of the created message
1348    pub role: Role,
1349    /// Content of the created message
1350    pub content: Content,
1351    /// Model used
1352    #[serde(skip_serializing_if = "Option::is_none")]
1353    pub model: Option<String>,
1354    /// Stop reason
1355    #[serde(rename = "stopReason", skip_serializing_if = "Option::is_none")]
1356    pub stop_reason: Option<String>,
1357    /// Optional metadata per MCP 2025-06-18 specification
1358    #[serde(skip_serializing_if = "Option::is_none")]
1359    pub _meta: Option<serde_json::Value>,
1360}
1361
1362// ============================================================================
1363// ELICITATION (SERVER-INITIATED USER INPUT)
1364// ============================================================================
1365
1366/// Primitive schema definition for elicitation requests
1367/// Only allows primitive types without nesting, as per MCP 2025-06-18 spec
1368#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1369#[serde(tag = "type")]
1370pub enum PrimitiveSchemaDefinition {
1371    /// String field schema definition
1372    #[serde(rename = "string")]
1373    String {
1374        /// Field title
1375        #[serde(skip_serializing_if = "Option::is_none")]
1376        title: Option<String>,
1377        /// Field description
1378        #[serde(skip_serializing_if = "Option::is_none")]
1379        description: Option<String>,
1380        /// String format (email, uri, date, date-time, etc.)
1381        #[serde(skip_serializing_if = "Option::is_none")]
1382        format: Option<String>,
1383        /// Minimum string length
1384        #[serde(skip_serializing_if = "Option::is_none")]
1385        #[serde(rename = "minLength")]
1386        min_length: Option<u32>,
1387        /// Maximum string length
1388        #[serde(skip_serializing_if = "Option::is_none")]
1389        #[serde(rename = "maxLength")]
1390        max_length: Option<u32>,
1391        /// Allowed enum values
1392        #[serde(skip_serializing_if = "Option::is_none")]
1393        #[serde(rename = "enum")]
1394        enum_values: Option<Vec<String>>,
1395        /// Display names for enum values
1396        #[serde(skip_serializing_if = "Option::is_none")]
1397        #[serde(rename = "enumNames")]
1398        enum_names: Option<Vec<String>>,
1399    },
1400    /// Number field schema definition
1401    #[serde(rename = "number")]
1402    Number {
1403        /// Field title
1404        #[serde(skip_serializing_if = "Option::is_none")]
1405        title: Option<String>,
1406        /// Field description
1407        #[serde(skip_serializing_if = "Option::is_none")]
1408        description: Option<String>,
1409        /// Minimum value
1410        #[serde(skip_serializing_if = "Option::is_none")]
1411        minimum: Option<f64>,
1412        /// Maximum value
1413        #[serde(skip_serializing_if = "Option::is_none")]
1414        maximum: Option<f64>,
1415    },
1416    /// Integer field schema definition
1417    #[serde(rename = "integer")]
1418    Integer {
1419        /// Field title
1420        #[serde(skip_serializing_if = "Option::is_none")]
1421        title: Option<String>,
1422        /// Field description
1423        #[serde(skip_serializing_if = "Option::is_none")]
1424        description: Option<String>,
1425        /// Minimum value
1426        #[serde(skip_serializing_if = "Option::is_none")]
1427        minimum: Option<i64>,
1428        /// Maximum value
1429        #[serde(skip_serializing_if = "Option::is_none")]
1430        maximum: Option<i64>,
1431    },
1432    /// Boolean field schema definition
1433    #[serde(rename = "boolean")]
1434    Boolean {
1435        /// Field title
1436        #[serde(skip_serializing_if = "Option::is_none")]
1437        title: Option<String>,
1438        /// Field description
1439        #[serde(skip_serializing_if = "Option::is_none")]
1440        description: Option<String>,
1441        /// Default value
1442        #[serde(skip_serializing_if = "Option::is_none")]
1443        default: Option<bool>,
1444    },
1445}
1446
1447/// Elicitation schema - restricted subset of JSON Schema for primitive types only
1448#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1449pub struct ElicitationSchema {
1450    /// Schema type (must be "object")
1451    #[serde(rename = "type")]
1452    pub schema_type: String,
1453    /// Schema properties (field definitions)
1454    pub properties: std::collections::HashMap<String, PrimitiveSchemaDefinition>,
1455    /// Required field names
1456    #[serde(skip_serializing_if = "Option::is_none")]
1457    pub required: Option<Vec<String>>,
1458}
1459
1460impl ElicitationSchema {
1461    /// Create a new elicitation schema
1462    pub fn new() -> Self {
1463        Self {
1464            schema_type: "object".to_string(),
1465            properties: std::collections::HashMap::new(),
1466            required: None,
1467        }
1468    }
1469
1470    /// Add a string property
1471    pub fn add_string_property<K: Into<String>>(
1472        mut self,
1473        name: K,
1474        required: bool,
1475        description: Option<String>,
1476    ) -> Self {
1477        let property = PrimitiveSchemaDefinition::String {
1478            title: None,
1479            description,
1480            format: None,
1481            min_length: None,
1482            max_length: None,
1483            enum_values: None,
1484            enum_names: None,
1485        };
1486
1487        let name = name.into();
1488        self.properties.insert(name.clone(), property);
1489
1490        if required {
1491            self.required.get_or_insert_with(Vec::new).push(name);
1492        }
1493
1494        self
1495    }
1496
1497    /// Add a number property
1498    pub fn add_number_property<K: Into<String>>(
1499        mut self,
1500        name: K,
1501        required: bool,
1502        description: Option<String>,
1503        min: Option<f64>,
1504        max: Option<f64>,
1505    ) -> Self {
1506        let property = PrimitiveSchemaDefinition::Number {
1507            title: None,
1508            description,
1509            minimum: min,
1510            maximum: max,
1511        };
1512
1513        let name = name.into();
1514        self.properties.insert(name.clone(), property);
1515
1516        if required {
1517            self.required.get_or_insert_with(Vec::new).push(name);
1518        }
1519
1520        self
1521    }
1522
1523    /// Add a boolean property
1524    pub fn add_boolean_property<K: Into<String>>(
1525        mut self,
1526        name: K,
1527        required: bool,
1528        description: Option<String>,
1529        default: Option<bool>,
1530    ) -> Self {
1531        let property = PrimitiveSchemaDefinition::Boolean {
1532            title: None,
1533            description,
1534            default,
1535        };
1536
1537        let name = name.into();
1538        self.properties.insert(name.clone(), property);
1539
1540        if required {
1541            self.required.get_or_insert_with(Vec::new).push(name);
1542        }
1543
1544        self
1545    }
1546
1547    /// Add an enum property
1548    pub fn add_enum_property<K: Into<String>>(
1549        mut self,
1550        name: K,
1551        required: bool,
1552        description: Option<String>,
1553        values: Vec<String>,
1554        names: Option<Vec<String>>,
1555    ) -> Self {
1556        let property = PrimitiveSchemaDefinition::String {
1557            title: None,
1558            description,
1559            format: None,
1560            min_length: None,
1561            max_length: None,
1562            enum_values: Some(values),
1563            enum_names: names,
1564        };
1565
1566        let name = name.into();
1567        self.properties.insert(name.clone(), property);
1568
1569        if required {
1570            self.required.get_or_insert_with(Vec::new).push(name);
1571        }
1572
1573        self
1574    }
1575}
1576
1577impl Default for ElicitationSchema {
1578    fn default() -> Self {
1579        Self::new()
1580    }
1581}
1582
1583/// Parameters for elicitation/create request
1584#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1585#[serde(rename_all = "camelCase")]
1586pub struct ElicitRequestParams {
1587    /// The message to present to the user
1588    pub message: String,
1589    /// JSON Schema defining the expected response structure
1590    pub requested_schema: ElicitationSchema,
1591    /// Optional metadata per MCP 2025-06-18 specification
1592    #[serde(skip_serializing_if = "Option::is_none")]
1593    pub _meta: Option<serde_json::Value>,
1594}
1595
1596/// Request to elicit user input (server-initiated)
1597#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1598pub struct ElicitRequest {
1599    /// The method name (always "elicitation/create")
1600    pub method: String,
1601    /// Request parameters
1602    pub params: ElicitRequestParams,
1603}
1604
1605impl ElicitRequest {
1606    /// Create a new elicit request
1607    pub fn new<M: Into<String>>(message: M, schema: ElicitationSchema) -> Self {
1608        Self {
1609            method: "elicitation/create".to_string(),
1610            params: ElicitRequestParams {
1611                message: message.into(),
1612                requested_schema: schema,
1613                _meta: None,
1614            },
1615        }
1616    }
1617}
1618
1619/// Action taken by user in response to elicitation
1620#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1621#[serde(rename_all = "lowercase")]
1622pub enum ElicitationAction {
1623    /// User submitted the form/confirmed the action
1624    Accept,
1625    /// User explicitly declined the action
1626    Decline,
1627    /// User dismissed without making an explicit choice
1628    Cancel,
1629}
1630
1631/// Client's response to an elicitation request
1632#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1633pub struct ElicitResult {
1634    /// The user action in response to the elicitation
1635    pub action: ElicitationAction,
1636    /// The submitted form data, only present when action is "accept"
1637    /// Contains values matching the requested schema
1638    #[serde(skip_serializing_if = "Option::is_none")]
1639    pub content: Option<std::collections::HashMap<String, serde_json::Value>>,
1640    /// Optional metadata
1641    #[serde(skip_serializing_if = "Option::is_none")]
1642    pub _meta: Option<serde_json::Value>,
1643}
1644
1645impl ElicitResult {
1646    /// Create an accept response with content
1647    pub fn accept(content: std::collections::HashMap<String, serde_json::Value>) -> Self {
1648        Self {
1649            action: ElicitationAction::Accept,
1650            content: Some(content),
1651            _meta: None,
1652        }
1653    }
1654
1655    /// Create a decline response
1656    pub fn decline() -> Self {
1657        Self {
1658            action: ElicitationAction::Decline,
1659            content: None,
1660            _meta: None,
1661        }
1662    }
1663
1664    /// Create a cancel response
1665    pub fn cancel() -> Self {
1666        Self {
1667            action: ElicitationAction::Cancel,
1668            content: None,
1669            _meta: None,
1670        }
1671    }
1672
1673    /// Add metadata
1674    pub fn with_meta(mut self, meta: serde_json::Value) -> Self {
1675        self._meta = Some(meta);
1676        self
1677    }
1678}
1679
1680// ============================================================================
1681// COMPLETION (ARGUMENT AUTOCOMPLETION)
1682// ============================================================================
1683
1684/// Information about the argument being completed
1685#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1686pub struct ArgumentInfo {
1687    /// The name of the argument
1688    pub name: String,
1689    /// The value of the argument to use for completion matching
1690    pub value: String,
1691}
1692
1693/// Context for completion requests
1694#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1695pub struct CompletionContext {
1696    /// Previously-resolved variables in a URI template or prompt
1697    #[serde(skip_serializing_if = "Option::is_none")]
1698    pub arguments: Option<std::collections::HashMap<String, String>>,
1699}
1700
1701/// Reference to a prompt for completion
1702#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1703pub struct PromptReference {
1704    /// Reference type (always "ref/prompt")
1705    #[serde(rename = "type")]
1706    pub ref_type: String,
1707    /// The name of the prompt
1708    pub name: String,
1709    /// Human-readable title
1710    #[serde(skip_serializing_if = "Option::is_none")]
1711    pub title: Option<String>,
1712}
1713
1714impl PromptReference {
1715    /// Create a new prompt reference
1716    pub fn new<N: Into<String>>(name: N) -> Self {
1717        Self {
1718            ref_type: "ref/prompt".to_string(),
1719            name: name.into(),
1720            title: None,
1721        }
1722    }
1723
1724    /// Add a title to the reference
1725    pub fn with_title<T: Into<String>>(mut self, title: T) -> Self {
1726        self.title = Some(title.into());
1727        self
1728    }
1729}
1730
1731/// Reference to a resource template for completion
1732#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1733pub struct ResourceTemplateReference {
1734    /// Reference type (always "ref/resource")
1735    #[serde(rename = "type")]
1736    pub ref_type: String,
1737    /// The URI or URI template of the resource
1738    pub uri: String,
1739}
1740
1741impl ResourceTemplateReference {
1742    /// Create a new resource template reference
1743    pub fn new<U: Into<String>>(uri: U) -> Self {
1744        Self {
1745            ref_type: "ref/resource".to_string(),
1746            uri: uri.into(),
1747        }
1748    }
1749}
1750
1751/// Reference types for completion requests
1752#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1753#[serde(tag = "type")]
1754pub enum CompletionReference {
1755    /// Reference to a prompt
1756    #[serde(rename = "ref/prompt")]
1757    Prompt(PromptReferenceData),
1758    /// Reference to a resource template
1759    #[serde(rename = "ref/resource")]
1760    ResourceTemplate(ResourceTemplateReferenceData),
1761}
1762
1763/// Data for prompt reference (excluding the type field)
1764#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1765pub struct PromptReferenceData {
1766    /// The name of the prompt
1767    pub name: String,
1768    /// Human-readable title
1769    #[serde(skip_serializing_if = "Option::is_none")]
1770    pub title: Option<String>,
1771}
1772
1773/// Data for resource template reference (excluding the type field)
1774#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1775pub struct ResourceTemplateReferenceData {
1776    /// The URI or URI template of the resource
1777    pub uri: String,
1778}
1779
1780/// Parameters for completion/complete request
1781#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1782pub struct CompleteRequestParams {
1783    /// The argument's information
1784    pub argument: ArgumentInfo,
1785    /// Reference to the item being completed
1786    #[serde(rename = "ref")]
1787    pub reference: CompletionReference,
1788    /// Additional context for completions
1789    #[serde(skip_serializing_if = "Option::is_none")]
1790    pub context: Option<CompletionContext>,
1791    /// Optional metadata per MCP 2025-06-18 specification
1792    #[serde(skip_serializing_if = "Option::is_none")]
1793    pub _meta: Option<serde_json::Value>,
1794}
1795
1796/// Request for argument completion
1797#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1798pub struct CompleteRequest {
1799    /// The method name (always "completion/complete")
1800    pub method: String,
1801    /// Request parameters
1802    pub params: CompleteRequestParams,
1803}
1804
1805impl CompleteRequest {
1806    /// Create a new completion request
1807    pub fn new(argument: ArgumentInfo, reference: CompletionReference) -> Self {
1808        Self {
1809            method: "completion/complete".to_string(),
1810            params: CompleteRequestParams {
1811                argument,
1812                reference,
1813                context: None,
1814                _meta: None,
1815            },
1816        }
1817    }
1818
1819    /// Add context to the request
1820    pub fn with_context(mut self, context: CompletionContext) -> Self {
1821        self.params.context = Some(context);
1822        self
1823    }
1824}
1825
1826/// Completion response information
1827#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1828#[serde(rename_all = "camelCase")]
1829pub struct CompletionResponse {
1830    /// Completion values (max 100 items)
1831    pub values: Vec<String>,
1832    /// Total number of completion options available
1833    #[serde(skip_serializing_if = "Option::is_none")]
1834    pub total: Option<u32>,
1835    /// Whether there are additional completion options beyond those provided
1836    #[serde(skip_serializing_if = "Option::is_none")]
1837    pub has_more: Option<bool>,
1838}
1839
1840impl CompletionResponse {
1841    /// Create a new completion response
1842    pub fn new(values: Vec<String>) -> Self {
1843        Self {
1844            values,
1845            total: None,
1846            has_more: None,
1847        }
1848    }
1849
1850    /// Set total count
1851    pub fn with_total(mut self, total: u32) -> Self {
1852        self.total = Some(total);
1853        self
1854    }
1855
1856    /// Set has_more flag
1857    pub fn with_has_more(mut self, has_more: bool) -> Self {
1858        self.has_more = Some(has_more);
1859        self
1860    }
1861
1862    /// Create response with pagination info
1863    pub fn paginated(values: Vec<String>, total: u32, has_more: bool) -> Self {
1864        Self {
1865            values,
1866            total: Some(total),
1867            has_more: Some(has_more),
1868        }
1869    }
1870}
1871
1872/// Server's response to a completion request
1873#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1874pub struct CompleteResult {
1875    /// Completion information
1876    pub completion: CompletionResponse,
1877    /// Optional metadata
1878    #[serde(skip_serializing_if = "Option::is_none")]
1879    pub _meta: Option<serde_json::Value>,
1880}
1881
1882impl CompleteResult {
1883    /// Create a new completion result
1884    pub fn new(completion: CompletionResponse) -> Self {
1885        Self {
1886            completion,
1887            _meta: None,
1888        }
1889    }
1890
1891    /// Add metadata
1892    pub fn with_meta(mut self, meta: serde_json::Value) -> Self {
1893        self._meta = Some(meta);
1894        self
1895    }
1896}
1897
1898// ============================================================================
1899// RESOURCE TEMPLATES (PARAMETERIZED RESOURCE ACCESS)
1900// ============================================================================
1901
1902/// A template description for resources available on the server
1903/// Supports RFC 6570 URI template expansion
1904#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1905#[serde(rename_all = "camelCase")]
1906pub struct ResourceTemplate {
1907    /// Programmatic identifier
1908    pub name: String,
1909    /// URI template (RFC 6570)
1910    pub uri_template: String,
1911    /// Human-readable title
1912    #[serde(skip_serializing_if = "Option::is_none")]
1913    pub title: Option<String>,
1914    /// Description of what this template is for
1915    #[serde(skip_serializing_if = "Option::is_none")]
1916    pub description: Option<String>,
1917    /// MIME type for all resources matching this template (if uniform)
1918    #[serde(skip_serializing_if = "Option::is_none")]
1919    pub mime_type: Option<String>,
1920    /// Optional annotations
1921    #[serde(skip_serializing_if = "Option::is_none")]
1922    pub annotations: Option<Annotations>,
1923    /// Optional metadata
1924    #[serde(skip_serializing_if = "Option::is_none")]
1925    pub _meta: Option<serde_json::Value>,
1926}
1927
1928impl ResourceTemplate {
1929    /// Create a new resource template
1930    pub fn new<N: Into<String>, U: Into<String>>(name: N, uri_template: U) -> Self {
1931        Self {
1932            name: name.into(),
1933            uri_template: uri_template.into(),
1934            title: None,
1935            description: None,
1936            mime_type: None,
1937            annotations: None,
1938            _meta: None,
1939        }
1940    }
1941
1942    /// Set the title
1943    pub fn with_title<T: Into<String>>(mut self, title: T) -> Self {
1944        self.title = Some(title.into());
1945        self
1946    }
1947
1948    /// Set the description
1949    pub fn with_description<D: Into<String>>(mut self, description: D) -> Self {
1950        self.description = Some(description.into());
1951        self
1952    }
1953
1954    /// Set the MIME type
1955    pub fn with_mime_type<M: Into<String>>(mut self, mime_type: M) -> Self {
1956        self.mime_type = Some(mime_type.into());
1957        self
1958    }
1959
1960    /// Set annotations
1961    pub fn with_annotations(mut self, annotations: Annotations) -> Self {
1962        self.annotations = Some(annotations);
1963        self
1964    }
1965
1966    /// Add metadata
1967    pub fn with_meta(mut self, meta: serde_json::Value) -> Self {
1968        self._meta = Some(meta);
1969        self
1970    }
1971
1972    /// Create a file system template
1973    pub fn file_system<N: Into<String>>(name: N, base_path: &str) -> Self {
1974        Self::new(name, format!("file://{}/{{path}}", base_path))
1975            .with_title("File System Access")
1976            .with_description("Access files within the specified directory")
1977    }
1978
1979    /// Create an API endpoint template
1980    pub fn api_endpoint<N: Into<String>>(name: N, base_url: &str) -> Self {
1981        Self::new(name, format!("{}/{{endpoint}}", base_url))
1982            .with_mime_type("application/json")
1983            .with_title("API Endpoint Access")
1984            .with_description("Access API endpoints")
1985    }
1986
1987    /// Create a database query template
1988    pub fn database_query<N: Into<String>>(name: N) -> Self {
1989        Self::new(name, "db://query/{table}?{query*}")
1990            .with_title("Database Query")
1991            .with_description("Execute database queries")
1992    }
1993}
1994
1995/// Parameters for listing resource templates
1996#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
1997pub struct ListResourceTemplatesParams {
1998    /// Pagination cursor
1999    #[serde(skip_serializing_if = "Option::is_none")]
2000    pub cursor: Option<String>,
2001}
2002
2003/// Request to list resource templates
2004#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2005pub struct ListResourceTemplatesRequest {
2006    /// Request parameters
2007    #[serde(skip_serializing_if = "Option::is_none")]
2008    pub params: Option<ListResourceTemplatesParams>,
2009}
2010
2011impl ListResourceTemplatesRequest {
2012    /// Create a new list templates request
2013    pub fn new() -> Self {
2014        Self { params: None }
2015    }
2016
2017    /// Create request with cursor for pagination
2018    pub fn with_cursor<C: Into<String>>(cursor: C) -> Self {
2019        Self {
2020            params: Some(ListResourceTemplatesParams {
2021                cursor: Some(cursor.into()),
2022            }),
2023        }
2024    }
2025}
2026
2027impl Default for ListResourceTemplatesRequest {
2028    fn default() -> Self {
2029        Self::new()
2030    }
2031}
2032
2033/// Result of listing resource templates
2034#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2035#[serde(rename_all = "camelCase")]
2036pub struct ListResourceTemplatesResult {
2037    /// Array of resource templates
2038    pub resource_templates: Vec<ResourceTemplate>,
2039    /// Pagination cursor for next page
2040    #[serde(skip_serializing_if = "Option::is_none")]
2041    pub next_cursor: Option<String>,
2042    /// Optional metadata
2043    #[serde(skip_serializing_if = "Option::is_none")]
2044    pub _meta: Option<serde_json::Value>,
2045}
2046
2047impl ListResourceTemplatesResult {
2048    /// Create a new result
2049    pub fn new(templates: Vec<ResourceTemplate>) -> Self {
2050        Self {
2051            resource_templates: templates,
2052            next_cursor: None,
2053            _meta: None,
2054        }
2055    }
2056
2057    /// Create result with pagination
2058    pub fn paginated(templates: Vec<ResourceTemplate>, next_cursor: String) -> Self {
2059        Self {
2060            resource_templates: templates,
2061            next_cursor: Some(next_cursor),
2062            _meta: None,
2063        }
2064    }
2065
2066    /// Add metadata
2067    pub fn with_meta(mut self, meta: serde_json::Value) -> Self {
2068        self._meta = Some(meta);
2069        self
2070    }
2071}
2072
2073// ============================================================================
2074// PING PROTOCOL (CONNECTION HEALTH MONITORING)
2075// ============================================================================
2076
2077/// Parameters for ping requests
2078#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
2079pub struct PingParams {
2080    /// Optional metadata
2081    #[serde(skip_serializing_if = "Option::is_none")]
2082    pub _meta: Option<serde_json::Value>,
2083}
2084
2085impl PingParams {
2086    /// Create a new ping parameters
2087    pub fn new() -> Self {
2088        Self { _meta: None }
2089    }
2090
2091    /// Add metadata
2092    pub fn with_meta(mut self, meta: serde_json::Value) -> Self {
2093        self._meta = Some(meta);
2094        self
2095    }
2096}
2097
2098/// A ping request to check connection health
2099#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2100pub struct PingRequest {
2101    /// The method name (always "ping")
2102    pub method: String,
2103    /// Request parameters
2104    #[serde(skip_serializing_if = "Option::is_none")]
2105    pub params: Option<PingParams>,
2106}
2107
2108impl PingRequest {
2109    /// Create a new ping request
2110    pub fn new() -> Self {
2111        Self {
2112            method: "ping".to_string(),
2113            params: None,
2114        }
2115    }
2116
2117    /// Create ping request with metadata
2118    pub fn with_meta(meta: serde_json::Value) -> Self {
2119        Self {
2120            method: "ping".to_string(),
2121            params: Some(PingParams::new().with_meta(meta)),
2122        }
2123    }
2124}
2125
2126impl Default for PingRequest {
2127    fn default() -> Self {
2128        Self::new()
2129    }
2130}
2131
2132/// Response to a ping request (usually empty)
2133#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2134pub struct PingResult {
2135    /// Optional metadata
2136    #[serde(skip_serializing_if = "Option::is_none")]
2137    pub _meta: Option<serde_json::Value>,
2138}
2139
2140impl PingResult {
2141    /// Create a new ping result
2142    pub fn new() -> Self {
2143        Self { _meta: None }
2144    }
2145
2146    /// Create result with metadata
2147    pub fn with_meta(meta: serde_json::Value) -> Self {
2148        Self { _meta: Some(meta) }
2149    }
2150}
2151
2152impl Default for PingResult {
2153    fn default() -> Self {
2154        Self::new()
2155    }
2156}
2157
2158// ============================================================================
2159// Roots Types
2160// ============================================================================
2161
2162/// Filesystem root
2163#[derive(Debug, Clone, Serialize, Deserialize)]
2164pub struct Root {
2165    /// Root URI
2166    pub uri: Uri,
2167    /// Root name
2168    #[serde(skip_serializing_if = "Option::is_none")]
2169    pub name: Option<String>,
2170}
2171
2172/// List roots request (no parameters)
2173#[derive(Debug, Clone, Serialize, Deserialize)]
2174pub struct ListRootsRequest;
2175
2176/// List roots result
2177#[derive(Debug, Clone, Serialize, Deserialize)]
2178pub struct ListRootsResult {
2179    /// Available roots
2180    pub roots: Vec<Root>,
2181    /// Optional metadata per MCP 2025-06-18 specification
2182    #[serde(skip_serializing_if = "Option::is_none")]
2183    pub _meta: Option<serde_json::Value>,
2184}
2185
2186/// Roots list changed notification (no parameters)
2187#[derive(Debug, Clone, Serialize, Deserialize)]
2188pub struct RootsListChangedNotification;
2189
2190/// Empty result for operations that don't return data
2191#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2192pub struct EmptyResult {}
2193
2194#[cfg(test)]
2195mod tests {
2196    use super::*;
2197
2198    #[test]
2199    fn test_serialize_deserialize() {
2200        let tool = Tool {
2201            name: "test_tool".to_string(),
2202            title: Some("Test Tool".to_string()),
2203            description: Some("A test tool".to_string()),
2204            input_schema: ToolInputSchema {
2205                schema_type: "object".to_string(),
2206                properties: None,
2207                required: None,
2208                additional_properties: None,
2209            },
2210            output_schema: None,
2211            annotations: None,
2212            meta: None,
2213        };
2214
2215        let json = serde_json::to_string(&tool).unwrap();
2216        let deserialized: Tool = serde_json::from_str(&json).unwrap();
2217        assert_eq!(tool.name, deserialized.name);
2218    }
2219
2220    #[test]
2221    fn test_content_types() {
2222        let text_content = ContentBlock::Text(TextContent {
2223            text: "Hello, World!".to_string(),
2224            annotations: None,
2225            meta: None,
2226        });
2227
2228        let json = serde_json::to_string(&text_content).unwrap();
2229        let _deserialized: ContentBlock = serde_json::from_str(&json).unwrap();
2230
2231        // Test the compatibility alias
2232        let _compatible: Content = text_content;
2233    }
2234
2235    #[test]
2236    fn test_elicitation_schema_builder() {
2237        let schema = ElicitationSchema::new()
2238            .add_string_property("username", true, Some("Your username".to_string()))
2239            .add_number_property(
2240                "age",
2241                false,
2242                Some("Your age".to_string()),
2243                Some(0.0),
2244                Some(150.0),
2245            )
2246            .add_boolean_property(
2247                "subscribe",
2248                true,
2249                Some("Subscribe to newsletter".to_string()),
2250                Some(false),
2251            )
2252            .add_enum_property(
2253                "role",
2254                true,
2255                Some("Your role".to_string()),
2256                vec!["admin".to_string(), "user".to_string(), "guest".to_string()],
2257                None,
2258            );
2259
2260        assert_eq!(schema.schema_type, "object");
2261        assert_eq!(schema.properties.len(), 4);
2262        assert_eq!(schema.required.as_ref().unwrap().len(), 3);
2263
2264        // Verify username property
2265        let username_prop = &schema.properties["username"];
2266        match username_prop {
2267            PrimitiveSchemaDefinition::String { description, .. } => {
2268                assert_eq!(description.as_ref().unwrap(), "Your username");
2269            }
2270            _ => panic!("Expected string property"),
2271        }
2272
2273        // Verify age property
2274        let age_prop = &schema.properties["age"];
2275        match age_prop {
2276            PrimitiveSchemaDefinition::Number {
2277                minimum, maximum, ..
2278            } => {
2279                assert_eq!(*minimum, Some(0.0));
2280                assert_eq!(*maximum, Some(150.0));
2281            }
2282            _ => panic!("Expected number property"),
2283        }
2284    }
2285
2286    #[test]
2287    fn test_elicit_request_serialization() {
2288        let schema = ElicitationSchema::new()
2289            .add_string_property("name", true, Some("Your name".to_string()))
2290            .add_boolean_property("confirm", true, None, Some(false));
2291
2292        let request = ElicitRequest::new("Please provide your details", schema);
2293
2294        // Serialize to JSON
2295        let json = serde_json::to_string(&request).unwrap();
2296
2297        // Verify it contains expected structure
2298        assert!(json.contains("elicitation/create"));
2299        assert!(json.contains("Please provide your details"));
2300        assert!(json.contains("requestedSchema"));
2301
2302        // Deserialize back
2303        let deserialized: ElicitRequest = serde_json::from_str(&json).unwrap();
2304        assert_eq!(deserialized.method, "elicitation/create");
2305        assert_eq!(deserialized.params.message, "Please provide your details");
2306    }
2307
2308    #[test]
2309    fn test_elicit_result_actions() {
2310        // Test accept result
2311        let mut content = std::collections::HashMap::new();
2312        content.insert(
2313            "name".to_string(),
2314            serde_json::Value::String("John".to_string()),
2315        );
2316        content.insert(
2317            "age".to_string(),
2318            serde_json::Value::Number(serde_json::Number::from(30)),
2319        );
2320
2321        let accept_result = ElicitResult::accept(content);
2322        assert_eq!(accept_result.action, ElicitationAction::Accept);
2323        assert!(accept_result.content.is_some());
2324
2325        // Test decline result
2326        let decline_result = ElicitResult::decline();
2327        assert_eq!(decline_result.action, ElicitationAction::Decline);
2328        assert!(decline_result.content.is_none());
2329
2330        // Test cancel result
2331        let cancel_result = ElicitResult::cancel();
2332        assert_eq!(cancel_result.action, ElicitationAction::Cancel);
2333        assert!(cancel_result.content.is_none());
2334    }
2335
2336    #[test]
2337    fn test_elicit_result_serialization_compliance() {
2338        // Test that serialization matches MCP spec exactly
2339        let mut content = std::collections::HashMap::new();
2340        content.insert(
2341            "field1".to_string(),
2342            serde_json::Value::String("value1".to_string()),
2343        );
2344
2345        let result = ElicitResult::accept(content);
2346        let json = serde_json::to_string(&result).unwrap();
2347
2348        // Parse back to ensure it's valid
2349        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2350
2351        // Check action field
2352        assert_eq!(parsed["action"].as_str().unwrap(), "accept");
2353
2354        // Check content field
2355        assert!(parsed["content"].is_object());
2356        assert_eq!(parsed["content"]["field1"].as_str().unwrap(), "value1");
2357    }
2358
2359    #[test]
2360    fn test_primitive_schema_serialization() {
2361        // Test string schema
2362        let string_schema = PrimitiveSchemaDefinition::String {
2363            title: Some("Title".to_string()),
2364            description: Some("Description".to_string()),
2365            format: Some("email".to_string()),
2366            min_length: Some(1),
2367            max_length: Some(100),
2368            enum_values: None,
2369            enum_names: None,
2370        };
2371
2372        let json = serde_json::to_string(&string_schema).unwrap();
2373        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2374
2375        assert_eq!(parsed["type"].as_str().unwrap(), "string");
2376        assert_eq!(parsed["format"].as_str().unwrap(), "email");
2377        assert_eq!(parsed["minLength"].as_u64().unwrap(), 1);
2378        assert_eq!(parsed["maxLength"].as_u64().unwrap(), 100);
2379
2380        // Test enum schema
2381        let enum_schema = PrimitiveSchemaDefinition::String {
2382            title: None,
2383            description: Some("Select option".to_string()),
2384            format: None,
2385            min_length: None,
2386            max_length: None,
2387            enum_values: Some(vec!["option1".to_string(), "option2".to_string()]),
2388            enum_names: Some(vec!["Option 1".to_string(), "Option 2".to_string()]),
2389        };
2390
2391        let enum_json = serde_json::to_string(&enum_schema).unwrap();
2392        let enum_parsed: serde_json::Value = serde_json::from_str(&enum_json).unwrap();
2393
2394        assert_eq!(enum_parsed["type"].as_str().unwrap(), "string");
2395        assert_eq!(enum_parsed["enum"].as_array().unwrap().len(), 2);
2396        assert_eq!(enum_parsed["enumNames"].as_array().unwrap().len(), 2);
2397    }
2398
2399    #[test]
2400    fn test_server_request_with_elicitation() {
2401        let schema = ElicitationSchema::new().add_string_property(
2402            "email",
2403            true,
2404            Some("Your email address".to_string()),
2405        );
2406
2407        let request_params = ElicitRequestParams {
2408            message: "Please provide your email".to_string(),
2409            requested_schema: schema,
2410            _meta: None,
2411        };
2412
2413        let server_request = ServerRequest::ElicitationCreate(request_params);
2414
2415        // Serialize and verify
2416        let json = serde_json::to_string(&server_request).unwrap();
2417        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2418
2419        assert_eq!(parsed["method"].as_str().unwrap(), "elicitation/create");
2420        assert!(parsed["message"].is_string());
2421        assert!(parsed["requestedSchema"].is_object());
2422    }
2423
2424    #[test]
2425    fn test_completion_request_serialization() {
2426        let argument = ArgumentInfo {
2427            name: "file_path".to_string(),
2428            value: "/home/user/doc".to_string(),
2429        };
2430
2431        let reference = CompletionReference::ResourceTemplate(ResourceTemplateReferenceData {
2432            uri: "/files/{path}".to_string(),
2433        });
2434
2435        let request = CompleteRequest::new(argument, reference);
2436
2437        // Serialize
2438        let json = serde_json::to_string(&request).unwrap();
2439        assert!(json.contains("completion/complete"));
2440        assert!(json.contains("file_path"));
2441        assert!(json.contains("/home/user/doc"));
2442
2443        // Deserialize
2444        let deserialized: CompleteRequest = serde_json::from_str(&json).unwrap();
2445        assert_eq!(deserialized.method, "completion/complete");
2446        assert_eq!(deserialized.params.argument.name, "file_path");
2447    }
2448
2449    #[test]
2450    fn test_completion_reference_types() {
2451        // Test prompt reference
2452        let prompt_ref = CompletionReference::Prompt(PromptReferenceData {
2453            name: "code_review".to_string(),
2454            title: Some("Code Review Assistant".to_string()),
2455        });
2456
2457        let json = serde_json::to_string(&prompt_ref).unwrap();
2458        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2459        assert_eq!(parsed["type"].as_str().unwrap(), "ref/prompt");
2460        assert_eq!(parsed["name"].as_str().unwrap(), "code_review");
2461
2462        // Test resource template reference
2463        let resource_ref = CompletionReference::ResourceTemplate(ResourceTemplateReferenceData {
2464            uri: "/api/{endpoint}".to_string(),
2465        });
2466
2467        let json = serde_json::to_string(&resource_ref).unwrap();
2468        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2469        assert_eq!(parsed["type"].as_str().unwrap(), "ref/resource");
2470        assert_eq!(parsed["uri"].as_str().unwrap(), "/api/{endpoint}");
2471    }
2472
2473    #[test]
2474    fn test_completion_response_with_pagination() {
2475        // Test simple response
2476        let simple =
2477            CompletionResponse::new(vec!["file1.txt".to_string(), "file2.txt".to_string()]);
2478        assert_eq!(simple.values.len(), 2);
2479        assert!(simple.total.is_none());
2480
2481        // Test paginated response
2482        let paginated = CompletionResponse::paginated(
2483            vec!["item1".to_string(), "item2".to_string()],
2484            100,
2485            true,
2486        );
2487        assert_eq!(paginated.values.len(), 2);
2488        assert_eq!(paginated.total, Some(100));
2489        assert_eq!(paginated.has_more, Some(true));
2490
2491        // Test serialization
2492        let json = serde_json::to_string(&paginated).unwrap();
2493        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2494        assert_eq!(parsed["total"].as_u64().unwrap(), 100);
2495        assert!(parsed["hasMore"].as_bool().unwrap());
2496        assert_eq!(parsed["values"].as_array().unwrap().len(), 2);
2497    }
2498
2499    #[test]
2500    fn test_complete_result_structure() {
2501        let completion = CompletionResponse::paginated(
2502            vec!["option1".to_string(), "option2".to_string()],
2503            50,
2504            false,
2505        );
2506
2507        let result = CompleteResult::new(completion);
2508
2509        // Serialize and verify structure
2510        let json = serde_json::to_string(&result).unwrap();
2511        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2512
2513        // Check completion field structure
2514        assert!(parsed["completion"].is_object());
2515        assert!(parsed["completion"]["values"].is_array());
2516        assert_eq!(parsed["completion"]["total"].as_u64().unwrap(), 50);
2517        assert!(!parsed["completion"]["hasMore"].as_bool().unwrap());
2518
2519        // Deserialize back
2520        let deserialized: CompleteResult = serde_json::from_str(&json).unwrap();
2521        assert_eq!(deserialized.completion.values.len(), 2);
2522        assert_eq!(deserialized.completion.total, Some(50));
2523    }
2524
2525    #[test]
2526    fn test_completion_context() {
2527        let mut context_args = std::collections::HashMap::new();
2528        context_args.insert("user_id".to_string(), "12345".to_string());
2529        context_args.insert("project".to_string(), "main".to_string());
2530
2531        let context = CompletionContext {
2532            arguments: Some(context_args),
2533        };
2534
2535        let argument = ArgumentInfo {
2536            name: "endpoint".to_string(),
2537            value: "api".to_string(),
2538        };
2539
2540        let reference = CompletionReference::ResourceTemplate(ResourceTemplateReferenceData {
2541            uri: "/projects/{project}/endpoints/{endpoint}".to_string(),
2542        });
2543
2544        let request = CompleteRequest::new(argument, reference).with_context(context);
2545
2546        // Verify context is included
2547        let json = serde_json::to_string(&request).unwrap();
2548        assert!(json.contains("user_id"));
2549        assert!(json.contains("12345"));
2550        assert!(json.contains("project"));
2551        assert!(json.contains("main"));
2552    }
2553
2554    #[test]
2555    fn test_client_request_with_completion() {
2556        let argument = ArgumentInfo {
2557            name: "query".to_string(),
2558            value: "hello".to_string(),
2559        };
2560
2561        let reference = CompletionReference::Prompt(PromptReferenceData {
2562            name: "greeting".to_string(),
2563            title: None,
2564        });
2565
2566        let complete_params = CompleteRequestParams {
2567            argument,
2568            reference,
2569            context: None,
2570            _meta: None,
2571        };
2572
2573        let client_request = ClientRequest::Complete(complete_params);
2574
2575        // Serialize and verify
2576        let json = serde_json::to_string(&client_request).unwrap();
2577        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2578
2579        assert_eq!(parsed["method"].as_str().unwrap(), "completion/complete");
2580        assert_eq!(parsed["argument"]["name"].as_str().unwrap(), "query");
2581        assert_eq!(parsed["ref"]["type"].as_str().unwrap(), "ref/prompt");
2582    }
2583
2584    #[test]
2585    fn test_resource_template_creation() {
2586        // Test basic creation
2587        let template = ResourceTemplate::new("file_access", "/files/{path}");
2588        assert_eq!(template.name, "file_access");
2589        assert_eq!(template.uri_template, "/files/{path}");
2590
2591        // Test builder pattern
2592        let enhanced_template = ResourceTemplate::new("api_access", "/api/{endpoint}")
2593            .with_title("API Access")
2594            .with_description("Access to REST API endpoints")
2595            .with_mime_type("application/json");
2596
2597        assert_eq!(enhanced_template.title, Some("API Access".to_string()));
2598        assert_eq!(
2599            enhanced_template.description,
2600            Some("Access to REST API endpoints".to_string())
2601        );
2602        assert_eq!(
2603            enhanced_template.mime_type,
2604            Some("application/json".to_string())
2605        );
2606    }
2607
2608    #[test]
2609    fn test_resource_template_presets() {
2610        // Test file system template
2611        let fs_template = ResourceTemplate::file_system("files", "/home/user");
2612        assert_eq!(fs_template.name, "files");
2613        assert_eq!(fs_template.uri_template, "file:///home/user/{path}");
2614        assert_eq!(fs_template.title, Some("File System Access".to_string()));
2615
2616        // Test API endpoint template
2617        let api_template = ResourceTemplate::api_endpoint("api", "https://api.example.com");
2618        assert_eq!(
2619            api_template.uri_template,
2620            "https://api.example.com/{endpoint}"
2621        );
2622        assert_eq!(api_template.mime_type, Some("application/json".to_string()));
2623
2624        // Test database query template
2625        let db_template = ResourceTemplate::database_query("queries");
2626        assert_eq!(db_template.uri_template, "db://query/{table}?{query*}");
2627        assert_eq!(db_template.title, Some("Database Query".to_string()));
2628    }
2629
2630    #[test]
2631    fn test_resource_template_serialization() {
2632        let template = ResourceTemplate::new("test_template", "/test/{id}")
2633            .with_title("Test Template")
2634            .with_description("A template for testing")
2635            .with_mime_type("text/plain");
2636
2637        let json = serde_json::to_string(&template).unwrap();
2638        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2639
2640        assert_eq!(parsed["name"].as_str().unwrap(), "test_template");
2641        assert_eq!(parsed["uriTemplate"].as_str().unwrap(), "/test/{id}");
2642        assert_eq!(parsed["title"].as_str().unwrap(), "Test Template");
2643        assert_eq!(
2644            parsed["description"].as_str().unwrap(),
2645            "A template for testing"
2646        );
2647        assert_eq!(parsed["mimeType"].as_str().unwrap(), "text/plain");
2648
2649        // Test deserialization
2650        let deserialized: ResourceTemplate = serde_json::from_str(&json).unwrap();
2651        assert_eq!(deserialized.name, "test_template");
2652        assert_eq!(deserialized.uri_template, "/test/{id}");
2653    }
2654
2655    #[test]
2656    fn test_list_resource_templates_request() {
2657        // Test basic request
2658        let request = ListResourceTemplatesRequest::new();
2659        assert!(request.params.is_none());
2660
2661        // Test request with cursor
2662        let paginated_request = ListResourceTemplatesRequest::with_cursor("cursor123");
2663        assert!(paginated_request.params.is_some());
2664        assert_eq!(
2665            paginated_request.params.unwrap().cursor,
2666            Some("cursor123".to_string())
2667        );
2668
2669        // Test serialization
2670        let json = serde_json::to_string(&request).unwrap();
2671        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2672
2673        // Should serialize to an empty object when no params
2674        assert!(parsed.as_object().unwrap().is_empty());
2675    }
2676
2677    #[test]
2678    fn test_list_resource_templates_result() {
2679        let templates = vec![
2680            ResourceTemplate::new("template1", "/api/{endpoint}"),
2681            ResourceTemplate::new("template2", "/files/{path}"),
2682        ];
2683
2684        // Test basic result
2685        let result = ListResourceTemplatesResult::new(templates.clone());
2686        assert_eq!(result.resource_templates.len(), 2);
2687        assert!(result.next_cursor.is_none());
2688
2689        // Test paginated result
2690        let paginated_result =
2691            ListResourceTemplatesResult::paginated(templates, "next_cursor".to_string());
2692        assert_eq!(paginated_result.resource_templates.len(), 2);
2693        assert_eq!(
2694            paginated_result.next_cursor,
2695            Some("next_cursor".to_string())
2696        );
2697
2698        // Test serialization
2699        let json = serde_json::to_string(&paginated_result).unwrap();
2700        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2701
2702        assert!(parsed["resourceTemplates"].is_array());
2703        assert_eq!(parsed["resourceTemplates"].as_array().unwrap().len(), 2);
2704        assert_eq!(parsed["nextCursor"].as_str().unwrap(), "next_cursor");
2705
2706        // Test deserialization
2707        let deserialized: ListResourceTemplatesResult = serde_json::from_str(&json).unwrap();
2708        assert_eq!(deserialized.resource_templates.len(), 2);
2709        assert_eq!(deserialized.next_cursor, Some("next_cursor".to_string()));
2710    }
2711
2712    #[test]
2713    fn test_client_request_with_resource_templates() {
2714        let request = ListResourceTemplatesRequest::with_cursor("abc123");
2715        let client_request = ClientRequest::ListResourceTemplates(request);
2716
2717        // Serialize and verify
2718        let json = serde_json::to_string(&client_request).unwrap();
2719        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2720
2721        assert_eq!(
2722            parsed["method"].as_str().unwrap(),
2723            "resources/templates/list"
2724        );
2725        assert_eq!(parsed["params"]["cursor"].as_str().unwrap(), "abc123");
2726    }
2727
2728    #[test]
2729    fn test_complex_uri_templates() {
2730        // Test RFC 6570 style templates
2731        let complex_templates = vec![
2732            ResourceTemplate::new(
2733                "github",
2734                "https://api.github.com/repos/{owner}/{repo}/contents/{+path}",
2735            ),
2736            ResourceTemplate::new("search", "/search{?q,type,sort,order}"),
2737            ResourceTemplate::new("matrix", "/matrix{;x,y}/data"),
2738            ResourceTemplate::new("fragment", "/documents/{id}{#section}"),
2739        ];
2740
2741        for template in complex_templates {
2742            let json = serde_json::to_string(&template).unwrap();
2743            let deserialized: ResourceTemplate = serde_json::from_str(&json).unwrap();
2744            assert_eq!(template.uri_template, deserialized.uri_template);
2745        }
2746    }
2747
2748    #[test]
2749    fn test_resource_template_with_annotations() {
2750        let annotations = Annotations {
2751            priority: Some(1.0),
2752            ..Default::default()
2753        };
2754
2755        let template =
2756            ResourceTemplate::new("important", "/critical/{id}").with_annotations(annotations);
2757
2758        assert!(template.annotations.is_some());
2759        assert_eq!(template.annotations.unwrap().priority, Some(1.0));
2760    }
2761
2762    #[test]
2763    fn test_ping_request_creation() {
2764        // Test basic ping
2765        let ping = PingRequest::new();
2766        assert_eq!(ping.method, "ping");
2767        assert!(ping.params.is_none());
2768
2769        // Test ping with metadata
2770        let meta_value = serde_json::json!({"timestamp": "2025-08-29T12:00:00Z"});
2771        let ping_with_meta = PingRequest::with_meta(meta_value.clone());
2772        assert_eq!(ping_with_meta.method, "ping");
2773        assert!(ping_with_meta.params.is_some());
2774        assert_eq!(ping_with_meta.params.unwrap()._meta, Some(meta_value));
2775    }
2776
2777    #[test]
2778    fn test_ping_serialization() {
2779        // Test basic ping serialization
2780        let ping = PingRequest::new();
2781        let json = serde_json::to_string(&ping).unwrap();
2782        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2783        assert_eq!(parsed["method"].as_str().unwrap(), "ping");
2784
2785        // Test deserialization
2786        let deserialized: PingRequest = serde_json::from_str(&json).unwrap();
2787        assert_eq!(deserialized.method, "ping");
2788
2789        // Test ping with metadata
2790        let meta_value = serde_json::json!({"client": "test", "version": "1.0"});
2791        let ping_with_meta = PingRequest::with_meta(meta_value.clone());
2792        let json_with_meta = serde_json::to_string(&ping_with_meta).unwrap();
2793        let parsed_meta: serde_json::Value = serde_json::from_str(&json_with_meta).unwrap();
2794
2795        assert!(parsed_meta["params"].is_object());
2796        assert_eq!(
2797            parsed_meta["params"]["_meta"]["client"].as_str().unwrap(),
2798            "test"
2799        );
2800    }
2801
2802    #[test]
2803    fn test_ping_result() {
2804        // Test basic result
2805        let result = PingResult::new();
2806        assert!(result._meta.is_none());
2807
2808        // Test result with metadata
2809        let meta = serde_json::json!({"latency_ms": 42});
2810        let result_with_meta = PingResult::with_meta(meta.clone());
2811        assert_eq!(result_with_meta._meta, Some(meta));
2812
2813        // Test serialization
2814        let json = serde_json::to_string(&result).unwrap();
2815        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2816        // Empty result should serialize to empty object
2817        assert!(parsed.as_object().unwrap().is_empty());
2818
2819        // Test deserialization
2820        let deserialized: PingResult = serde_json::from_str(&json).unwrap();
2821        assert!(deserialized._meta.is_none());
2822    }
2823
2824    #[test]
2825    fn test_ping_params() {
2826        // Test basic params
2827        let params = PingParams::new();
2828        assert!(params._meta.is_none());
2829
2830        // Test params with metadata
2831        let meta = serde_json::json!({"timeout": 5000});
2832        let params_with_meta = PingParams::new().with_meta(meta.clone());
2833        assert_eq!(params_with_meta._meta, Some(meta));
2834
2835        // Test serialization
2836        let json = serde_json::to_string(&params).unwrap();
2837        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2838        assert!(parsed.as_object().unwrap().is_empty());
2839    }
2840
2841    #[test]
2842    fn test_server_request_with_ping() {
2843        let ping_params = PingParams::new();
2844        let server_request = ServerRequest::Ping(ping_params);
2845
2846        // Serialize and verify
2847        let json = serde_json::to_string(&server_request).unwrap();
2848        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2849
2850        assert_eq!(parsed["method"].as_str().unwrap(), "ping");
2851    }
2852
2853    #[test]
2854    fn test_client_request_with_ping() {
2855        let ping_params = PingParams::new();
2856        let client_request = ClientRequest::Ping(ping_params);
2857
2858        // Serialize and verify
2859        let json = serde_json::to_string(&client_request).unwrap();
2860        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2861
2862        assert_eq!(parsed["method"].as_str().unwrap(), "ping");
2863    }
2864
2865    #[test]
2866    fn test_ping_protocol_bidirectional() {
2867        // Test that ping can be used from both client and server
2868        let meta = serde_json::json!({"source": "test"});
2869
2870        // Client-initiated ping
2871        let client_ping = ClientRequest::Ping(PingParams::new().with_meta(meta.clone()));
2872        let client_json = serde_json::to_string(&client_ping).unwrap();
2873
2874        // Server-initiated ping
2875        let server_ping = ServerRequest::Ping(PingParams::new().with_meta(meta.clone()));
2876        let server_json = serde_json::to_string(&server_ping).unwrap();
2877
2878        // Both should have same structure
2879        let client_parsed: serde_json::Value = serde_json::from_str(&client_json).unwrap();
2880        let server_parsed: serde_json::Value = serde_json::from_str(&server_json).unwrap();
2881
2882        assert_eq!(client_parsed["method"], server_parsed["method"]);
2883        assert_eq!(
2884            client_parsed["_meta"]["source"],
2885            server_parsed["_meta"]["source"]
2886        );
2887    }
2888}