Skip to main content

tower_mcp/
protocol.rs

1//! MCP protocol types based on JSON-RPC 2.0
2//!
3//! These types follow the MCP specification (2025-03-26):
4//! <https://modelcontextprotocol.io/specification/2025-03-26>
5
6use serde::{Deserialize, Serialize};
7use serde_json::Value;
8
9use crate::error::JsonRpcError;
10
11/// The JSON-RPC version. MUST be "2.0".
12pub const JSONRPC_VERSION: &str = "2.0";
13
14/// The latest supported MCP protocol version.
15pub const LATEST_PROTOCOL_VERSION: &str = "2025-03-26";
16
17/// All supported MCP protocol versions (newest first).
18pub const SUPPORTED_PROTOCOL_VERSIONS: &[&str] = &["2025-03-26"];
19
20/// JSON-RPC 2.0 request.
21#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct JsonRpcRequest {
23    /// JSON-RPC version, must be "2.0".
24    pub jsonrpc: String,
25    /// Request identifier.
26    pub id: RequestId,
27    /// Method name to invoke.
28    pub method: String,
29    /// Optional parameters for the method.
30    #[serde(default, skip_serializing_if = "Option::is_none")]
31    pub params: Option<Value>,
32}
33
34impl JsonRpcRequest {
35    /// Create a new JSON-RPC request.
36    pub fn new(id: impl Into<RequestId>, method: impl Into<String>) -> Self {
37        Self {
38            jsonrpc: JSONRPC_VERSION.to_string(),
39            id: id.into(),
40            method: method.into(),
41            params: None,
42        }
43    }
44
45    /// Add parameters to the request.
46    pub fn with_params(mut self, params: Value) -> Self {
47        self.params = Some(params);
48        self
49    }
50
51    /// Validate that this request conforms to JSON-RPC 2.0.
52    /// Returns an error if the jsonrpc version is not "2.0".
53    pub fn validate(&self) -> Result<(), JsonRpcError> {
54        if self.jsonrpc != JSONRPC_VERSION {
55            return Err(JsonRpcError::invalid_request(format!(
56                "Invalid JSON-RPC version: expected '{}', got '{}'",
57                JSONRPC_VERSION, self.jsonrpc
58            )));
59        }
60        Ok(())
61    }
62}
63
64/// JSON-RPC 2.0 success response.
65#[derive(Debug, Clone, Serialize, Deserialize)]
66pub struct JsonRpcResultResponse {
67    /// JSON-RPC version, always "2.0".
68    pub jsonrpc: String,
69    /// Request identifier (matches the request).
70    pub id: RequestId,
71    /// The result value.
72    pub result: Value,
73}
74
75/// JSON-RPC 2.0 error response.
76#[derive(Debug, Clone, Serialize, Deserialize)]
77pub struct JsonRpcErrorResponse {
78    /// JSON-RPC version, always "2.0".
79    pub jsonrpc: String,
80    /// Request identifier (may be null for parse errors).
81    #[serde(skip_serializing_if = "Option::is_none")]
82    pub id: Option<RequestId>,
83    /// The error details.
84    pub error: JsonRpcError,
85}
86
87/// JSON-RPC 2.0 response (either success or error).
88#[derive(Debug, Clone, Serialize, Deserialize)]
89#[serde(untagged)]
90pub enum JsonRpcResponse {
91    /// Successful response with result.
92    Result(JsonRpcResultResponse),
93    /// Error response.
94    Error(JsonRpcErrorResponse),
95}
96
97impl JsonRpcResponse {
98    /// Create a success response.
99    pub fn result(id: RequestId, result: Value) -> Self {
100        Self::Result(JsonRpcResultResponse {
101            jsonrpc: JSONRPC_VERSION.to_string(),
102            id,
103            result,
104        })
105    }
106
107    /// Create an error response.
108    pub fn error(id: Option<RequestId>, error: JsonRpcError) -> Self {
109        Self::Error(JsonRpcErrorResponse {
110            jsonrpc: JSONRPC_VERSION.to_string(),
111            id,
112            error,
113        })
114    }
115}
116
117/// JSON-RPC 2.0 message - can be a single request or a batch
118#[derive(Debug, Clone, Serialize, Deserialize)]
119#[serde(untagged)]
120pub enum JsonRpcMessage {
121    /// A single request
122    Single(JsonRpcRequest),
123    /// A batch of requests
124    Batch(Vec<JsonRpcRequest>),
125}
126
127impl JsonRpcMessage {
128    /// Returns true if this is a batch message
129    pub fn is_batch(&self) -> bool {
130        matches!(self, JsonRpcMessage::Batch(_))
131    }
132
133    /// Returns the number of requests in this message
134    pub fn len(&self) -> usize {
135        match self {
136            JsonRpcMessage::Single(_) => 1,
137            JsonRpcMessage::Batch(batch) => batch.len(),
138        }
139    }
140
141    /// Returns true if this message contains no requests
142    pub fn is_empty(&self) -> bool {
143        self.len() == 0
144    }
145}
146
147/// JSON-RPC 2.0 response message - can be a single response or a batch
148#[derive(Debug, Clone, Serialize, Deserialize)]
149#[serde(untagged)]
150pub enum JsonRpcResponseMessage {
151    /// A single response
152    Single(JsonRpcResponse),
153    /// A batch of responses
154    Batch(Vec<JsonRpcResponse>),
155}
156
157impl JsonRpcResponseMessage {
158    /// Returns true if this is a batch response
159    pub fn is_batch(&self) -> bool {
160        matches!(self, JsonRpcResponseMessage::Batch(_))
161    }
162}
163
164/// JSON-RPC 2.0 notification (no response expected)
165#[derive(Debug, Clone, Serialize, Deserialize)]
166pub struct JsonRpcNotification {
167    pub jsonrpc: String,
168    pub method: String,
169    #[serde(default, skip_serializing_if = "Option::is_none")]
170    pub params: Option<Value>,
171}
172
173impl JsonRpcNotification {
174    pub fn new(method: impl Into<String>) -> Self {
175        Self {
176            jsonrpc: JSONRPC_VERSION.to_string(),
177            method: method.into(),
178            params: None,
179        }
180    }
181
182    pub fn with_params(mut self, params: Value) -> Self {
183        self.params = Some(params);
184        self
185    }
186}
187
188/// MCP notification methods
189pub mod notifications {
190    /// Sent by client after receiving initialize response
191    pub const INITIALIZED: &str = "notifications/initialized";
192    /// Sent when a request is cancelled
193    pub const CANCELLED: &str = "notifications/cancelled";
194    /// Progress updates for long-running operations
195    pub const PROGRESS: &str = "notifications/progress";
196    /// Tool list has changed
197    pub const TOOLS_LIST_CHANGED: &str = "notifications/tools/list_changed";
198    /// Resource list has changed
199    pub const RESOURCES_LIST_CHANGED: &str = "notifications/resources/list_changed";
200    /// Specific resource has been updated
201    pub const RESOURCE_UPDATED: &str = "notifications/resources/updated";
202    /// Prompt list has changed
203    pub const PROMPTS_LIST_CHANGED: &str = "notifications/prompts/list_changed";
204    /// Roots list has changed (client to server)
205    pub const ROOTS_LIST_CHANGED: &str = "notifications/roots/list_changed";
206    /// Log message notification
207    pub const MESSAGE: &str = "notifications/message";
208    /// Task status changed
209    pub const TASK_STATUS_CHANGED: &str = "notifications/tasks/status_changed";
210    /// Elicitation completed (for URL-based elicitation)
211    pub const ELICITATION_COMPLETE: &str = "notifications/elicitation/complete";
212}
213
214/// Log severity levels following RFC 5424 (syslog)
215///
216/// Levels are ordered from most severe (emergency) to least severe (debug).
217#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
218#[serde(rename_all = "lowercase")]
219pub enum LogLevel {
220    /// System is unusable
221    Emergency,
222    /// Action must be taken immediately
223    Alert,
224    /// Critical conditions
225    Critical,
226    /// Error conditions
227    Error,
228    /// Warning conditions
229    Warning,
230    /// Normal but significant events
231    Notice,
232    /// General informational messages
233    #[default]
234    Info,
235    /// Detailed debugging information
236    Debug,
237}
238
239impl std::fmt::Display for LogLevel {
240    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
241        match self {
242            LogLevel::Emergency => write!(f, "emergency"),
243            LogLevel::Alert => write!(f, "alert"),
244            LogLevel::Critical => write!(f, "critical"),
245            LogLevel::Error => write!(f, "error"),
246            LogLevel::Warning => write!(f, "warning"),
247            LogLevel::Notice => write!(f, "notice"),
248            LogLevel::Info => write!(f, "info"),
249            LogLevel::Debug => write!(f, "debug"),
250        }
251    }
252}
253
254/// Parameters for logging message notification
255#[derive(Debug, Clone, Serialize, Deserialize)]
256pub struct LoggingMessageParams {
257    /// Severity level of the message
258    pub level: LogLevel,
259    /// Optional logger name (e.g., "database", "auth", "tools")
260    #[serde(skip_serializing_if = "Option::is_none")]
261    pub logger: Option<String>,
262    /// Optional structured data
263    #[serde(skip_serializing_if = "Option::is_none")]
264    pub data: Option<Value>,
265}
266
267impl LoggingMessageParams {
268    /// Create a new logging message with the given level
269    pub fn new(level: LogLevel) -> Self {
270        Self {
271            level,
272            logger: None,
273            data: None,
274        }
275    }
276
277    /// Set the logger name
278    pub fn with_logger(mut self, logger: impl Into<String>) -> Self {
279        self.logger = Some(logger.into());
280        self
281    }
282
283    /// Set the structured data
284    pub fn with_data(mut self, data: Value) -> Self {
285        self.data = Some(data);
286        self
287    }
288}
289
290/// Parameters for setting log level
291#[derive(Debug, Clone, Deserialize)]
292pub struct SetLogLevelParams {
293    /// Minimum log level to receive
294    pub level: LogLevel,
295}
296
297/// Request ID - can be string or number per JSON-RPC spec
298#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
299#[serde(untagged)]
300pub enum RequestId {
301    String(String),
302    Number(i64),
303}
304
305impl From<String> for RequestId {
306    fn from(s: String) -> Self {
307        RequestId::String(s)
308    }
309}
310
311impl From<&str> for RequestId {
312    fn from(s: &str) -> Self {
313        RequestId::String(s.to_string())
314    }
315}
316
317impl From<i64> for RequestId {
318    fn from(n: i64) -> Self {
319        RequestId::Number(n)
320    }
321}
322
323impl From<i32> for RequestId {
324    fn from(n: i32) -> Self {
325        RequestId::Number(n as i64)
326    }
327}
328
329// =============================================================================
330// MCP-specific request/response types
331// =============================================================================
332
333/// High-level MCP request (parsed from JSON-RPC)
334#[derive(Debug, Clone)]
335pub enum McpRequest {
336    /// Initialize session
337    Initialize(InitializeParams),
338    /// List available tools
339    ListTools(ListToolsParams),
340    /// Call a tool
341    CallTool(CallToolParams),
342    /// List available resources
343    ListResources(ListResourcesParams),
344    /// List resource templates
345    ListResourceTemplates(ListResourceTemplatesParams),
346    /// Read a resource
347    ReadResource(ReadResourceParams),
348    /// Subscribe to resource updates
349    SubscribeResource(SubscribeResourceParams),
350    /// Unsubscribe from resource updates
351    UnsubscribeResource(UnsubscribeResourceParams),
352    /// List available prompts
353    ListPrompts(ListPromptsParams),
354    /// Get a prompt
355    GetPrompt(GetPromptParams),
356    /// Enqueue an async task
357    EnqueueTask(EnqueueTaskParams),
358    /// List tasks
359    ListTasks(ListTasksParams),
360    /// Get task info
361    GetTaskInfo(GetTaskInfoParams),
362    /// Get task result
363    GetTaskResult(GetTaskResultParams),
364    /// Cancel a task
365    CancelTask(CancelTaskParams),
366    /// Ping (keepalive)
367    Ping,
368    /// Set logging level
369    SetLoggingLevel(SetLogLevelParams),
370    /// Request completion suggestions
371    Complete(CompleteParams),
372    /// Unknown method
373    Unknown {
374        method: String,
375        params: Option<Value>,
376    },
377}
378
379impl McpRequest {
380    /// Get the method name for this request
381    pub fn method_name(&self) -> &str {
382        match self {
383            McpRequest::Initialize(_) => "initialize",
384            McpRequest::ListTools(_) => "tools/list",
385            McpRequest::CallTool(_) => "tools/call",
386            McpRequest::ListResources(_) => "resources/list",
387            McpRequest::ListResourceTemplates(_) => "resources/templates/list",
388            McpRequest::ReadResource(_) => "resources/read",
389            McpRequest::SubscribeResource(_) => "resources/subscribe",
390            McpRequest::UnsubscribeResource(_) => "resources/unsubscribe",
391            McpRequest::ListPrompts(_) => "prompts/list",
392            McpRequest::GetPrompt(_) => "prompts/get",
393            McpRequest::EnqueueTask(_) => "tasks/enqueue",
394            McpRequest::ListTasks(_) => "tasks/list",
395            McpRequest::GetTaskInfo(_) => "tasks/get",
396            McpRequest::GetTaskResult(_) => "tasks/result",
397            McpRequest::CancelTask(_) => "tasks/cancel",
398            McpRequest::Ping => "ping",
399            McpRequest::SetLoggingLevel(_) => "logging/setLevel",
400            McpRequest::Complete(_) => "completion/complete",
401            McpRequest::Unknown { method, .. } => method,
402        }
403    }
404}
405
406/// High-level MCP notification (parsed from JSON-RPC)
407#[derive(Debug, Clone)]
408pub enum McpNotification {
409    /// Client has completed initialization
410    Initialized,
411    /// Request cancellation
412    Cancelled(CancelledParams),
413    /// Progress update
414    Progress(ProgressParams),
415    /// Roots list has changed (client to server)
416    RootsListChanged,
417    /// Unknown notification
418    Unknown {
419        method: String,
420        params: Option<Value>,
421    },
422}
423
424/// Parameters for cancellation notification
425#[derive(Debug, Clone, Serialize, Deserialize)]
426#[serde(rename_all = "camelCase")]
427pub struct CancelledParams {
428    /// The ID of the request to cancel
429    pub request_id: RequestId,
430    /// Optional reason for cancellation
431    #[serde(skip_serializing_if = "Option::is_none")]
432    pub reason: Option<String>,
433}
434
435/// Parameters for progress notification
436#[derive(Debug, Clone, Serialize, Deserialize)]
437#[serde(rename_all = "camelCase")]
438pub struct ProgressParams {
439    /// The progress token from the original request
440    pub progress_token: ProgressToken,
441    /// Current progress value (must increase with each notification)
442    pub progress: f64,
443    /// Total expected value (if known)
444    #[serde(skip_serializing_if = "Option::is_none")]
445    pub total: Option<f64>,
446    /// Human-readable progress message
447    #[serde(skip_serializing_if = "Option::is_none")]
448    pub message: Option<String>,
449}
450
451/// Progress token - can be string or number
452#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
453#[serde(untagged)]
454pub enum ProgressToken {
455    String(String),
456    Number(i64),
457}
458
459/// Request metadata that can include progress token
460#[derive(Debug, Clone, Default, Serialize, Deserialize)]
461#[serde(rename_all = "camelCase")]
462pub struct RequestMeta {
463    /// Progress token for receiving progress notifications
464    #[serde(skip_serializing_if = "Option::is_none")]
465    pub progress_token: Option<ProgressToken>,
466}
467
468/// High-level MCP response
469#[derive(Debug, Clone, Serialize)]
470#[serde(untagged)]
471pub enum McpResponse {
472    Initialize(InitializeResult),
473    ListTools(ListToolsResult),
474    CallTool(CallToolResult),
475    ListResources(ListResourcesResult),
476    ListResourceTemplates(ListResourceTemplatesResult),
477    ReadResource(ReadResourceResult),
478    SubscribeResource(EmptyResult),
479    UnsubscribeResource(EmptyResult),
480    ListPrompts(ListPromptsResult),
481    GetPrompt(GetPromptResult),
482    EnqueueTask(EnqueueTaskResult),
483    ListTasks(ListTasksResult),
484    GetTaskInfo(TaskInfo),
485    GetTaskResult(GetTaskResultResult),
486    CancelTask(CancelTaskResult),
487    SetLoggingLevel(EmptyResult),
488    Complete(CompleteResult),
489    Pong(EmptyResult),
490    Empty(EmptyResult),
491}
492
493// =============================================================================
494// Initialize
495// =============================================================================
496
497#[derive(Debug, Clone, Serialize, Deserialize)]
498#[serde(rename_all = "camelCase")]
499pub struct InitializeParams {
500    pub protocol_version: String,
501    pub capabilities: ClientCapabilities,
502    pub client_info: Implementation,
503}
504
505#[derive(Debug, Clone, Default, Deserialize, Serialize)]
506pub struct ClientCapabilities {
507    #[serde(default, skip_serializing_if = "Option::is_none")]
508    pub roots: Option<RootsCapability>,
509    #[serde(default, skip_serializing_if = "Option::is_none")]
510    pub sampling: Option<SamplingCapability>,
511    #[serde(default, skip_serializing_if = "Option::is_none")]
512    pub elicitation: Option<ElicitationCapability>,
513}
514
515/// Client capability for elicitation (requesting user input)
516#[derive(Debug, Clone, Default, Deserialize, Serialize)]
517pub struct ElicitationCapability {
518    /// Support for form-based elicitation
519    #[serde(default, skip_serializing_if = "Option::is_none")]
520    pub form: Option<ElicitationFormCapability>,
521    /// Support for URL-based elicitation
522    #[serde(default, skip_serializing_if = "Option::is_none")]
523    pub url: Option<ElicitationUrlCapability>,
524}
525
526/// Marker for form-based elicitation support
527#[derive(Debug, Clone, Default, Deserialize, Serialize)]
528pub struct ElicitationFormCapability {}
529
530/// Marker for URL-based elicitation support
531#[derive(Debug, Clone, Default, Deserialize, Serialize)]
532pub struct ElicitationUrlCapability {}
533
534/// Client capability for roots (filesystem access)
535#[derive(Debug, Clone, Default, Deserialize, Serialize)]
536#[serde(rename_all = "camelCase")]
537pub struct RootsCapability {
538    /// Whether the client supports roots list changed notifications
539    #[serde(default)]
540    pub list_changed: bool,
541}
542
543/// Represents a root directory or file that the server can operate on
544///
545/// Roots allow clients to expose filesystem roots to servers, enabling:
546/// - Scoped file access
547/// - Workspace awareness
548/// - Security boundaries
549#[derive(Debug, Clone, Deserialize, Serialize)]
550pub struct Root {
551    /// The URI identifying the root. Must start with `file://` for now.
552    pub uri: String,
553    /// Optional human-readable name for the root
554    #[serde(default, skip_serializing_if = "Option::is_none")]
555    pub name: Option<String>,
556}
557
558impl Root {
559    /// Create a new root with just a URI
560    pub fn new(uri: impl Into<String>) -> Self {
561        Self {
562            uri: uri.into(),
563            name: None,
564        }
565    }
566
567    /// Create a new root with a URI and name
568    pub fn with_name(uri: impl Into<String>, name: impl Into<String>) -> Self {
569        Self {
570            uri: uri.into(),
571            name: Some(name.into()),
572        }
573    }
574}
575
576/// Parameters for roots/list request (server to client)
577#[derive(Debug, Clone, Default, Deserialize, Serialize)]
578pub struct ListRootsParams {
579    /// Optional metadata
580    #[serde(default, rename = "_meta", skip_serializing_if = "Option::is_none")]
581    pub meta: Option<RequestMeta>,
582}
583
584/// Result of roots/list request
585#[derive(Debug, Clone, Deserialize, Serialize)]
586pub struct ListRootsResult {
587    /// The list of roots available to the server
588    pub roots: Vec<Root>,
589}
590
591#[derive(Debug, Clone, Default, Deserialize, Serialize)]
592pub struct SamplingCapability {}
593
594/// Server capability for providing completions
595#[derive(Debug, Clone, Default, Deserialize, Serialize)]
596pub struct CompletionsCapability {}
597
598// =============================================================================
599// Completion Types
600// =============================================================================
601
602/// Reference to a prompt for completion
603#[derive(Debug, Clone, Serialize, Deserialize)]
604pub struct PromptReference {
605    /// Type discriminator, always "ref/prompt"
606    #[serde(rename = "type")]
607    pub ref_type: String,
608    /// The name of the prompt or prompt template
609    pub name: String,
610}
611
612impl PromptReference {
613    /// Create a new prompt reference
614    pub fn new(name: impl Into<String>) -> Self {
615        Self {
616            ref_type: "ref/prompt".to_string(),
617            name: name.into(),
618        }
619    }
620}
621
622/// Reference to a resource for completion
623#[derive(Debug, Clone, Serialize, Deserialize)]
624pub struct ResourceReference {
625    /// Type discriminator, always "ref/resource"
626    #[serde(rename = "type")]
627    pub ref_type: String,
628    /// The URI or URI template of the resource
629    pub uri: String,
630}
631
632impl ResourceReference {
633    /// Create a new resource reference
634    pub fn new(uri: impl Into<String>) -> Self {
635        Self {
636            ref_type: "ref/resource".to_string(),
637            uri: uri.into(),
638        }
639    }
640}
641
642/// Reference for completion - either a prompt or resource reference
643#[derive(Debug, Clone, Serialize, Deserialize)]
644#[serde(tag = "type")]
645pub enum CompletionReference {
646    /// Reference to a prompt
647    #[serde(rename = "ref/prompt")]
648    Prompt {
649        /// The name of the prompt
650        name: String,
651    },
652    /// Reference to a resource
653    #[serde(rename = "ref/resource")]
654    Resource {
655        /// The URI of the resource
656        uri: String,
657    },
658}
659
660impl CompletionReference {
661    /// Create a prompt reference
662    pub fn prompt(name: impl Into<String>) -> Self {
663        Self::Prompt { name: name.into() }
664    }
665
666    /// Create a resource reference
667    pub fn resource(uri: impl Into<String>) -> Self {
668        Self::Resource { uri: uri.into() }
669    }
670}
671
672/// Argument being completed
673#[derive(Debug, Clone, Serialize, Deserialize)]
674pub struct CompletionArgument {
675    /// The name of the argument
676    pub name: String,
677    /// The current value of the argument (partial input)
678    pub value: String,
679}
680
681impl CompletionArgument {
682    /// Create a new completion argument
683    pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
684        Self {
685            name: name.into(),
686            value: value.into(),
687        }
688    }
689}
690
691/// Parameters for completion/complete request
692#[derive(Debug, Clone, Serialize, Deserialize)]
693#[serde(rename_all = "camelCase")]
694pub struct CompleteParams {
695    /// The reference (prompt or resource) being completed
696    #[serde(rename = "ref")]
697    pub reference: CompletionReference,
698    /// The argument being completed
699    pub argument: CompletionArgument,
700}
701
702/// Completion suggestions
703#[derive(Debug, Clone, Serialize, Deserialize)]
704#[serde(rename_all = "camelCase")]
705pub struct Completion {
706    /// Suggested completion values
707    pub values: Vec<String>,
708    /// Total number of available completions (if known)
709    #[serde(default, skip_serializing_if = "Option::is_none")]
710    pub total: Option<u32>,
711    /// Whether there are more completions available
712    #[serde(default, skip_serializing_if = "Option::is_none")]
713    pub has_more: Option<bool>,
714}
715
716impl Completion {
717    /// Create a new completion result
718    pub fn new(values: Vec<String>) -> Self {
719        Self {
720            values,
721            total: None,
722            has_more: None,
723        }
724    }
725
726    /// Create a completion result with pagination info
727    pub fn with_pagination(values: Vec<String>, total: u32, has_more: bool) -> Self {
728        Self {
729            values,
730            total: Some(total),
731            has_more: Some(has_more),
732        }
733    }
734}
735
736/// Result of completion/complete request
737#[derive(Debug, Clone, Serialize, Deserialize)]
738pub struct CompleteResult {
739    /// The completion suggestions
740    pub completion: Completion,
741}
742
743impl CompleteResult {
744    /// Create a new completion result
745    pub fn new(values: Vec<String>) -> Self {
746        Self {
747            completion: Completion::new(values),
748        }
749    }
750
751    /// Create a completion result with pagination info
752    pub fn with_pagination(values: Vec<String>, total: u32, has_more: bool) -> Self {
753        Self {
754            completion: Completion::with_pagination(values, total, has_more),
755        }
756    }
757}
758
759// =============================================================================
760// Sampling Types
761// =============================================================================
762
763/// Hint for model selection
764#[derive(Debug, Clone, Serialize, Deserialize)]
765pub struct ModelHint {
766    /// Suggested model name (partial match allowed)
767    pub name: String,
768}
769
770impl ModelHint {
771    /// Create a new model hint
772    pub fn new(name: impl Into<String>) -> Self {
773        Self { name: name.into() }
774    }
775}
776
777/// Preferences for model selection during sampling
778#[derive(Debug, Clone, Default, Serialize, Deserialize)]
779#[serde(rename_all = "camelCase")]
780pub struct ModelPreferences {
781    /// Priority for response speed (0.0 to 1.0)
782    #[serde(default, skip_serializing_if = "Option::is_none")]
783    pub speed_priority: Option<f64>,
784    /// Priority for model intelligence/capability (0.0 to 1.0)
785    #[serde(default, skip_serializing_if = "Option::is_none")]
786    pub intelligence_priority: Option<f64>,
787    /// Priority for cost efficiency (0.0 to 1.0)
788    #[serde(default, skip_serializing_if = "Option::is_none")]
789    pub cost_priority: Option<f64>,
790    /// Hints for model selection
791    #[serde(default, skip_serializing_if = "Vec::is_empty")]
792    pub hints: Vec<ModelHint>,
793}
794
795impl ModelPreferences {
796    /// Create new model preferences
797    pub fn new() -> Self {
798        Self::default()
799    }
800
801    /// Set speed priority (0.0 to 1.0)
802    pub fn speed(mut self, priority: f64) -> Self {
803        self.speed_priority = Some(priority.clamp(0.0, 1.0));
804        self
805    }
806
807    /// Set intelligence priority (0.0 to 1.0)
808    pub fn intelligence(mut self, priority: f64) -> Self {
809        self.intelligence_priority = Some(priority.clamp(0.0, 1.0));
810        self
811    }
812
813    /// Set cost priority (0.0 to 1.0)
814    pub fn cost(mut self, priority: f64) -> Self {
815        self.cost_priority = Some(priority.clamp(0.0, 1.0));
816        self
817    }
818
819    /// Add a model hint
820    pub fn hint(mut self, name: impl Into<String>) -> Self {
821        self.hints.push(ModelHint::new(name));
822        self
823    }
824}
825
826/// Context inclusion mode for sampling
827#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
828#[serde(rename_all = "camelCase")]
829pub enum IncludeContext {
830    /// Include context from all connected MCP servers
831    AllServers,
832    /// Include context from this server only
833    ThisServer,
834    /// Don't include any additional context
835    #[default]
836    None,
837}
838
839/// Message for sampling request
840#[derive(Debug, Clone, Serialize, Deserialize)]
841pub struct SamplingMessage {
842    /// The role of the message sender
843    pub role: ContentRole,
844    /// The content of the message
845    pub content: SamplingContent,
846}
847
848impl SamplingMessage {
849    /// Create a user message with text content
850    pub fn user(text: impl Into<String>) -> Self {
851        Self {
852            role: ContentRole::User,
853            content: SamplingContent::Text { text: text.into() },
854        }
855    }
856
857    /// Create an assistant message with text content
858    pub fn assistant(text: impl Into<String>) -> Self {
859        Self {
860            role: ContentRole::Assistant,
861            content: SamplingContent::Text { text: text.into() },
862        }
863    }
864}
865
866/// Content types for sampling messages
867#[derive(Debug, Clone, Serialize, Deserialize)]
868#[serde(tag = "type", rename_all = "lowercase")]
869pub enum SamplingContent {
870    /// Text content
871    Text {
872        /// The text content
873        text: String,
874    },
875    /// Image content
876    Image {
877        /// Base64-encoded image data
878        data: String,
879        /// MIME type of the image
880        #[serde(rename = "mimeType")]
881        mime_type: String,
882    },
883    /// Audio content (if supported)
884    Audio {
885        /// Base64-encoded audio data
886        data: String,
887        /// MIME type of the audio
888        #[serde(rename = "mimeType")]
889        mime_type: String,
890    },
891}
892
893/// Parameters for sampling/createMessage request
894#[derive(Debug, Clone, Serialize, Deserialize)]
895#[serde(rename_all = "camelCase")]
896pub struct CreateMessageParams {
897    /// The messages to send to the LLM
898    pub messages: Vec<SamplingMessage>,
899    /// Maximum number of tokens to generate
900    pub max_tokens: u32,
901    /// Optional system prompt
902    #[serde(default, skip_serializing_if = "Option::is_none")]
903    pub system_prompt: Option<String>,
904    /// Sampling temperature (0.0 to 1.0)
905    #[serde(default, skip_serializing_if = "Option::is_none")]
906    pub temperature: Option<f64>,
907    /// Stop sequences
908    #[serde(default, skip_serializing_if = "Vec::is_empty")]
909    pub stop_sequences: Vec<String>,
910    /// Model preferences
911    #[serde(default, skip_serializing_if = "Option::is_none")]
912    pub model_preferences: Option<ModelPreferences>,
913    /// Context inclusion mode
914    #[serde(default, skip_serializing_if = "Option::is_none")]
915    pub include_context: Option<IncludeContext>,
916    /// Additional metadata
917    #[serde(default, skip_serializing_if = "Option::is_none")]
918    pub metadata: Option<serde_json::Map<String, Value>>,
919}
920
921impl CreateMessageParams {
922    /// Create a new sampling request
923    pub fn new(messages: Vec<SamplingMessage>, max_tokens: u32) -> Self {
924        Self {
925            messages,
926            max_tokens,
927            system_prompt: None,
928            temperature: None,
929            stop_sequences: Vec::new(),
930            model_preferences: None,
931            include_context: None,
932            metadata: None,
933        }
934    }
935
936    /// Set the system prompt
937    pub fn system_prompt(mut self, prompt: impl Into<String>) -> Self {
938        self.system_prompt = Some(prompt.into());
939        self
940    }
941
942    /// Set the temperature
943    pub fn temperature(mut self, temp: f64) -> Self {
944        self.temperature = Some(temp.clamp(0.0, 1.0));
945        self
946    }
947
948    /// Add a stop sequence
949    pub fn stop_sequence(mut self, seq: impl Into<String>) -> Self {
950        self.stop_sequences.push(seq.into());
951        self
952    }
953
954    /// Set model preferences
955    pub fn model_preferences(mut self, prefs: ModelPreferences) -> Self {
956        self.model_preferences = Some(prefs);
957        self
958    }
959
960    /// Set context inclusion mode
961    pub fn include_context(mut self, mode: IncludeContext) -> Self {
962        self.include_context = Some(mode);
963        self
964    }
965}
966
967/// Result of sampling/createMessage request
968#[derive(Debug, Clone, Serialize, Deserialize)]
969#[serde(rename_all = "camelCase")]
970pub struct CreateMessageResult {
971    /// The generated content
972    pub content: SamplingContent,
973    /// The model that generated the response
974    pub model: String,
975    /// The role of the response (always assistant)
976    pub role: ContentRole,
977    /// Why the generation stopped
978    #[serde(default, skip_serializing_if = "Option::is_none")]
979    pub stop_reason: Option<String>,
980}
981
982#[derive(Debug, Clone, Deserialize, Serialize)]
983pub struct Implementation {
984    pub name: String,
985    pub version: String,
986}
987
988#[derive(Debug, Clone, Serialize, Deserialize)]
989#[serde(rename_all = "camelCase")]
990pub struct InitializeResult {
991    pub protocol_version: String,
992    pub capabilities: ServerCapabilities,
993    pub server_info: Implementation,
994    /// Optional instructions describing how to use this server.
995    /// These hints help LLMs understand the server's features.
996    #[serde(skip_serializing_if = "Option::is_none")]
997    pub instructions: Option<String>,
998}
999
1000#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1001#[serde(rename_all = "camelCase")]
1002pub struct ServerCapabilities {
1003    #[serde(default, skip_serializing_if = "Option::is_none")]
1004    pub tools: Option<ToolsCapability>,
1005    #[serde(default, skip_serializing_if = "Option::is_none")]
1006    pub resources: Option<ResourcesCapability>,
1007    #[serde(default, skip_serializing_if = "Option::is_none")]
1008    pub prompts: Option<PromptsCapability>,
1009    /// Logging capability - servers that emit log notifications declare this
1010    #[serde(default, skip_serializing_if = "Option::is_none")]
1011    pub logging: Option<LoggingCapability>,
1012    #[serde(default, skip_serializing_if = "Option::is_none")]
1013    pub tasks: Option<TasksCapability>,
1014    /// Completion capability - server provides autocomplete suggestions
1015    #[serde(default, skip_serializing_if = "Option::is_none")]
1016    pub completions: Option<CompletionsCapability>,
1017}
1018
1019/// Logging capability declaration
1020#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1021pub struct LoggingCapability {}
1022
1023/// Capability for async task management
1024#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1025#[serde(rename_all = "camelCase")]
1026pub struct TasksCapability {
1027    /// Default poll interval suggestion in seconds
1028    #[serde(default, skip_serializing_if = "Option::is_none")]
1029    pub default_poll_interval: Option<u64>,
1030}
1031
1032#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1033#[serde(rename_all = "camelCase")]
1034pub struct ToolsCapability {
1035    #[serde(default)]
1036    pub list_changed: bool,
1037}
1038
1039#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1040#[serde(rename_all = "camelCase")]
1041pub struct ResourcesCapability {
1042    #[serde(default)]
1043    pub subscribe: bool,
1044    #[serde(default)]
1045    pub list_changed: bool,
1046}
1047
1048#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1049#[serde(rename_all = "camelCase")]
1050pub struct PromptsCapability {
1051    #[serde(default)]
1052    pub list_changed: bool,
1053}
1054
1055// =============================================================================
1056// Tools
1057// =============================================================================
1058
1059#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1060pub struct ListToolsParams {
1061    #[serde(default)]
1062    pub cursor: Option<String>,
1063}
1064
1065#[derive(Debug, Clone, Serialize, Deserialize)]
1066#[serde(rename_all = "camelCase")]
1067pub struct ListToolsResult {
1068    pub tools: Vec<ToolDefinition>,
1069    #[serde(default, skip_serializing_if = "Option::is_none")]
1070    pub next_cursor: Option<String>,
1071}
1072
1073/// Tool definition as returned by tools/list
1074#[derive(Debug, Clone, Serialize, Deserialize)]
1075#[serde(rename_all = "camelCase")]
1076pub struct ToolDefinition {
1077    pub name: String,
1078    /// Human-readable title for display purposes
1079    #[serde(skip_serializing_if = "Option::is_none")]
1080    pub title: Option<String>,
1081    #[serde(skip_serializing_if = "Option::is_none")]
1082    pub description: Option<String>,
1083    pub input_schema: Value,
1084    /// Optional JSON Schema defining expected output structure
1085    #[serde(skip_serializing_if = "Option::is_none")]
1086    pub output_schema: Option<Value>,
1087    /// Optional icons for display in user interfaces
1088    #[serde(skip_serializing_if = "Option::is_none")]
1089    pub icons: Option<Vec<ToolIcon>>,
1090    /// Optional annotations describing tool behavior.
1091    /// Note: Clients MUST consider these untrusted unless from a trusted server.
1092    #[serde(skip_serializing_if = "Option::is_none")]
1093    pub annotations: Option<ToolAnnotations>,
1094}
1095
1096/// Icon for tool display in user interfaces
1097#[derive(Debug, Clone, Serialize, Deserialize)]
1098#[serde(rename_all = "camelCase")]
1099pub struct ToolIcon {
1100    /// URL or data URI of the icon
1101    pub src: String,
1102    /// MIME type of the icon (e.g., "image/png", "image/svg+xml")
1103    #[serde(skip_serializing_if = "Option::is_none")]
1104    pub mime_type: Option<String>,
1105    /// Available sizes (e.g., ["48x48", "96x96"])
1106    #[serde(skip_serializing_if = "Option::is_none")]
1107    pub sizes: Option<Vec<String>>,
1108}
1109
1110/// Annotations describing tool behavior for trust and safety.
1111/// Clients MUST consider these untrusted unless the server is trusted.
1112#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1113#[serde(rename_all = "camelCase")]
1114pub struct ToolAnnotations {
1115    /// Human-readable title for the tool
1116    #[serde(skip_serializing_if = "Option::is_none")]
1117    pub title: Option<String>,
1118    /// If true, the tool does not modify state. Default: false
1119    #[serde(default, skip_serializing_if = "std::ops::Not::not")]
1120    pub read_only_hint: bool,
1121    /// If true, the tool may have destructive effects. Default: true
1122    /// Only meaningful when read_only_hint is false.
1123    #[serde(default = "default_true", skip_serializing_if = "is_true")]
1124    pub destructive_hint: bool,
1125    /// If true, calling repeatedly with same args has same effect. Default: false
1126    /// Only meaningful when read_only_hint is false.
1127    #[serde(default, skip_serializing_if = "std::ops::Not::not")]
1128    pub idempotent_hint: bool,
1129    /// If true, tool interacts with external entities. Default: true
1130    #[serde(default = "default_true", skip_serializing_if = "is_true")]
1131    pub open_world_hint: bool,
1132}
1133
1134fn default_true() -> bool {
1135    true
1136}
1137
1138fn is_true(v: &bool) -> bool {
1139    *v
1140}
1141
1142#[derive(Debug, Clone, Serialize, Deserialize)]
1143pub struct CallToolParams {
1144    pub name: String,
1145    #[serde(default)]
1146    pub arguments: Value,
1147    /// Request metadata including progress token
1148    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1149    pub meta: Option<RequestMeta>,
1150}
1151
1152/// Result of a tool invocation.
1153///
1154/// This is the return type for tool handlers. Use the convenience constructors
1155/// like [`CallToolResult::text`], [`CallToolResult::json`], or [`CallToolResult::error`]
1156/// to create results easily.
1157///
1158/// # Example
1159///
1160/// ```rust
1161/// use tower_mcp::CallToolResult;
1162///
1163/// // Simple text result
1164/// let result = CallToolResult::text("Hello, world!");
1165///
1166/// // JSON result with structured content
1167/// let result = CallToolResult::json(serde_json::json!({"key": "value"}));
1168///
1169/// // Error result
1170/// let result = CallToolResult::error("Something went wrong");
1171/// ```
1172#[derive(Debug, Clone, Serialize, Deserialize)]
1173#[serde(rename_all = "camelCase")]
1174pub struct CallToolResult {
1175    /// The content items returned by the tool.
1176    pub content: Vec<Content>,
1177    /// Whether this result represents an error.
1178    #[serde(default, skip_serializing_if = "std::ops::Not::not")]
1179    pub is_error: bool,
1180    /// Optional structured content for programmatic access.
1181    #[serde(default, skip_serializing_if = "Option::is_none")]
1182    pub structured_content: Option<Value>,
1183}
1184
1185impl CallToolResult {
1186    /// Create a text result.
1187    ///
1188    /// This is the most common result type for tools that return plain text.
1189    pub fn text(text: impl Into<String>) -> Self {
1190        Self {
1191            content: vec![Content::Text {
1192                text: text.into(),
1193                annotations: None,
1194            }],
1195            is_error: false,
1196            structured_content: None,
1197        }
1198    }
1199
1200    /// Create an error result.
1201    ///
1202    /// Use this when the tool encounters an error during execution.
1203    /// The `is_error` flag will be set to `true`.
1204    pub fn error(message: impl Into<String>) -> Self {
1205        Self {
1206            content: vec![Content::Text {
1207                text: message.into(),
1208                annotations: None,
1209            }],
1210            is_error: true,
1211            structured_content: None,
1212        }
1213    }
1214
1215    /// Create a JSON result with structured content.
1216    ///
1217    /// The JSON value is serialized to pretty-printed text for display,
1218    /// and also stored in `structured_content` for programmatic access.
1219    pub fn json(value: Value) -> Self {
1220        let text = serde_json::to_string_pretty(&value).unwrap_or_default();
1221        Self {
1222            content: vec![Content::Text {
1223                text,
1224                annotations: None,
1225            }],
1226            is_error: false,
1227            structured_content: Some(value),
1228        }
1229    }
1230
1231    /// Create a result with an image
1232    pub fn image(data: impl Into<String>, mime_type: impl Into<String>) -> Self {
1233        Self {
1234            content: vec![Content::Image {
1235                data: data.into(),
1236                mime_type: mime_type.into(),
1237                annotations: None,
1238            }],
1239            is_error: false,
1240            structured_content: None,
1241        }
1242    }
1243
1244    /// Create a result with audio
1245    pub fn audio(data: impl Into<String>, mime_type: impl Into<String>) -> Self {
1246        Self {
1247            content: vec![Content::Audio {
1248                data: data.into(),
1249                mime_type: mime_type.into(),
1250                annotations: None,
1251            }],
1252            is_error: false,
1253            structured_content: None,
1254        }
1255    }
1256
1257    /// Create a result with a resource link
1258    pub fn resource_link(uri: impl Into<String>) -> Self {
1259        Self {
1260            content: vec![Content::ResourceLink {
1261                uri: uri.into(),
1262                name: None,
1263                description: None,
1264                mime_type: None,
1265                annotations: None,
1266            }],
1267            is_error: false,
1268            structured_content: None,
1269        }
1270    }
1271
1272    /// Create a result with a resource link including metadata
1273    pub fn resource_link_with_meta(
1274        uri: impl Into<String>,
1275        name: Option<String>,
1276        description: Option<String>,
1277        mime_type: Option<String>,
1278    ) -> Self {
1279        Self {
1280            content: vec![Content::ResourceLink {
1281                uri: uri.into(),
1282                name,
1283                description,
1284                mime_type,
1285                annotations: None,
1286            }],
1287            is_error: false,
1288            structured_content: None,
1289        }
1290    }
1291
1292    /// Create a result with an embedded resource
1293    pub fn resource(resource: ResourceContent) -> Self {
1294        Self {
1295            content: vec![Content::Resource {
1296                resource,
1297                annotations: None,
1298            }],
1299            is_error: false,
1300            structured_content: None,
1301        }
1302    }
1303}
1304
1305/// Content types for tool results, resources, and prompts.
1306///
1307/// Content can be text, images, audio, or embedded resources. Each variant
1308/// supports optional annotations for audience targeting and priority hints.
1309#[derive(Debug, Clone, Serialize, Deserialize)]
1310#[serde(tag = "type", rename_all = "snake_case")]
1311pub enum Content {
1312    /// Plain text content.
1313    Text {
1314        /// The text content.
1315        text: String,
1316        /// Optional annotations for this content.
1317        #[serde(skip_serializing_if = "Option::is_none")]
1318        annotations: Option<ContentAnnotations>,
1319    },
1320    /// Base64-encoded image content.
1321    Image {
1322        /// Base64-encoded image data.
1323        data: String,
1324        /// MIME type (e.g., "image/png", "image/jpeg").
1325        #[serde(rename = "mimeType")]
1326        mime_type: String,
1327        /// Optional annotations for this content.
1328        #[serde(skip_serializing_if = "Option::is_none")]
1329        annotations: Option<ContentAnnotations>,
1330    },
1331    /// Base64-encoded audio content.
1332    Audio {
1333        /// Base64-encoded audio data.
1334        data: String,
1335        /// MIME type (e.g., "audio/wav", "audio/mp3").
1336        #[serde(rename = "mimeType")]
1337        mime_type: String,
1338        /// Optional annotations for this content.
1339        #[serde(skip_serializing_if = "Option::is_none")]
1340        annotations: Option<ContentAnnotations>,
1341    },
1342    /// Embedded resource content.
1343    Resource {
1344        /// The embedded resource.
1345        resource: ResourceContent,
1346        /// Optional annotations for this content.
1347        #[serde(skip_serializing_if = "Option::is_none")]
1348        annotations: Option<ContentAnnotations>,
1349    },
1350    /// Link to a resource (without embedding the content)
1351    ResourceLink {
1352        /// URI of the resource
1353        uri: String,
1354        /// Human-readable name
1355        #[serde(skip_serializing_if = "Option::is_none")]
1356        name: Option<String>,
1357        /// Description of the resource
1358        #[serde(skip_serializing_if = "Option::is_none")]
1359        description: Option<String>,
1360        /// MIME type of the resource
1361        #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
1362        mime_type: Option<String>,
1363        #[serde(skip_serializing_if = "Option::is_none")]
1364        annotations: Option<ContentAnnotations>,
1365    },
1366}
1367
1368/// Annotations for content items
1369#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1370pub struct ContentAnnotations {
1371    /// Intended audience for this content
1372    #[serde(skip_serializing_if = "Option::is_none")]
1373    pub audience: Option<Vec<ContentRole>>,
1374    /// Priority hint from 0 (optional) to 1 (required)
1375    #[serde(skip_serializing_if = "Option::is_none")]
1376    pub priority: Option<f64>,
1377}
1378
1379/// Role indicating who content is intended for.
1380///
1381/// Used in content annotations to specify the target audience.
1382#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1383#[serde(rename_all = "lowercase")]
1384pub enum ContentRole {
1385    /// Content intended for the human user.
1386    User,
1387    /// Content intended for the AI assistant.
1388    Assistant,
1389}
1390
1391/// Content of an embedded resource.
1392///
1393/// Contains either text or binary (blob) content along with metadata.
1394#[derive(Debug, Clone, Serialize, Deserialize)]
1395#[serde(rename_all = "camelCase")]
1396pub struct ResourceContent {
1397    /// The URI identifying this resource.
1398    pub uri: String,
1399    /// MIME type of the content.
1400    #[serde(skip_serializing_if = "Option::is_none")]
1401    pub mime_type: Option<String>,
1402    /// Text content (for text-based resources).
1403    #[serde(skip_serializing_if = "Option::is_none")]
1404    pub text: Option<String>,
1405    /// Base64-encoded binary content (for binary resources).
1406    #[serde(skip_serializing_if = "Option::is_none")]
1407    pub blob: Option<String>,
1408}
1409
1410// =============================================================================
1411// Resources
1412// =============================================================================
1413
1414#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1415pub struct ListResourcesParams {
1416    #[serde(default)]
1417    pub cursor: Option<String>,
1418}
1419
1420#[derive(Debug, Clone, Serialize, Deserialize)]
1421#[serde(rename_all = "camelCase")]
1422pub struct ListResourcesResult {
1423    pub resources: Vec<ResourceDefinition>,
1424    #[serde(default, skip_serializing_if = "Option::is_none")]
1425    pub next_cursor: Option<String>,
1426}
1427
1428#[derive(Debug, Clone, Serialize, Deserialize)]
1429#[serde(rename_all = "camelCase")]
1430pub struct ResourceDefinition {
1431    pub uri: String,
1432    pub name: String,
1433    #[serde(skip_serializing_if = "Option::is_none")]
1434    pub description: Option<String>,
1435    #[serde(skip_serializing_if = "Option::is_none")]
1436    pub mime_type: Option<String>,
1437}
1438
1439#[derive(Debug, Clone, Serialize, Deserialize)]
1440pub struct ReadResourceParams {
1441    pub uri: String,
1442}
1443
1444#[derive(Debug, Clone, Serialize, Deserialize)]
1445pub struct ReadResourceResult {
1446    pub contents: Vec<ResourceContent>,
1447}
1448
1449impl ReadResourceResult {
1450    /// Create a result with text content.
1451    ///
1452    /// # Example
1453    ///
1454    /// ```rust
1455    /// use tower_mcp::ReadResourceResult;
1456    ///
1457    /// let result = ReadResourceResult::text("file://readme.md", "# Hello World");
1458    /// ```
1459    pub fn text(uri: impl Into<String>, content: impl Into<String>) -> Self {
1460        Self {
1461            contents: vec![ResourceContent {
1462                uri: uri.into(),
1463                mime_type: Some("text/plain".to_string()),
1464                text: Some(content.into()),
1465                blob: None,
1466            }],
1467        }
1468    }
1469
1470    /// Create a result with text content and a specific MIME type.
1471    ///
1472    /// # Example
1473    ///
1474    /// ```rust
1475    /// use tower_mcp::ReadResourceResult;
1476    ///
1477    /// let result = ReadResourceResult::text_with_mime(
1478    ///     "file://readme.md",
1479    ///     "# Hello World",
1480    ///     "text/markdown"
1481    /// );
1482    /// ```
1483    pub fn text_with_mime(
1484        uri: impl Into<String>,
1485        content: impl Into<String>,
1486        mime_type: impl Into<String>,
1487    ) -> Self {
1488        Self {
1489            contents: vec![ResourceContent {
1490                uri: uri.into(),
1491                mime_type: Some(mime_type.into()),
1492                text: Some(content.into()),
1493                blob: None,
1494            }],
1495        }
1496    }
1497
1498    /// Create a result with JSON content.
1499    ///
1500    /// The value is serialized to a JSON string automatically.
1501    ///
1502    /// # Example
1503    ///
1504    /// ```rust
1505    /// use tower_mcp::ReadResourceResult;
1506    /// use serde_json::json;
1507    ///
1508    /// let data = json!({"name": "example", "count": 42});
1509    /// let result = ReadResourceResult::json("data://config", &data);
1510    /// ```
1511    pub fn json<T: serde::Serialize>(uri: impl Into<String>, value: &T) -> Self {
1512        let json_string =
1513            serde_json::to_string_pretty(value).unwrap_or_else(|_| "null".to_string());
1514        Self {
1515            contents: vec![ResourceContent {
1516                uri: uri.into(),
1517                mime_type: Some("application/json".to_string()),
1518                text: Some(json_string),
1519                blob: None,
1520            }],
1521        }
1522    }
1523
1524    /// Create a result with binary content (base64 encoded).
1525    ///
1526    /// # Example
1527    ///
1528    /// ```rust
1529    /// use tower_mcp::ReadResourceResult;
1530    ///
1531    /// let bytes = vec![0x89, 0x50, 0x4E, 0x47]; // PNG magic bytes
1532    /// let result = ReadResourceResult::blob("file://image.png", &bytes);
1533    /// ```
1534    pub fn blob(uri: impl Into<String>, bytes: &[u8]) -> Self {
1535        use base64::Engine;
1536        let encoded = base64::engine::general_purpose::STANDARD.encode(bytes);
1537        Self {
1538            contents: vec![ResourceContent {
1539                uri: uri.into(),
1540                mime_type: Some("application/octet-stream".to_string()),
1541                text: None,
1542                blob: Some(encoded),
1543            }],
1544        }
1545    }
1546
1547    /// Create a result with binary content and a specific MIME type.
1548    ///
1549    /// # Example
1550    ///
1551    /// ```rust
1552    /// use tower_mcp::ReadResourceResult;
1553    ///
1554    /// let bytes = vec![0x89, 0x50, 0x4E, 0x47];
1555    /// let result = ReadResourceResult::blob_with_mime("file://image.png", &bytes, "image/png");
1556    /// ```
1557    pub fn blob_with_mime(
1558        uri: impl Into<String>,
1559        bytes: &[u8],
1560        mime_type: impl Into<String>,
1561    ) -> Self {
1562        use base64::Engine;
1563        let encoded = base64::engine::general_purpose::STANDARD.encode(bytes);
1564        Self {
1565            contents: vec![ResourceContent {
1566                uri: uri.into(),
1567                mime_type: Some(mime_type.into()),
1568                text: None,
1569                blob: Some(encoded),
1570            }],
1571        }
1572    }
1573}
1574
1575#[derive(Debug, Clone, Deserialize)]
1576pub struct SubscribeResourceParams {
1577    pub uri: String,
1578}
1579
1580#[derive(Debug, Clone, Deserialize)]
1581pub struct UnsubscribeResourceParams {
1582    pub uri: String,
1583}
1584
1585/// Parameters for listing resource templates
1586#[derive(Debug, Clone, Default, Deserialize)]
1587pub struct ListResourceTemplatesParams {
1588    /// Pagination cursor from previous response
1589    #[serde(default)]
1590    pub cursor: Option<String>,
1591}
1592
1593/// Result of listing resource templates
1594#[derive(Debug, Clone, Serialize)]
1595#[serde(rename_all = "camelCase")]
1596pub struct ListResourceTemplatesResult {
1597    /// Available resource templates
1598    pub resource_templates: Vec<ResourceTemplateDefinition>,
1599    /// Cursor for next page (if more templates available)
1600    #[serde(skip_serializing_if = "Option::is_none")]
1601    pub next_cursor: Option<String>,
1602}
1603
1604/// Definition of a resource template as returned by resources/templates/list
1605///
1606/// Resource templates allow servers to expose parameterized resources using
1607/// [URI templates (RFC 6570)](https://datatracker.ietf.org/doc/html/rfc6570).
1608///
1609/// # Example
1610///
1611/// ```json
1612/// {
1613///     "uriTemplate": "file:///{path}",
1614///     "name": "Project Files",
1615///     "description": "Access files in the project directory",
1616///     "mimeType": "application/octet-stream"
1617/// }
1618/// ```
1619#[derive(Debug, Clone, Serialize, Deserialize)]
1620#[serde(rename_all = "camelCase")]
1621pub struct ResourceTemplateDefinition {
1622    /// URI template following RFC 6570 (e.g., `file:///{path}`)
1623    pub uri_template: String,
1624    /// Human-readable name for this template
1625    pub name: String,
1626    /// Description of what resources this template provides
1627    #[serde(skip_serializing_if = "Option::is_none")]
1628    pub description: Option<String>,
1629    /// MIME type hint for resources from this template
1630    #[serde(skip_serializing_if = "Option::is_none")]
1631    pub mime_type: Option<String>,
1632}
1633
1634// =============================================================================
1635// Prompts
1636// =============================================================================
1637
1638#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1639pub struct ListPromptsParams {
1640    #[serde(default)]
1641    pub cursor: Option<String>,
1642}
1643
1644#[derive(Debug, Clone, Serialize, Deserialize)]
1645#[serde(rename_all = "camelCase")]
1646pub struct ListPromptsResult {
1647    pub prompts: Vec<PromptDefinition>,
1648    #[serde(default, skip_serializing_if = "Option::is_none")]
1649    pub next_cursor: Option<String>,
1650}
1651
1652#[derive(Debug, Clone, Serialize, Deserialize)]
1653pub struct PromptDefinition {
1654    pub name: String,
1655    #[serde(skip_serializing_if = "Option::is_none")]
1656    pub description: Option<String>,
1657    #[serde(default, skip_serializing_if = "Vec::is_empty")]
1658    pub arguments: Vec<PromptArgument>,
1659}
1660
1661#[derive(Debug, Clone, Serialize, Deserialize)]
1662pub struct PromptArgument {
1663    pub name: String,
1664    #[serde(skip_serializing_if = "Option::is_none")]
1665    pub description: Option<String>,
1666    #[serde(default)]
1667    pub required: bool,
1668}
1669
1670#[derive(Debug, Clone, Serialize, Deserialize)]
1671pub struct GetPromptParams {
1672    pub name: String,
1673    #[serde(default)]
1674    pub arguments: std::collections::HashMap<String, String>,
1675}
1676
1677#[derive(Debug, Clone, Serialize, Deserialize)]
1678pub struct GetPromptResult {
1679    #[serde(default, skip_serializing_if = "Option::is_none")]
1680    pub description: Option<String>,
1681    pub messages: Vec<PromptMessage>,
1682}
1683
1684impl GetPromptResult {
1685    /// Create a result with a single user message.
1686    ///
1687    /// # Example
1688    ///
1689    /// ```rust
1690    /// use tower_mcp::GetPromptResult;
1691    ///
1692    /// let result = GetPromptResult::user_message("Please analyze this code.");
1693    /// ```
1694    pub fn user_message(text: impl Into<String>) -> Self {
1695        Self {
1696            description: None,
1697            messages: vec![PromptMessage {
1698                role: PromptRole::User,
1699                content: Content::Text {
1700                    text: text.into(),
1701                    annotations: None,
1702                },
1703            }],
1704        }
1705    }
1706
1707    /// Create a result with a single user message and description.
1708    ///
1709    /// # Example
1710    ///
1711    /// ```rust
1712    /// use tower_mcp::GetPromptResult;
1713    ///
1714    /// let result = GetPromptResult::user_message_with_description(
1715    ///     "Please analyze this code.",
1716    ///     "Code analysis prompt"
1717    /// );
1718    /// ```
1719    pub fn user_message_with_description(
1720        text: impl Into<String>,
1721        description: impl Into<String>,
1722    ) -> Self {
1723        Self {
1724            description: Some(description.into()),
1725            messages: vec![PromptMessage {
1726                role: PromptRole::User,
1727                content: Content::Text {
1728                    text: text.into(),
1729                    annotations: None,
1730                },
1731            }],
1732        }
1733    }
1734
1735    /// Create a result with a single assistant message.
1736    ///
1737    /// # Example
1738    ///
1739    /// ```rust
1740    /// use tower_mcp::GetPromptResult;
1741    ///
1742    /// let result = GetPromptResult::assistant_message("Here is my analysis...");
1743    /// ```
1744    pub fn assistant_message(text: impl Into<String>) -> Self {
1745        Self {
1746            description: None,
1747            messages: vec![PromptMessage {
1748                role: PromptRole::Assistant,
1749                content: Content::Text {
1750                    text: text.into(),
1751                    annotations: None,
1752                },
1753            }],
1754        }
1755    }
1756
1757    /// Create a builder for constructing prompts with multiple messages.
1758    ///
1759    /// # Example
1760    ///
1761    /// ```rust
1762    /// use tower_mcp::GetPromptResult;
1763    ///
1764    /// let result = GetPromptResult::builder()
1765    ///     .description("Multi-turn conversation prompt")
1766    ///     .user("What is the weather today?")
1767    ///     .assistant("I don't have access to weather data, but I can help you find it.")
1768    ///     .user("Where should I look?")
1769    ///     .build();
1770    /// ```
1771    pub fn builder() -> GetPromptResultBuilder {
1772        GetPromptResultBuilder::new()
1773    }
1774}
1775
1776/// Builder for constructing [`GetPromptResult`] with multiple messages.
1777#[derive(Debug, Clone, Default)]
1778pub struct GetPromptResultBuilder {
1779    description: Option<String>,
1780    messages: Vec<PromptMessage>,
1781}
1782
1783impl GetPromptResultBuilder {
1784    /// Create a new builder.
1785    pub fn new() -> Self {
1786        Self::default()
1787    }
1788
1789    /// Set the prompt description.
1790    pub fn description(mut self, description: impl Into<String>) -> Self {
1791        self.description = Some(description.into());
1792        self
1793    }
1794
1795    /// Add a user message.
1796    pub fn user(mut self, text: impl Into<String>) -> Self {
1797        self.messages.push(PromptMessage {
1798            role: PromptRole::User,
1799            content: Content::Text {
1800                text: text.into(),
1801                annotations: None,
1802            },
1803        });
1804        self
1805    }
1806
1807    /// Add an assistant message.
1808    pub fn assistant(mut self, text: impl Into<String>) -> Self {
1809        self.messages.push(PromptMessage {
1810            role: PromptRole::Assistant,
1811            content: Content::Text {
1812                text: text.into(),
1813                annotations: None,
1814            },
1815        });
1816        self
1817    }
1818
1819    /// Build the final result.
1820    pub fn build(self) -> GetPromptResult {
1821        GetPromptResult {
1822            description: self.description,
1823            messages: self.messages,
1824        }
1825    }
1826}
1827
1828#[derive(Debug, Clone, Serialize, Deserialize)]
1829pub struct PromptMessage {
1830    pub role: PromptRole,
1831    pub content: Content,
1832}
1833
1834#[derive(Debug, Clone, Serialize, Deserialize)]
1835#[serde(rename_all = "lowercase")]
1836pub enum PromptRole {
1837    User,
1838    Assistant,
1839}
1840
1841// =============================================================================
1842// Tasks (async operations)
1843// =============================================================================
1844
1845/// Status of an async task
1846#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1847#[serde(rename_all = "snake_case")]
1848pub enum TaskStatus {
1849    /// Task is actively being processed
1850    Working,
1851    /// Task requires user input to continue
1852    InputRequired,
1853    /// Task completed successfully
1854    Completed,
1855    /// Task failed with an error
1856    Failed,
1857    /// Task was cancelled by user request
1858    Cancelled,
1859}
1860
1861impl std::fmt::Display for TaskStatus {
1862    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1863        match self {
1864            TaskStatus::Working => write!(f, "working"),
1865            TaskStatus::InputRequired => write!(f, "input_required"),
1866            TaskStatus::Completed => write!(f, "completed"),
1867            TaskStatus::Failed => write!(f, "failed"),
1868            TaskStatus::Cancelled => write!(f, "cancelled"),
1869        }
1870    }
1871}
1872
1873impl TaskStatus {
1874    /// Check if this status represents a terminal state
1875    pub fn is_terminal(&self) -> bool {
1876        matches!(
1877            self,
1878            TaskStatus::Completed | TaskStatus::Failed | TaskStatus::Cancelled
1879        )
1880    }
1881}
1882
1883/// Information about a task
1884#[derive(Debug, Clone, Serialize, Deserialize)]
1885#[serde(rename_all = "camelCase")]
1886pub struct TaskInfo {
1887    /// Unique task identifier
1888    pub task_id: String,
1889    /// Current task status
1890    pub status: TaskStatus,
1891    /// ISO 8601 timestamp when the task was created
1892    pub created_at: String,
1893    /// Time-to-live in seconds (how long to keep the result after completion)
1894    #[serde(skip_serializing_if = "Option::is_none")]
1895    pub ttl: Option<u64>,
1896    /// Suggested polling interval in seconds
1897    #[serde(skip_serializing_if = "Option::is_none")]
1898    pub poll_interval: Option<u64>,
1899    /// Progress percentage (0-100) if available
1900    #[serde(skip_serializing_if = "Option::is_none")]
1901    pub progress: Option<f64>,
1902    /// Human-readable status message
1903    #[serde(skip_serializing_if = "Option::is_none")]
1904    pub message: Option<String>,
1905}
1906
1907/// Parameters for enqueuing a task
1908#[derive(Debug, Clone, Deserialize)]
1909#[serde(rename_all = "camelCase")]
1910pub struct EnqueueTaskParams {
1911    /// Tool name to execute
1912    pub tool_name: String,
1913    /// Arguments to pass to the tool
1914    #[serde(default)]
1915    pub arguments: Value,
1916    /// Optional time-to-live for the task result in seconds
1917    #[serde(default)]
1918    pub ttl: Option<u64>,
1919}
1920
1921/// Result of enqueuing a task
1922#[derive(Debug, Clone, Serialize)]
1923#[serde(rename_all = "camelCase")]
1924pub struct EnqueueTaskResult {
1925    /// The task ID for tracking
1926    pub task_id: String,
1927    /// Initial status (should be Working)
1928    pub status: TaskStatus,
1929    /// Suggested polling interval in seconds
1930    #[serde(skip_serializing_if = "Option::is_none")]
1931    pub poll_interval: Option<u64>,
1932}
1933
1934/// Parameters for listing tasks
1935#[derive(Debug, Clone, Default, Deserialize)]
1936#[serde(rename_all = "camelCase")]
1937pub struct ListTasksParams {
1938    /// Filter by status (optional)
1939    #[serde(default)]
1940    pub status: Option<TaskStatus>,
1941    /// Pagination cursor
1942    #[serde(default)]
1943    pub cursor: Option<String>,
1944}
1945
1946/// Result of listing tasks
1947#[derive(Debug, Clone, Serialize)]
1948#[serde(rename_all = "camelCase")]
1949pub struct ListTasksResult {
1950    /// List of tasks
1951    pub tasks: Vec<TaskInfo>,
1952    /// Next cursor for pagination
1953    #[serde(skip_serializing_if = "Option::is_none")]
1954    pub next_cursor: Option<String>,
1955}
1956
1957/// Parameters for getting task info
1958#[derive(Debug, Clone, Deserialize)]
1959#[serde(rename_all = "camelCase")]
1960pub struct GetTaskInfoParams {
1961    /// Task ID to query
1962    pub task_id: String,
1963}
1964
1965/// Result of getting task info
1966pub type GetTaskInfoResult = TaskInfo;
1967
1968/// Parameters for getting task result
1969#[derive(Debug, Clone, Deserialize)]
1970#[serde(rename_all = "camelCase")]
1971pub struct GetTaskResultParams {
1972    /// Task ID to get result for
1973    pub task_id: String,
1974}
1975
1976/// Result of getting task result
1977#[derive(Debug, Clone, Serialize)]
1978#[serde(rename_all = "camelCase")]
1979pub struct GetTaskResultResult {
1980    /// Task ID
1981    pub task_id: String,
1982    /// Task status
1983    pub status: TaskStatus,
1984    /// The tool call result (if completed)
1985    #[serde(skip_serializing_if = "Option::is_none")]
1986    pub result: Option<CallToolResult>,
1987    /// Error message (if failed)
1988    #[serde(skip_serializing_if = "Option::is_none")]
1989    pub error: Option<String>,
1990}
1991
1992/// Parameters for cancelling a task
1993#[derive(Debug, Clone, Deserialize)]
1994#[serde(rename_all = "camelCase")]
1995pub struct CancelTaskParams {
1996    /// Task ID to cancel
1997    pub task_id: String,
1998    /// Optional reason for cancellation
1999    #[serde(default)]
2000    pub reason: Option<String>,
2001}
2002
2003/// Result of cancelling a task
2004#[derive(Debug, Clone, Serialize)]
2005#[serde(rename_all = "camelCase")]
2006pub struct CancelTaskResult {
2007    /// Whether the cancellation was successful
2008    pub cancelled: bool,
2009    /// Updated task status
2010    pub status: TaskStatus,
2011}
2012
2013/// Notification params when task status changes
2014#[derive(Debug, Clone, Serialize, Deserialize)]
2015#[serde(rename_all = "camelCase")]
2016pub struct TaskStatusChangedParams {
2017    /// Task ID
2018    pub task_id: String,
2019    /// New status
2020    pub status: TaskStatus,
2021    /// Human-readable message
2022    #[serde(skip_serializing_if = "Option::is_none")]
2023    pub message: Option<String>,
2024}
2025
2026// =============================================================================
2027// Elicitation (server-to-client user input requests)
2028// =============================================================================
2029
2030/// Parameters for form-based elicitation request
2031#[derive(Debug, Clone, Serialize, Deserialize)]
2032#[serde(rename_all = "camelCase")]
2033pub struct ElicitFormParams {
2034    /// The elicitation mode
2035    pub mode: ElicitMode,
2036    /// Message to present to the user explaining what information is needed
2037    pub message: String,
2038    /// Schema for the form fields (restricted subset of JSON Schema)
2039    pub requested_schema: ElicitFormSchema,
2040    /// Request metadata including progress token
2041    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
2042    pub meta: Option<RequestMeta>,
2043}
2044
2045/// Parameters for URL-based elicitation request
2046#[derive(Debug, Clone, Serialize, Deserialize)]
2047#[serde(rename_all = "camelCase")]
2048pub struct ElicitUrlParams {
2049    /// The elicitation mode
2050    pub mode: ElicitMode,
2051    /// Unique ID for this elicitation (opaque to client)
2052    pub elicitation_id: String,
2053    /// Message explaining why the user needs to navigate to the URL
2054    pub message: String,
2055    /// The URL the user should navigate to
2056    pub url: String,
2057    /// Request metadata including progress token
2058    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
2059    pub meta: Option<RequestMeta>,
2060}
2061
2062/// Elicitation request parameters (union of form and URL modes)
2063#[derive(Debug, Clone, Serialize, Deserialize)]
2064#[serde(untagged)]
2065pub enum ElicitRequestParams {
2066    Form(ElicitFormParams),
2067    Url(ElicitUrlParams),
2068}
2069
2070/// Elicitation mode
2071#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
2072#[serde(rename_all = "lowercase")]
2073pub enum ElicitMode {
2074    /// Form-based elicitation with structured input
2075    Form,
2076    /// URL-based elicitation (out-of-band)
2077    Url,
2078}
2079
2080/// Restricted JSON Schema for elicitation forms
2081///
2082/// Only allows top-level properties with primitive types.
2083#[derive(Debug, Clone, Serialize, Deserialize)]
2084pub struct ElicitFormSchema {
2085    /// Must be "object"
2086    #[serde(rename = "type")]
2087    pub schema_type: String,
2088    /// Map of property names to their schema definitions
2089    pub properties: std::collections::HashMap<String, PrimitiveSchemaDefinition>,
2090    /// List of required property names
2091    #[serde(default, skip_serializing_if = "Vec::is_empty")]
2092    pub required: Vec<String>,
2093}
2094
2095impl ElicitFormSchema {
2096    /// Create a new form schema
2097    pub fn new() -> Self {
2098        Self {
2099            schema_type: "object".to_string(),
2100            properties: std::collections::HashMap::new(),
2101            required: Vec::new(),
2102        }
2103    }
2104
2105    /// Add a string field
2106    pub fn string_field(mut self, name: &str, description: Option<&str>, required: bool) -> Self {
2107        self.properties.insert(
2108            name.to_string(),
2109            PrimitiveSchemaDefinition::String(StringSchema {
2110                schema_type: "string".to_string(),
2111                description: description.map(|s| s.to_string()),
2112                format: None,
2113                min_length: None,
2114                max_length: None,
2115            }),
2116        );
2117        if required {
2118            self.required.push(name.to_string());
2119        }
2120        self
2121    }
2122
2123    /// Add a number field
2124    pub fn number_field(mut self, name: &str, description: Option<&str>, required: bool) -> Self {
2125        self.properties.insert(
2126            name.to_string(),
2127            PrimitiveSchemaDefinition::Number(NumberSchema {
2128                schema_type: "number".to_string(),
2129                description: description.map(|s| s.to_string()),
2130                minimum: None,
2131                maximum: None,
2132            }),
2133        );
2134        if required {
2135            self.required.push(name.to_string());
2136        }
2137        self
2138    }
2139
2140    /// Add a boolean field
2141    pub fn boolean_field(mut self, name: &str, description: Option<&str>, required: bool) -> Self {
2142        self.properties.insert(
2143            name.to_string(),
2144            PrimitiveSchemaDefinition::Boolean(BooleanSchema {
2145                schema_type: "boolean".to_string(),
2146                description: description.map(|s| s.to_string()),
2147            }),
2148        );
2149        if required {
2150            self.required.push(name.to_string());
2151        }
2152        self
2153    }
2154
2155    /// Add a single-select enum field
2156    pub fn enum_field(
2157        mut self,
2158        name: &str,
2159        description: Option<&str>,
2160        options: Vec<String>,
2161        required: bool,
2162    ) -> Self {
2163        self.properties.insert(
2164            name.to_string(),
2165            PrimitiveSchemaDefinition::SingleSelectEnum(SingleSelectEnumSchema {
2166                schema_type: "string".to_string(),
2167                description: description.map(|s| s.to_string()),
2168                enum_values: options,
2169            }),
2170        );
2171        if required {
2172            self.required.push(name.to_string());
2173        }
2174        self
2175    }
2176}
2177
2178impl Default for ElicitFormSchema {
2179    fn default() -> Self {
2180        Self::new()
2181    }
2182}
2183
2184/// Primitive schema definition for form fields
2185#[derive(Debug, Clone, Serialize, Deserialize)]
2186#[serde(untagged)]
2187pub enum PrimitiveSchemaDefinition {
2188    String(StringSchema),
2189    Number(NumberSchema),
2190    Boolean(BooleanSchema),
2191    SingleSelectEnum(SingleSelectEnumSchema),
2192    MultiSelectEnum(MultiSelectEnumSchema),
2193}
2194
2195/// String field schema
2196#[derive(Debug, Clone, Serialize, Deserialize)]
2197#[serde(rename_all = "camelCase")]
2198pub struct StringSchema {
2199    #[serde(rename = "type")]
2200    pub schema_type: String,
2201    #[serde(skip_serializing_if = "Option::is_none")]
2202    pub description: Option<String>,
2203    #[serde(skip_serializing_if = "Option::is_none")]
2204    pub format: Option<String>,
2205    #[serde(skip_serializing_if = "Option::is_none")]
2206    pub min_length: Option<u64>,
2207    #[serde(skip_serializing_if = "Option::is_none")]
2208    pub max_length: Option<u64>,
2209}
2210
2211/// Number field schema
2212#[derive(Debug, Clone, Serialize, Deserialize)]
2213#[serde(rename_all = "camelCase")]
2214pub struct NumberSchema {
2215    #[serde(rename = "type")]
2216    pub schema_type: String,
2217    #[serde(skip_serializing_if = "Option::is_none")]
2218    pub description: Option<String>,
2219    #[serde(skip_serializing_if = "Option::is_none")]
2220    pub minimum: Option<f64>,
2221    #[serde(skip_serializing_if = "Option::is_none")]
2222    pub maximum: Option<f64>,
2223}
2224
2225/// Boolean field schema
2226#[derive(Debug, Clone, Serialize, Deserialize)]
2227#[serde(rename_all = "camelCase")]
2228pub struct BooleanSchema {
2229    #[serde(rename = "type")]
2230    pub schema_type: String,
2231    #[serde(skip_serializing_if = "Option::is_none")]
2232    pub description: Option<String>,
2233}
2234
2235/// Single-select enum schema
2236#[derive(Debug, Clone, Serialize, Deserialize)]
2237#[serde(rename_all = "camelCase")]
2238pub struct SingleSelectEnumSchema {
2239    #[serde(rename = "type")]
2240    pub schema_type: String,
2241    #[serde(skip_serializing_if = "Option::is_none")]
2242    pub description: Option<String>,
2243    #[serde(rename = "enum")]
2244    pub enum_values: Vec<String>,
2245}
2246
2247/// Multi-select enum schema
2248#[derive(Debug, Clone, Serialize, Deserialize)]
2249#[serde(rename_all = "camelCase")]
2250pub struct MultiSelectEnumSchema {
2251    #[serde(rename = "type")]
2252    pub schema_type: String,
2253    #[serde(skip_serializing_if = "Option::is_none")]
2254    pub description: Option<String>,
2255    pub items: MultiSelectEnumItems,
2256    #[serde(skip_serializing_if = "Option::is_none")]
2257    pub unique_items: Option<bool>,
2258}
2259
2260/// Items definition for multi-select enum
2261#[derive(Debug, Clone, Serialize, Deserialize)]
2262pub struct MultiSelectEnumItems {
2263    #[serde(rename = "type")]
2264    pub schema_type: String,
2265    #[serde(rename = "enum")]
2266    pub enum_values: Vec<String>,
2267}
2268
2269/// User action in response to elicitation
2270#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
2271#[serde(rename_all = "lowercase")]
2272pub enum ElicitAction {
2273    /// User submitted the form/confirmed the action
2274    Accept,
2275    /// User explicitly declined the action
2276    Decline,
2277    /// User dismissed without making an explicit choice
2278    Cancel,
2279}
2280
2281/// Result of an elicitation request
2282#[derive(Debug, Clone, Serialize, Deserialize)]
2283pub struct ElicitResult {
2284    /// The user's action
2285    pub action: ElicitAction,
2286    /// Submitted form data (only present when action is Accept and mode was Form)
2287    #[serde(default, skip_serializing_if = "Option::is_none")]
2288    pub content: Option<std::collections::HashMap<String, ElicitFieldValue>>,
2289}
2290
2291impl ElicitResult {
2292    /// Create an accept result with content
2293    pub fn accept(content: std::collections::HashMap<String, ElicitFieldValue>) -> Self {
2294        Self {
2295            action: ElicitAction::Accept,
2296            content: Some(content),
2297        }
2298    }
2299
2300    /// Create a decline result
2301    pub fn decline() -> Self {
2302        Self {
2303            action: ElicitAction::Decline,
2304            content: None,
2305        }
2306    }
2307
2308    /// Create a cancel result
2309    pub fn cancel() -> Self {
2310        Self {
2311            action: ElicitAction::Cancel,
2312            content: None,
2313        }
2314    }
2315}
2316
2317/// Value from an elicitation form field
2318#[derive(Debug, Clone, Serialize, Deserialize)]
2319#[serde(untagged)]
2320pub enum ElicitFieldValue {
2321    String(String),
2322    Number(f64),
2323    Integer(i64),
2324    Boolean(bool),
2325    StringArray(Vec<String>),
2326}
2327
2328/// Parameters for elicitation complete notification
2329#[derive(Debug, Clone, Serialize, Deserialize)]
2330#[serde(rename_all = "camelCase")]
2331pub struct ElicitationCompleteParams {
2332    /// The ID of the elicitation that completed
2333    pub elicitation_id: String,
2334}
2335
2336// =============================================================================
2337// Common
2338// =============================================================================
2339
2340#[derive(Debug, Clone, Default, Serialize)]
2341pub struct EmptyResult {}
2342
2343// =============================================================================
2344// Parsing
2345// =============================================================================
2346
2347impl McpRequest {
2348    /// Parse from JSON-RPC request
2349    pub fn from_jsonrpc(req: &JsonRpcRequest) -> Result<Self, crate::error::Error> {
2350        let params = req
2351            .params
2352            .clone()
2353            .unwrap_or(Value::Object(Default::default()));
2354
2355        match req.method.as_str() {
2356            "initialize" => {
2357                let p: InitializeParams = serde_json::from_value(params)?;
2358                Ok(McpRequest::Initialize(p))
2359            }
2360            "tools/list" => {
2361                let p: ListToolsParams = serde_json::from_value(params).unwrap_or_default();
2362                Ok(McpRequest::ListTools(p))
2363            }
2364            "tools/call" => {
2365                let p: CallToolParams = serde_json::from_value(params)?;
2366                Ok(McpRequest::CallTool(p))
2367            }
2368            "resources/list" => {
2369                let p: ListResourcesParams = serde_json::from_value(params).unwrap_or_default();
2370                Ok(McpRequest::ListResources(p))
2371            }
2372            "resources/templates/list" => {
2373                let p: ListResourceTemplatesParams =
2374                    serde_json::from_value(params).unwrap_or_default();
2375                Ok(McpRequest::ListResourceTemplates(p))
2376            }
2377            "resources/read" => {
2378                let p: ReadResourceParams = serde_json::from_value(params)?;
2379                Ok(McpRequest::ReadResource(p))
2380            }
2381            "resources/subscribe" => {
2382                let p: SubscribeResourceParams = serde_json::from_value(params)?;
2383                Ok(McpRequest::SubscribeResource(p))
2384            }
2385            "resources/unsubscribe" => {
2386                let p: UnsubscribeResourceParams = serde_json::from_value(params)?;
2387                Ok(McpRequest::UnsubscribeResource(p))
2388            }
2389            "prompts/list" => {
2390                let p: ListPromptsParams = serde_json::from_value(params).unwrap_or_default();
2391                Ok(McpRequest::ListPrompts(p))
2392            }
2393            "prompts/get" => {
2394                let p: GetPromptParams = serde_json::from_value(params)?;
2395                Ok(McpRequest::GetPrompt(p))
2396            }
2397            "tasks/enqueue" => {
2398                let p: EnqueueTaskParams = serde_json::from_value(params)?;
2399                Ok(McpRequest::EnqueueTask(p))
2400            }
2401            "tasks/list" => {
2402                let p: ListTasksParams = serde_json::from_value(params).unwrap_or_default();
2403                Ok(McpRequest::ListTasks(p))
2404            }
2405            "tasks/get" => {
2406                let p: GetTaskInfoParams = serde_json::from_value(params)?;
2407                Ok(McpRequest::GetTaskInfo(p))
2408            }
2409            "tasks/result" => {
2410                let p: GetTaskResultParams = serde_json::from_value(params)?;
2411                Ok(McpRequest::GetTaskResult(p))
2412            }
2413            "tasks/cancel" => {
2414                let p: CancelTaskParams = serde_json::from_value(params)?;
2415                Ok(McpRequest::CancelTask(p))
2416            }
2417            "ping" => Ok(McpRequest::Ping),
2418            "logging/setLevel" => {
2419                let p: SetLogLevelParams = serde_json::from_value(params)?;
2420                Ok(McpRequest::SetLoggingLevel(p))
2421            }
2422            "completion/complete" => {
2423                let p: CompleteParams = serde_json::from_value(params)?;
2424                Ok(McpRequest::Complete(p))
2425            }
2426            method => Ok(McpRequest::Unknown {
2427                method: method.to_string(),
2428                params: req.params.clone(),
2429            }),
2430        }
2431    }
2432}
2433
2434impl McpNotification {
2435    /// Parse from JSON-RPC notification
2436    pub fn from_jsonrpc(notif: &JsonRpcNotification) -> Result<Self, crate::error::Error> {
2437        let params = notif
2438            .params
2439            .clone()
2440            .unwrap_or(Value::Object(Default::default()));
2441
2442        match notif.method.as_str() {
2443            notifications::INITIALIZED => Ok(McpNotification::Initialized),
2444            notifications::CANCELLED => {
2445                let p: CancelledParams = serde_json::from_value(params)?;
2446                Ok(McpNotification::Cancelled(p))
2447            }
2448            notifications::PROGRESS => {
2449                let p: ProgressParams = serde_json::from_value(params)?;
2450                Ok(McpNotification::Progress(p))
2451            }
2452            notifications::ROOTS_LIST_CHANGED => Ok(McpNotification::RootsListChanged),
2453            method => Ok(McpNotification::Unknown {
2454                method: method.to_string(),
2455                params: notif.params.clone(),
2456            }),
2457        }
2458    }
2459}
2460
2461#[cfg(test)]
2462mod tests {
2463    use super::*;
2464
2465    #[test]
2466    fn test_elicit_form_schema_builder() {
2467        let schema = ElicitFormSchema::new()
2468            .string_field("name", Some("Your name"), true)
2469            .number_field("age", Some("Your age"), false)
2470            .boolean_field("agree", Some("Do you agree?"), true)
2471            .enum_field(
2472                "color",
2473                Some("Favorite color"),
2474                vec!["red".to_string(), "green".to_string(), "blue".to_string()],
2475                false,
2476            );
2477
2478        assert_eq!(schema.schema_type, "object");
2479        assert_eq!(schema.properties.len(), 4);
2480        assert_eq!(schema.required.len(), 2);
2481        assert!(schema.required.contains(&"name".to_string()));
2482        assert!(schema.required.contains(&"agree".to_string()));
2483    }
2484
2485    #[test]
2486    fn test_elicit_form_schema_serialization() {
2487        let schema = ElicitFormSchema::new().string_field("username", Some("Enter username"), true);
2488
2489        let json = serde_json::to_value(&schema).unwrap();
2490        assert_eq!(json["type"], "object");
2491        assert!(json["properties"]["username"]["type"] == "string");
2492        assert!(
2493            json["required"]
2494                .as_array()
2495                .unwrap()
2496                .contains(&serde_json::json!("username"))
2497        );
2498    }
2499
2500    #[test]
2501    fn test_elicit_result_accept() {
2502        let mut content = std::collections::HashMap::new();
2503        content.insert(
2504            "name".to_string(),
2505            ElicitFieldValue::String("Alice".to_string()),
2506        );
2507        content.insert("age".to_string(), ElicitFieldValue::Integer(30));
2508
2509        let result = ElicitResult::accept(content);
2510        assert_eq!(result.action, ElicitAction::Accept);
2511        assert!(result.content.is_some());
2512    }
2513
2514    #[test]
2515    fn test_elicit_result_decline() {
2516        let result = ElicitResult::decline();
2517        assert_eq!(result.action, ElicitAction::Decline);
2518        assert!(result.content.is_none());
2519    }
2520
2521    #[test]
2522    fn test_elicit_result_cancel() {
2523        let result = ElicitResult::cancel();
2524        assert_eq!(result.action, ElicitAction::Cancel);
2525        assert!(result.content.is_none());
2526    }
2527
2528    #[test]
2529    fn test_elicit_mode_serialization() {
2530        assert_eq!(
2531            serde_json::to_string(&ElicitMode::Form).unwrap(),
2532            "\"form\""
2533        );
2534        assert_eq!(serde_json::to_string(&ElicitMode::Url).unwrap(), "\"url\"");
2535    }
2536
2537    #[test]
2538    fn test_elicit_action_serialization() {
2539        assert_eq!(
2540            serde_json::to_string(&ElicitAction::Accept).unwrap(),
2541            "\"accept\""
2542        );
2543        assert_eq!(
2544            serde_json::to_string(&ElicitAction::Decline).unwrap(),
2545            "\"decline\""
2546        );
2547        assert_eq!(
2548            serde_json::to_string(&ElicitAction::Cancel).unwrap(),
2549            "\"cancel\""
2550        );
2551    }
2552
2553    #[test]
2554    fn test_elicitation_capability() {
2555        let cap = ElicitationCapability {
2556            form: Some(ElicitationFormCapability {}),
2557            url: None,
2558        };
2559
2560        let json = serde_json::to_value(&cap).unwrap();
2561        assert!(json["form"].is_object());
2562        assert!(json.get("url").is_none());
2563    }
2564
2565    #[test]
2566    fn test_client_capabilities_with_elicitation() {
2567        let caps = ClientCapabilities {
2568            roots: None,
2569            sampling: None,
2570            elicitation: Some(ElicitationCapability {
2571                form: Some(ElicitationFormCapability {}),
2572                url: Some(ElicitationUrlCapability {}),
2573            }),
2574        };
2575
2576        let json = serde_json::to_value(&caps).unwrap();
2577        assert!(json["elicitation"]["form"].is_object());
2578        assert!(json["elicitation"]["url"].is_object());
2579    }
2580
2581    #[test]
2582    fn test_elicit_url_params() {
2583        let params = ElicitUrlParams {
2584            mode: ElicitMode::Url,
2585            elicitation_id: "abc123".to_string(),
2586            message: "Please authorize".to_string(),
2587            url: "https://example.com/auth".to_string(),
2588            meta: None,
2589        };
2590
2591        let json = serde_json::to_value(&params).unwrap();
2592        assert_eq!(json["mode"], "url");
2593        assert_eq!(json["elicitationId"], "abc123");
2594        assert_eq!(json["message"], "Please authorize");
2595        assert_eq!(json["url"], "https://example.com/auth");
2596    }
2597
2598    #[test]
2599    fn test_elicitation_complete_params() {
2600        let params = ElicitationCompleteParams {
2601            elicitation_id: "xyz789".to_string(),
2602        };
2603
2604        let json = serde_json::to_value(&params).unwrap();
2605        assert_eq!(json["elicitationId"], "xyz789");
2606    }
2607
2608    #[test]
2609    fn test_root_new() {
2610        let root = Root::new("file:///home/user/project");
2611        assert_eq!(root.uri, "file:///home/user/project");
2612        assert!(root.name.is_none());
2613    }
2614
2615    #[test]
2616    fn test_root_with_name() {
2617        let root = Root::with_name("file:///home/user/project", "My Project");
2618        assert_eq!(root.uri, "file:///home/user/project");
2619        assert_eq!(root.name.as_deref(), Some("My Project"));
2620    }
2621
2622    #[test]
2623    fn test_root_serialization() {
2624        let root = Root::with_name("file:///workspace", "Workspace");
2625        let json = serde_json::to_value(&root).unwrap();
2626        assert_eq!(json["uri"], "file:///workspace");
2627        assert_eq!(json["name"], "Workspace");
2628    }
2629
2630    #[test]
2631    fn test_root_serialization_without_name() {
2632        let root = Root::new("file:///workspace");
2633        let json = serde_json::to_value(&root).unwrap();
2634        assert_eq!(json["uri"], "file:///workspace");
2635        assert!(json.get("name").is_none());
2636    }
2637
2638    #[test]
2639    fn test_root_deserialization() {
2640        let json = serde_json::json!({
2641            "uri": "file:///home/user",
2642            "name": "Home"
2643        });
2644        let root: Root = serde_json::from_value(json).unwrap();
2645        assert_eq!(root.uri, "file:///home/user");
2646        assert_eq!(root.name.as_deref(), Some("Home"));
2647    }
2648
2649    #[test]
2650    fn test_list_roots_result() {
2651        let result = ListRootsResult {
2652            roots: vec![
2653                Root::new("file:///project1"),
2654                Root::with_name("file:///project2", "Project 2"),
2655            ],
2656        };
2657
2658        let json = serde_json::to_value(&result).unwrap();
2659        let roots = json["roots"].as_array().unwrap();
2660        assert_eq!(roots.len(), 2);
2661        assert_eq!(roots[0]["uri"], "file:///project1");
2662        assert_eq!(roots[1]["name"], "Project 2");
2663    }
2664
2665    #[test]
2666    fn test_roots_capability_serialization() {
2667        let cap = RootsCapability { list_changed: true };
2668        let json = serde_json::to_value(&cap).unwrap();
2669        assert_eq!(json["listChanged"], true);
2670    }
2671
2672    #[test]
2673    fn test_client_capabilities_with_roots() {
2674        let caps = ClientCapabilities {
2675            roots: Some(RootsCapability { list_changed: true }),
2676            sampling: None,
2677            elicitation: None,
2678        };
2679
2680        let json = serde_json::to_value(&caps).unwrap();
2681        assert_eq!(json["roots"]["listChanged"], true);
2682    }
2683
2684    #[test]
2685    fn test_roots_list_changed_notification_parsing() {
2686        let notif = JsonRpcNotification {
2687            jsonrpc: "2.0".to_string(),
2688            method: notifications::ROOTS_LIST_CHANGED.to_string(),
2689            params: None,
2690        };
2691
2692        let mcp_notif = McpNotification::from_jsonrpc(&notif).unwrap();
2693        assert!(matches!(mcp_notif, McpNotification::RootsListChanged));
2694    }
2695
2696    // =========================================================================
2697    // Completion Tests
2698    // =========================================================================
2699
2700    #[test]
2701    fn test_prompt_reference() {
2702        let ref_ = PromptReference::new("my-prompt");
2703        assert_eq!(ref_.ref_type, "ref/prompt");
2704        assert_eq!(ref_.name, "my-prompt");
2705
2706        let json = serde_json::to_value(&ref_).unwrap();
2707        assert_eq!(json["type"], "ref/prompt");
2708        assert_eq!(json["name"], "my-prompt");
2709    }
2710
2711    #[test]
2712    fn test_resource_reference() {
2713        let ref_ = ResourceReference::new("file:///path/to/file");
2714        assert_eq!(ref_.ref_type, "ref/resource");
2715        assert_eq!(ref_.uri, "file:///path/to/file");
2716
2717        let json = serde_json::to_value(&ref_).unwrap();
2718        assert_eq!(json["type"], "ref/resource");
2719        assert_eq!(json["uri"], "file:///path/to/file");
2720    }
2721
2722    #[test]
2723    fn test_completion_reference_prompt() {
2724        let ref_ = CompletionReference::prompt("test-prompt");
2725        let json = serde_json::to_value(&ref_).unwrap();
2726        assert_eq!(json["type"], "ref/prompt");
2727        assert_eq!(json["name"], "test-prompt");
2728    }
2729
2730    #[test]
2731    fn test_completion_reference_resource() {
2732        let ref_ = CompletionReference::resource("file:///test");
2733        let json = serde_json::to_value(&ref_).unwrap();
2734        assert_eq!(json["type"], "ref/resource");
2735        assert_eq!(json["uri"], "file:///test");
2736    }
2737
2738    #[test]
2739    fn test_completion_argument() {
2740        let arg = CompletionArgument::new("query", "SELECT * FROM");
2741        assert_eq!(arg.name, "query");
2742        assert_eq!(arg.value, "SELECT * FROM");
2743    }
2744
2745    #[test]
2746    fn test_complete_params_serialization() {
2747        let params = CompleteParams {
2748            reference: CompletionReference::prompt("sql-prompt"),
2749            argument: CompletionArgument::new("query", "SEL"),
2750        };
2751
2752        let json = serde_json::to_value(&params).unwrap();
2753        assert_eq!(json["ref"]["type"], "ref/prompt");
2754        assert_eq!(json["ref"]["name"], "sql-prompt");
2755        assert_eq!(json["argument"]["name"], "query");
2756        assert_eq!(json["argument"]["value"], "SEL");
2757    }
2758
2759    #[test]
2760    fn test_completion_new() {
2761        let completion = Completion::new(vec!["SELECT".to_string(), "SET".to_string()]);
2762        assert_eq!(completion.values.len(), 2);
2763        assert!(completion.total.is_none());
2764        assert!(completion.has_more.is_none());
2765    }
2766
2767    #[test]
2768    fn test_completion_with_pagination() {
2769        let completion =
2770            Completion::with_pagination(vec!["a".to_string(), "b".to_string()], 100, true);
2771        assert_eq!(completion.values.len(), 2);
2772        assert_eq!(completion.total, Some(100));
2773        assert_eq!(completion.has_more, Some(true));
2774    }
2775
2776    #[test]
2777    fn test_complete_result() {
2778        let result = CompleteResult::new(vec!["option1".to_string(), "option2".to_string()]);
2779        let json = serde_json::to_value(&result).unwrap();
2780        assert!(json["completion"]["values"].is_array());
2781        assert_eq!(json["completion"]["values"][0], "option1");
2782    }
2783
2784    // =========================================================================
2785    // Sampling Tests
2786    // =========================================================================
2787
2788    #[test]
2789    fn test_model_hint() {
2790        let hint = ModelHint::new("claude-3-opus");
2791        assert_eq!(hint.name, "claude-3-opus");
2792    }
2793
2794    #[test]
2795    fn test_model_preferences_builder() {
2796        let prefs = ModelPreferences::new()
2797            .speed(0.8)
2798            .intelligence(0.9)
2799            .cost(0.5)
2800            .hint("gpt-4")
2801            .hint("claude-3");
2802
2803        assert_eq!(prefs.speed_priority, Some(0.8));
2804        assert_eq!(prefs.intelligence_priority, Some(0.9));
2805        assert_eq!(prefs.cost_priority, Some(0.5));
2806        assert_eq!(prefs.hints.len(), 2);
2807    }
2808
2809    #[test]
2810    fn test_model_preferences_clamping() {
2811        let prefs = ModelPreferences::new().speed(1.5).cost(-0.5);
2812
2813        assert_eq!(prefs.speed_priority, Some(1.0)); // Clamped to max
2814        assert_eq!(prefs.cost_priority, Some(0.0)); // Clamped to min
2815    }
2816
2817    #[test]
2818    fn test_include_context_serialization() {
2819        assert_eq!(
2820            serde_json::to_string(&IncludeContext::AllServers).unwrap(),
2821            "\"allServers\""
2822        );
2823        assert_eq!(
2824            serde_json::to_string(&IncludeContext::ThisServer).unwrap(),
2825            "\"thisServer\""
2826        );
2827        assert_eq!(
2828            serde_json::to_string(&IncludeContext::None).unwrap(),
2829            "\"none\""
2830        );
2831    }
2832
2833    #[test]
2834    fn test_sampling_message_user() {
2835        let msg = SamplingMessage::user("Hello, how are you?");
2836        assert_eq!(msg.role, ContentRole::User);
2837        assert!(
2838            matches!(msg.content, SamplingContent::Text { text } if text == "Hello, how are you?")
2839        );
2840    }
2841
2842    #[test]
2843    fn test_sampling_message_assistant() {
2844        let msg = SamplingMessage::assistant("I'm doing well!");
2845        assert_eq!(msg.role, ContentRole::Assistant);
2846    }
2847
2848    #[test]
2849    fn test_sampling_content_text_serialization() {
2850        let content = SamplingContent::Text {
2851            text: "Hello".to_string(),
2852        };
2853        let json = serde_json::to_value(&content).unwrap();
2854        assert_eq!(json["type"], "text");
2855        assert_eq!(json["text"], "Hello");
2856    }
2857
2858    #[test]
2859    fn test_sampling_content_image_serialization() {
2860        let content = SamplingContent::Image {
2861            data: "base64data".to_string(),
2862            mime_type: "image/png".to_string(),
2863        };
2864        let json = serde_json::to_value(&content).unwrap();
2865        assert_eq!(json["type"], "image");
2866        assert_eq!(json["data"], "base64data");
2867        assert_eq!(json["mimeType"], "image/png");
2868    }
2869
2870    #[test]
2871    fn test_create_message_params() {
2872        let params = CreateMessageParams::new(
2873            vec![
2874                SamplingMessage::user("What is 2+2?"),
2875                SamplingMessage::assistant("4"),
2876                SamplingMessage::user("And 3+3?"),
2877            ],
2878            100,
2879        )
2880        .system_prompt("You are a math tutor")
2881        .temperature(0.7)
2882        .stop_sequence("END")
2883        .include_context(IncludeContext::ThisServer);
2884
2885        assert_eq!(params.messages.len(), 3);
2886        assert_eq!(params.max_tokens, 100);
2887        assert_eq!(
2888            params.system_prompt.as_deref(),
2889            Some("You are a math tutor")
2890        );
2891        assert_eq!(params.temperature, Some(0.7));
2892        assert_eq!(params.stop_sequences.len(), 1);
2893        assert_eq!(params.include_context, Some(IncludeContext::ThisServer));
2894    }
2895
2896    #[test]
2897    fn test_create_message_params_serialization() {
2898        let params = CreateMessageParams::new(vec![SamplingMessage::user("Hello")], 50);
2899
2900        let json = serde_json::to_value(&params).unwrap();
2901        assert!(json["messages"].is_array());
2902        assert_eq!(json["maxTokens"], 50);
2903    }
2904
2905    #[test]
2906    fn test_create_message_result_deserialization() {
2907        let json = serde_json::json!({
2908            "content": {
2909                "type": "text",
2910                "text": "The answer is 42"
2911            },
2912            "model": "claude-3-opus",
2913            "role": "assistant",
2914            "stopReason": "end_turn"
2915        });
2916
2917        let result: CreateMessageResult = serde_json::from_value(json).unwrap();
2918        assert_eq!(result.model, "claude-3-opus");
2919        assert_eq!(result.role, ContentRole::Assistant);
2920        assert_eq!(result.stop_reason.as_deref(), Some("end_turn"));
2921    }
2922
2923    #[test]
2924    fn test_completions_capability_serialization() {
2925        let cap = CompletionsCapability {};
2926        let json = serde_json::to_value(&cap).unwrap();
2927        assert!(json.is_object());
2928    }
2929
2930    #[test]
2931    fn test_server_capabilities_with_completions() {
2932        let caps = ServerCapabilities {
2933            completions: Some(CompletionsCapability {}),
2934            ..Default::default()
2935        };
2936
2937        let json = serde_json::to_value(&caps).unwrap();
2938        assert!(json["completions"].is_object());
2939    }
2940
2941    #[test]
2942    fn test_content_resource_link_serialization() {
2943        let content = Content::ResourceLink {
2944            uri: "file:///test.txt".to_string(),
2945            name: Some("test.txt".to_string()),
2946            description: Some("A test file".to_string()),
2947            mime_type: Some("text/plain".to_string()),
2948            annotations: None,
2949        };
2950        let json = serde_json::to_value(&content).unwrap();
2951        assert_eq!(json["type"], "resource_link");
2952        assert_eq!(json["uri"], "file:///test.txt");
2953        assert_eq!(json["name"], "test.txt");
2954        assert_eq!(json["description"], "A test file");
2955        assert_eq!(json["mimeType"], "text/plain");
2956    }
2957
2958    #[test]
2959    fn test_call_tool_result_resource_link() {
2960        let result = CallToolResult::resource_link("file:///output.json");
2961        assert_eq!(result.content.len(), 1);
2962        assert!(!result.is_error);
2963        match &result.content[0] {
2964            Content::ResourceLink { uri, .. } => assert_eq!(uri, "file:///output.json"),
2965            _ => panic!("Expected ResourceLink content"),
2966        }
2967    }
2968
2969    #[test]
2970    fn test_call_tool_result_image() {
2971        let result = CallToolResult::image("base64data", "image/png");
2972        assert_eq!(result.content.len(), 1);
2973        match &result.content[0] {
2974            Content::Image {
2975                data, mime_type, ..
2976            } => {
2977                assert_eq!(data, "base64data");
2978                assert_eq!(mime_type, "image/png");
2979            }
2980            _ => panic!("Expected Image content"),
2981        }
2982    }
2983
2984    #[test]
2985    fn test_call_tool_result_audio() {
2986        let result = CallToolResult::audio("audiodata", "audio/wav");
2987        assert_eq!(result.content.len(), 1);
2988        match &result.content[0] {
2989            Content::Audio {
2990                data, mime_type, ..
2991            } => {
2992                assert_eq!(data, "audiodata");
2993                assert_eq!(mime_type, "audio/wav");
2994            }
2995            _ => panic!("Expected Audio content"),
2996        }
2997    }
2998}