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
636/// Tool input schema definition
637#[derive(Debug, Clone, Serialize, Deserialize)]
638pub struct ToolInputSchema {
639    /// Must be "object" for tool input schemas
640    #[serde(rename = "type")]
641    pub schema_type: String,
642    /// Schema properties defining the tool parameters
643    #[serde(skip_serializing_if = "Option::is_none")]
644    pub properties: Option<HashMap<String, serde_json::Value>>,
645    /// List of required property names
646    #[serde(skip_serializing_if = "Option::is_none")]
647    pub required: Option<Vec<String>>,
648    /// Whether additional properties are allowed
649    #[serde(
650        rename = "additionalProperties",
651        skip_serializing_if = "Option::is_none"
652    )]
653    pub additional_properties: Option<bool>,
654}
655
656/// Tool output schema definition
657#[derive(Debug, Clone, Serialize, Deserialize)]
658pub struct ToolOutputSchema {
659    /// Must be "object" for tool output schemas
660    #[serde(rename = "type")]
661    pub schema_type: String,
662    /// Schema properties defining the tool output structure
663    #[serde(skip_serializing_if = "Option::is_none")]
664    pub properties: Option<HashMap<String, serde_json::Value>>,
665    /// List of required property names
666    #[serde(skip_serializing_if = "Option::is_none")]
667    pub required: Option<Vec<String>>,
668    /// Whether additional properties are allowed
669    #[serde(
670        rename = "additionalProperties",
671        skip_serializing_if = "Option::is_none"
672    )]
673    pub additional_properties: Option<bool>,
674}
675
676/// List tools request (no parameters)
677#[derive(Debug, Clone, Serialize, Deserialize)]
678pub struct ListToolsRequest;
679
680/// List tools result
681#[derive(Debug, Clone, Serialize, Deserialize)]
682pub struct ListToolsResult {
683    /// Available tools
684    pub tools: Vec<Tool>,
685    /// Optional continuation token
686    #[serde(rename = "nextCursor", skip_serializing_if = "Option::is_none")]
687    pub next_cursor: Option<String>,
688}
689
690/// Call tool request
691#[derive(Debug, Clone, Serialize, Deserialize)]
692pub struct CallToolRequest {
693    /// Tool name
694    pub name: String,
695    /// Tool arguments
696    #[serde(skip_serializing_if = "Option::is_none")]
697    pub arguments: Option<HashMap<String, serde_json::Value>>,
698}
699
700/// Call tool result
701#[derive(Debug, Clone, Serialize, Deserialize)]
702pub struct CallToolResult {
703    /// Result content
704    pub content: Vec<ContentBlock>,
705    /// Whether the operation failed
706    #[serde(rename = "isError", skip_serializing_if = "Option::is_none")]
707    pub is_error: Option<bool>,
708}
709
710// ============================================================================
711// Prompt Types
712// ============================================================================
713
714/// Prompt definition per MCP 2025-06-18 specification
715#[derive(Debug, Clone, Serialize, Deserialize)]
716pub struct Prompt {
717    /// Prompt name (programmatic identifier)
718    pub name: String,
719
720    /// Display title for UI contexts (optional, falls back to name if not provided)
721    #[serde(skip_serializing_if = "Option::is_none")]
722    pub title: Option<String>,
723
724    /// An optional description of what this prompt provides
725    #[serde(skip_serializing_if = "Option::is_none")]
726    pub description: Option<String>,
727
728    /// A list of arguments to use for templating the prompt
729    #[serde(skip_serializing_if = "Option::is_none")]
730    pub arguments: Option<Vec<PromptArgument>>,
731
732    /// General metadata field for extensions and custom data
733    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
734    pub meta: Option<HashMap<String, serde_json::Value>>,
735}
736
737/// Prompt argument definition per MCP 2025-06-18 specification
738#[derive(Debug, Clone, Serialize, Deserialize)]
739pub struct PromptArgument {
740    /// Argument name (programmatic identifier)
741    pub name: String,
742
743    /// Display title for UI contexts (optional, falls back to name if not provided)
744    #[serde(skip_serializing_if = "Option::is_none")]
745    pub title: Option<String>,
746
747    /// A human-readable description of the argument
748    #[serde(skip_serializing_if = "Option::is_none")]
749    pub description: Option<String>,
750
751    /// Whether this argument must be provided
752    #[serde(skip_serializing_if = "Option::is_none")]
753    pub required: Option<bool>,
754}
755
756/// Prompt input parameters
757pub type PromptInput = HashMap<String, serde_json::Value>;
758
759/// List prompts request (no parameters)
760#[derive(Debug, Clone, Serialize, Deserialize)]
761pub struct ListPromptsRequest;
762
763/// List prompts result
764#[derive(Debug, Clone, Serialize, Deserialize)]
765pub struct ListPromptsResult {
766    /// Available prompts
767    pub prompts: Vec<Prompt>,
768    /// Optional continuation token
769    #[serde(rename = "nextCursor", skip_serializing_if = "Option::is_none")]
770    pub next_cursor: Option<String>,
771}
772
773/// Get prompt request
774#[derive(Debug, Clone, Serialize, Deserialize)]
775pub struct GetPromptRequest {
776    /// Prompt name
777    pub name: String,
778    /// Prompt arguments
779    #[serde(skip_serializing_if = "Option::is_none")]
780    pub arguments: Option<PromptInput>,
781}
782
783/// Get prompt result
784#[derive(Debug, Clone, Serialize, Deserialize)]
785pub struct GetPromptResult {
786    /// Prompt description
787    #[serde(skip_serializing_if = "Option::is_none")]
788    pub description: Option<String>,
789    /// Prompt messages
790    pub messages: Vec<PromptMessage>,
791}
792
793/// Prompt message
794#[derive(Debug, Clone, Serialize, Deserialize)]
795pub struct PromptMessage {
796    /// Message role
797    pub role: Role,
798    /// Message content
799    pub content: Content,
800}
801
802// ============================================================================
803// Resource Types
804// ============================================================================
805
806/// Resource definition per MCP 2025-06-18 specification
807#[derive(Debug, Clone, Serialize, Deserialize)]
808pub struct Resource {
809    /// Resource name (programmatic identifier)
810    pub name: String,
811
812    /// Display title for UI contexts (optional, falls back to name if not provided)
813    #[serde(skip_serializing_if = "Option::is_none")]
814    pub title: Option<String>,
815
816    /// The URI of this resource
817    pub uri: String,
818
819    /// A description of what this resource represents
820    /// This can be used by clients to improve the LLM's understanding of available resources
821    #[serde(skip_serializing_if = "Option::is_none")]
822    pub description: Option<String>,
823
824    /// The MIME type of this resource, if known
825    #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
826    pub mime_type: Option<String>,
827
828    /// Optional annotations for the client
829    #[serde(skip_serializing_if = "Option::is_none")]
830    pub annotations: Option<Annotations>,
831
832    /// The size of the raw resource content, in bytes (before base64 encoding or tokenization), if known
833    /// This can be used by Hosts to display file sizes and estimate context window usage
834    #[serde(skip_serializing_if = "Option::is_none")]
835    pub size: Option<u64>,
836
837    /// General metadata field for extensions and custom data
838    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
839    pub meta: Option<HashMap<String, serde_json::Value>>,
840}
841
842/// Base resource contents interface
843#[derive(Debug, Clone, Serialize, Deserialize)]
844pub struct ResourceContents {
845    /// The URI of this resource
846    pub uri: String,
847    /// The MIME type of this resource, if known
848    #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
849    pub mime_type: Option<String>,
850    /// General metadata field for extensions and custom data
851    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
852    pub meta: Option<HashMap<String, serde_json::Value>>,
853}
854
855/// Text resource contents
856#[derive(Debug, Clone, Serialize, Deserialize)]
857pub struct TextResourceContents {
858    /// The URI of this resource
859    pub uri: String,
860    /// The MIME type of this resource, if known
861    #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
862    pub mime_type: Option<String>,
863    /// The text content (must only be set for text-representable data)
864    pub text: String,
865    /// General metadata field for extensions and custom data
866    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
867    pub meta: Option<HashMap<String, serde_json::Value>>,
868}
869
870/// Binary resource contents
871#[derive(Debug, Clone, Serialize, Deserialize)]
872pub struct BlobResourceContents {
873    /// The URI of this resource
874    pub uri: String,
875    /// The MIME type of this resource, if known
876    #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
877    pub mime_type: Option<String>,
878    /// Base64-encoded binary data
879    pub blob: String,
880    /// General metadata field for extensions and custom data
881    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
882    pub meta: Option<HashMap<String, serde_json::Value>>,
883}
884
885/// Union type for resource contents (text or binary)
886#[derive(Debug, Clone, Serialize, Deserialize)]
887#[serde(untagged)]
888pub enum ResourceContent {
889    /// Text resource content
890    Text(TextResourceContents),
891    /// Binary resource content
892    Blob(BlobResourceContents),
893}
894
895/// List resources request
896#[derive(Debug, Clone, Serialize, Deserialize)]
897pub struct ListResourcesRequest {
898    /// Optional cursor for pagination
899    #[serde(skip_serializing_if = "Option::is_none")]
900    pub cursor: Option<String>,
901}
902
903/// List resources result
904#[derive(Debug, Clone, Serialize, Deserialize)]
905pub struct ListResourcesResult {
906    /// Available resources
907    pub resources: Vec<Resource>,
908    /// Optional continuation token
909    #[serde(rename = "nextCursor", skip_serializing_if = "Option::is_none")]
910    pub next_cursor: Option<String>,
911}
912
913/// Read resource request
914#[derive(Debug, Clone, Serialize, Deserialize)]
915pub struct ReadResourceRequest {
916    /// Resource URI
917    pub uri: Uri,
918}
919
920/// Read resource result
921#[derive(Debug, Clone, Serialize, Deserialize)]
922pub struct ReadResourceResult {
923    /// Resource contents (can be text or binary)
924    pub contents: Vec<ResourceContent>,
925}
926
927/// Subscribe to resource request
928#[derive(Debug, Clone, Serialize, Deserialize)]
929pub struct SubscribeRequest {
930    /// Resource URI
931    pub uri: Uri,
932}
933
934/// Unsubscribe from resource request
935#[derive(Debug, Clone, Serialize, Deserialize)]
936pub struct UnsubscribeRequest {
937    /// Resource URI
938    pub uri: Uri,
939}
940
941/// Resource updated notification
942#[derive(Debug, Clone, Serialize, Deserialize)]
943pub struct ResourceUpdatedNotification {
944    /// Resource URI
945    pub uri: Uri,
946}
947
948// ============================================================================
949// Logging Types
950// ============================================================================
951
952/// Log level
953#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
954#[serde(rename_all = "lowercase")]
955pub enum LogLevel {
956    /// Debug level
957    Debug,
958    /// Info level
959    Info,
960    /// Notice level
961    Notice,
962    /// Warning level
963    Warning,
964    /// Error level
965    Error,
966    /// Critical level
967    Critical,
968    /// Alert level
969    Alert,
970    /// Emergency level
971    Emergency,
972}
973
974/// Set log level request
975#[derive(Debug, Clone, Serialize, Deserialize)]
976pub struct SetLevelRequest {
977    /// Log level to set
978    pub level: LogLevel,
979}
980
981/// Set log level result (no data)
982#[derive(Debug, Clone, Serialize, Deserialize)]
983pub struct SetLevelResult;
984
985/// Logging notification
986#[derive(Debug, Clone, Serialize, Deserialize)]
987pub struct LoggingNotification {
988    /// Log level
989    pub level: LogLevel,
990    /// Log data
991    pub data: serde_json::Value,
992    /// Optional logger name
993    #[serde(skip_serializing_if = "Option::is_none")]
994    pub logger: Option<String>,
995}
996
997// ============================================================================
998// Progress Types
999// ============================================================================
1000
1001/// Progress notification per MCP 2025-06-18 specification
1002#[derive(Debug, Clone, Serialize, Deserialize)]
1003pub struct ProgressNotification {
1004    /// The progress token which was given in the initial request
1005    /// Used to associate this notification with the request that is proceeding
1006    #[serde(rename = "progressToken")]
1007    pub progress_token: ProgressToken,
1008    /// The progress thus far. This should increase every time progress is made,
1009    /// even if the total is unknown
1010    pub progress: f64,
1011    /// Total number of items to process (or total progress required), if known
1012    #[serde(skip_serializing_if = "Option::is_none")]
1013    pub total: Option<f64>,
1014    /// An optional message describing the current progress
1015    #[serde(skip_serializing_if = "Option::is_none")]
1016    pub message: Option<String>,
1017}
1018
1019/// Cancellation notification per MCP 2025-06-18 specification
1020#[derive(Debug, Clone, Serialize, Deserialize)]
1021pub struct CancelledNotification {
1022    /// The ID of the request to cancel
1023    /// This MUST correspond to the ID of a request previously issued in the same direction
1024    #[serde(rename = "requestId")]
1025    pub request_id: RequestId,
1026    /// An optional string describing the reason for the cancellation
1027    /// This MAY be logged or presented to the user
1028    #[serde(skip_serializing_if = "Option::is_none")]
1029    pub reason: Option<String>,
1030}
1031
1032// ============================================================================
1033// Sampling Types
1034// ============================================================================
1035
1036/// Create message request
1037#[derive(Debug, Clone, Serialize, Deserialize)]
1038pub struct CreateMessageRequest {
1039    /// Messages to include
1040    pub messages: Vec<SamplingMessage>,
1041    /// Model preferences
1042    #[serde(rename = "modelPreferences", skip_serializing_if = "Option::is_none")]
1043    pub model_preferences: Option<ModelPreferences>,
1044    /// System prompt
1045    #[serde(rename = "systemPrompt", skip_serializing_if = "Option::is_none")]
1046    pub system_prompt: Option<String>,
1047    /// Include context
1048    #[serde(rename = "includeContext", skip_serializing_if = "Option::is_none")]
1049    pub include_context: Option<IncludeContext>,
1050    /// Temperature
1051    #[serde(skip_serializing_if = "Option::is_none")]
1052    pub temperature: Option<f64>,
1053    /// Max tokens (required by MCP 2025-06-18 spec)
1054    #[serde(rename = "maxTokens")]
1055    pub max_tokens: u32,
1056    /// Stop sequences
1057    #[serde(rename = "stopSequences", skip_serializing_if = "Option::is_none")]
1058    pub stop_sequences: Option<Vec<String>>,
1059    /// Metadata
1060    #[serde(skip_serializing_if = "Option::is_none")]
1061    pub metadata: Option<HashMap<String, serde_json::Value>>,
1062}
1063
1064/// Model preferences
1065#[derive(Debug, Clone, Serialize, Deserialize)]
1066pub struct ModelPreferences {
1067    /// Preferred hints
1068    #[serde(skip_serializing_if = "Option::is_none")]
1069    pub hints: Option<Vec<ModelHint>>,
1070    /// Cost priority
1071    #[serde(rename = "costPriority", skip_serializing_if = "Option::is_none")]
1072    pub cost_priority: Option<f64>,
1073    /// Speed priority
1074    #[serde(rename = "speedPriority", skip_serializing_if = "Option::is_none")]
1075    pub speed_priority: Option<f64>,
1076    /// Intelligence priority
1077    #[serde(
1078        rename = "intelligencePriority",
1079        skip_serializing_if = "Option::is_none"
1080    )]
1081    pub intelligence_priority: Option<f64>,
1082}
1083
1084/// Model hint
1085#[derive(Debug, Clone, Serialize, Deserialize)]
1086pub struct ModelHint {
1087    /// Hint name (required by MCP 2025-06-18 spec)
1088    pub name: String,
1089}
1090
1091/// Include context options
1092#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1093#[serde(rename_all = "lowercase")]
1094pub enum IncludeContext {
1095    /// No context
1096    None,
1097    /// This server only
1098    ThisServer,
1099    /// All servers
1100    AllServers,
1101}
1102
1103/// Sampling message
1104#[derive(Debug, Clone, Serialize, Deserialize)]
1105pub struct SamplingMessage {
1106    /// Message role
1107    pub role: Role,
1108    /// Message content
1109    pub content: Content,
1110}
1111
1112/// Create message result
1113#[derive(Debug, Clone, Serialize, Deserialize)]
1114pub struct CreateMessageResult {
1115    /// Role of the created message
1116    pub role: Role,
1117    /// Content of the created message
1118    pub content: Content,
1119    /// Model used
1120    #[serde(skip_serializing_if = "Option::is_none")]
1121    pub model: Option<String>,
1122    /// Stop reason
1123    #[serde(rename = "stopReason", skip_serializing_if = "Option::is_none")]
1124    pub stop_reason: Option<String>,
1125}
1126
1127// ============================================================================
1128// ELICITATION (SERVER-INITIATED USER INPUT)
1129// ============================================================================
1130
1131/// Primitive schema definition for elicitation requests
1132/// Only allows primitive types without nesting, as per MCP 2025-06-18 spec
1133#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1134#[serde(tag = "type")]
1135pub enum PrimitiveSchemaDefinition {
1136    /// String field schema definition
1137    #[serde(rename = "string")]
1138    String {
1139        /// Field title
1140        #[serde(skip_serializing_if = "Option::is_none")]
1141        title: Option<String>,
1142        /// Field description
1143        #[serde(skip_serializing_if = "Option::is_none")]
1144        description: Option<String>,
1145        /// String format (email, uri, date, date-time, etc.)
1146        #[serde(skip_serializing_if = "Option::is_none")]
1147        format: Option<String>,
1148        /// Minimum string length
1149        #[serde(skip_serializing_if = "Option::is_none")]
1150        #[serde(rename = "minLength")]
1151        min_length: Option<u32>,
1152        /// Maximum string length
1153        #[serde(skip_serializing_if = "Option::is_none")]
1154        #[serde(rename = "maxLength")]
1155        max_length: Option<u32>,
1156        /// Allowed enum values
1157        #[serde(skip_serializing_if = "Option::is_none")]
1158        #[serde(rename = "enum")]
1159        enum_values: Option<Vec<String>>,
1160        /// Display names for enum values
1161        #[serde(skip_serializing_if = "Option::is_none")]
1162        #[serde(rename = "enumNames")]
1163        enum_names: Option<Vec<String>>,
1164    },
1165    /// Number field schema definition
1166    #[serde(rename = "number")]
1167    Number {
1168        /// Field title
1169        #[serde(skip_serializing_if = "Option::is_none")]
1170        title: Option<String>,
1171        /// Field description
1172        #[serde(skip_serializing_if = "Option::is_none")]
1173        description: Option<String>,
1174        /// Minimum value
1175        #[serde(skip_serializing_if = "Option::is_none")]
1176        minimum: Option<f64>,
1177        /// Maximum value
1178        #[serde(skip_serializing_if = "Option::is_none")]
1179        maximum: Option<f64>,
1180    },
1181    /// Integer field schema definition
1182    #[serde(rename = "integer")]
1183    Integer {
1184        /// Field title
1185        #[serde(skip_serializing_if = "Option::is_none")]
1186        title: Option<String>,
1187        /// Field description
1188        #[serde(skip_serializing_if = "Option::is_none")]
1189        description: Option<String>,
1190        /// Minimum value
1191        #[serde(skip_serializing_if = "Option::is_none")]
1192        minimum: Option<i64>,
1193        /// Maximum value
1194        #[serde(skip_serializing_if = "Option::is_none")]
1195        maximum: Option<i64>,
1196    },
1197    /// Boolean field schema definition
1198    #[serde(rename = "boolean")]
1199    Boolean {
1200        /// Field title
1201        #[serde(skip_serializing_if = "Option::is_none")]
1202        title: Option<String>,
1203        /// Field description
1204        #[serde(skip_serializing_if = "Option::is_none")]
1205        description: Option<String>,
1206        /// Default value
1207        #[serde(skip_serializing_if = "Option::is_none")]
1208        default: Option<bool>,
1209    },
1210}
1211
1212/// Elicitation schema - restricted subset of JSON Schema for primitive types only
1213#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1214pub struct ElicitationSchema {
1215    /// Schema type (must be "object")
1216    #[serde(rename = "type")]
1217    pub schema_type: String,
1218    /// Schema properties (field definitions)
1219    pub properties: std::collections::HashMap<String, PrimitiveSchemaDefinition>,
1220    /// Required field names
1221    #[serde(skip_serializing_if = "Option::is_none")]
1222    pub required: Option<Vec<String>>,
1223}
1224
1225impl ElicitationSchema {
1226    /// Create a new elicitation schema
1227    pub fn new() -> Self {
1228        Self {
1229            schema_type: "object".to_string(),
1230            properties: std::collections::HashMap::new(),
1231            required: None,
1232        }
1233    }
1234
1235    /// Add a string property
1236    pub fn add_string_property<K: Into<String>>(
1237        mut self,
1238        name: K,
1239        required: bool,
1240        description: Option<String>,
1241    ) -> Self {
1242        let property = PrimitiveSchemaDefinition::String {
1243            title: None,
1244            description,
1245            format: None,
1246            min_length: None,
1247            max_length: None,
1248            enum_values: None,
1249            enum_names: None,
1250        };
1251
1252        let name = name.into();
1253        self.properties.insert(name.clone(), property);
1254
1255        if required {
1256            self.required.get_or_insert_with(Vec::new).push(name);
1257        }
1258
1259        self
1260    }
1261
1262    /// Add a number property
1263    pub fn add_number_property<K: Into<String>>(
1264        mut self,
1265        name: K,
1266        required: bool,
1267        description: Option<String>,
1268        min: Option<f64>,
1269        max: Option<f64>,
1270    ) -> Self {
1271        let property = PrimitiveSchemaDefinition::Number {
1272            title: None,
1273            description,
1274            minimum: min,
1275            maximum: max,
1276        };
1277
1278        let name = name.into();
1279        self.properties.insert(name.clone(), property);
1280
1281        if required {
1282            self.required.get_or_insert_with(Vec::new).push(name);
1283        }
1284
1285        self
1286    }
1287
1288    /// Add a boolean property
1289    pub fn add_boolean_property<K: Into<String>>(
1290        mut self,
1291        name: K,
1292        required: bool,
1293        description: Option<String>,
1294        default: Option<bool>,
1295    ) -> Self {
1296        let property = PrimitiveSchemaDefinition::Boolean {
1297            title: None,
1298            description,
1299            default,
1300        };
1301
1302        let name = name.into();
1303        self.properties.insert(name.clone(), property);
1304
1305        if required {
1306            self.required.get_or_insert_with(Vec::new).push(name);
1307        }
1308
1309        self
1310    }
1311
1312    /// Add an enum property
1313    pub fn add_enum_property<K: Into<String>>(
1314        mut self,
1315        name: K,
1316        required: bool,
1317        description: Option<String>,
1318        values: Vec<String>,
1319        names: Option<Vec<String>>,
1320    ) -> Self {
1321        let property = PrimitiveSchemaDefinition::String {
1322            title: None,
1323            description,
1324            format: None,
1325            min_length: None,
1326            max_length: None,
1327            enum_values: Some(values),
1328            enum_names: names,
1329        };
1330
1331        let name = name.into();
1332        self.properties.insert(name.clone(), property);
1333
1334        if required {
1335            self.required.get_or_insert_with(Vec::new).push(name);
1336        }
1337
1338        self
1339    }
1340}
1341
1342impl Default for ElicitationSchema {
1343    fn default() -> Self {
1344        Self::new()
1345    }
1346}
1347
1348/// Parameters for elicitation/create request
1349#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1350#[serde(rename_all = "camelCase")]
1351pub struct ElicitRequestParams {
1352    /// The message to present to the user
1353    pub message: String,
1354    /// JSON Schema defining the expected response structure
1355    pub requested_schema: ElicitationSchema,
1356}
1357
1358/// Request to elicit user input (server-initiated)
1359#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1360pub struct ElicitRequest {
1361    /// The method name (always "elicitation/create")
1362    pub method: String,
1363    /// Request parameters
1364    pub params: ElicitRequestParams,
1365}
1366
1367impl ElicitRequest {
1368    /// Create a new elicit request
1369    pub fn new<M: Into<String>>(message: M, schema: ElicitationSchema) -> Self {
1370        Self {
1371            method: "elicitation/create".to_string(),
1372            params: ElicitRequestParams {
1373                message: message.into(),
1374                requested_schema: schema,
1375            },
1376        }
1377    }
1378}
1379
1380/// Action taken by user in response to elicitation
1381#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1382#[serde(rename_all = "lowercase")]
1383pub enum ElicitationAction {
1384    /// User submitted the form/confirmed the action
1385    Accept,
1386    /// User explicitly declined the action
1387    Decline,
1388    /// User dismissed without making an explicit choice
1389    Cancel,
1390}
1391
1392/// Client's response to an elicitation request
1393#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1394pub struct ElicitResult {
1395    /// The user action in response to the elicitation
1396    pub action: ElicitationAction,
1397    /// The submitted form data, only present when action is "accept"
1398    /// Contains values matching the requested schema
1399    #[serde(skip_serializing_if = "Option::is_none")]
1400    pub content: Option<std::collections::HashMap<String, serde_json::Value>>,
1401    /// Optional metadata
1402    #[serde(skip_serializing_if = "Option::is_none")]
1403    pub _meta: Option<serde_json::Value>,
1404}
1405
1406impl ElicitResult {
1407    /// Create an accept response with content
1408    pub fn accept(content: std::collections::HashMap<String, serde_json::Value>) -> Self {
1409        Self {
1410            action: ElicitationAction::Accept,
1411            content: Some(content),
1412            _meta: None,
1413        }
1414    }
1415
1416    /// Create a decline response
1417    pub fn decline() -> Self {
1418        Self {
1419            action: ElicitationAction::Decline,
1420            content: None,
1421            _meta: None,
1422        }
1423    }
1424
1425    /// Create a cancel response
1426    pub fn cancel() -> Self {
1427        Self {
1428            action: ElicitationAction::Cancel,
1429            content: None,
1430            _meta: None,
1431        }
1432    }
1433
1434    /// Add metadata
1435    pub fn with_meta(mut self, meta: serde_json::Value) -> Self {
1436        self._meta = Some(meta);
1437        self
1438    }
1439}
1440
1441// ============================================================================
1442// COMPLETION (ARGUMENT AUTOCOMPLETION)
1443// ============================================================================
1444
1445/// Information about the argument being completed
1446#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1447pub struct ArgumentInfo {
1448    /// The name of the argument
1449    pub name: String,
1450    /// The value of the argument to use for completion matching
1451    pub value: String,
1452}
1453
1454/// Context for completion requests
1455#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1456pub struct CompletionContext {
1457    /// Previously-resolved variables in a URI template or prompt
1458    #[serde(skip_serializing_if = "Option::is_none")]
1459    pub arguments: Option<std::collections::HashMap<String, String>>,
1460}
1461
1462/// Reference to a prompt for completion
1463#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1464pub struct PromptReference {
1465    /// Reference type (always "ref/prompt")
1466    #[serde(rename = "type")]
1467    pub ref_type: String,
1468    /// The name of the prompt
1469    pub name: String,
1470    /// Human-readable title
1471    #[serde(skip_serializing_if = "Option::is_none")]
1472    pub title: Option<String>,
1473}
1474
1475impl PromptReference {
1476    /// Create a new prompt reference
1477    pub fn new<N: Into<String>>(name: N) -> Self {
1478        Self {
1479            ref_type: "ref/prompt".to_string(),
1480            name: name.into(),
1481            title: None,
1482        }
1483    }
1484
1485    /// Add a title to the reference
1486    pub fn with_title<T: Into<String>>(mut self, title: T) -> Self {
1487        self.title = Some(title.into());
1488        self
1489    }
1490}
1491
1492/// Reference to a resource template for completion
1493#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1494pub struct ResourceTemplateReference {
1495    /// Reference type (always "ref/resource")
1496    #[serde(rename = "type")]
1497    pub ref_type: String,
1498    /// The URI or URI template of the resource
1499    pub uri: String,
1500}
1501
1502impl ResourceTemplateReference {
1503    /// Create a new resource template reference
1504    pub fn new<U: Into<String>>(uri: U) -> Self {
1505        Self {
1506            ref_type: "ref/resource".to_string(),
1507            uri: uri.into(),
1508        }
1509    }
1510}
1511
1512/// Reference types for completion requests
1513#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1514#[serde(tag = "type")]
1515pub enum CompletionReference {
1516    /// Reference to a prompt
1517    #[serde(rename = "ref/prompt")]
1518    Prompt(PromptReferenceData),
1519    /// Reference to a resource template
1520    #[serde(rename = "ref/resource")]
1521    ResourceTemplate(ResourceTemplateReferenceData),
1522}
1523
1524/// Data for prompt reference (excluding the type field)
1525#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1526pub struct PromptReferenceData {
1527    /// The name of the prompt
1528    pub name: String,
1529    /// Human-readable title
1530    #[serde(skip_serializing_if = "Option::is_none")]
1531    pub title: Option<String>,
1532}
1533
1534/// Data for resource template reference (excluding the type field)
1535#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1536pub struct ResourceTemplateReferenceData {
1537    /// The URI or URI template of the resource
1538    pub uri: String,
1539}
1540
1541/// Parameters for completion/complete request
1542#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1543pub struct CompleteRequestParams {
1544    /// The argument's information
1545    pub argument: ArgumentInfo,
1546    /// Reference to the item being completed
1547    #[serde(rename = "ref")]
1548    pub reference: CompletionReference,
1549    /// Additional context for completions
1550    #[serde(skip_serializing_if = "Option::is_none")]
1551    pub context: Option<CompletionContext>,
1552}
1553
1554/// Request for argument completion
1555#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1556pub struct CompleteRequest {
1557    /// The method name (always "completion/complete")
1558    pub method: String,
1559    /// Request parameters
1560    pub params: CompleteRequestParams,
1561}
1562
1563impl CompleteRequest {
1564    /// Create a new completion request
1565    pub fn new(argument: ArgumentInfo, reference: CompletionReference) -> Self {
1566        Self {
1567            method: "completion/complete".to_string(),
1568            params: CompleteRequestParams {
1569                argument,
1570                reference,
1571                context: None,
1572            },
1573        }
1574    }
1575
1576    /// Add context to the request
1577    pub fn with_context(mut self, context: CompletionContext) -> Self {
1578        self.params.context = Some(context);
1579        self
1580    }
1581}
1582
1583/// Completion response information
1584#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1585#[serde(rename_all = "camelCase")]
1586pub struct CompletionResponse {
1587    /// Completion values (max 100 items)
1588    pub values: Vec<String>,
1589    /// Total number of completion options available
1590    #[serde(skip_serializing_if = "Option::is_none")]
1591    pub total: Option<u32>,
1592    /// Whether there are additional completion options beyond those provided
1593    #[serde(skip_serializing_if = "Option::is_none")]
1594    pub has_more: Option<bool>,
1595}
1596
1597impl CompletionResponse {
1598    /// Create a new completion response
1599    pub fn new(values: Vec<String>) -> Self {
1600        Self {
1601            values,
1602            total: None,
1603            has_more: None,
1604        }
1605    }
1606
1607    /// Set total count
1608    pub fn with_total(mut self, total: u32) -> Self {
1609        self.total = Some(total);
1610        self
1611    }
1612
1613    /// Set has_more flag
1614    pub fn with_has_more(mut self, has_more: bool) -> Self {
1615        self.has_more = Some(has_more);
1616        self
1617    }
1618
1619    /// Create response with pagination info
1620    pub fn paginated(values: Vec<String>, total: u32, has_more: bool) -> Self {
1621        Self {
1622            values,
1623            total: Some(total),
1624            has_more: Some(has_more),
1625        }
1626    }
1627}
1628
1629/// Server's response to a completion request
1630#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1631pub struct CompleteResult {
1632    /// Completion information
1633    pub completion: CompletionResponse,
1634    /// Optional metadata
1635    #[serde(skip_serializing_if = "Option::is_none")]
1636    pub _meta: Option<serde_json::Value>,
1637}
1638
1639impl CompleteResult {
1640    /// Create a new completion result
1641    pub fn new(completion: CompletionResponse) -> Self {
1642        Self {
1643            completion,
1644            _meta: None,
1645        }
1646    }
1647
1648    /// Add metadata
1649    pub fn with_meta(mut self, meta: serde_json::Value) -> Self {
1650        self._meta = Some(meta);
1651        self
1652    }
1653}
1654
1655// ============================================================================
1656// RESOURCE TEMPLATES (PARAMETERIZED RESOURCE ACCESS)
1657// ============================================================================
1658
1659/// A template description for resources available on the server
1660/// Supports RFC 6570 URI template expansion
1661#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1662#[serde(rename_all = "camelCase")]
1663pub struct ResourceTemplate {
1664    /// Programmatic identifier
1665    pub name: String,
1666    /// URI template (RFC 6570)
1667    pub uri_template: String,
1668    /// Human-readable title
1669    #[serde(skip_serializing_if = "Option::is_none")]
1670    pub title: Option<String>,
1671    /// Description of what this template is for
1672    #[serde(skip_serializing_if = "Option::is_none")]
1673    pub description: Option<String>,
1674    /// MIME type for all resources matching this template (if uniform)
1675    #[serde(skip_serializing_if = "Option::is_none")]
1676    pub mime_type: Option<String>,
1677    /// Optional annotations
1678    #[serde(skip_serializing_if = "Option::is_none")]
1679    pub annotations: Option<Annotations>,
1680    /// Optional metadata
1681    #[serde(skip_serializing_if = "Option::is_none")]
1682    pub _meta: Option<serde_json::Value>,
1683}
1684
1685impl ResourceTemplate {
1686    /// Create a new resource template
1687    pub fn new<N: Into<String>, U: Into<String>>(name: N, uri_template: U) -> Self {
1688        Self {
1689            name: name.into(),
1690            uri_template: uri_template.into(),
1691            title: None,
1692            description: None,
1693            mime_type: None,
1694            annotations: None,
1695            _meta: None,
1696        }
1697    }
1698
1699    /// Set the title
1700    pub fn with_title<T: Into<String>>(mut self, title: T) -> Self {
1701        self.title = Some(title.into());
1702        self
1703    }
1704
1705    /// Set the description
1706    pub fn with_description<D: Into<String>>(mut self, description: D) -> Self {
1707        self.description = Some(description.into());
1708        self
1709    }
1710
1711    /// Set the MIME type
1712    pub fn with_mime_type<M: Into<String>>(mut self, mime_type: M) -> Self {
1713        self.mime_type = Some(mime_type.into());
1714        self
1715    }
1716
1717    /// Set annotations
1718    pub fn with_annotations(mut self, annotations: Annotations) -> Self {
1719        self.annotations = Some(annotations);
1720        self
1721    }
1722
1723    /// Add metadata
1724    pub fn with_meta(mut self, meta: serde_json::Value) -> Self {
1725        self._meta = Some(meta);
1726        self
1727    }
1728
1729    /// Create a file system template
1730    pub fn file_system<N: Into<String>>(name: N, base_path: &str) -> Self {
1731        Self::new(name, format!("file://{}/{{path}}", base_path))
1732            .with_title("File System Access")
1733            .with_description("Access files within the specified directory")
1734    }
1735
1736    /// Create an API endpoint template
1737    pub fn api_endpoint<N: Into<String>>(name: N, base_url: &str) -> Self {
1738        Self::new(name, format!("{}/{{endpoint}}", base_url))
1739            .with_mime_type("application/json")
1740            .with_title("API Endpoint Access")
1741            .with_description("Access API endpoints")
1742    }
1743
1744    /// Create a database query template
1745    pub fn database_query<N: Into<String>>(name: N) -> Self {
1746        Self::new(name, "db://query/{table}?{query*}")
1747            .with_title("Database Query")
1748            .with_description("Execute database queries")
1749    }
1750}
1751
1752/// Parameters for listing resource templates
1753#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
1754pub struct ListResourceTemplatesParams {
1755    /// Pagination cursor
1756    #[serde(skip_serializing_if = "Option::is_none")]
1757    pub cursor: Option<String>,
1758}
1759
1760/// Request to list resource templates
1761#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1762pub struct ListResourceTemplatesRequest {
1763    /// Request parameters
1764    #[serde(skip_serializing_if = "Option::is_none")]
1765    pub params: Option<ListResourceTemplatesParams>,
1766}
1767
1768impl ListResourceTemplatesRequest {
1769    /// Create a new list templates request
1770    pub fn new() -> Self {
1771        Self { params: None }
1772    }
1773
1774    /// Create request with cursor for pagination
1775    pub fn with_cursor<C: Into<String>>(cursor: C) -> Self {
1776        Self {
1777            params: Some(ListResourceTemplatesParams {
1778                cursor: Some(cursor.into()),
1779            }),
1780        }
1781    }
1782}
1783
1784impl Default for ListResourceTemplatesRequest {
1785    fn default() -> Self {
1786        Self::new()
1787    }
1788}
1789
1790/// Result of listing resource templates
1791#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1792#[serde(rename_all = "camelCase")]
1793pub struct ListResourceTemplatesResult {
1794    /// Array of resource templates
1795    pub resource_templates: Vec<ResourceTemplate>,
1796    /// Pagination cursor for next page
1797    #[serde(skip_serializing_if = "Option::is_none")]
1798    pub next_cursor: Option<String>,
1799    /// Optional metadata
1800    #[serde(skip_serializing_if = "Option::is_none")]
1801    pub _meta: Option<serde_json::Value>,
1802}
1803
1804impl ListResourceTemplatesResult {
1805    /// Create a new result
1806    pub fn new(templates: Vec<ResourceTemplate>) -> Self {
1807        Self {
1808            resource_templates: templates,
1809            next_cursor: None,
1810            _meta: None,
1811        }
1812    }
1813
1814    /// Create result with pagination
1815    pub fn paginated(templates: Vec<ResourceTemplate>, next_cursor: String) -> Self {
1816        Self {
1817            resource_templates: templates,
1818            next_cursor: Some(next_cursor),
1819            _meta: None,
1820        }
1821    }
1822
1823    /// Add metadata
1824    pub fn with_meta(mut self, meta: serde_json::Value) -> Self {
1825        self._meta = Some(meta);
1826        self
1827    }
1828}
1829
1830// ============================================================================
1831// PING PROTOCOL (CONNECTION HEALTH MONITORING)
1832// ============================================================================
1833
1834/// Parameters for ping requests
1835#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
1836pub struct PingParams {
1837    /// Optional metadata
1838    #[serde(skip_serializing_if = "Option::is_none")]
1839    pub _meta: Option<serde_json::Value>,
1840}
1841
1842impl PingParams {
1843    /// Create a new ping parameters
1844    pub fn new() -> Self {
1845        Self { _meta: None }
1846    }
1847
1848    /// Add metadata
1849    pub fn with_meta(mut self, meta: serde_json::Value) -> Self {
1850        self._meta = Some(meta);
1851        self
1852    }
1853}
1854
1855/// A ping request to check connection health
1856#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1857pub struct PingRequest {
1858    /// The method name (always "ping")
1859    pub method: String,
1860    /// Request parameters
1861    #[serde(skip_serializing_if = "Option::is_none")]
1862    pub params: Option<PingParams>,
1863}
1864
1865impl PingRequest {
1866    /// Create a new ping request
1867    pub fn new() -> Self {
1868        Self {
1869            method: "ping".to_string(),
1870            params: None,
1871        }
1872    }
1873
1874    /// Create ping request with metadata
1875    pub fn with_meta(meta: serde_json::Value) -> Self {
1876        Self {
1877            method: "ping".to_string(),
1878            params: Some(PingParams::new().with_meta(meta)),
1879        }
1880    }
1881}
1882
1883impl Default for PingRequest {
1884    fn default() -> Self {
1885        Self::new()
1886    }
1887}
1888
1889/// Response to a ping request (usually empty)
1890#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1891pub struct PingResult {
1892    /// Optional metadata
1893    #[serde(skip_serializing_if = "Option::is_none")]
1894    pub _meta: Option<serde_json::Value>,
1895}
1896
1897impl PingResult {
1898    /// Create a new ping result
1899    pub fn new() -> Self {
1900        Self { _meta: None }
1901    }
1902
1903    /// Create result with metadata
1904    pub fn with_meta(meta: serde_json::Value) -> Self {
1905        Self { _meta: Some(meta) }
1906    }
1907}
1908
1909impl Default for PingResult {
1910    fn default() -> Self {
1911        Self::new()
1912    }
1913}
1914
1915// ============================================================================
1916// Roots Types
1917// ============================================================================
1918
1919/// Filesystem root
1920#[derive(Debug, Clone, Serialize, Deserialize)]
1921pub struct Root {
1922    /// Root URI
1923    pub uri: Uri,
1924    /// Root name
1925    #[serde(skip_serializing_if = "Option::is_none")]
1926    pub name: Option<String>,
1927}
1928
1929/// List roots request (no parameters)
1930#[derive(Debug, Clone, Serialize, Deserialize)]
1931pub struct ListRootsRequest;
1932
1933/// List roots result
1934#[derive(Debug, Clone, Serialize, Deserialize)]
1935pub struct ListRootsResult {
1936    /// Available roots
1937    pub roots: Vec<Root>,
1938}
1939
1940/// Roots list changed notification (no parameters)
1941#[derive(Debug, Clone, Serialize, Deserialize)]
1942pub struct RootsListChangedNotification;
1943
1944/// Empty result for operations that don't return data
1945#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1946pub struct EmptyResult {}
1947
1948#[cfg(test)]
1949mod tests {
1950    use super::*;
1951
1952    #[test]
1953    fn test_serialize_deserialize() {
1954        let tool = Tool {
1955            name: "test_tool".to_string(),
1956            title: Some("Test Tool".to_string()),
1957            description: Some("A test tool".to_string()),
1958            input_schema: ToolInputSchema {
1959                schema_type: "object".to_string(),
1960                properties: None,
1961                required: None,
1962                additional_properties: None,
1963            },
1964            output_schema: None,
1965            annotations: None,
1966            meta: None,
1967        };
1968
1969        let json = serde_json::to_string(&tool).unwrap();
1970        let deserialized: Tool = serde_json::from_str(&json).unwrap();
1971        assert_eq!(tool.name, deserialized.name);
1972    }
1973
1974    #[test]
1975    fn test_content_types() {
1976        let text_content = ContentBlock::Text(TextContent {
1977            text: "Hello, World!".to_string(),
1978            annotations: None,
1979            meta: None,
1980        });
1981
1982        let json = serde_json::to_string(&text_content).unwrap();
1983        let _deserialized: ContentBlock = serde_json::from_str(&json).unwrap();
1984
1985        // Test the compatibility alias
1986        let _compatible: Content = text_content;
1987    }
1988
1989    #[test]
1990    fn test_elicitation_schema_builder() {
1991        let schema = ElicitationSchema::new()
1992            .add_string_property("username", true, Some("Your username".to_string()))
1993            .add_number_property(
1994                "age",
1995                false,
1996                Some("Your age".to_string()),
1997                Some(0.0),
1998                Some(150.0),
1999            )
2000            .add_boolean_property(
2001                "subscribe",
2002                true,
2003                Some("Subscribe to newsletter".to_string()),
2004                Some(false),
2005            )
2006            .add_enum_property(
2007                "role",
2008                true,
2009                Some("Your role".to_string()),
2010                vec!["admin".to_string(), "user".to_string(), "guest".to_string()],
2011                None,
2012            );
2013
2014        assert_eq!(schema.schema_type, "object");
2015        assert_eq!(schema.properties.len(), 4);
2016        assert_eq!(schema.required.as_ref().unwrap().len(), 3);
2017
2018        // Verify username property
2019        let username_prop = &schema.properties["username"];
2020        match username_prop {
2021            PrimitiveSchemaDefinition::String { description, .. } => {
2022                assert_eq!(description.as_ref().unwrap(), "Your username");
2023            }
2024            _ => panic!("Expected string property"),
2025        }
2026
2027        // Verify age property
2028        let age_prop = &schema.properties["age"];
2029        match age_prop {
2030            PrimitiveSchemaDefinition::Number {
2031                minimum, maximum, ..
2032            } => {
2033                assert_eq!(*minimum, Some(0.0));
2034                assert_eq!(*maximum, Some(150.0));
2035            }
2036            _ => panic!("Expected number property"),
2037        }
2038    }
2039
2040    #[test]
2041    fn test_elicit_request_serialization() {
2042        let schema = ElicitationSchema::new()
2043            .add_string_property("name", true, Some("Your name".to_string()))
2044            .add_boolean_property("confirm", true, None, Some(false));
2045
2046        let request = ElicitRequest::new("Please provide your details", schema);
2047
2048        // Serialize to JSON
2049        let json = serde_json::to_string(&request).unwrap();
2050
2051        // Verify it contains expected structure
2052        assert!(json.contains("elicitation/create"));
2053        assert!(json.contains("Please provide your details"));
2054        assert!(json.contains("requestedSchema"));
2055
2056        // Deserialize back
2057        let deserialized: ElicitRequest = serde_json::from_str(&json).unwrap();
2058        assert_eq!(deserialized.method, "elicitation/create");
2059        assert_eq!(deserialized.params.message, "Please provide your details");
2060    }
2061
2062    #[test]
2063    fn test_elicit_result_actions() {
2064        // Test accept result
2065        let mut content = std::collections::HashMap::new();
2066        content.insert(
2067            "name".to_string(),
2068            serde_json::Value::String("John".to_string()),
2069        );
2070        content.insert(
2071            "age".to_string(),
2072            serde_json::Value::Number(serde_json::Number::from(30)),
2073        );
2074
2075        let accept_result = ElicitResult::accept(content);
2076        assert_eq!(accept_result.action, ElicitationAction::Accept);
2077        assert!(accept_result.content.is_some());
2078
2079        // Test decline result
2080        let decline_result = ElicitResult::decline();
2081        assert_eq!(decline_result.action, ElicitationAction::Decline);
2082        assert!(decline_result.content.is_none());
2083
2084        // Test cancel result
2085        let cancel_result = ElicitResult::cancel();
2086        assert_eq!(cancel_result.action, ElicitationAction::Cancel);
2087        assert!(cancel_result.content.is_none());
2088    }
2089
2090    #[test]
2091    fn test_elicit_result_serialization_compliance() {
2092        // Test that serialization matches MCP spec exactly
2093        let mut content = std::collections::HashMap::new();
2094        content.insert(
2095            "field1".to_string(),
2096            serde_json::Value::String("value1".to_string()),
2097        );
2098
2099        let result = ElicitResult::accept(content);
2100        let json = serde_json::to_string(&result).unwrap();
2101
2102        // Parse back to ensure it's valid
2103        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2104
2105        // Check action field
2106        assert_eq!(parsed["action"].as_str().unwrap(), "accept");
2107
2108        // Check content field
2109        assert!(parsed["content"].is_object());
2110        assert_eq!(parsed["content"]["field1"].as_str().unwrap(), "value1");
2111    }
2112
2113    #[test]
2114    fn test_primitive_schema_serialization() {
2115        // Test string schema
2116        let string_schema = PrimitiveSchemaDefinition::String {
2117            title: Some("Title".to_string()),
2118            description: Some("Description".to_string()),
2119            format: Some("email".to_string()),
2120            min_length: Some(1),
2121            max_length: Some(100),
2122            enum_values: None,
2123            enum_names: None,
2124        };
2125
2126        let json = serde_json::to_string(&string_schema).unwrap();
2127        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2128
2129        assert_eq!(parsed["type"].as_str().unwrap(), "string");
2130        assert_eq!(parsed["format"].as_str().unwrap(), "email");
2131        assert_eq!(parsed["minLength"].as_u64().unwrap(), 1);
2132        assert_eq!(parsed["maxLength"].as_u64().unwrap(), 100);
2133
2134        // Test enum schema
2135        let enum_schema = PrimitiveSchemaDefinition::String {
2136            title: None,
2137            description: Some("Select option".to_string()),
2138            format: None,
2139            min_length: None,
2140            max_length: None,
2141            enum_values: Some(vec!["option1".to_string(), "option2".to_string()]),
2142            enum_names: Some(vec!["Option 1".to_string(), "Option 2".to_string()]),
2143        };
2144
2145        let enum_json = serde_json::to_string(&enum_schema).unwrap();
2146        let enum_parsed: serde_json::Value = serde_json::from_str(&enum_json).unwrap();
2147
2148        assert_eq!(enum_parsed["type"].as_str().unwrap(), "string");
2149        assert_eq!(enum_parsed["enum"].as_array().unwrap().len(), 2);
2150        assert_eq!(enum_parsed["enumNames"].as_array().unwrap().len(), 2);
2151    }
2152
2153    #[test]
2154    fn test_server_request_with_elicitation() {
2155        let schema = ElicitationSchema::new().add_string_property(
2156            "email",
2157            true,
2158            Some("Your email address".to_string()),
2159        );
2160
2161        let request_params = ElicitRequestParams {
2162            message: "Please provide your email".to_string(),
2163            requested_schema: schema,
2164        };
2165
2166        let server_request = ServerRequest::ElicitationCreate(request_params);
2167
2168        // Serialize and verify
2169        let json = serde_json::to_string(&server_request).unwrap();
2170        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2171
2172        assert_eq!(parsed["method"].as_str().unwrap(), "elicitation/create");
2173        assert!(parsed["message"].is_string());
2174        assert!(parsed["requestedSchema"].is_object());
2175    }
2176
2177    #[test]
2178    fn test_completion_request_serialization() {
2179        let argument = ArgumentInfo {
2180            name: "file_path".to_string(),
2181            value: "/home/user/doc".to_string(),
2182        };
2183
2184        let reference = CompletionReference::ResourceTemplate(ResourceTemplateReferenceData {
2185            uri: "/files/{path}".to_string(),
2186        });
2187
2188        let request = CompleteRequest::new(argument, reference);
2189
2190        // Serialize
2191        let json = serde_json::to_string(&request).unwrap();
2192        assert!(json.contains("completion/complete"));
2193        assert!(json.contains("file_path"));
2194        assert!(json.contains("/home/user/doc"));
2195
2196        // Deserialize
2197        let deserialized: CompleteRequest = serde_json::from_str(&json).unwrap();
2198        assert_eq!(deserialized.method, "completion/complete");
2199        assert_eq!(deserialized.params.argument.name, "file_path");
2200    }
2201
2202    #[test]
2203    fn test_completion_reference_types() {
2204        // Test prompt reference
2205        let prompt_ref = CompletionReference::Prompt(PromptReferenceData {
2206            name: "code_review".to_string(),
2207            title: Some("Code Review Assistant".to_string()),
2208        });
2209
2210        let json = serde_json::to_string(&prompt_ref).unwrap();
2211        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2212        assert_eq!(parsed["type"].as_str().unwrap(), "ref/prompt");
2213        assert_eq!(parsed["name"].as_str().unwrap(), "code_review");
2214
2215        // Test resource template reference
2216        let resource_ref = CompletionReference::ResourceTemplate(ResourceTemplateReferenceData {
2217            uri: "/api/{endpoint}".to_string(),
2218        });
2219
2220        let json = serde_json::to_string(&resource_ref).unwrap();
2221        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2222        assert_eq!(parsed["type"].as_str().unwrap(), "ref/resource");
2223        assert_eq!(parsed["uri"].as_str().unwrap(), "/api/{endpoint}");
2224    }
2225
2226    #[test]
2227    fn test_completion_response_with_pagination() {
2228        // Test simple response
2229        let simple =
2230            CompletionResponse::new(vec!["file1.txt".to_string(), "file2.txt".to_string()]);
2231        assert_eq!(simple.values.len(), 2);
2232        assert!(simple.total.is_none());
2233
2234        // Test paginated response
2235        let paginated = CompletionResponse::paginated(
2236            vec!["item1".to_string(), "item2".to_string()],
2237            100,
2238            true,
2239        );
2240        assert_eq!(paginated.values.len(), 2);
2241        assert_eq!(paginated.total, Some(100));
2242        assert_eq!(paginated.has_more, Some(true));
2243
2244        // Test serialization
2245        let json = serde_json::to_string(&paginated).unwrap();
2246        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2247        assert_eq!(parsed["total"].as_u64().unwrap(), 100);
2248        assert!(parsed["hasMore"].as_bool().unwrap());
2249        assert_eq!(parsed["values"].as_array().unwrap().len(), 2);
2250    }
2251
2252    #[test]
2253    fn test_complete_result_structure() {
2254        let completion = CompletionResponse::paginated(
2255            vec!["option1".to_string(), "option2".to_string()],
2256            50,
2257            false,
2258        );
2259
2260        let result = CompleteResult::new(completion);
2261
2262        // Serialize and verify structure
2263        let json = serde_json::to_string(&result).unwrap();
2264        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2265
2266        // Check completion field structure
2267        assert!(parsed["completion"].is_object());
2268        assert!(parsed["completion"]["values"].is_array());
2269        assert_eq!(parsed["completion"]["total"].as_u64().unwrap(), 50);
2270        assert!(!parsed["completion"]["hasMore"].as_bool().unwrap());
2271
2272        // Deserialize back
2273        let deserialized: CompleteResult = serde_json::from_str(&json).unwrap();
2274        assert_eq!(deserialized.completion.values.len(), 2);
2275        assert_eq!(deserialized.completion.total, Some(50));
2276    }
2277
2278    #[test]
2279    fn test_completion_context() {
2280        let mut context_args = std::collections::HashMap::new();
2281        context_args.insert("user_id".to_string(), "12345".to_string());
2282        context_args.insert("project".to_string(), "main".to_string());
2283
2284        let context = CompletionContext {
2285            arguments: Some(context_args),
2286        };
2287
2288        let argument = ArgumentInfo {
2289            name: "endpoint".to_string(),
2290            value: "api".to_string(),
2291        };
2292
2293        let reference = CompletionReference::ResourceTemplate(ResourceTemplateReferenceData {
2294            uri: "/projects/{project}/endpoints/{endpoint}".to_string(),
2295        });
2296
2297        let request = CompleteRequest::new(argument, reference).with_context(context);
2298
2299        // Verify context is included
2300        let json = serde_json::to_string(&request).unwrap();
2301        assert!(json.contains("user_id"));
2302        assert!(json.contains("12345"));
2303        assert!(json.contains("project"));
2304        assert!(json.contains("main"));
2305    }
2306
2307    #[test]
2308    fn test_client_request_with_completion() {
2309        let argument = ArgumentInfo {
2310            name: "query".to_string(),
2311            value: "hello".to_string(),
2312        };
2313
2314        let reference = CompletionReference::Prompt(PromptReferenceData {
2315            name: "greeting".to_string(),
2316            title: None,
2317        });
2318
2319        let complete_params = CompleteRequestParams {
2320            argument,
2321            reference,
2322            context: None,
2323        };
2324
2325        let client_request = ClientRequest::Complete(complete_params);
2326
2327        // Serialize and verify
2328        let json = serde_json::to_string(&client_request).unwrap();
2329        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2330
2331        assert_eq!(parsed["method"].as_str().unwrap(), "completion/complete");
2332        assert_eq!(parsed["argument"]["name"].as_str().unwrap(), "query");
2333        assert_eq!(parsed["ref"]["type"].as_str().unwrap(), "ref/prompt");
2334    }
2335
2336    #[test]
2337    fn test_resource_template_creation() {
2338        // Test basic creation
2339        let template = ResourceTemplate::new("file_access", "/files/{path}");
2340        assert_eq!(template.name, "file_access");
2341        assert_eq!(template.uri_template, "/files/{path}");
2342
2343        // Test builder pattern
2344        let enhanced_template = ResourceTemplate::new("api_access", "/api/{endpoint}")
2345            .with_title("API Access")
2346            .with_description("Access to REST API endpoints")
2347            .with_mime_type("application/json");
2348
2349        assert_eq!(enhanced_template.title, Some("API Access".to_string()));
2350        assert_eq!(
2351            enhanced_template.description,
2352            Some("Access to REST API endpoints".to_string())
2353        );
2354        assert_eq!(
2355            enhanced_template.mime_type,
2356            Some("application/json".to_string())
2357        );
2358    }
2359
2360    #[test]
2361    fn test_resource_template_presets() {
2362        // Test file system template
2363        let fs_template = ResourceTemplate::file_system("files", "/home/user");
2364        assert_eq!(fs_template.name, "files");
2365        assert_eq!(fs_template.uri_template, "file:///home/user/{path}");
2366        assert_eq!(fs_template.title, Some("File System Access".to_string()));
2367
2368        // Test API endpoint template
2369        let api_template = ResourceTemplate::api_endpoint("api", "https://api.example.com");
2370        assert_eq!(
2371            api_template.uri_template,
2372            "https://api.example.com/{endpoint}"
2373        );
2374        assert_eq!(api_template.mime_type, Some("application/json".to_string()));
2375
2376        // Test database query template
2377        let db_template = ResourceTemplate::database_query("queries");
2378        assert_eq!(db_template.uri_template, "db://query/{table}?{query*}");
2379        assert_eq!(db_template.title, Some("Database Query".to_string()));
2380    }
2381
2382    #[test]
2383    fn test_resource_template_serialization() {
2384        let template = ResourceTemplate::new("test_template", "/test/{id}")
2385            .with_title("Test Template")
2386            .with_description("A template for testing")
2387            .with_mime_type("text/plain");
2388
2389        let json = serde_json::to_string(&template).unwrap();
2390        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2391
2392        assert_eq!(parsed["name"].as_str().unwrap(), "test_template");
2393        assert_eq!(parsed["uriTemplate"].as_str().unwrap(), "/test/{id}");
2394        assert_eq!(parsed["title"].as_str().unwrap(), "Test Template");
2395        assert_eq!(
2396            parsed["description"].as_str().unwrap(),
2397            "A template for testing"
2398        );
2399        assert_eq!(parsed["mimeType"].as_str().unwrap(), "text/plain");
2400
2401        // Test deserialization
2402        let deserialized: ResourceTemplate = serde_json::from_str(&json).unwrap();
2403        assert_eq!(deserialized.name, "test_template");
2404        assert_eq!(deserialized.uri_template, "/test/{id}");
2405    }
2406
2407    #[test]
2408    fn test_list_resource_templates_request() {
2409        // Test basic request
2410        let request = ListResourceTemplatesRequest::new();
2411        assert!(request.params.is_none());
2412
2413        // Test request with cursor
2414        let paginated_request = ListResourceTemplatesRequest::with_cursor("cursor123");
2415        assert!(paginated_request.params.is_some());
2416        assert_eq!(
2417            paginated_request.params.unwrap().cursor,
2418            Some("cursor123".to_string())
2419        );
2420
2421        // Test serialization
2422        let json = serde_json::to_string(&request).unwrap();
2423        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2424
2425        // Should serialize to an empty object when no params
2426        assert!(parsed.as_object().unwrap().is_empty());
2427    }
2428
2429    #[test]
2430    fn test_list_resource_templates_result() {
2431        let templates = vec![
2432            ResourceTemplate::new("template1", "/api/{endpoint}"),
2433            ResourceTemplate::new("template2", "/files/{path}"),
2434        ];
2435
2436        // Test basic result
2437        let result = ListResourceTemplatesResult::new(templates.clone());
2438        assert_eq!(result.resource_templates.len(), 2);
2439        assert!(result.next_cursor.is_none());
2440
2441        // Test paginated result
2442        let paginated_result =
2443            ListResourceTemplatesResult::paginated(templates, "next_cursor".to_string());
2444        assert_eq!(paginated_result.resource_templates.len(), 2);
2445        assert_eq!(
2446            paginated_result.next_cursor,
2447            Some("next_cursor".to_string())
2448        );
2449
2450        // Test serialization
2451        let json = serde_json::to_string(&paginated_result).unwrap();
2452        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2453
2454        assert!(parsed["resourceTemplates"].is_array());
2455        assert_eq!(parsed["resourceTemplates"].as_array().unwrap().len(), 2);
2456        assert_eq!(parsed["nextCursor"].as_str().unwrap(), "next_cursor");
2457
2458        // Test deserialization
2459        let deserialized: ListResourceTemplatesResult = serde_json::from_str(&json).unwrap();
2460        assert_eq!(deserialized.resource_templates.len(), 2);
2461        assert_eq!(deserialized.next_cursor, Some("next_cursor".to_string()));
2462    }
2463
2464    #[test]
2465    fn test_client_request_with_resource_templates() {
2466        let request = ListResourceTemplatesRequest::with_cursor("abc123");
2467        let client_request = ClientRequest::ListResourceTemplates(request);
2468
2469        // Serialize and verify
2470        let json = serde_json::to_string(&client_request).unwrap();
2471        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2472
2473        assert_eq!(
2474            parsed["method"].as_str().unwrap(),
2475            "resources/templates/list"
2476        );
2477        assert_eq!(parsed["params"]["cursor"].as_str().unwrap(), "abc123");
2478    }
2479
2480    #[test]
2481    fn test_complex_uri_templates() {
2482        // Test RFC 6570 style templates
2483        let complex_templates = vec![
2484            ResourceTemplate::new(
2485                "github",
2486                "https://api.github.com/repos/{owner}/{repo}/contents/{+path}",
2487            ),
2488            ResourceTemplate::new("search", "/search{?q,type,sort,order}"),
2489            ResourceTemplate::new("matrix", "/matrix{;x,y}/data"),
2490            ResourceTemplate::new("fragment", "/documents/{id}{#section}"),
2491        ];
2492
2493        for template in complex_templates {
2494            let json = serde_json::to_string(&template).unwrap();
2495            let deserialized: ResourceTemplate = serde_json::from_str(&json).unwrap();
2496            assert_eq!(template.uri_template, deserialized.uri_template);
2497        }
2498    }
2499
2500    #[test]
2501    fn test_resource_template_with_annotations() {
2502        let annotations = Annotations {
2503            priority: Some(1.0),
2504            ..Default::default()
2505        };
2506
2507        let template =
2508            ResourceTemplate::new("important", "/critical/{id}").with_annotations(annotations);
2509
2510        assert!(template.annotations.is_some());
2511        assert_eq!(template.annotations.unwrap().priority, Some(1.0));
2512    }
2513
2514    #[test]
2515    fn test_ping_request_creation() {
2516        // Test basic ping
2517        let ping = PingRequest::new();
2518        assert_eq!(ping.method, "ping");
2519        assert!(ping.params.is_none());
2520
2521        // Test ping with metadata
2522        let meta_value = serde_json::json!({"timestamp": "2025-08-29T12:00:00Z"});
2523        let ping_with_meta = PingRequest::with_meta(meta_value.clone());
2524        assert_eq!(ping_with_meta.method, "ping");
2525        assert!(ping_with_meta.params.is_some());
2526        assert_eq!(ping_with_meta.params.unwrap()._meta, Some(meta_value));
2527    }
2528
2529    #[test]
2530    fn test_ping_serialization() {
2531        // Test basic ping serialization
2532        let ping = PingRequest::new();
2533        let json = serde_json::to_string(&ping).unwrap();
2534        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2535        assert_eq!(parsed["method"].as_str().unwrap(), "ping");
2536
2537        // Test deserialization
2538        let deserialized: PingRequest = serde_json::from_str(&json).unwrap();
2539        assert_eq!(deserialized.method, "ping");
2540
2541        // Test ping with metadata
2542        let meta_value = serde_json::json!({"client": "test", "version": "1.0"});
2543        let ping_with_meta = PingRequest::with_meta(meta_value.clone());
2544        let json_with_meta = serde_json::to_string(&ping_with_meta).unwrap();
2545        let parsed_meta: serde_json::Value = serde_json::from_str(&json_with_meta).unwrap();
2546
2547        assert!(parsed_meta["params"].is_object());
2548        assert_eq!(
2549            parsed_meta["params"]["_meta"]["client"].as_str().unwrap(),
2550            "test"
2551        );
2552    }
2553
2554    #[test]
2555    fn test_ping_result() {
2556        // Test basic result
2557        let result = PingResult::new();
2558        assert!(result._meta.is_none());
2559
2560        // Test result with metadata
2561        let meta = serde_json::json!({"latency_ms": 42});
2562        let result_with_meta = PingResult::with_meta(meta.clone());
2563        assert_eq!(result_with_meta._meta, Some(meta));
2564
2565        // Test serialization
2566        let json = serde_json::to_string(&result).unwrap();
2567        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2568        // Empty result should serialize to empty object
2569        assert!(parsed.as_object().unwrap().is_empty());
2570
2571        // Test deserialization
2572        let deserialized: PingResult = serde_json::from_str(&json).unwrap();
2573        assert!(deserialized._meta.is_none());
2574    }
2575
2576    #[test]
2577    fn test_ping_params() {
2578        // Test basic params
2579        let params = PingParams::new();
2580        assert!(params._meta.is_none());
2581
2582        // Test params with metadata
2583        let meta = serde_json::json!({"timeout": 5000});
2584        let params_with_meta = PingParams::new().with_meta(meta.clone());
2585        assert_eq!(params_with_meta._meta, Some(meta));
2586
2587        // Test serialization
2588        let json = serde_json::to_string(&params).unwrap();
2589        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2590        assert!(parsed.as_object().unwrap().is_empty());
2591    }
2592
2593    #[test]
2594    fn test_server_request_with_ping() {
2595        let ping_params = PingParams::new();
2596        let server_request = ServerRequest::Ping(ping_params);
2597
2598        // Serialize and verify
2599        let json = serde_json::to_string(&server_request).unwrap();
2600        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2601
2602        assert_eq!(parsed["method"].as_str().unwrap(), "ping");
2603    }
2604
2605    #[test]
2606    fn test_client_request_with_ping() {
2607        let ping_params = PingParams::new();
2608        let client_request = ClientRequest::Ping(ping_params);
2609
2610        // Serialize and verify
2611        let json = serde_json::to_string(&client_request).unwrap();
2612        let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
2613
2614        assert_eq!(parsed["method"].as_str().unwrap(), "ping");
2615    }
2616
2617    #[test]
2618    fn test_ping_protocol_bidirectional() {
2619        // Test that ping can be used from both client and server
2620        let meta = serde_json::json!({"source": "test"});
2621
2622        // Client-initiated ping
2623        let client_ping = ClientRequest::Ping(PingParams::new().with_meta(meta.clone()));
2624        let client_json = serde_json::to_string(&client_ping).unwrap();
2625
2626        // Server-initiated ping
2627        let server_ping = ServerRequest::Ping(PingParams::new().with_meta(meta.clone()));
2628        let server_json = serde_json::to_string(&server_ping).unwrap();
2629
2630        // Both should have same structure
2631        let client_parsed: serde_json::Value = serde_json::from_str(&client_json).unwrap();
2632        let server_parsed: serde_json::Value = serde_json::from_str(&server_json).unwrap();
2633
2634        assert_eq!(client_parsed["method"], server_parsed["method"]);
2635        assert_eq!(
2636            client_parsed["_meta"]["source"],
2637            server_parsed["_meta"]["source"]
2638        );
2639    }
2640}