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