Skip to main content

model_context_protocol/
protocol.rs

1//! MCP JSON-RPC Protocol Types
2//!
3//! This module defines the core JSON-RPC 2.0 protocol types used for
4//! communicating with Model Context Protocol (MCP) servers.
5
6use serde::{Deserialize, Serialize};
7use serde_json::Value;
8use std::fmt;
9
10// Re-export protocol version from lib.rs
11pub use crate::MCP_PROTOCOL_VERSION;
12
13/// JSON-RPC 2.0 Request
14#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct JsonRpcRequest {
16    pub jsonrpc: String,
17    pub id: JsonRpcId,
18    pub method: String,
19    #[serde(skip_serializing_if = "Option::is_none")]
20    pub params: Option<Value>,
21}
22
23impl JsonRpcRequest {
24    pub fn new(id: JsonRpcId, method: impl Into<String>, params: Option<Value>) -> Self {
25        Self {
26            jsonrpc: "2.0".to_string(),
27            id,
28            method: method.into(),
29            params,
30        }
31    }
32}
33
34/// JSON-RPC 2.0 Response
35#[derive(Debug, Clone, Serialize, Deserialize)]
36pub struct JsonRpcResponse {
37    pub jsonrpc: String,
38    pub id: JsonRpcId,
39    #[serde(flatten)]
40    pub payload: JsonRpcPayload,
41}
42
43impl JsonRpcResponse {
44    /// Create a success response.
45    pub fn success(id: impl Into<JsonRpcId>, result: Value) -> Self {
46        Self {
47            jsonrpc: "2.0".to_string(),
48            id: id.into(),
49            payload: JsonRpcPayload::Success { result },
50        }
51    }
52
53    /// Create an error response.
54    pub fn error(
55        id: impl Into<JsonRpcId>,
56        code: i32,
57        message: impl Into<String>,
58        data: Option<Value>,
59    ) -> Self {
60        Self {
61            jsonrpc: "2.0".to_string(),
62            id: id.into(),
63            payload: JsonRpcPayload::Error {
64                error: JsonRpcError {
65                    code,
66                    message: message.into(),
67                    data,
68                },
69            },
70        }
71    }
72
73    /// Get the result if this is a success response.
74    pub fn result(&self) -> Option<&Value> {
75        match &self.payload {
76            JsonRpcPayload::Success { result } => Some(result),
77            JsonRpcPayload::Error { .. } => None,
78        }
79    }
80
81    /// Returns true if this is a success response.
82    pub fn is_success(&self) -> bool {
83        matches!(&self.payload, JsonRpcPayload::Success { .. })
84    }
85
86    /// Returns true if this is an error response.
87    pub fn is_error(&self) -> bool {
88        matches!(&self.payload, JsonRpcPayload::Error { .. })
89    }
90
91    /// Get the error if this is an error response.
92    pub fn error_info(&self) -> Option<&JsonRpcError> {
93        match &self.payload {
94            JsonRpcPayload::Success { .. } => None,
95            JsonRpcPayload::Error { error } => Some(error),
96        }
97    }
98}
99
100/// JSON-RPC 2.0 Notification (no id, no response expected)
101#[derive(Debug, Clone, Serialize, Deserialize)]
102pub struct JsonRpcNotification {
103    pub jsonrpc: String,
104    pub method: String,
105    #[serde(skip_serializing_if = "Option::is_none")]
106    pub params: Option<Value>,
107}
108
109impl JsonRpcNotification {
110    /// Create a new notification.
111    pub fn new(method: impl Into<String>, params: Option<Value>) -> Self {
112        Self {
113            jsonrpc: "2.0".to_string(),
114            method: method.into(),
115            params,
116        }
117    }
118}
119
120/// Outbound message from server to client.
121#[derive(Debug, Clone)]
122pub enum ServerOutbound {
123    /// A request that expects a response from the client.
124    Request(JsonRpcRequest),
125    /// A notification that does not expect a response.
126    Notification(JsonRpcNotification),
127    /// A response to a client request.
128    Response(JsonRpcResponse),
129}
130
131impl ServerOutbound {
132    /// Serialize to JSON string.
133    pub fn to_json(&self) -> Result<String, serde_json::Error> {
134        match self {
135            ServerOutbound::Request(r) => serde_json::to_string(r),
136            ServerOutbound::Notification(n) => serde_json::to_string(n),
137            ServerOutbound::Response(r) => serde_json::to_string(r),
138        }
139    }
140}
141
142/// Inbound message from client to server.
143#[derive(Debug, Clone)]
144pub enum ClientInbound {
145    /// A request from the client that expects a response.
146    Request(JsonRpcRequest),
147    /// A response to a server request.
148    Response(JsonRpcResponse),
149    /// A notification from the client.
150    Notification(JsonRpcNotification),
151}
152
153/// A JSON-RPC message that can be any of request, response, or notification.
154/// Used for parsing incoming messages when the type is unknown.
155#[derive(Debug, Clone, Serialize, Deserialize)]
156#[serde(untagged)]
157pub enum JsonRpcMessage {
158    Request(JsonRpcRequest),
159    Response(JsonRpcResponse),
160    Notification(JsonRpcNotification),
161}
162
163impl JsonRpcMessage {
164    /// Parse a JSON string into a message.
165    pub fn parse(s: &str) -> Result<Self, serde_json::Error> {
166        serde_json::from_str(s)
167    }
168
169    /// Convert to ClientInbound for server processing.
170    pub fn into_client_inbound(self) -> ClientInbound {
171        match self {
172            JsonRpcMessage::Request(r) => ClientInbound::Request(r),
173            JsonRpcMessage::Response(r) => ClientInbound::Response(r),
174            JsonRpcMessage::Notification(n) => ClientInbound::Notification(n),
175        }
176    }
177}
178
179#[derive(Debug, Clone, Serialize, Deserialize)]
180#[serde(untagged)]
181pub enum JsonRpcPayload {
182    Success { result: Value },
183    Error { error: JsonRpcError },
184}
185
186/// JSON-RPC 2.0 Error
187#[derive(Debug, Clone, Serialize, Deserialize)]
188pub struct JsonRpcError {
189    pub code: i32,
190    pub message: String,
191    #[serde(skip_serializing_if = "Option::is_none")]
192    pub data: Option<Value>,
193}
194
195impl fmt::Display for JsonRpcError {
196    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
197        write!(f, "JSON-RPC Error {}: {}", self.code, self.message)
198    }
199}
200
201impl std::error::Error for JsonRpcError {}
202
203/// Standard JSON-RPC error codes
204pub mod error_codes {
205    /// Invalid JSON was received by the server
206    pub const PARSE_ERROR: i32 = -32700;
207    /// The JSON sent is not a valid Request object
208    pub const INVALID_REQUEST: i32 = -32600;
209    /// The method does not exist / is not available
210    pub const METHOD_NOT_FOUND: i32 = -32601;
211    /// Invalid method parameter(s)
212    pub const INVALID_PARAMS: i32 = -32602;
213    /// Internal JSON-RPC error
214    pub const INTERNAL_ERROR: i32 = -32603;
215    /// URL elicitation required (implementation-specific)
216    pub const URL_ELICITATION_REQUIRED: i32 = -32042;
217}
218
219// =============================================================================
220// Core Types (2025-11-25)
221// =============================================================================
222
223/// An optionally-sized icon that can be displayed in a user interface.
224#[derive(Debug, Clone, Serialize, Deserialize)]
225pub struct Icon {
226    /// A standard URI pointing to an icon resource.
227    /// May be an HTTP/HTTPS URL or a `data:` URI with Base64-encoded image data.
228    pub src: String,
229
230    /// Optional MIME type override if the source MIME type is missing or generic.
231    #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
232    pub mime_type: Option<String>,
233
234    /// Optional array of strings that specify sizes at which the icon can be used.
235    /// Each string should be in WxH format (e.g., "48x48", "96x96") or "any" for scalable formats.
236    #[serde(skip_serializing_if = "Option::is_none")]
237    pub sizes: Option<Vec<String>>,
238
239    /// Optional specifier for the theme this icon is designed for.
240    #[serde(skip_serializing_if = "Option::is_none")]
241    pub theme: Option<IconTheme>,
242}
243
244/// Theme specifier for an icon.
245#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
246#[serde(rename_all = "snake_case")]
247pub enum IconTheme {
248    Light,
249    Dark,
250}
251
252/// Base metadata with name (identifier) and title (display name) properties.
253#[derive(Debug, Clone, Serialize, Deserialize)]
254pub struct BaseMetadata {
255    /// Intended for programmatic or logical use.
256    pub name: String,
257
258    /// Intended for UI and end-user contexts — optimized to be human-readable.
259    #[serde(skip_serializing_if = "Option::is_none")]
260    pub title: Option<String>,
261}
262
263/// Optional annotations for the client.
264#[derive(Debug, Clone, Serialize, Deserialize, Default)]
265pub struct Annotations {
266    /// Describes who the intended audience of this object or data is.
267    #[serde(skip_serializing_if = "Option::is_none")]
268    pub audience: Option<Vec<Role>>,
269
270    /// Describes how important this data is (0.0 = least, 1.0 = most important).
271    #[serde(skip_serializing_if = "Option::is_none")]
272    pub priority: Option<f64>,
273
274    /// The moment the resource was last modified, as an ISO 8601 formatted string.
275    #[serde(rename = "lastModified", skip_serializing_if = "Option::is_none")]
276    pub last_modified: Option<String>,
277}
278
279/// The sender or recipient of messages and data in a conversation.
280#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
281#[serde(rename_all = "snake_case")]
282pub enum Role {
283    User,
284    Assistant,
285}
286
287// =============================================================================
288// MCP Server Types
289// =============================================================================
290
291/// MCP Implementation info (server or client).
292/// Describes the MCP implementation with name, version, icons, and description.
293#[derive(Debug, Clone, Serialize, Deserialize)]
294pub struct Implementation {
295    /// Intended for programmatic or logical use.
296    pub name: String,
297
298    /// The version of the implementation.
299    pub version: String,
300
301    /// Intended for UI and end-user contexts — optimized to be human-readable.
302    #[serde(skip_serializing_if = "Option::is_none")]
303    pub title: Option<String>,
304
305    /// An optional human-readable description of what this implementation does.
306    #[serde(skip_serializing_if = "Option::is_none")]
307    pub description: Option<String>,
308
309    /// Optional set of sized icons that the client can display.
310    #[serde(skip_serializing_if = "Option::is_none")]
311    pub icons: Option<Vec<Icon>>,
312
313    /// An optional URL of the website for this implementation.
314    #[serde(rename = "websiteUrl", skip_serializing_if = "Option::is_none")]
315    pub website_url: Option<String>,
316}
317
318/// MCP server information (legacy alias for Implementation).
319pub type McpServerInfo = Implementation;
320
321/// MCP server capabilities (legacy format).
322#[derive(Debug, Clone, Serialize, Deserialize, Default)]
323pub struct McpCapabilities {
324    #[serde(skip_serializing_if = "Option::is_none")]
325    pub tools: Option<Value>,
326    #[serde(skip_serializing_if = "Option::is_none")]
327    pub resources: Option<Value>,
328    #[serde(skip_serializing_if = "Option::is_none")]
329    pub prompts: Option<Value>,
330    #[serde(skip_serializing_if = "Option::is_none")]
331    pub logging: Option<Value>,
332    #[serde(skip_serializing_if = "Option::is_none")]
333    pub completions: Option<Value>,
334    #[serde(skip_serializing_if = "Option::is_none")]
335    pub elicitation: Option<Value>,
336    #[serde(skip_serializing_if = "Option::is_none")]
337    pub tasks: Option<Value>,
338    #[serde(skip_serializing_if = "Option::is_none")]
339    pub experimental: Option<Value>,
340}
341
342// =============================================================================
343// JSON-RPC ID
344// =============================================================================
345
346/// JSON-RPC ID can be string, number, or null
347#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
348#[serde(untagged)]
349pub enum JsonRpcId {
350    String(String),
351    Number(i64),
352    Null,
353}
354
355impl From<i64> for JsonRpcId {
356    fn from(n: i64) -> Self {
357        JsonRpcId::Number(n)
358    }
359}
360
361impl From<String> for JsonRpcId {
362    fn from(s: String) -> Self {
363        JsonRpcId::String(s)
364    }
365}
366
367impl From<&str> for JsonRpcId {
368    fn from(s: &str) -> Self {
369        JsonRpcId::String(s.to_string())
370    }
371}
372
373impl From<Value> for JsonRpcId {
374    fn from(v: Value) -> Self {
375        match v {
376            Value::String(s) => JsonRpcId::String(s),
377            Value::Number(n) => JsonRpcId::Number(n.as_i64().unwrap_or(0)),
378            Value::Null => JsonRpcId::Null,
379            _ => JsonRpcId::Null,
380        }
381    }
382}
383
384impl From<JsonRpcId> for Value {
385    fn from(id: JsonRpcId) -> Self {
386        match id {
387            JsonRpcId::String(s) => Value::String(s),
388            JsonRpcId::Number(n) => Value::Number(n.into()),
389            JsonRpcId::Null => Value::Null,
390        }
391    }
392}
393
394impl fmt::Display for JsonRpcId {
395    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
396        match self {
397            JsonRpcId::String(s) => write!(f, "{}", s),
398            JsonRpcId::Number(n) => write!(f, "{}", n),
399            JsonRpcId::Null => write!(f, "null"),
400        }
401    }
402}
403
404// =============================================================================
405// MCP Tool Types
406// =============================================================================
407
408/// Additional properties describing a Tool to clients.
409/// NOTE: all properties in ToolAnnotations are **hints**.
410#[derive(Debug, Clone, Serialize, Deserialize, Default)]
411pub struct ToolAnnotations {
412    /// A human-readable title for the tool.
413    #[serde(skip_serializing_if = "Option::is_none")]
414    pub title: Option<String>,
415
416    /// If true, the tool does not modify its environment. Default: false
417    #[serde(rename = "readOnlyHint", skip_serializing_if = "Option::is_none")]
418    pub read_only_hint: Option<bool>,
419
420    /// If true, the tool may perform destructive updates. Default: true
421    #[serde(rename = "destructiveHint", skip_serializing_if = "Option::is_none")]
422    pub destructive_hint: Option<bool>,
423
424    /// If true, calling the tool repeatedly with the same arguments has no additional effect. Default: false
425    #[serde(rename = "idempotentHint", skip_serializing_if = "Option::is_none")]
426    pub idempotent_hint: Option<bool>,
427
428    /// If true, this tool may interact with an "open world" of external entities. Default: true
429    #[serde(rename = "openWorldHint", skip_serializing_if = "Option::is_none")]
430    pub open_world_hint: Option<bool>,
431}
432
433/// Indicates whether a tool supports task-augmented execution.
434#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
435#[serde(rename_all = "snake_case")]
436pub enum TaskSupport {
437    /// Tool does not support task-augmented execution (default)
438    #[default]
439    Forbidden,
440    /// Tool may support task-augmented execution
441    Optional,
442    /// Tool requires task-augmented execution
443    Required,
444}
445
446/// Execution-related properties for a tool.
447#[derive(Debug, Clone, Serialize, Deserialize, Default)]
448pub struct ToolExecution {
449    /// Indicates whether this tool supports task-augmented execution.
450    #[serde(rename = "taskSupport", skip_serializing_if = "Option::is_none")]
451    pub task_support: Option<TaskSupport>,
452}
453
454/// MCP Tool Definition (from tools/list response)
455#[derive(Debug, Clone, Serialize, Deserialize)]
456pub struct McpToolDefinition {
457    pub name: String,
458
459    /// Intended for UI and end-user contexts — optimized to be human-readable.
460    #[serde(skip_serializing_if = "Option::is_none")]
461    pub title: Option<String>,
462
463    #[serde(skip_serializing_if = "Option::is_none")]
464    pub description: Option<String>,
465
466    #[serde(skip_serializing_if = "Option::is_none")]
467    pub group: Option<String>,
468
469    /// Optional set of sized icons that the client can display.
470    #[serde(skip_serializing_if = "Option::is_none")]
471    pub icons: Option<Vec<Icon>>,
472
473    #[serde(rename = "inputSchema", default = "default_input_schema")]
474    pub input_schema: Value,
475
476    /// An optional JSON Schema object defining the structure of the tool's output.
477    #[serde(rename = "outputSchema", skip_serializing_if = "Option::is_none")]
478    pub output_schema: Option<Value>,
479
480    /// Execution-related properties for this tool.
481    #[serde(skip_serializing_if = "Option::is_none")]
482    pub execution: Option<ToolExecution>,
483
484    /// Optional additional tool information.
485    #[serde(skip_serializing_if = "Option::is_none")]
486    pub annotations: Option<ToolAnnotations>,
487
488    /// See General fields: `_meta` for notes on `_meta` usage.
489    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
490    pub meta: Option<Value>,
491}
492
493fn default_input_schema() -> Value {
494    serde_json::json!({"type": "object"})
495}
496
497impl McpToolDefinition {
498    /// Create a new tool definition.
499    pub fn new(name: impl Into<String>) -> Self {
500        Self {
501            name: name.into(),
502            title: None,
503            description: None,
504            group: None,
505            icons: None,
506            input_schema: default_input_schema(),
507            output_schema: None,
508            execution: None,
509            annotations: None,
510            meta: None,
511        }
512    }
513
514    /// Set the title.
515    pub fn with_title(mut self, title: impl Into<String>) -> Self {
516        self.title = Some(title.into());
517        self
518    }
519
520    /// Set the group.
521    pub fn with_group(mut self, group: impl Into<String>) -> Self {
522        self.group = Some(group.into());
523        self
524    }
525
526    /// Set the description.
527    pub fn with_description(mut self, desc: impl Into<String>) -> Self {
528        self.description = Some(desc.into());
529        self
530    }
531
532    /// Set the input schema.
533    pub fn with_schema(mut self, schema: Value) -> Self {
534        self.input_schema = schema;
535        self
536    }
537
538    /// Set the output schema.
539    pub fn with_output_schema(mut self, schema: Value) -> Self {
540        self.output_schema = Some(schema);
541        self
542    }
543
544    /// Set the annotations.
545    pub fn with_annotations(mut self, annotations: ToolAnnotations) -> Self {
546        self.annotations = Some(annotations);
547        self
548    }
549
550    /// Set the execution properties.
551    pub fn with_execution(mut self, execution: ToolExecution) -> Self {
552        self.execution = Some(execution);
553        self
554    }
555
556    /// Get the description, defaulting to empty string.
557    pub fn description_or_default(&self) -> &str {
558        self.description.as_deref().unwrap_or("")
559    }
560
561    /// Get a copy of the input schema as parameters value.
562    pub fn parameters(&self) -> Value {
563        self.input_schema.clone()
564    }
565}
566
567/// JSON Schema for tool inputs (legacy format)
568#[derive(Debug, Clone, Serialize, Deserialize, Default)]
569pub struct ToolInputSchema {
570    #[serde(rename = "type")]
571    pub schema_type: String,
572    #[serde(skip_serializing_if = "Option::is_none")]
573    pub properties: Option<Value>,
574    #[serde(skip_serializing_if = "Option::is_none")]
575    pub required: Option<Vec<String>>,
576}
577
578/// MCP tools/list request parameters
579#[derive(Debug, Clone, Serialize, Deserialize, Default)]
580pub struct ListToolsParams {
581    #[serde(skip_serializing_if = "Option::is_none")]
582    pub cursor: Option<String>,
583}
584
585/// MCP tools/list response
586#[derive(Debug, Clone, Serialize, Deserialize)]
587pub struct ListToolsResult {
588    pub tools: Vec<McpToolDefinition>,
589    #[serde(skip_serializing_if = "Option::is_none")]
590    pub next_cursor: Option<String>,
591}
592
593/// MCP tools/call request parameters
594#[derive(Debug, Clone, Serialize, Deserialize)]
595pub struct CallToolParams {
596    pub name: String,
597    #[serde(skip_serializing_if = "Option::is_none")]
598    pub arguments: Option<Value>,
599    /// If specified, the caller is requesting task-augmented execution.
600    #[serde(skip_serializing_if = "Option::is_none")]
601    pub task: Option<TaskMetadata>,
602    /// Request metadata.
603    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
604    pub meta: Option<Value>,
605}
606
607/// MCP tools/call response
608#[derive(Debug, Clone, Serialize, Deserialize)]
609pub struct CallToolResult {
610    /// A list of content objects that represent the unstructured result of the tool call.
611    #[serde(default)]
612    pub content: Vec<ToolContent>,
613    /// An optional JSON object that represents the structured result of the tool call.
614    #[serde(rename = "structuredContent", skip_serializing_if = "Option::is_none")]
615    pub structured_content: Option<Value>,
616    /// Whether the tool call ended in an error.
617    #[serde(rename = "isError", skip_serializing_if = "Option::is_none")]
618    pub is_error: Option<bool>,
619}
620
621/// Tool execution content (text, image, audio, or resource types)
622#[derive(Debug, Clone, Serialize, Deserialize)]
623#[serde(tag = "type")]
624pub enum ToolContent {
625    #[serde(rename = "text")]
626    Text {
627        text: String,
628        #[serde(skip_serializing_if = "Option::is_none")]
629        annotations: Option<Annotations>,
630        #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
631        meta: Option<Value>,
632    },
633    #[serde(rename = "image")]
634    Image {
635        data: String,
636        #[serde(rename = "mimeType")]
637        mime_type: String,
638        #[serde(skip_serializing_if = "Option::is_none")]
639        annotations: Option<Annotations>,
640        #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
641        meta: Option<Value>,
642    },
643    #[serde(rename = "audio")]
644    Audio {
645        data: String,
646        #[serde(rename = "mimeType")]
647        mime_type: String,
648        #[serde(skip_serializing_if = "Option::is_none")]
649        annotations: Option<Annotations>,
650        #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
651        meta: Option<Value>,
652    },
653    #[serde(rename = "resource")]
654    Resource {
655        uri: String,
656        #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
657        mime_type: Option<String>,
658    },
659    #[serde(rename = "resource_link")]
660    ResourceLink {
661        uri: String,
662        name: String,
663        #[serde(skip_serializing_if = "Option::is_none")]
664        title: Option<String>,
665        #[serde(skip_serializing_if = "Option::is_none")]
666        description: Option<String>,
667        #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
668        mime_type: Option<String>,
669        #[serde(skip_serializing_if = "Option::is_none")]
670        annotations: Option<Annotations>,
671    },
672}
673
674impl ToolContent {
675    /// Create a text content item.
676    pub fn text(text: impl Into<String>) -> Self {
677        Self::Text {
678            text: text.into(),
679            annotations: None,
680            meta: None,
681        }
682    }
683
684    /// Create an image content item.
685    pub fn image(data: impl Into<String>, mime_type: impl Into<String>) -> Self {
686        Self::Image {
687            data: data.into(),
688            mime_type: mime_type.into(),
689            annotations: None,
690            meta: None,
691        }
692    }
693
694    /// Create an audio content item.
695    pub fn audio(data: impl Into<String>, mime_type: impl Into<String>) -> Self {
696        Self::Audio {
697            data: data.into(),
698            mime_type: mime_type.into(),
699            annotations: None,
700            meta: None,
701        }
702    }
703
704    /// Create a resource content item.
705    pub fn resource(uri: impl Into<String>, mime_type: Option<String>) -> Self {
706        Self::Resource {
707            uri: uri.into(),
708            mime_type,
709        }
710    }
711
712    /// Get text content if this is a text item.
713    pub fn as_text(&self) -> Option<&str> {
714        match self {
715            Self::Text { text, .. } => Some(text),
716            _ => None,
717        }
718    }
719
720    /// Check if this is a text item.
721    pub fn is_text(&self) -> bool {
722        matches!(self, Self::Text { .. })
723    }
724}
725
726// =============================================================================
727// Tasks Subsystem (2025-11-25)
728// =============================================================================
729
730/// The status of a task.
731#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
732#[serde(rename_all = "snake_case")]
733pub enum TaskStatus {
734    /// The request is currently being processed
735    Working,
736    /// The task is waiting for input (e.g., elicitation or sampling)
737    InputRequired,
738    /// The request completed successfully and results are available
739    Completed,
740    /// The request did not complete successfully
741    Failed,
742    /// The request was cancelled before completion
743    Cancelled,
744}
745
746/// Metadata for augmenting a request with task execution.
747#[derive(Debug, Clone, Serialize, Deserialize, Default)]
748pub struct TaskMetadata {
749    /// Requested duration in milliseconds to retain task from creation.
750    #[serde(skip_serializing_if = "Option::is_none")]
751    pub ttl: Option<u64>,
752}
753
754/// Metadata for associating messages with a task.
755#[derive(Debug, Clone, Serialize, Deserialize)]
756pub struct RelatedTaskMetadata {
757    /// The task identifier this message is associated with.
758    #[serde(rename = "taskId")]
759    pub task_id: String,
760}
761
762/// Data associated with a task.
763#[derive(Debug, Clone, Serialize, Deserialize)]
764pub struct Task {
765    /// The task identifier.
766    #[serde(rename = "taskId")]
767    pub task_id: String,
768
769    /// Current task state.
770    pub status: TaskStatus,
771
772    /// Optional human-readable message describing the current task state.
773    #[serde(rename = "statusMessage", skip_serializing_if = "Option::is_none")]
774    pub status_message: Option<String>,
775
776    /// ISO 8601 timestamp when the task was created.
777    #[serde(rename = "createdAt")]
778    pub created_at: String,
779
780    /// ISO 8601 timestamp when the task was last updated.
781    #[serde(rename = "lastUpdatedAt")]
782    pub last_updated_at: String,
783
784    /// Actual retention duration from creation in milliseconds, null for unlimited.
785    pub ttl: Option<u64>,
786
787    /// Suggested polling interval in milliseconds.
788    #[serde(rename = "pollInterval", skip_serializing_if = "Option::is_none")]
789    pub poll_interval: Option<u64>,
790}
791
792/// A response to a task-augmented request.
793#[derive(Debug, Clone, Serialize, Deserialize)]
794pub struct CreateTaskResult {
795    pub task: Task,
796}
797
798/// Parameters for tasks/get request.
799#[derive(Debug, Clone, Serialize, Deserialize)]
800pub struct GetTaskParams {
801    /// The task identifier to query.
802    #[serde(rename = "taskId")]
803    pub task_id: String,
804}
805
806/// Parameters for tasks/result request.
807#[derive(Debug, Clone, Serialize, Deserialize)]
808pub struct GetTaskPayloadParams {
809    /// The task identifier to retrieve results for.
810    #[serde(rename = "taskId")]
811    pub task_id: String,
812}
813
814/// Parameters for tasks/cancel request.
815#[derive(Debug, Clone, Serialize, Deserialize)]
816pub struct CancelTaskParams {
817    /// The task identifier to cancel.
818    #[serde(rename = "taskId")]
819    pub task_id: String,
820}
821
822/// Parameters for tasks/list request.
823#[derive(Debug, Clone, Serialize, Deserialize, Default)]
824pub struct ListTasksParams {
825    /// An opaque token representing the current pagination position.
826    #[serde(skip_serializing_if = "Option::is_none")]
827    pub cursor: Option<String>,
828}
829
830/// Response to a tasks/list request.
831#[derive(Debug, Clone, Serialize, Deserialize)]
832pub struct ListTasksResult {
833    pub tasks: Vec<Task>,
834    #[serde(rename = "nextCursor", skip_serializing_if = "Option::is_none")]
835    pub next_cursor: Option<String>,
836}
837
838/// Parameters for notifications/tasks/status notification.
839#[derive(Debug, Clone, Serialize, Deserialize)]
840pub struct TaskStatusNotificationParams {
841    /// The task identifier.
842    #[serde(rename = "taskId")]
843    pub task_id: String,
844
845    /// Current task state.
846    pub status: TaskStatus,
847
848    /// Optional human-readable message describing the current task state.
849    #[serde(rename = "statusMessage", skip_serializing_if = "Option::is_none")]
850    pub status_message: Option<String>,
851
852    /// ISO 8601 timestamp when the task was created.
853    #[serde(rename = "createdAt")]
854    pub created_at: String,
855
856    /// ISO 8601 timestamp when the task was last updated.
857    #[serde(rename = "lastUpdatedAt")]
858    pub last_updated_at: String,
859
860    /// Actual retention duration from creation in milliseconds.
861    pub ttl: Option<u64>,
862
863    /// Suggested polling interval in milliseconds.
864    #[serde(rename = "pollInterval", skip_serializing_if = "Option::is_none")]
865    pub poll_interval: Option<u64>,
866}
867
868// =============================================================================
869// Elicitation Subsystem (2025-11-25)
870// =============================================================================
871
872/// Parameters for elicitation/create request with form mode.
873#[derive(Debug, Clone, Serialize, Deserialize)]
874pub struct ElicitRequestFormParams {
875    /// The elicitation mode.
876    #[serde(skip_serializing_if = "Option::is_none")]
877    pub mode: Option<String>,
878
879    /// The message to present to the user describing what information is being requested.
880    pub message: String,
881
882    /// A restricted subset of JSON Schema for the form fields.
883    #[serde(rename = "requestedSchema")]
884    pub requested_schema: Value,
885
886    /// Task metadata if requesting task-augmented execution.
887    #[serde(skip_serializing_if = "Option::is_none")]
888    pub task: Option<TaskMetadata>,
889
890    /// Request metadata.
891    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
892    pub meta: Option<Value>,
893}
894
895/// Parameters for elicitation/create request with URL mode.
896#[derive(Debug, Clone, Serialize, Deserialize)]
897pub struct ElicitRequestUrlParams {
898    /// The elicitation mode.
899    pub mode: String,
900
901    /// The message to present to the user explaining why the interaction is needed.
902    pub message: String,
903
904    /// The ID of the elicitation, which must be unique within the context of the server.
905    #[serde(rename = "elicitationId")]
906    pub elicitation_id: String,
907
908    /// The URL that the user should navigate to.
909    pub url: String,
910
911    /// Task metadata if requesting task-augmented execution.
912    #[serde(skip_serializing_if = "Option::is_none")]
913    pub task: Option<TaskMetadata>,
914
915    /// Request metadata.
916    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
917    pub meta: Option<Value>,
918}
919
920/// Parameters for elicitation/create request.
921#[derive(Debug, Clone, Serialize, Deserialize)]
922#[serde(untagged)]
923pub enum ElicitRequestParams {
924    Form(ElicitRequestFormParams),
925    Url(ElicitRequestUrlParams),
926}
927
928/// User action in response to an elicitation.
929#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
930#[serde(rename_all = "snake_case")]
931pub enum ElicitAction {
932    /// User submitted the form/confirmed the action
933    Accept,
934    /// User explicitly declined the action
935    Decline,
936    /// User dismissed without making an explicit choice
937    Cancel,
938}
939
940/// The client's response to an elicitation request.
941#[derive(Debug, Clone, Serialize, Deserialize)]
942pub struct ElicitResult {
943    /// The user action in response to the elicitation.
944    pub action: ElicitAction,
945
946    /// The submitted form data, only present when action is "accept" and mode was "form".
947    #[serde(skip_serializing_if = "Option::is_none")]
948    pub content: Option<Value>,
949}
950
951/// Parameters for notifications/elicitation/complete notification.
952#[derive(Debug, Clone, Serialize, Deserialize)]
953pub struct ElicitationCompleteParams {
954    /// The ID of the elicitation that completed.
955    #[serde(rename = "elicitationId")]
956    pub elicitation_id: String,
957}
958
959// =============================================================================
960// Primitive Schema Definitions for Elicitation (2025-11-25)
961// =============================================================================
962
963/// String schema for elicitation forms.
964#[derive(Debug, Clone, Serialize, Deserialize)]
965pub struct StringSchema {
966    #[serde(rename = "type")]
967    pub schema_type: String, // Always "string"
968    #[serde(skip_serializing_if = "Option::is_none")]
969    pub title: Option<String>,
970    #[serde(skip_serializing_if = "Option::is_none")]
971    pub description: Option<String>,
972    #[serde(rename = "minLength", skip_serializing_if = "Option::is_none")]
973    pub min_length: Option<u32>,
974    #[serde(rename = "maxLength", skip_serializing_if = "Option::is_none")]
975    pub max_length: Option<u32>,
976    #[serde(skip_serializing_if = "Option::is_none")]
977    pub format: Option<StringSchemaFormat>,
978    #[serde(skip_serializing_if = "Option::is_none")]
979    pub default: Option<String>,
980}
981
982/// Format options for string schema.
983#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
984#[serde(rename_all = "kebab-case")]
985pub enum StringSchemaFormat {
986    Email,
987    Uri,
988    Date,
989    DateTime,
990}
991
992/// Number schema for elicitation forms.
993#[derive(Debug, Clone, Serialize, Deserialize)]
994pub struct NumberSchema {
995    #[serde(rename = "type")]
996    pub schema_type: String, // "number" or "integer"
997    #[serde(skip_serializing_if = "Option::is_none")]
998    pub title: Option<String>,
999    #[serde(skip_serializing_if = "Option::is_none")]
1000    pub description: Option<String>,
1001    #[serde(skip_serializing_if = "Option::is_none")]
1002    pub minimum: Option<f64>,
1003    #[serde(skip_serializing_if = "Option::is_none")]
1004    pub maximum: Option<f64>,
1005    #[serde(skip_serializing_if = "Option::is_none")]
1006    pub default: Option<f64>,
1007}
1008
1009/// Boolean schema for elicitation forms.
1010#[derive(Debug, Clone, Serialize, Deserialize)]
1011pub struct BooleanSchema {
1012    #[serde(rename = "type")]
1013    pub schema_type: String, // Always "boolean"
1014    #[serde(skip_serializing_if = "Option::is_none")]
1015    pub title: Option<String>,
1016    #[serde(skip_serializing_if = "Option::is_none")]
1017    pub description: Option<String>,
1018    #[serde(skip_serializing_if = "Option::is_none")]
1019    pub default: Option<bool>,
1020}
1021
1022/// Single-select enum option with title.
1023#[derive(Debug, Clone, Serialize, Deserialize)]
1024pub struct TitledEnumOption {
1025    /// The enum value.
1026    #[serde(rename = "const")]
1027    pub const_value: String,
1028    /// Display label for this option.
1029    pub title: String,
1030}
1031
1032/// Multi-select enum item schema (untitled).
1033#[derive(Debug, Clone, Serialize, Deserialize)]
1034pub struct MultiSelectEnumItems {
1035    #[serde(rename = "type")]
1036    pub schema_type: String, // Always "string"
1037    /// Array of enum values to choose from.
1038    #[serde(rename = "enum")]
1039    pub enum_values: Vec<String>,
1040}
1041
1042/// Multi-select enum item schema (titled).
1043#[derive(Debug, Clone, Serialize, Deserialize)]
1044pub struct TitledMultiSelectEnumItems {
1045    /// Array of enum options with values and display labels.
1046    #[serde(rename = "anyOf")]
1047    pub any_of: Vec<TitledEnumOption>,
1048}
1049
1050// =============================================================================
1051// Sampling Types (2025-11-25)
1052// =============================================================================
1053
1054/// Controls tool selection behavior for sampling requests.
1055#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
1056#[serde(rename_all = "snake_case")]
1057pub enum ToolChoiceMode {
1058    /// Model decides whether to use tools (default)
1059    #[default]
1060    Auto,
1061    /// Model MUST use at least one tool before completing
1062    Required,
1063    /// Model MUST NOT use any tools
1064    None,
1065}
1066
1067/// Controls tool selection behavior for sampling requests.
1068#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1069pub struct ToolChoice {
1070    /// Controls the tool use ability of the model.
1071    #[serde(skip_serializing_if = "Option::is_none")]
1072    pub mode: Option<ToolChoiceMode>,
1073}
1074
1075/// A request from the assistant to call a tool.
1076#[derive(Debug, Clone, Serialize, Deserialize)]
1077pub struct ToolUseContent {
1078    /// A unique identifier for this tool use.
1079    pub id: String,
1080    /// The name of the tool to call.
1081    pub name: String,
1082    /// The arguments to pass to the tool.
1083    pub input: Value,
1084    /// Optional metadata about the tool use.
1085    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1086    pub meta: Option<Value>,
1087}
1088
1089/// The result of a tool use, provided by the user back to the assistant.
1090#[derive(Debug, Clone, Serialize, Deserialize)]
1091pub struct ToolResultContent {
1092    /// The ID of the tool use this result corresponds to.
1093    #[serde(rename = "toolUseId")]
1094    pub tool_use_id: String,
1095    /// The unstructured result content of the tool use.
1096    pub content: Vec<ToolContent>,
1097    /// An optional structured result object.
1098    #[serde(rename = "structuredContent", skip_serializing_if = "Option::is_none")]
1099    pub structured_content: Option<Value>,
1100    /// Whether the tool use resulted in an error.
1101    #[serde(rename = "isError", skip_serializing_if = "Option::is_none")]
1102    pub is_error: Option<bool>,
1103    /// Optional metadata about the tool result.
1104    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1105    pub meta: Option<Value>,
1106}
1107
1108/// Sampling message content block types.
1109#[derive(Debug, Clone, Serialize, Deserialize)]
1110#[serde(tag = "type")]
1111pub enum SamplingContent {
1112    #[serde(rename = "text")]
1113    Text {
1114        text: String,
1115        #[serde(skip_serializing_if = "Option::is_none")]
1116        annotations: Option<Annotations>,
1117        #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1118        meta: Option<Value>,
1119    },
1120    #[serde(rename = "image")]
1121    Image {
1122        data: String,
1123        #[serde(rename = "mimeType")]
1124        mime_type: String,
1125        #[serde(skip_serializing_if = "Option::is_none")]
1126        annotations: Option<Annotations>,
1127        #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1128        meta: Option<Value>,
1129    },
1130    #[serde(rename = "audio")]
1131    Audio {
1132        data: String,
1133        #[serde(rename = "mimeType")]
1134        mime_type: String,
1135        #[serde(skip_serializing_if = "Option::is_none")]
1136        annotations: Option<Annotations>,
1137        #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1138        meta: Option<Value>,
1139    },
1140    #[serde(rename = "tool_use")]
1141    ToolUse {
1142        id: String,
1143        name: String,
1144        input: Value,
1145        #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1146        meta: Option<Value>,
1147    },
1148    #[serde(rename = "tool_result")]
1149    ToolResult {
1150        #[serde(rename = "toolUseId")]
1151        tool_use_id: String,
1152        content: Vec<ToolContent>,
1153        #[serde(rename = "structuredContent", skip_serializing_if = "Option::is_none")]
1154        structured_content: Option<Value>,
1155        #[serde(rename = "isError", skip_serializing_if = "Option::is_none")]
1156        is_error: Option<bool>,
1157        #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1158        meta: Option<Value>,
1159    },
1160}
1161
1162/// Describes a message issued to or received from an LLM API.
1163#[derive(Debug, Clone, Serialize, Deserialize)]
1164pub struct SamplingMessage {
1165    pub role: Role,
1166    pub content: Vec<SamplingContent>,
1167    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1168    pub meta: Option<Value>,
1169}
1170
1171/// Hints to use for model selection.
1172#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1173pub struct ModelHint {
1174    /// A hint for a model name.
1175    #[serde(skip_serializing_if = "Option::is_none")]
1176    pub name: Option<String>,
1177}
1178
1179/// The server's preferences for model selection.
1180#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1181pub struct ModelPreferences {
1182    /// Optional hints to use for model selection.
1183    #[serde(skip_serializing_if = "Option::is_none")]
1184    pub hints: Option<Vec<ModelHint>>,
1185
1186    /// How much to prioritize cost when selecting a model (0.0 - 1.0).
1187    #[serde(rename = "costPriority", skip_serializing_if = "Option::is_none")]
1188    pub cost_priority: Option<f64>,
1189
1190    /// How much to prioritize sampling speed (0.0 - 1.0).
1191    #[serde(rename = "speedPriority", skip_serializing_if = "Option::is_none")]
1192    pub speed_priority: Option<f64>,
1193
1194    /// How much to prioritize intelligence and capabilities (0.0 - 1.0).
1195    #[serde(
1196        rename = "intelligencePriority",
1197        skip_serializing_if = "Option::is_none"
1198    )]
1199    pub intelligence_priority: Option<f64>,
1200}
1201
1202/// Parameters for sampling/createMessage request.
1203#[derive(Debug, Clone, Serialize, Deserialize)]
1204pub struct CreateMessageParams {
1205    pub messages: Vec<SamplingMessage>,
1206
1207    /// The server's preferences for which model to select.
1208    #[serde(rename = "modelPreferences", skip_serializing_if = "Option::is_none")]
1209    pub model_preferences: Option<ModelPreferences>,
1210
1211    /// An optional system prompt the server wants to use for sampling.
1212    #[serde(rename = "systemPrompt", skip_serializing_if = "Option::is_none")]
1213    pub system_prompt: Option<String>,
1214
1215    /// A request to include context from one or more MCP servers.
1216    #[serde(rename = "includeContext", skip_serializing_if = "Option::is_none")]
1217    pub include_context: Option<String>,
1218
1219    #[serde(skip_serializing_if = "Option::is_none")]
1220    pub temperature: Option<f64>,
1221
1222    /// The requested maximum number of tokens to sample.
1223    #[serde(rename = "maxTokens")]
1224    pub max_tokens: u32,
1225
1226    #[serde(rename = "stopSequences", skip_serializing_if = "Option::is_none")]
1227    pub stop_sequences: Option<Vec<String>>,
1228
1229    /// Optional metadata to pass through to the LLM provider.
1230    #[serde(skip_serializing_if = "Option::is_none")]
1231    pub metadata: Option<Value>,
1232
1233    /// Tools that the model may use during generation.
1234    #[serde(skip_serializing_if = "Option::is_none")]
1235    pub tools: Option<Vec<McpToolDefinition>>,
1236
1237    /// Controls how the model uses tools.
1238    #[serde(rename = "toolChoice", skip_serializing_if = "Option::is_none")]
1239    pub tool_choice: Option<ToolChoice>,
1240
1241    /// Task metadata if requesting task-augmented execution.
1242    #[serde(skip_serializing_if = "Option::is_none")]
1243    pub task: Option<TaskMetadata>,
1244
1245    /// Request metadata.
1246    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1247    pub meta: Option<Value>,
1248}
1249
1250/// Standard stop reasons for sampling.
1251#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1252#[serde(rename_all = "camelCase")]
1253pub enum StopReason {
1254    /// Natural end of the assistant's turn
1255    EndTurn,
1256    /// A stop sequence was encountered
1257    StopSequence,
1258    /// Maximum token limit was reached
1259    MaxTokens,
1260    /// The model wants to use one or more tools
1261    ToolUse,
1262    /// Provider-specific stop reason
1263    #[serde(untagged)]
1264    Other(String),
1265}
1266
1267/// The client's response to a sampling/createMessage request.
1268#[derive(Debug, Clone, Serialize, Deserialize)]
1269pub struct CreateMessageResult {
1270    pub role: Role,
1271    pub content: Vec<SamplingContent>,
1272    /// The name of the model that generated the message.
1273    pub model: String,
1274    /// The reason why sampling stopped, if known.
1275    #[serde(rename = "stopReason", skip_serializing_if = "Option::is_none")]
1276    pub stop_reason: Option<String>,
1277    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1278    pub meta: Option<Value>,
1279}
1280
1281// =============================================================================
1282// Logging Types (2025-11-25)
1283// =============================================================================
1284
1285/// The severity of a log message (RFC-5424 syslog severities).
1286#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1287#[serde(rename_all = "snake_case")]
1288pub enum LoggingLevel {
1289    Debug,
1290    Info,
1291    Notice,
1292    Warning,
1293    Error,
1294    Critical,
1295    Alert,
1296    Emergency,
1297}
1298
1299/// Parameters for logging/setLevel request.
1300#[derive(Debug, Clone, Serialize, Deserialize)]
1301pub struct SetLevelParams {
1302    /// The level of logging that the client wants to receive from the server.
1303    pub level: LoggingLevel,
1304}
1305
1306/// Parameters for notifications/message notification.
1307#[derive(Debug, Clone, Serialize, Deserialize)]
1308pub struct LoggingMessageParams {
1309    /// The severity of this log message.
1310    pub level: LoggingLevel,
1311    /// An optional name of the logger issuing this message.
1312    #[serde(skip_serializing_if = "Option::is_none")]
1313    pub logger: Option<String>,
1314    /// The data to be logged.
1315    pub data: Value,
1316}
1317
1318// =============================================================================
1319// Progress Notifications (2025-11-25)
1320// =============================================================================
1321
1322/// Parameters for notifications/progress notification.
1323#[derive(Debug, Clone, Serialize, Deserialize)]
1324pub struct ProgressNotificationParams {
1325    /// The progress token which was given in the initial request.
1326    #[serde(rename = "progressToken")]
1327    pub progress_token: ProgressToken,
1328
1329    /// The progress thus far.
1330    pub progress: f64,
1331
1332    /// Total number of items to process, if known.
1333    #[serde(skip_serializing_if = "Option::is_none")]
1334    pub total: Option<f64>,
1335
1336    /// An optional message describing the current progress.
1337    #[serde(skip_serializing_if = "Option::is_none")]
1338    pub message: Option<String>,
1339}
1340
1341/// A progress token, used to associate progress notifications with the original request.
1342#[derive(Debug, Clone, Serialize, Deserialize)]
1343#[serde(untagged)]
1344pub enum ProgressToken {
1345    String(String),
1346    Number(i64),
1347}
1348
1349// =============================================================================
1350// Roots Types (2025-11-25)
1351// =============================================================================
1352
1353/// Represents a root directory or file that the server can operate on.
1354#[derive(Debug, Clone, Serialize, Deserialize)]
1355pub struct Root {
1356    /// The URI identifying the root. Must start with file:// for now.
1357    pub uri: String,
1358
1359    /// An optional name for the root.
1360    #[serde(skip_serializing_if = "Option::is_none")]
1361    pub name: Option<String>,
1362
1363    /// Request metadata.
1364    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1365    pub meta: Option<Value>,
1366}
1367
1368/// Response to a roots/list request.
1369#[derive(Debug, Clone, Serialize, Deserialize)]
1370pub struct ListRootsResult {
1371    pub roots: Vec<Root>,
1372}
1373
1374// =============================================================================
1375// Completion Types (2025-11-25)
1376// =============================================================================
1377
1378/// A reference to a prompt.
1379#[derive(Debug, Clone, Serialize, Deserialize)]
1380pub struct PromptReference {
1381    #[serde(rename = "type")]
1382    pub ref_type: String, // "ref/prompt"
1383    pub name: String,
1384    #[serde(skip_serializing_if = "Option::is_none")]
1385    pub title: Option<String>,
1386}
1387
1388/// A reference to a resource or resource template.
1389#[derive(Debug, Clone, Serialize, Deserialize)]
1390pub struct ResourceTemplateReference {
1391    #[serde(rename = "type")]
1392    pub ref_type: String, // "ref/resource"
1393    pub uri: String,
1394}
1395
1396/// Parameters for completion/complete request.
1397#[derive(Debug, Clone, Serialize, Deserialize)]
1398pub struct CompleteParams {
1399    pub r#ref: Value, // Can be PromptReference or ResourceTemplateReference
1400    pub argument: CompleteArgument,
1401    #[serde(skip_serializing_if = "Option::is_none")]
1402    pub context: Option<CompleteContext>,
1403}
1404
1405/// Argument information for completion.
1406#[derive(Debug, Clone, Serialize, Deserialize)]
1407pub struct CompleteArgument {
1408    /// The name of the argument.
1409    pub name: String,
1410    /// The value of the argument to use for completion matching.
1411    pub value: String,
1412}
1413
1414/// Additional context for completions.
1415#[derive(Debug, Clone, Serialize, Deserialize)]
1416pub struct CompleteContext {
1417    /// Previously-resolved variables in a URI template or prompt.
1418    #[serde(skip_serializing_if = "Option::is_none")]
1419    pub arguments: Option<Value>,
1420}
1421
1422/// Response to a completion/complete request.
1423#[derive(Debug, Clone, Serialize, Deserialize)]
1424pub struct CompleteResult {
1425    pub completion: CompletionData,
1426}
1427
1428/// Completion data.
1429#[derive(Debug, Clone, Serialize, Deserialize)]
1430pub struct CompletionData {
1431    /// An array of completion values. Must not exceed 100 items.
1432    pub values: Vec<String>,
1433    /// The total number of completion options available.
1434    #[serde(skip_serializing_if = "Option::is_none")]
1435    pub total: Option<u32>,
1436    /// Indicates whether there are additional completion options.
1437    #[serde(rename = "hasMore", skip_serializing_if = "Option::is_none")]
1438    pub has_more: Option<bool>,
1439}
1440
1441#[cfg(test)]
1442mod tests {
1443    use super::*;
1444
1445    #[test]
1446    fn test_jsonrpc_request_serialization() {
1447        let req = JsonRpcRequest::new(JsonRpcId::Number(1), "tools/list", None);
1448
1449        let json = serde_json::to_string(&req).unwrap();
1450        assert!(json.contains(r#""jsonrpc":"2.0""#));
1451        assert!(json.contains(r#""id":1"#));
1452        assert!(json.contains(r#""method":"tools/list""#));
1453    }
1454
1455    #[test]
1456    fn test_jsonrpc_response_success() {
1457        let json = r#"{"jsonrpc":"2.0","id":1,"result":{"tools":[]}}"#;
1458        let resp: JsonRpcResponse = serde_json::from_str(json).unwrap();
1459
1460        assert!(matches!(resp.payload, JsonRpcPayload::Success { .. }));
1461    }
1462
1463    #[test]
1464    fn test_jsonrpc_response_error() {
1465        let json =
1466            r#"{"jsonrpc":"2.0","id":1,"error":{"code":-32601,"message":"Method not found"}}"#;
1467        let resp: JsonRpcResponse = serde_json::from_str(json).unwrap();
1468
1469        assert!(matches!(resp.payload, JsonRpcPayload::Error { .. }));
1470    }
1471
1472    #[test]
1473    fn test_tool_content_text() {
1474        let content = ToolContent::text("Hello, world!");
1475        assert_eq!(content.as_text(), Some("Hello, world!"));
1476
1477        let json = serde_json::to_string(&content).unwrap();
1478        assert!(json.contains(r#""type":"text""#));
1479        assert!(json.contains(r#""text":"Hello, world!""#));
1480    }
1481
1482    #[test]
1483    fn test_jsonrpc_id_display() {
1484        assert_eq!(JsonRpcId::Number(42).to_string(), "42");
1485        assert_eq!(JsonRpcId::String("test".to_string()).to_string(), "test");
1486        assert_eq!(JsonRpcId::Null.to_string(), "null");
1487    }
1488
1489    #[test]
1490    fn test_mcp_tool_deserialization() {
1491        let json = r#"{
1492            "name": "test_tool",
1493            "description": "A test tool",
1494            "input_schema": {
1495                "type": "object",
1496                "properties": {
1497                    "name": {"type": "string"}
1498                },
1499                "required": ["name"]
1500            }
1501        }"#;
1502
1503        let tool: McpToolDefinition = serde_json::from_str(json).unwrap();
1504        assert_eq!(tool.name, "test_tool");
1505        assert_eq!(tool.description, Some("A test tool".to_string()));
1506        assert_eq!(tool.input_schema["type"], "object");
1507    }
1508}