turbomcp_protocol/
types.rs

1//! # MCP Protocol Types
2//!
3//! This module contains all the type definitions for the Model Context Protocol
4//! according to the 2025-06-18 specification.
5
6use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8use turbomcp_core::MessageId;
9
10/// Protocol version string
11pub type ProtocolVersion = String;
12
13/// JSON-RPC request identifier
14pub type RequestId = MessageId;
15
16/// Progress token for tracking long-running operations
17pub type ProgressToken = String;
18
19/// URI string
20pub type Uri = String;
21
22/// MIME type
23pub type MimeType = String;
24
25/// Base64 encoded data
26pub type Base64String = String;
27
28// ============================================================================
29// JSON-RPC Error Codes
30// ============================================================================
31
32/// Standard JSON-RPC error codes per specification
33pub mod error_codes {
34    /// Parse error - Invalid JSON was received by the server
35    pub const PARSE_ERROR: i32 = -32700;
36    /// Invalid Request - The JSON sent is not a valid Request object
37    pub const INVALID_REQUEST: i32 = -32600;
38    /// Method not found - The method does not exist / is not available
39    pub const METHOD_NOT_FOUND: i32 = -32601;
40    /// Invalid params - Invalid method parameter(s)
41    pub const INVALID_PARAMS: i32 = -32602;
42    /// Internal error - Internal JSON-RPC error
43    pub const INTERNAL_ERROR: i32 = -32603;
44}
45
46/// JSON-RPC error structure per MCP 2025-06-18 specification
47#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
48pub struct JsonRpcError {
49    /// The error type that occurred
50    pub code: i32,
51    /// A short description of the error (should be limited to a concise single sentence)
52    pub message: String,
53    /// Additional information about the error (detailed error information, nested errors, etc.)
54    #[serde(skip_serializing_if = "Option::is_none")]
55    pub data: Option<serde_json::Value>,
56}
57
58impl JsonRpcError {
59    /// Create a new JSON-RPC error
60    pub fn new(code: i32, message: String) -> Self {
61        Self {
62            code,
63            message,
64            data: None,
65        }
66    }
67
68    /// Create a new JSON-RPC error with additional data
69    pub fn with_data(code: i32, message: String, data: serde_json::Value) -> Self {
70        Self {
71            code,
72            message,
73            data: Some(data),
74        }
75    }
76
77    /// Create a parse error
78    pub fn parse_error() -> Self {
79        Self::new(error_codes::PARSE_ERROR, "Parse error".to_string())
80    }
81
82    /// Create an invalid request error
83    pub fn invalid_request() -> Self {
84        Self::new(error_codes::INVALID_REQUEST, "Invalid Request".to_string())
85    }
86
87    /// Create a method not found error
88    pub fn method_not_found(method: &str) -> Self {
89        Self::new(
90            error_codes::METHOD_NOT_FOUND,
91            format!("Method not found: {method}"),
92        )
93    }
94
95    /// Create an invalid params error
96    pub fn invalid_params(details: &str) -> Self {
97        Self::new(
98            error_codes::INVALID_PARAMS,
99            format!("Invalid params: {details}"),
100        )
101    }
102
103    /// Create an internal error
104    pub fn internal_error(details: &str) -> Self {
105        Self::new(
106            error_codes::INTERNAL_ERROR,
107            format!("Internal error: {details}"),
108        )
109    }
110}
111
112/// Cursor for pagination
113pub type Cursor = String;
114
115// ============================================================================
116// Base Metadata Interface
117// ============================================================================
118
119/// Base interface for metadata with name (identifier) and title (display name) properties.
120/// Per MCP specification 2025-06-18, this is the foundation for Tool, Resource, and Prompt metadata.
121#[derive(Debug, Clone, Serialize, Deserialize)]
122pub struct BaseMetadata {
123    /// Intended for programmatic or logical use, but used as a display name in past specs or fallback (if title isn't present).
124    pub name: String,
125
126    /// Intended for UI and end-user contexts — optimized to be human-readable and easily understood,
127    /// even by those unfamiliar with domain-specific terminology.
128    ///
129    /// If not provided, the name should be used for display (except for Tool,
130    /// where `annotations.title` should be given precedence over using `name`, if present).
131    #[serde(skip_serializing_if = "Option::is_none")]
132    pub title: Option<String>,
133}
134
135/// Implementation information for MCP clients and servers
136#[derive(Debug, Clone, Serialize, Deserialize)]
137pub struct Implementation {
138    /// Implementation name
139    pub name: String,
140    /// Implementation display title
141    #[serde(skip_serializing_if = "Option::is_none")]
142    pub title: Option<String>,
143    /// Implementation version
144    pub version: String,
145}
146
147/// General annotations that can be attached to various MCP objects
148#[derive(Debug, Clone, Serialize, Deserialize, Default)]
149pub struct Annotations {
150    /// Audience-specific hints or information
151    #[serde(skip_serializing_if = "Option::is_none")]
152    pub audience: Option<Vec<String>>,
153    /// Priority level for ordering or importance
154    #[serde(skip_serializing_if = "Option::is_none")]
155    pub priority: Option<f64>,
156    /// Additional custom annotations
157    #[serde(flatten)]
158    pub custom: HashMap<String, serde_json::Value>,
159}
160
161// ============================================================================
162// Core Protocol Types
163// ============================================================================
164
165/// Client-initiated request
166#[derive(Debug, Clone, Serialize, Deserialize)]
167#[serde(tag = "method")]
168pub enum ClientRequest {
169    /// Initialize the connection
170    #[serde(rename = "initialize")]
171    Initialize(InitializeRequest),
172
173    /// List available tools
174    #[serde(rename = "tools/list")]
175    ListTools(ListToolsRequest),
176
177    /// Call a tool
178    #[serde(rename = "tools/call")]
179    CallTool(CallToolRequest),
180
181    /// List available prompts
182    #[serde(rename = "prompts/list")]
183    ListPrompts(ListPromptsRequest),
184
185    /// Get a specific prompt
186    #[serde(rename = "prompts/get")]
187    GetPrompt(GetPromptRequest),
188
189    /// List available resources
190    #[serde(rename = "resources/list")]
191    ListResources(ListResourcesRequest),
192
193    /// Read a resource
194    #[serde(rename = "resources/read")]
195    ReadResource(ReadResourceRequest),
196
197    /// Subscribe to resource updates
198    #[serde(rename = "resources/subscribe")]
199    Subscribe(SubscribeRequest),
200
201    /// Unsubscribe from resource updates
202    #[serde(rename = "resources/unsubscribe")]
203    Unsubscribe(UnsubscribeRequest),
204
205    /// Set logging level
206    #[serde(rename = "logging/setLevel")]
207    SetLevel(SetLevelRequest),
208
209    /// Create a message (sampling)
210    #[serde(rename = "sampling/createMessage")]
211    CreateMessage(CreateMessageRequest),
212
213    /// List filesystem roots
214    #[serde(rename = "roots/list")]
215    ListRoots(ListRootsRequest),
216}
217
218/// Server-initiated request
219#[derive(Debug, Clone, Serialize, Deserialize)]
220#[serde(tag = "method")]
221pub enum ServerRequest {
222    /// Ping to check connection
223    #[serde(rename = "ping")]
224    Ping,
225}
226
227/// Client-initiated notification
228#[derive(Debug, Clone, Serialize, Deserialize)]
229#[serde(tag = "method")]
230pub enum ClientNotification {
231    /// Connection initialized
232    #[serde(rename = "notifications/initialized")]
233    Initialized(InitializedNotification),
234
235    /// Progress update
236    #[serde(rename = "notifications/progress")]
237    Progress(ProgressNotification),
238
239    /// Roots list changed
240    #[serde(rename = "notifications/roots/list_changed")]
241    RootsListChanged(RootsListChangedNotification),
242}
243
244/// Server-initiated notification
245#[derive(Debug, Clone, Serialize, Deserialize)]
246#[serde(tag = "method")]
247pub enum ServerNotification {
248    /// Log message
249    #[serde(rename = "notifications/message")]
250    Message(LoggingNotification),
251
252    /// Resource updated
253    #[serde(rename = "notifications/resources/updated")]
254    ResourceUpdated(ResourceUpdatedNotification),
255
256    /// Resource list changed
257    #[serde(rename = "notifications/resources/list_changed")]
258    ResourceListChanged,
259
260    /// Progress update
261    #[serde(rename = "notifications/progress")]
262    Progress(ProgressNotification),
263
264    /// Request cancellation
265    #[serde(rename = "notifications/cancelled")]
266    Cancelled(CancelledNotification),
267
268    /// Prompts list changed
269    #[serde(rename = "notifications/prompts/list_changed")]
270    PromptsListChanged,
271
272    /// Tools list changed
273    #[serde(rename = "notifications/tools/list_changed")]
274    ToolsListChanged,
275
276    /// Roots list changed
277    #[serde(rename = "notifications/roots/list_changed")]
278    RootsListChanged,
279}
280
281// ============================================================================
282// Initialization
283// ============================================================================
284
285/// Initialize request
286#[derive(Debug, Clone, Serialize, Deserialize)]
287pub struct InitializeRequest {
288    /// Protocol version
289    #[serde(rename = "protocolVersion")]
290    pub protocol_version: ProtocolVersion,
291    /// Client capabilities
292    pub capabilities: ClientCapabilities,
293    /// Client implementation info
294    #[serde(rename = "clientInfo")]
295    pub client_info: Implementation,
296}
297
298/// Initialize result
299#[derive(Debug, Clone, Serialize, Deserialize)]
300pub struct InitializeResult {
301    /// Protocol version
302    #[serde(rename = "protocolVersion")]
303    pub protocol_version: ProtocolVersion,
304    /// Server capabilities
305    pub capabilities: ServerCapabilities,
306    /// Server implementation info
307    #[serde(rename = "serverInfo")]
308    pub server_info: Implementation,
309    /// Additional instructions for the client
310    #[serde(skip_serializing_if = "Option::is_none")]
311    pub instructions: Option<String>,
312}
313
314/// Initialized notification (no parameters)
315#[derive(Debug, Clone, Serialize, Deserialize)]
316pub struct InitializedNotification;
317
318// ============================================================================
319// Capabilities
320// ============================================================================
321
322/// Client capabilities per MCP 2025-06-18 specification
323#[derive(Debug, Clone, Serialize, Deserialize, Default)]
324pub struct ClientCapabilities {
325    /// Experimental, non-standard capabilities that the client supports
326    #[serde(skip_serializing_if = "Option::is_none")]
327    pub experimental: Option<HashMap<String, serde_json::Value>>,
328
329    /// Present if the client supports listing roots
330    #[serde(skip_serializing_if = "Option::is_none")]
331    pub roots: Option<RootsCapabilities>,
332
333    /// Present if the client supports sampling from an LLM
334    #[serde(skip_serializing_if = "Option::is_none")]
335    pub sampling: Option<SamplingCapabilities>,
336
337    /// Present if the client supports elicitation from the server
338    #[serde(skip_serializing_if = "Option::is_none")]
339    pub elicitation: Option<ElicitationCapabilities>,
340}
341
342/// Server capabilities per MCP 2025-06-18 specification
343#[derive(Debug, Clone, Serialize, Deserialize, Default)]
344pub struct ServerCapabilities {
345    /// Experimental, non-standard capabilities that the server supports
346    #[serde(skip_serializing_if = "Option::is_none")]
347    pub experimental: Option<HashMap<String, serde_json::Value>>,
348
349    /// Present if the server supports sending log messages to the client
350    #[serde(skip_serializing_if = "Option::is_none")]
351    pub logging: Option<LoggingCapabilities>,
352
353    /// Present if the server supports argument autocompletion suggestions
354    #[serde(skip_serializing_if = "Option::is_none")]
355    pub completions: Option<CompletionCapabilities>,
356
357    /// Present if the server offers any prompt templates
358    #[serde(skip_serializing_if = "Option::is_none")]
359    pub prompts: Option<PromptsCapabilities>,
360
361    /// Present if the server offers any resources to read
362    #[serde(skip_serializing_if = "Option::is_none")]
363    pub resources: Option<ResourcesCapabilities>,
364
365    /// Present if the server offers any tools to call
366    #[serde(skip_serializing_if = "Option::is_none")]
367    pub tools: Option<ToolsCapabilities>,
368}
369
370/// Sampling capabilities
371#[derive(Debug, Clone, Serialize, Deserialize, Default)]
372pub struct SamplingCapabilities;
373
374/// Elicitation capabilities
375#[derive(Debug, Clone, Serialize, Deserialize, Default)]
376pub struct ElicitationCapabilities;
377
378/// Completion capabilities
379#[derive(Debug, Clone, Serialize, Deserialize, Default)]
380pub struct CompletionCapabilities;
381
382/// Roots capabilities
383#[derive(Debug, Clone, Serialize, Deserialize, Default)]
384pub struct RootsCapabilities {
385    /// Whether list can change
386    #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
387    pub list_changed: Option<bool>,
388}
389
390/// Logging capabilities
391#[derive(Debug, Clone, Serialize, Deserialize, Default)]
392pub struct LoggingCapabilities;
393
394/// Prompts capabilities
395#[derive(Debug, Clone, Serialize, Deserialize, Default)]
396pub struct PromptsCapabilities {
397    /// Whether list can change
398    #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
399    pub list_changed: Option<bool>,
400}
401
402/// Resources capabilities
403#[derive(Debug, Clone, Serialize, Deserialize, Default)]
404pub struct ResourcesCapabilities {
405    /// Whether subscribe is supported
406    #[serde(skip_serializing_if = "Option::is_none")]
407    pub subscribe: Option<bool>,
408
409    /// Whether list can change
410    #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
411    pub list_changed: Option<bool>,
412}
413
414/// Tools capabilities
415#[derive(Debug, Clone, Serialize, Deserialize, Default)]
416pub struct ToolsCapabilities {
417    /// Whether list can change
418    #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
419    pub list_changed: Option<bool>,
420}
421
422// ============================================================================
423// Content Types
424// ============================================================================
425
426/// Content block union type per MCP 2025-06-18 specification
427#[derive(Debug, Clone, Serialize, Deserialize)]
428#[serde(tag = "type")]
429pub enum ContentBlock {
430    /// Text content
431    #[serde(rename = "text")]
432    Text(TextContent),
433    /// Image content
434    #[serde(rename = "image")]
435    Image(ImageContent),
436    /// Audio content
437    #[serde(rename = "audio")]
438    Audio(AudioContent),
439    /// Resource link
440    #[serde(rename = "resource_link")]
441    ResourceLink(ResourceLink),
442    /// Embedded resource
443    #[serde(rename = "resource")]
444    Resource(EmbeddedResource),
445}
446
447/// Compatibility alias for the old Content enum
448pub type Content = ContentBlock;
449
450/// Text content per MCP 2025-06-18 specification
451#[derive(Debug, Clone, Serialize, Deserialize)]
452pub struct TextContent {
453    /// The text content of the message
454    pub text: String,
455    /// Optional annotations for the client
456    #[serde(skip_serializing_if = "Option::is_none")]
457    pub annotations: Option<Annotations>,
458    /// General metadata field for extensions and custom data
459    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
460    pub meta: Option<HashMap<String, serde_json::Value>>,
461}
462
463/// Image content per MCP 2025-06-18 specification
464#[derive(Debug, Clone, Serialize, Deserialize)]
465pub struct ImageContent {
466    /// The base64-encoded image data
467    pub data: String,
468    /// The MIME type of the image. Different providers may support different image types
469    #[serde(rename = "mimeType")]
470    pub mime_type: String,
471    /// Optional annotations for the client
472    #[serde(skip_serializing_if = "Option::is_none")]
473    pub annotations: Option<Annotations>,
474    /// General metadata field for extensions and custom data
475    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
476    pub meta: Option<HashMap<String, serde_json::Value>>,
477}
478
479/// Audio content per MCP 2025-06-18 specification
480#[derive(Debug, Clone, Serialize, Deserialize)]
481pub struct AudioContent {
482    /// The base64-encoded audio data
483    pub data: String,
484    /// The MIME type of the audio. Different providers may support different audio types
485    #[serde(rename = "mimeType")]
486    pub mime_type: String,
487    /// Optional annotations for the client
488    #[serde(skip_serializing_if = "Option::is_none")]
489    pub annotations: Option<Annotations>,
490    /// General metadata field for extensions and custom data
491    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
492    pub meta: Option<HashMap<String, serde_json::Value>>,
493}
494
495/// Resource link per MCP 2025-06-18 specification
496#[derive(Debug, Clone, Serialize, Deserialize)]
497pub struct ResourceLink {
498    /// Resource name (programmatic identifier)
499    pub name: String,
500    /// Display title for UI contexts (optional, falls back to name if not provided)
501    #[serde(skip_serializing_if = "Option::is_none")]
502    pub title: Option<String>,
503    /// The URI of this resource
504    pub uri: String,
505    /// A description of what this resource represents
506    #[serde(skip_serializing_if = "Option::is_none")]
507    pub description: Option<String>,
508    /// The MIME type of this resource, if known
509    #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
510    pub mime_type: Option<String>,
511    /// Optional annotations for the client
512    #[serde(skip_serializing_if = "Option::is_none")]
513    pub annotations: Option<Annotations>,
514    /// The size of the raw resource content, if known
515    #[serde(skip_serializing_if = "Option::is_none")]
516    pub size: Option<u64>,
517    /// General metadata field for extensions and custom data
518    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
519    pub meta: Option<HashMap<String, serde_json::Value>>,
520}
521
522/// Embedded resource content per MCP 2025-06-18 specification
523#[derive(Debug, Clone, Serialize, Deserialize)]
524pub struct EmbeddedResource {
525    /// The embedded resource content (text or binary)
526    pub resource: ResourceContent,
527    /// Optional annotations for the client
528    #[serde(skip_serializing_if = "Option::is_none")]
529    pub annotations: Option<Annotations>,
530    /// General metadata field for extensions and custom data
531    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
532    pub meta: Option<HashMap<String, serde_json::Value>>,
533}
534
535/// Role in conversation
536#[derive(Debug, Clone, Serialize, Deserialize)]
537#[serde(rename_all = "lowercase")]
538pub enum Role {
539    /// User role
540    User,
541    /// Assistant role
542    Assistant,
543}
544
545// ============================================================================
546// Tool Types
547// ============================================================================
548
549/// Tool-specific annotations for additional tool information
550#[derive(Debug, Clone, Serialize, Deserialize, Default)]
551pub struct ToolAnnotations {
552    /// Title for display purposes - takes precedence over name for UI
553    #[serde(skip_serializing_if = "Option::is_none")]
554    pub title: Option<String>,
555    /// Audience-specific information
556    #[serde(skip_serializing_if = "Option::is_none")]
557    pub audience: Option<Vec<String>>,
558    /// Priority for ordering
559    #[serde(skip_serializing_if = "Option::is_none")]
560    pub priority: Option<f64>,
561    /// Additional custom annotations
562    #[serde(flatten)]
563    pub custom: HashMap<String, serde_json::Value>,
564}
565
566/// Tool definition per MCP 2025-06-18 specification
567#[derive(Debug, Clone, Serialize, Deserialize)]
568pub struct Tool {
569    /// Tool name (programmatic identifier)
570    pub name: String,
571
572    /// Display title for UI contexts (optional, falls back to name if not provided)
573    #[serde(skip_serializing_if = "Option::is_none")]
574    pub title: Option<String>,
575
576    /// Human-readable description of the tool
577    /// This can be used by clients to improve the LLM's understanding of available tools
578    #[serde(skip_serializing_if = "Option::is_none")]
579    pub description: Option<String>,
580
581    /// JSON Schema object defining the expected parameters for the tool
582    #[serde(rename = "inputSchema")]
583    pub input_schema: ToolInputSchema,
584
585    /// Optional JSON Schema object defining the structure of the tool's output
586    /// returned in the structuredContent field of a CallToolResult
587    #[serde(rename = "outputSchema", skip_serializing_if = "Option::is_none")]
588    pub output_schema: Option<ToolOutputSchema>,
589
590    /// Optional additional tool information
591    /// Display name precedence order is: title, annotations.title, then name
592    #[serde(skip_serializing_if = "Option::is_none")]
593    pub annotations: Option<ToolAnnotations>,
594
595    /// General metadata field for extensions and custom data
596    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
597    pub meta: Option<HashMap<String, serde_json::Value>>,
598}
599
600/// Tool input schema definition
601#[derive(Debug, Clone, Serialize, Deserialize)]
602pub struct ToolInputSchema {
603    /// Must be "object" for tool input schemas
604    #[serde(rename = "type")]
605    pub schema_type: String,
606    /// Schema properties defining the tool parameters
607    #[serde(skip_serializing_if = "Option::is_none")]
608    pub properties: Option<HashMap<String, serde_json::Value>>,
609    /// List of required property names
610    #[serde(skip_serializing_if = "Option::is_none")]
611    pub required: Option<Vec<String>>,
612    /// Whether additional properties are allowed
613    #[serde(
614        rename = "additionalProperties",
615        skip_serializing_if = "Option::is_none"
616    )]
617    pub additional_properties: Option<bool>,
618}
619
620/// Tool output schema definition
621#[derive(Debug, Clone, Serialize, Deserialize)]
622pub struct ToolOutputSchema {
623    /// Must be "object" for tool output schemas
624    #[serde(rename = "type")]
625    pub schema_type: String,
626    /// Schema properties defining the tool output structure
627    #[serde(skip_serializing_if = "Option::is_none")]
628    pub properties: Option<HashMap<String, serde_json::Value>>,
629    /// List of required property names
630    #[serde(skip_serializing_if = "Option::is_none")]
631    pub required: Option<Vec<String>>,
632    /// Whether additional properties are allowed
633    #[serde(
634        rename = "additionalProperties",
635        skip_serializing_if = "Option::is_none"
636    )]
637    pub additional_properties: Option<bool>,
638}
639
640/// List tools request (no parameters)
641#[derive(Debug, Clone, Serialize, Deserialize)]
642pub struct ListToolsRequest;
643
644/// List tools result
645#[derive(Debug, Clone, Serialize, Deserialize)]
646pub struct ListToolsResult {
647    /// Available tools
648    pub tools: Vec<Tool>,
649    /// Optional continuation token
650    #[serde(rename = "nextCursor", skip_serializing_if = "Option::is_none")]
651    pub next_cursor: Option<String>,
652}
653
654/// Call tool request
655#[derive(Debug, Clone, Serialize, Deserialize)]
656pub struct CallToolRequest {
657    /// Tool name
658    pub name: String,
659    /// Tool arguments
660    #[serde(skip_serializing_if = "Option::is_none")]
661    pub arguments: Option<HashMap<String, serde_json::Value>>,
662}
663
664/// Call tool result
665#[derive(Debug, Clone, Serialize, Deserialize)]
666pub struct CallToolResult {
667    /// Result content
668    pub content: Vec<ContentBlock>,
669    /// Whether the operation failed
670    #[serde(rename = "isError", skip_serializing_if = "Option::is_none")]
671    pub is_error: Option<bool>,
672}
673
674// ============================================================================
675// Prompt Types
676// ============================================================================
677
678/// Prompt definition per MCP 2025-06-18 specification
679#[derive(Debug, Clone, Serialize, Deserialize)]
680pub struct Prompt {
681    /// Prompt name (programmatic identifier)
682    pub name: String,
683
684    /// Display title for UI contexts (optional, falls back to name if not provided)
685    #[serde(skip_serializing_if = "Option::is_none")]
686    pub title: Option<String>,
687
688    /// An optional description of what this prompt provides
689    #[serde(skip_serializing_if = "Option::is_none")]
690    pub description: Option<String>,
691
692    /// A list of arguments to use for templating the prompt
693    #[serde(skip_serializing_if = "Option::is_none")]
694    pub arguments: Option<Vec<PromptArgument>>,
695
696    /// General metadata field for extensions and custom data
697    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
698    pub meta: Option<HashMap<String, serde_json::Value>>,
699}
700
701/// Prompt argument definition per MCP 2025-06-18 specification
702#[derive(Debug, Clone, Serialize, Deserialize)]
703pub struct PromptArgument {
704    /// Argument name (programmatic identifier)
705    pub name: String,
706
707    /// Display title for UI contexts (optional, falls back to name if not provided)
708    #[serde(skip_serializing_if = "Option::is_none")]
709    pub title: Option<String>,
710
711    /// A human-readable description of the argument
712    #[serde(skip_serializing_if = "Option::is_none")]
713    pub description: Option<String>,
714
715    /// Whether this argument must be provided
716    #[serde(skip_serializing_if = "Option::is_none")]
717    pub required: Option<bool>,
718}
719
720/// Prompt input parameters
721pub type PromptInput = HashMap<String, serde_json::Value>;
722
723/// List prompts request (no parameters)
724#[derive(Debug, Clone, Serialize, Deserialize)]
725pub struct ListPromptsRequest;
726
727/// List prompts result
728#[derive(Debug, Clone, Serialize, Deserialize)]
729pub struct ListPromptsResult {
730    /// Available prompts
731    pub prompts: Vec<Prompt>,
732    /// Optional continuation token
733    #[serde(rename = "nextCursor", skip_serializing_if = "Option::is_none")]
734    pub next_cursor: Option<String>,
735}
736
737/// Get prompt request
738#[derive(Debug, Clone, Serialize, Deserialize)]
739pub struct GetPromptRequest {
740    /// Prompt name
741    pub name: String,
742    /// Prompt arguments
743    #[serde(skip_serializing_if = "Option::is_none")]
744    pub arguments: Option<PromptInput>,
745}
746
747/// Get prompt result
748#[derive(Debug, Clone, Serialize, Deserialize)]
749pub struct GetPromptResult {
750    /// Prompt description
751    #[serde(skip_serializing_if = "Option::is_none")]
752    pub description: Option<String>,
753    /// Prompt messages
754    pub messages: Vec<PromptMessage>,
755}
756
757/// Prompt message
758#[derive(Debug, Clone, Serialize, Deserialize)]
759pub struct PromptMessage {
760    /// Message role
761    pub role: Role,
762    /// Message content
763    pub content: Content,
764}
765
766// ============================================================================
767// Resource Types
768// ============================================================================
769
770/// Resource definition per MCP 2025-06-18 specification
771#[derive(Debug, Clone, Serialize, Deserialize)]
772pub struct Resource {
773    /// Resource name (programmatic identifier)
774    pub name: String,
775
776    /// Display title for UI contexts (optional, falls back to name if not provided)
777    #[serde(skip_serializing_if = "Option::is_none")]
778    pub title: Option<String>,
779
780    /// The URI of this resource
781    pub uri: String,
782
783    /// A description of what this resource represents
784    /// This can be used by clients to improve the LLM's understanding of available resources
785    #[serde(skip_serializing_if = "Option::is_none")]
786    pub description: Option<String>,
787
788    /// The MIME type of this resource, if known
789    #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
790    pub mime_type: Option<String>,
791
792    /// Optional annotations for the client
793    #[serde(skip_serializing_if = "Option::is_none")]
794    pub annotations: Option<Annotations>,
795
796    /// The size of the raw resource content, in bytes (before base64 encoding or tokenization), if known
797    /// This can be used by Hosts to display file sizes and estimate context window usage
798    #[serde(skip_serializing_if = "Option::is_none")]
799    pub size: Option<u64>,
800
801    /// General metadata field for extensions and custom data
802    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
803    pub meta: Option<HashMap<String, serde_json::Value>>,
804}
805
806/// Base resource contents interface
807#[derive(Debug, Clone, Serialize, Deserialize)]
808pub struct ResourceContents {
809    /// The URI of this resource
810    pub uri: String,
811    /// The MIME type of this resource, if known
812    #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
813    pub mime_type: Option<String>,
814    /// General metadata field for extensions and custom data
815    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
816    pub meta: Option<HashMap<String, serde_json::Value>>,
817}
818
819/// Text resource contents
820#[derive(Debug, Clone, Serialize, Deserialize)]
821pub struct TextResourceContents {
822    /// The URI of this resource
823    pub uri: String,
824    /// The MIME type of this resource, if known
825    #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
826    pub mime_type: Option<String>,
827    /// The text content (must only be set for text-representable data)
828    pub text: String,
829    /// General metadata field for extensions and custom data
830    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
831    pub meta: Option<HashMap<String, serde_json::Value>>,
832}
833
834/// Binary resource contents
835#[derive(Debug, Clone, Serialize, Deserialize)]
836pub struct BlobResourceContents {
837    /// The URI of this resource
838    pub uri: String,
839    /// The MIME type of this resource, if known
840    #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
841    pub mime_type: Option<String>,
842    /// Base64-encoded binary data
843    pub blob: String,
844    /// General metadata field for extensions and custom data
845    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
846    pub meta: Option<HashMap<String, serde_json::Value>>,
847}
848
849/// Union type for resource contents (text or binary)
850#[derive(Debug, Clone, Serialize, Deserialize)]
851#[serde(untagged)]
852pub enum ResourceContent {
853    /// Text resource content
854    Text(TextResourceContents),
855    /// Binary resource content
856    Blob(BlobResourceContents),
857}
858
859/// List resources request
860#[derive(Debug, Clone, Serialize, Deserialize)]
861pub struct ListResourcesRequest {
862    /// Optional cursor for pagination
863    #[serde(skip_serializing_if = "Option::is_none")]
864    pub cursor: Option<String>,
865}
866
867/// List resources result
868#[derive(Debug, Clone, Serialize, Deserialize)]
869pub struct ListResourcesResult {
870    /// Available resources
871    pub resources: Vec<Resource>,
872    /// Optional continuation token
873    #[serde(rename = "nextCursor", skip_serializing_if = "Option::is_none")]
874    pub next_cursor: Option<String>,
875}
876
877/// Read resource request
878#[derive(Debug, Clone, Serialize, Deserialize)]
879pub struct ReadResourceRequest {
880    /// Resource URI
881    pub uri: Uri,
882}
883
884/// Read resource result
885#[derive(Debug, Clone, Serialize, Deserialize)]
886pub struct ReadResourceResult {
887    /// Resource contents (can be text or binary)
888    pub contents: Vec<ResourceContent>,
889}
890
891/// Subscribe to resource request
892#[derive(Debug, Clone, Serialize, Deserialize)]
893pub struct SubscribeRequest {
894    /// Resource URI
895    pub uri: Uri,
896}
897
898/// Unsubscribe from resource request
899#[derive(Debug, Clone, Serialize, Deserialize)]
900pub struct UnsubscribeRequest {
901    /// Resource URI
902    pub uri: Uri,
903}
904
905/// Resource updated notification
906#[derive(Debug, Clone, Serialize, Deserialize)]
907pub struct ResourceUpdatedNotification {
908    /// Resource URI
909    pub uri: Uri,
910}
911
912// ============================================================================
913// Logging Types
914// ============================================================================
915
916/// Log level
917#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
918#[serde(rename_all = "lowercase")]
919pub enum LogLevel {
920    /// Debug level
921    Debug,
922    /// Info level
923    Info,
924    /// Notice level
925    Notice,
926    /// Warning level
927    Warning,
928    /// Error level
929    Error,
930    /// Critical level
931    Critical,
932    /// Alert level
933    Alert,
934    /// Emergency level
935    Emergency,
936}
937
938/// Set log level request
939#[derive(Debug, Clone, Serialize, Deserialize)]
940pub struct SetLevelRequest {
941    /// Log level to set
942    pub level: LogLevel,
943}
944
945/// Set log level result (no data)
946#[derive(Debug, Clone, Serialize, Deserialize)]
947pub struct SetLevelResult;
948
949/// Logging notification
950#[derive(Debug, Clone, Serialize, Deserialize)]
951pub struct LoggingNotification {
952    /// Log level
953    pub level: LogLevel,
954    /// Log data
955    pub data: serde_json::Value,
956    /// Optional logger name
957    #[serde(skip_serializing_if = "Option::is_none")]
958    pub logger: Option<String>,
959}
960
961// ============================================================================
962// Progress Types
963// ============================================================================
964
965/// Progress notification per MCP 2025-06-18 specification
966#[derive(Debug, Clone, Serialize, Deserialize)]
967pub struct ProgressNotification {
968    /// The progress token which was given in the initial request
969    /// Used to associate this notification with the request that is proceeding
970    #[serde(rename = "progressToken")]
971    pub progress_token: ProgressToken,
972    /// The progress thus far. This should increase every time progress is made,
973    /// even if the total is unknown
974    pub progress: f64,
975    /// Total number of items to process (or total progress required), if known
976    #[serde(skip_serializing_if = "Option::is_none")]
977    pub total: Option<f64>,
978    /// An optional message describing the current progress
979    #[serde(skip_serializing_if = "Option::is_none")]
980    pub message: Option<String>,
981}
982
983/// Cancellation notification per MCP 2025-06-18 specification
984#[derive(Debug, Clone, Serialize, Deserialize)]
985pub struct CancelledNotification {
986    /// The ID of the request to cancel
987    /// This MUST correspond to the ID of a request previously issued in the same direction
988    #[serde(rename = "requestId")]
989    pub request_id: RequestId,
990    /// An optional string describing the reason for the cancellation
991    /// This MAY be logged or presented to the user
992    #[serde(skip_serializing_if = "Option::is_none")]
993    pub reason: Option<String>,
994}
995
996// ============================================================================
997// Sampling Types
998// ============================================================================
999
1000/// Create message request
1001#[derive(Debug, Clone, Serialize, Deserialize)]
1002pub struct CreateMessageRequest {
1003    /// Messages to include
1004    pub messages: Vec<SamplingMessage>,
1005    /// Model preferences
1006    #[serde(rename = "modelPreferences", skip_serializing_if = "Option::is_none")]
1007    pub model_preferences: Option<ModelPreferences>,
1008    /// System prompt
1009    #[serde(rename = "systemPrompt", skip_serializing_if = "Option::is_none")]
1010    pub system_prompt: Option<String>,
1011    /// Include context
1012    #[serde(rename = "includeContext", skip_serializing_if = "Option::is_none")]
1013    pub include_context: Option<IncludeContext>,
1014    /// Temperature
1015    #[serde(skip_serializing_if = "Option::is_none")]
1016    pub temperature: Option<f64>,
1017    /// Max tokens
1018    #[serde(rename = "maxTokens", skip_serializing_if = "Option::is_none")]
1019    pub max_tokens: Option<u32>,
1020    /// Stop sequences
1021    #[serde(rename = "stopSequences", skip_serializing_if = "Option::is_none")]
1022    pub stop_sequences: Option<Vec<String>>,
1023    /// Metadata
1024    #[serde(skip_serializing_if = "Option::is_none")]
1025    pub metadata: Option<HashMap<String, serde_json::Value>>,
1026}
1027
1028/// Model preferences
1029#[derive(Debug, Clone, Serialize, Deserialize)]
1030pub struct ModelPreferences {
1031    /// Preferred hints
1032    #[serde(skip_serializing_if = "Option::is_none")]
1033    pub hints: Option<Vec<ModelHint>>,
1034    /// Cost priority
1035    #[serde(rename = "costPriority", skip_serializing_if = "Option::is_none")]
1036    pub cost_priority: Option<f64>,
1037    /// Speed priority
1038    #[serde(rename = "speedPriority", skip_serializing_if = "Option::is_none")]
1039    pub speed_priority: Option<f64>,
1040    /// Intelligence priority
1041    #[serde(
1042        rename = "intelligencePriority",
1043        skip_serializing_if = "Option::is_none"
1044    )]
1045    pub intelligence_priority: Option<f64>,
1046}
1047
1048/// Model hint
1049#[derive(Debug, Clone, Serialize, Deserialize)]
1050pub struct ModelHint {
1051    /// Hint name
1052    pub name: Option<String>,
1053}
1054
1055/// Include context options
1056#[derive(Debug, Clone, Serialize, Deserialize)]
1057#[serde(rename_all = "lowercase")]
1058pub enum IncludeContext {
1059    /// No context
1060    None,
1061    /// This server only
1062    ThisServer,
1063    /// All servers
1064    AllServers,
1065}
1066
1067/// Sampling message
1068#[derive(Debug, Clone, Serialize, Deserialize)]
1069pub struct SamplingMessage {
1070    /// Message role
1071    pub role: Role,
1072    /// Message content
1073    pub content: Content,
1074}
1075
1076/// Create message result
1077#[derive(Debug, Clone, Serialize, Deserialize)]
1078pub struct CreateMessageResult {
1079    /// Role of the created message
1080    pub role: Role,
1081    /// Content of the created message
1082    pub content: Content,
1083    /// Model used
1084    #[serde(skip_serializing_if = "Option::is_none")]
1085    pub model: Option<String>,
1086    /// Stop reason
1087    #[serde(rename = "stopReason", skip_serializing_if = "Option::is_none")]
1088    pub stop_reason: Option<String>,
1089}
1090
1091// ============================================================================
1092// Roots Types
1093// ============================================================================
1094
1095/// Filesystem root
1096#[derive(Debug, Clone, Serialize, Deserialize)]
1097pub struct Root {
1098    /// Root URI
1099    pub uri: Uri,
1100    /// Root name
1101    #[serde(skip_serializing_if = "Option::is_none")]
1102    pub name: Option<String>,
1103}
1104
1105/// List roots request (no parameters)
1106#[derive(Debug, Clone, Serialize, Deserialize)]
1107pub struct ListRootsRequest;
1108
1109/// List roots result
1110#[derive(Debug, Clone, Serialize, Deserialize)]
1111pub struct ListRootsResult {
1112    /// Available roots
1113    pub roots: Vec<Root>,
1114}
1115
1116/// Roots list changed notification (no parameters)
1117#[derive(Debug, Clone, Serialize, Deserialize)]
1118pub struct RootsListChangedNotification;
1119
1120/// Empty result for operations that don't return data
1121#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1122pub struct EmptyResult {}
1123
1124#[cfg(test)]
1125mod tests {
1126    use super::*;
1127
1128    #[test]
1129    fn test_serialize_deserialize() {
1130        let tool = Tool {
1131            name: "test_tool".to_string(),
1132            title: Some("Test Tool".to_string()),
1133            description: Some("A test tool".to_string()),
1134            input_schema: ToolInputSchema {
1135                schema_type: "object".to_string(),
1136                properties: None,
1137                required: None,
1138                additional_properties: None,
1139            },
1140            output_schema: None,
1141            annotations: None,
1142            meta: None,
1143        };
1144
1145        let json = serde_json::to_string(&tool).unwrap();
1146        let deserialized: Tool = serde_json::from_str(&json).unwrap();
1147        assert_eq!(tool.name, deserialized.name);
1148    }
1149
1150    #[test]
1151    fn test_content_types() {
1152        let text_content = ContentBlock::Text(TextContent {
1153            text: "Hello, World!".to_string(),
1154            annotations: None,
1155            meta: None,
1156        });
1157
1158        let json = serde_json::to_string(&text_content).unwrap();
1159        let _deserialized: ContentBlock = serde_json::from_str(&json).unwrap();
1160
1161        // Test the compatibility alias
1162        let _compatible: Content = text_content;
1163    }
1164}