airsprotocols_mcp/protocol/
types.rs

1//! Core MCP Protocol Types and Domain-Specific Newtypes
2//!
3//! This module provides domain-specific newtypes and core protocol structures
4//! with validation and proper encapsulation. These types are migrated from
5//! the shared/protocol/types module as part of the module consolidation.
6//!
7//! # Architecture
8//!
9//! All types use private internal fields with controlled access through validated
10//! constructors and accessor methods, ensuring type safety and preventing invalid
11//! protocol messages at compile time.
12//!
13//! # Examples
14//!
15//! ```rust
16//! use airsprotocols_mcp::protocol::{Uri, ProtocolVersion, ClientInfo};
17//!
18//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
19//! // Type-safe protocol construction
20//! let uri = Uri::new("file:///path/to/resource")?;
21//! let version = ProtocolVersion::current();
22//! let client_info = ClientInfo {
23//!     name: "example-client".to_string(),
24//!     version: "1.0.0".to_string(),
25//! };
26//!
27//! // All validation happens at construction time
28//! assert_eq!(uri.scheme(), Some("file"));
29//! assert_eq!(version.as_str(), "2025-06-18");
30//! # Ok(())
31//! # }
32//! ```
33
34// Layer 1: Standard library imports
35use std::collections::HashMap;
36use std::fmt;
37
38// Layer 2: Third-party crate imports
39use serde::{Deserialize, Serialize};
40use serde_json::{self, json};
41
42// Layer 3: Internal module imports
43use crate::protocol::errors::{ProtocolError, ProtocolResult};
44use crate::protocol::{JsonRpcRequest, RequestId};
45use crate::protocol::constants::methods;
46
47/// Protocol version with validation and proper encapsulation
48///
49/// Represents an MCP protocol version in the format YYYY-MM-DD.
50/// The internal string representation is private to ensure validation
51/// and provide flexibility for future implementation changes.
52///
53/// # Examples
54///
55/// ```rust
56/// use airsprotocols_mcp::protocol::ProtocolVersion;
57///
58/// // Create current protocol version
59/// let version = ProtocolVersion::current();
60/// assert_eq!(version.as_str(), "2025-06-18");
61///
62/// // Create custom version with validation
63/// let version = ProtocolVersion::new("2025-06-18")?;
64/// assert_eq!(version.as_str(), "2025-06-18");
65///
66/// // Invalid version format fails
67/// let result = ProtocolVersion::new("invalid");
68/// assert!(result.is_err());
69/// # Ok::<(), Box<dyn std::error::Error>>(())
70/// ```
71#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
72pub struct ProtocolVersion(String);
73
74impl ProtocolVersion {
75    /// Current supported protocol version
76    pub const CURRENT: &'static str = "2025-06-18";
77    
78    /// Create a new protocol version with validation
79    ///
80    /// # Errors
81    ///
82    /// Returns `ProtocolError::InvalidProtocolVersion` if the version
83    /// format is not YYYY-MM-DD.
84    pub fn new(version: impl Into<String>) -> ProtocolResult<Self> {
85        let version = version.into();
86        if Self::is_valid_version(&version) {
87            Ok(Self(version))
88        } else {
89            Err(ProtocolError::InvalidProtocolVersion(version))
90        }
91    }
92    
93    /// Create current protocol version
94    ///
95    /// This is guaranteed to be valid and will never fail.
96    pub fn current() -> Self {
97        Self(Self::CURRENT.to_string())
98    }
99    
100    /// Get the version string
101    pub fn as_str(&self) -> &str {
102        &self.0
103    }
104    
105    /// Check if this version is compatible with another version
106    ///
107    /// Currently implements exact version matching, but can be enhanced
108    /// for semantic version compatibility in the future.
109    pub fn is_compatible_with(&self, other: &Self) -> bool {
110        self.0 == other.0
111    }
112    
113    fn is_valid_version(version: &str) -> bool {
114        // Validate YYYY-MM-DD format
115        if version.len() != 10 {
116            return false;
117        }
118        
119        let chars: Vec<char> = version.chars().collect();
120        
121        // Check format: YYYY-MM-DD
122        chars.get(4) == Some(&'-') && 
123        chars.get(7) == Some(&'-') &&
124        chars[0..4].iter().all(|c| c.is_ascii_digit()) &&
125        chars[5..7].iter().all(|c| c.is_ascii_digit()) &&
126        chars[8..10].iter().all(|c| c.is_ascii_digit())
127    }
128}
129
130impl Default for ProtocolVersion {
131    fn default() -> Self {
132        Self::current()
133    }
134}
135
136impl fmt::Display for ProtocolVersion {
137    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
138        write!(f, "{}", self.0)
139    }
140}
141
142/// URI with validation and type safety
143///
144/// Represents a Uniform Resource Identifier with validation and utility methods.
145/// The internal string representation is private to ensure validation.
146///
147/// # Examples
148///
149/// ```rust
150/// use airsprotocols_mcp::protocol::Uri;
151///
152/// // Valid URI construction
153/// let uri = Uri::new("file:///path/to/file")?;
154/// assert_eq!(uri.scheme(), Some("file"));
155/// assert_eq!(uri.as_str(), "file:///path/to/file");
156///
157/// // Invalid URI fails validation
158/// let result = Uri::new("not-a-uri");
159/// assert!(result.is_err());
160///
161/// // Unchecked construction for trusted sources
162/// let uri = Uri::new_unchecked("custom://internal");
163/// # Ok::<(), Box<dyn std::error::Error>>(())
164/// ```
165#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
166pub struct Uri(String);
167
168impl Uri {
169    /// Create a new URI with validation
170    ///
171    /// # Errors
172    ///
173    /// Returns `ProtocolError::InvalidUri` if the URI format is invalid.
174    pub fn new(uri: impl Into<String>) -> ProtocolResult<Self> {
175        let uri = uri.into();
176        if Self::is_valid_uri(&uri) {
177            Ok(Self(uri))
178        } else {
179            Err(ProtocolError::InvalidUri(uri))
180        }
181    }
182    
183    /// Create URI without validation (for trusted sources)
184    ///
185    /// This should only be used when the URI is known to be valid,
186    /// such as constants or internally generated URIs.
187    pub fn new_unchecked(uri: impl Into<String>) -> Self {
188        Self(uri.into())
189    }
190    
191    /// Get the URI string
192    pub fn as_str(&self) -> &str {
193        &self.0
194    }
195    
196    /// Extract the URI scheme (e.g., "file", "http", "custom")
197    pub fn scheme(&self) -> Option<&str> {
198        self.0.split(':').next()
199    }
200    
201    /// Check if this is a file URI
202    pub fn is_file_uri(&self) -> bool {
203        self.scheme() == Some("file")
204    }
205    
206    /// Check if this is an HTTP/HTTPS URI
207    pub fn is_http_uri(&self) -> bool {
208        matches!(self.scheme(), Some("http") | Some("https"))
209    }
210    
211    fn is_valid_uri(uri: &str) -> bool {
212        // Basic URI validation - must have scheme and not be empty
213        !uri.is_empty() && uri.contains(':') && !uri.starts_with(':')
214    }
215}
216
217impl fmt::Display for Uri {
218    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
219        write!(f, "{}", self.0)
220    }
221}
222
223/// MIME type with validation
224///
225/// Represents a MIME type with validation to ensure proper format.
226/// The internal string representation is private to ensure validation.
227///
228/// # Examples
229///
230/// ```rust
231/// use airsprotocols_mcp::protocol::MimeType;
232///
233/// // Valid MIME type construction
234/// let mime = MimeType::new("text/plain")?;
235/// assert_eq!(mime.as_str(), "text/plain");
236/// assert_eq!(mime.main_type(), "text");
237/// assert_eq!(mime.sub_type(), "plain");
238///
239/// // Invalid MIME type fails validation
240/// let result = MimeType::new("invalid");
241/// assert!(result.is_err());
242/// # Ok::<(), Box<dyn std::error::Error>>(())
243/// ```
244#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
245pub struct MimeType(String);
246
247impl MimeType {
248    /// Create a new MIME type with validation
249    ///
250    /// # Errors
251    ///
252    /// Returns `ProtocolError::InvalidMimeType` if the MIME type format is invalid.
253    pub fn new(mime_type: impl Into<String>) -> ProtocolResult<Self> {
254        let mime_type = mime_type.into();
255        if Self::is_valid_mime_type(&mime_type) {
256            Ok(Self(mime_type))
257        } else {
258            Err(ProtocolError::InvalidMimeType(mime_type))
259        }
260    }
261    
262    /// Get the MIME type string
263    pub fn as_str(&self) -> &str {
264        &self.0
265    }
266    
267    /// Get the main type (e.g., "text" from "text/plain")
268    pub fn main_type(&self) -> &str {
269        self.0.split('/').next().unwrap_or("")
270    }
271    
272    /// Get the sub type (e.g., "plain" from "text/plain")
273    pub fn sub_type(&self) -> &str {
274        self.0.split('/').nth(1).unwrap_or("")
275    }
276    
277    /// Check if this is a text MIME type
278    pub fn is_text(&self) -> bool {
279        self.main_type() == "text"
280    }
281    
282    /// Check if this is an image MIME type
283    pub fn is_image(&self) -> bool {
284        self.main_type() == "image"
285    }
286    
287    fn is_valid_mime_type(mime_type: &str) -> bool {
288        // Basic MIME type validation: type/subtype
289        if !mime_type.contains('/') || mime_type.starts_with('/') || mime_type.ends_with('/') {
290            return false;
291        }
292        
293        let parts: Vec<&str> = mime_type.split('/').collect();
294        parts.len() == 2 && !parts[0].is_empty() && !parts[1].is_empty()
295    }
296}
297
298impl fmt::Display for MimeType {
299    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
300        write!(f, "{}", self.0)
301    }
302}
303
304/// Base64 encoded data with validation
305///
306/// Represents base64 encoded data with validation to ensure proper encoding.
307/// The internal string representation is private to ensure validation.
308///
309/// # Examples
310///
311/// ```rust
312/// use airsprotocols_mcp::protocol::Base64Data;
313///
314/// // Valid base64 construction
315/// let data = Base64Data::new("SGVsbG8gV29ybGQ=")?;
316/// assert_eq!(data.as_str(), "SGVsbG8gV29ybGQ=");
317///
318/// // Invalid base64 fails validation
319/// let result = Base64Data::new("invalid!@#");
320/// assert!(result.is_err());
321/// # Ok::<(), Box<dyn std::error::Error>>(())
322/// ```
323#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
324pub struct Base64Data(String);
325
326impl Base64Data {
327    /// Create new base64 data with validation
328    ///
329    /// # Errors
330    ///
331    /// Returns `ProtocolError::InvalidBase64Data` if the data is not valid base64.
332    pub fn new(data: impl Into<String>) -> ProtocolResult<Self> {
333        let data = data.into();
334        if Self::is_valid_base64(&data) {
335            Ok(Self(data))
336        } else {
337            Err(ProtocolError::InvalidBase64Data)
338        }
339    }
340    
341    /// Get the base64 string
342    pub fn as_str(&self) -> &str {
343        &self.0
344    }
345    
346    /// Get the length of the base64 string
347    pub fn len(&self) -> usize {
348        self.0.len()
349    }
350    
351    /// Check if the base64 string is empty
352    pub fn is_empty(&self) -> bool {
353        self.0.is_empty()
354    }
355    
356    fn is_valid_base64(data: &str) -> bool {
357        // Basic base64 validation - can be enhanced with proper base64 crate
358        if data.is_empty() {
359            return false;
360        }
361        
362        // Check that all characters are valid base64 characters
363        data.chars().all(|c| {
364            c.is_ascii_alphanumeric() || c == '+' || c == '/' || c == '='
365        }) && 
366        // Check padding is only at the end
367        !data.trim_end_matches('=').contains('=')
368    }
369}
370
371impl fmt::Display for Base64Data {
372    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
373        write!(f, "{}", self.0)
374    }
375}
376
377/// Client information for protocol initialization
378///
379/// Contains information about the MCP client, including name and version.
380/// This information is exchanged during the initialization handshake.
381///
382/// # Examples
383///
384/// ```rust
385/// use airsprotocols_mcp::protocol::ClientInfo;
386///
387/// let client_info = ClientInfo {
388///     name: "example-client".to_string(),
389///     version: "1.0.0".to_string(),
390/// };
391/// ```
392#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
393pub struct ClientInfo {
394    /// Name of the client application
395    pub name: String,
396    /// Version of the client application
397    pub version: String,
398}
399
400/// Server information for protocol initialization
401///
402/// Contains information about the MCP server, including name and version.
403/// This information is exchanged during the initialization handshake.
404///
405/// # Examples
406///
407/// ```rust
408/// use airsprotocols_mcp::protocol::ServerInfo;
409///
410/// let server_info = ServerInfo {
411///     name: "example-server".to_string(),
412///     version: "1.0.0".to_string(),
413/// };
414/// ```
415#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
416pub struct ServerInfo {
417    /// Name of the server application
418    pub name: String,
419    /// Version of the server application
420    pub version: String,
421}
422
423// TODO(DEBT-ARCH): Add content types from shared/protocol/types/content.rs
424// Reference: ResourceContent, TextContent, BlobContent structures
425// TODO(DEBT-ARCH): Add MCP message structures from shared/protocol/messages/
426// Reference: InitializeRequest, InitializeResponse, capability definitions
427
428// ==== Additional Types Restored from git for compilation ====
429
430/// Multi-modal content for MCP protocol messages
431#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
432#[serde(tag = "type")]
433pub enum Content {
434    /// Plain text content
435    #[serde(rename = "text")]
436    Text {
437        /// The text content
438        text: String,
439        /// URI of the resource (optional)
440        #[serde(skip_serializing_if = "Option::is_none")]
441        uri: Option<Uri>,
442        /// MIME type of the content
443        #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
444        mime_type: Option<MimeType>,
445    },
446
447    /// Image content with base64 encoded data
448    #[serde(rename = "image")]
449    Image {
450        /// Base64 encoded image data
451        #[serde(rename = "data")]
452        data: Base64Data,
453        /// MIME type of the image
454        #[serde(rename = "mimeType")]
455        mime_type: MimeType,
456        /// URI of the resource (optional)
457        #[serde(skip_serializing_if = "Option::is_none")]
458        uri: Option<Uri>,
459    },
460
461    /// Resource reference content
462    #[serde(rename = "resource")]
463    Resource {
464        /// URI of the resource
465        #[serde(rename = "uri")]
466        resource: Uri,
467        /// Optional text description of the resource
468        text: Option<String>,
469        /// Optional MIME type of the resource
470        #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
471        mime_type: Option<MimeType>,
472    },
473}
474
475impl Content {
476    /// Create text content
477    pub fn text(text: impl Into<String>) -> Self {
478        Self::Text {
479            text: text.into(),
480            uri: None,
481            mime_type: None,
482        }
483    }
484    
485    /// Create text content with URI
486    pub fn text_with_uri(text: impl Into<String>, uri: impl Into<String>) -> Result<Self, String> {
487        let uri_str = uri.into();
488        let uri = Uri::new_unchecked(uri_str);
489        Ok(Self::Text {
490            text: text.into(),
491            uri: Some(uri),
492            mime_type: None,
493        })
494    }
495
496    /// Extract text content if available
497    pub fn as_text(&self) -> Option<&str> {
498        match self {
499            Content::Text { text, .. } => Some(text),
500            Content::Resource { text: Some(text), .. } => Some(text),
501            _ => None,
502        }
503    }
504}
505
506/// Tool definition for MCP protocol
507#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
508pub struct Tool {
509    pub name: String,
510    pub description: Option<String>,
511    #[serde(rename = "inputSchema")]
512    pub input_schema: serde_json::Value,
513}
514
515/// Capability system definitions
516/// Client capabilities for MCP protocol
517#[derive(Debug, Clone, Serialize, Deserialize, Default)]
518pub struct ClientCapabilities {
519    pub experimental: Option<serde_json::Value>,
520    pub sampling: Option<SamplingCapabilities>,
521    pub roots: Option<RootsCapabilities>,
522}
523
524/// Server capabilities for MCP protocol
525#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
526pub struct ServerCapabilities {
527    pub experimental: Option<serde_json::Value>,
528    pub logging: Option<LoggingCapabilities>,
529    pub prompts: Option<PromptCapabilities>,
530    pub resources: Option<ResourceCapabilities>,
531    pub tools: Option<ToolCapabilities>,
532}
533
534impl Default for ServerCapabilities {
535    fn default() -> Self {
536        Self {
537            experimental: Some(json!({})), // Empty object instead of null
538            logging: None,
539            prompts: None,
540            resources: None,
541            tools: None,
542        }
543    }
544}
545
546/// Sampling capabilities
547#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
548pub struct SamplingCapabilities {}
549
550/// Roots capabilities
551#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
552pub struct RootsCapabilities {
553    pub list_changed: Option<bool>,
554}
555
556/// Logging capabilities
557#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
558#[derive(Default)]
559pub struct LoggingCapabilities {}
560
561
562/// Prompt capabilities
563#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
564pub struct PromptCapabilities {
565    pub list_changed: Option<bool>,
566}
567
568impl Default for PromptCapabilities {
569    fn default() -> Self {
570        Self {
571            list_changed: Some(false),
572        }
573    }
574}
575
576/// Resource capabilities
577#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
578pub struct ResourceCapabilities {
579    pub subscribe: Option<bool>,
580    pub list_changed: Option<bool>,
581}
582
583impl Default for ResourceCapabilities {
584    fn default() -> Self {
585        Self {
586            subscribe: Some(false),
587            list_changed: Some(false),
588        }
589    }
590}
591
592/// Tool capabilities
593#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
594pub struct ToolCapabilities {
595    pub list_changed: Option<bool>,
596}
597
598impl Default for ToolCapabilities {
599    fn default() -> Self {
600        Self {
601            list_changed: Some(false),
602        }
603    }
604}
605
606/// Represents a prompt template available from the server
607#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
608pub struct Prompt {
609    /// Unique identifier for the prompt
610    pub name: String,
611    /// Human-readable name for the prompt
612    pub title: Option<String>,
613    /// Optional description of the prompt's purpose
614    pub description: Option<String>,
615    /// Array of arguments this prompt accepts
616    pub arguments: Vec<PromptArgument>,
617}
618
619/// Represents an argument for a prompt template
620#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
621pub struct PromptArgument {
622    /// Name of the argument
623    pub name: String,
624    /// Description of the argument
625    pub description: Option<String>,
626    /// Whether this argument is required
627    pub required: bool,
628}
629
630impl PromptArgument {
631    /// Create a required argument
632    pub fn required(name: impl Into<String>, description: Option<impl Into<String>>) -> Self {
633        Self {
634            name: name.into(),
635            description: description.map(|d| d.into()),
636            required: true,
637        }
638    }
639    
640    /// Create an optional argument
641    pub fn optional(name: impl Into<String>, description: Option<impl Into<String>>) -> Self {
642        Self {
643            name: name.into(),
644            description: description.map(|d| d.into()),
645            required: false,
646        }
647    }
648}
649
650/// Prompt message content
651#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
652pub struct PromptMessage {
653    /// Role of the message sender
654    pub role: String,
655    /// Content of the message
656    pub content: Content,
657}
658
659impl PromptMessage {
660    /// Create a user message
661    pub fn user(content: Content) -> Self {
662        Self {
663            role: "user".to_string(),
664            content,
665        }
666    }
667    
668    /// Create an assistant message
669    pub fn assistant(content: Content) -> Self {
670        Self {
671            role: "assistant".to_string(),
672            content,
673        }
674    }
675    
676    /// Create a system message
677    pub fn system(content: Content) -> Self {
678        Self {
679            role: "system".to_string(),
680            content,
681        }
682    }
683}
684
685/// Represents a resource available from the server
686#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
687pub struct Resource {
688    /// URI of the resource
689    pub uri: Uri,
690    /// Name of the resource
691    pub name: String,
692    /// Description of the resource
693    pub description: Option<String>,
694    /// MIME type of the resource
695    #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
696    pub mime_type: Option<MimeType>,
697}
698
699/// Log level enumeration
700#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
701#[serde(rename_all = "lowercase")]
702pub enum LogLevel {
703    Debug,
704    Info,
705    Warning,
706    Error,
707    Critical,
708}
709
710impl LogLevel {
711    /// Convert LogLevel to string representation
712    pub fn as_str(&self) -> &'static str {
713        match self {
714            LogLevel::Debug => "debug",
715            LogLevel::Info => "info", 
716            LogLevel::Warning => "warning",
717            LogLevel::Error => "error",
718            LogLevel::Critical => "critical",
719        }
720    }
721}
722
723/// Logging configuration
724#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
725pub struct LoggingConfig {
726    /// Minimum log level to include
727    pub level: LogLevel,
728}
729
730impl Default for LoggingConfig {
731    fn default() -> Self {
732        Self {
733            level: LogLevel::Info,
734        }
735    }
736}
737
738impl LoggingConfig {
739    /// Create a new logging config with specified level
740    pub fn new(level: LogLevel) -> Self {
741        Self { level }
742    }
743    
744    /// Get the minimum level (compatibility with old API)
745    pub fn min_level(&self) -> &LogLevel {
746        &self.level
747    }
748}
749
750/// Initialize request message
751#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
752pub struct InitializeRequest {
753    /// Protocol version
754    #[serde(rename = "protocolVersion")]
755    pub protocol_version: ProtocolVersion,
756    /// Capabilities requested by client
757    pub capabilities: serde_json::Value,
758    /// Client information
759    #[serde(rename = "clientInfo")]
760    pub client_info: ClientInfo,
761}
762
763/// Initialize response message
764#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
765pub struct InitializeResponse {
766    /// Protocol version
767    #[serde(rename = "protocolVersion")]
768    pub protocol_version: ProtocolVersion,
769    /// Capabilities offered by server
770    pub capabilities: serde_json::Value,
771    /// Server information
772    #[serde(rename = "serverInfo")]
773    pub server_info: ServerInfo,
774}
775
776impl InitializeResponse {
777    /// Create a new initialize response
778    pub fn new(
779        capabilities: serde_json::Value,
780        server_info: ServerInfo,
781        _instructions: Option<String>, // instructions are handled elsewhere
782    ) -> Self {
783        Self {
784            protocol_version: ProtocolVersion::current(),
785            capabilities,
786            server_info,
787        }
788    }
789}
790
791/// Set logging request message
792#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
793pub struct SetLoggingRequest {
794    /// Logging level to set
795    pub level: LogLevel,
796}
797
798impl SetLoggingRequest {
799    /// Create a new set logging request
800    pub fn new(level: LogLevel) -> Self {
801        Self { level }
802    }
803}
804
805/// Get prompt request message
806#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
807pub struct GetPromptRequest {
808    /// Name of the prompt to get
809    pub name: String,
810    /// Arguments for the prompt
811    pub arguments: std::collections::HashMap<String, String>,
812}
813
814/// Read resource request message
815#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
816pub struct ReadResourceRequest {
817    /// URI of the resource to read
818    pub uri: Uri,
819}
820
821/// Subscribe resource request message
822#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
823pub struct SubscribeResourceRequest {
824    /// URI of the resource to subscribe to
825    pub uri: Uri,
826}
827
828/// Unsubscribe resource request message
829#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
830pub struct UnsubscribeResourceRequest {
831    /// URI of the resource to unsubscribe from
832    pub uri: Uri,
833}
834
835/// Call tool request message
836#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
837pub struct CallToolRequest {
838    /// Name of the tool to call
839    pub name: String,
840    /// Arguments for the tool
841    pub arguments: serde_json::Value,
842}
843
844/// List resources request
845#[derive(Debug, Clone, Serialize, Deserialize)]
846pub struct ListResourcesRequest {
847    pub cursor: Option<String>,
848}
849
850impl Default for ListResourcesRequest {
851    fn default() -> Self {
852        Self::new()
853    }
854}
855
856impl ListResourcesRequest {
857    /// Create a new list resources request
858    pub fn new() -> Self {
859        Self { cursor: None }
860    }
861
862    /// Create a new list resources request with cursor
863    pub fn with_cursor(cursor: impl Into<String>) -> Self {
864        Self { cursor: Some(cursor.into()) }
865    }
866
867    /// Convert to JSON-RPC request
868    pub fn to_jsonrpc_request(&self, id: RequestId) -> Result<JsonRpcRequest, ProtocolError> {
869        let params = serde_json::to_value(self)
870            .map_err(|e| ProtocolError::Serialization { message: format!("Failed to serialize ListResourcesRequest: {e}") })?;
871        
872        Ok(JsonRpcRequest {
873            jsonrpc: "2.0".to_string(),
874            method: methods::RESOURCES_LIST.to_string(),
875            params: Some(params),
876            id,
877        })
878    }
879}
880
881/// List resources response
882#[derive(Debug, Clone, Serialize, Deserialize)]
883pub struct ListResourcesResponse {
884    pub resources: Vec<Resource>,
885    pub next_cursor: Option<String>,
886}
887
888/// List prompts request
889#[derive(Debug, Clone, Serialize, Deserialize)]
890pub struct ListPromptsRequest {
891    pub cursor: Option<String>,
892}
893
894impl Default for ListPromptsRequest {
895    fn default() -> Self {
896        Self::new()
897    }
898}
899
900impl ListPromptsRequest {
901    /// Create a new list prompts request
902    pub fn new() -> Self {
903        Self { cursor: None }
904    }
905
906    /// Create a new list prompts request with cursor
907    pub fn with_cursor(cursor: impl Into<String>) -> Self {
908        Self { cursor: Some(cursor.into()) }
909    }
910
911    /// Convert to JSON-RPC request
912    pub fn to_jsonrpc_request(&self, id: RequestId) -> Result<JsonRpcRequest, ProtocolError> {
913        let params = serde_json::to_value(self)
914            .map_err(|e| ProtocolError::Serialization { message: format!("Failed to serialize ListPromptsRequest: {e}") })?;
915        
916        Ok(JsonRpcRequest {
917            jsonrpc: "2.0".to_string(),
918            method: methods::PROMPTS_LIST.to_string(),
919            params: Some(params),
920            id,
921        })
922    }
923}
924
925/// List prompts response
926#[derive(Debug, Clone, Serialize, Deserialize)]
927pub struct ListPromptsResponse {
928    pub prompts: Vec<Prompt>,
929    pub next_cursor: Option<String>,
930}
931
932/// List tools request
933#[derive(Debug, Clone, Serialize, Deserialize)]
934pub struct ListToolsRequest {
935    pub cursor: Option<String>,
936}
937
938impl Default for ListToolsRequest {
939    fn default() -> Self {
940        Self::new()
941    }
942}
943
944impl ListToolsRequest {
945    /// Create a new list tools request
946    pub fn new() -> Self {
947        Self { cursor: None }
948    }
949
950    /// Create a new list tools request with cursor
951    pub fn with_cursor(cursor: impl Into<String>) -> Self {
952        Self { cursor: Some(cursor.into()) }
953    }
954
955    /// Convert to JSON-RPC request
956    pub fn to_jsonrpc_request(&self, id: RequestId) -> Result<JsonRpcRequest, ProtocolError> {
957        let params = serde_json::to_value(self)
958            .map_err(|e| ProtocolError::Serialization { message: format!("Failed to serialize ListToolsRequest: {e}") })?;
959        
960        Ok(JsonRpcRequest {
961            jsonrpc: "2.0".to_string(),
962            method: methods::TOOLS_LIST.to_string(),
963            params: Some(params),
964            id,
965        })
966    }
967}
968
969/// List tools response
970#[derive(Debug, Clone, Serialize, Deserialize)]
971pub struct ListToolsResponse {
972    pub tools: Vec<Tool>,
973    pub next_cursor: Option<String>,
974}
975
976/// Call tool response
977#[derive(Debug, Clone, Serialize, Deserialize)]
978pub struct CallToolResponse {
979    pub content: Vec<Content>,
980    pub is_error: Option<bool>,
981}
982
983/// Get prompt response
984#[derive(Debug, Clone, Serialize, Deserialize)]
985pub struct GetPromptResponse {
986    pub description: Option<String>,
987    pub messages: Vec<PromptMessage>,
988}
989
990/// Read resource response
991#[derive(Debug, Clone, Serialize, Deserialize)]
992pub struct ReadResourceResponse {
993    pub contents: Vec<Content>,
994}
995
996/// Set logging response
997#[derive(Debug, Clone, Serialize, Deserialize)]
998pub struct SetLoggingResponse {
999    pub success: bool,
1000    pub message: Option<String>,
1001}
1002
1003/// List resource templates response
1004#[derive(Debug, Clone, Serialize, Deserialize)]
1005pub struct ListResourceTemplatesResponse {
1006    pub resource_templates: Vec<ResourceTemplate>,
1007    pub next_cursor: Option<String>,
1008}
1009
1010/// Resource template for dynamic resources
1011#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1012pub struct ResourceTemplate {
1013    pub uri_template: String,
1014    pub name: String,
1015    pub description: Option<String>,
1016    pub mime_type: Option<String>,
1017}
1018
1019// Constructor implementations for request types
1020impl InitializeRequest {
1021    /// Create a new InitializeRequest with specific protocol version
1022    pub fn with_version(
1023        protocol_version: ProtocolVersion,
1024        capabilities: serde_json::Value,
1025        client_info: ClientInfo,
1026    ) -> Self {
1027        Self {
1028            protocol_version,
1029            capabilities,
1030            client_info,
1031        }
1032    }
1033
1034    /// Convert to JSON-RPC request
1035    pub fn to_jsonrpc_request(&self, id: RequestId) -> Result<JsonRpcRequest, ProtocolError> {
1036        let params = serde_json::to_value(self)
1037            .map_err(|e| ProtocolError::Serialization { message: format!("Failed to serialize InitializeRequest: {e}") })?;
1038        
1039        Ok(JsonRpcRequest {
1040            jsonrpc: "2.0".to_string(),
1041            method: methods::INITIALIZE.to_string(),
1042            params: Some(params),
1043            id,
1044        })
1045    }
1046}
1047
1048impl ReadResourceRequest {
1049    /// Create a new ReadResourceRequest for a URI
1050    pub fn new(uri: String) -> Result<Self, crate::protocol::TransportError> {
1051        Ok(Self { uri: Uri::new_unchecked(uri) })
1052    }
1053}
1054
1055impl SubscribeResourceRequest {
1056    /// Create a new SubscribeResourceRequest for a URI
1057    pub fn new(uri: String) -> Result<Self, crate::protocol::TransportError> {
1058        Ok(Self { uri: Uri::new_unchecked(uri) })
1059    }
1060}
1061
1062impl CallToolRequest {
1063    /// Create a new CallToolRequest
1064    pub fn new(name: String, arguments: serde_json::Value) -> Self {
1065        Self { name, arguments }
1066    }
1067}
1068
1069impl GetPromptRequest {
1070    /// Create a new GetPromptRequest
1071    pub fn new(name: String, arguments: HashMap<String, String>) -> Self {
1072        Self { name, arguments }
1073    }
1074}
1075
1076// Constructor implementations for response types
1077impl CallToolResponse {
1078    /// Create a successful tool call response
1079    pub fn success(content: Vec<Content>) -> Self {
1080        Self {
1081            content,
1082            is_error: Some(false),
1083        }
1084    }
1085    
1086    /// Create an error tool call response
1087    pub fn error_text(error: String) -> Self {
1088        Self {
1089            content: vec![Content::text(error)],
1090            is_error: Some(true),
1091        }
1092    }
1093}
1094
1095/// Core MCP server configuration required by all transports
1096///
1097/// This contains only the universal MCP requirements that every transport needs,
1098/// regardless of transport type (STDIO, HTTP, WebSocket, etc.). This configuration
1099/// defines the fundamental server identity, capabilities, and protocol compliance
1100/// that must be consistent across all transport implementations.
1101///
1102/// # Architecture
1103///
1104/// This struct represents the protocol-level server configuration that sits at the
1105/// foundation of the MCP transport abstraction. All transport-specific configurations
1106/// should embed this as their core configuration to ensure protocol compliance.
1107///
1108/// # Examples
1109///
1110/// ```rust
1111/// use airsprotocols_mcp::protocol::types::{ServerConfig, ServerInfo, ServerCapabilities, ProtocolVersion};
1112///
1113/// // Default configuration
1114/// let config = ServerConfig::default();
1115///
1116/// // Custom configuration
1117/// let config = ServerConfig {
1118///     server_info: ServerInfo {
1119///         name: "my-mcp-server".to_string(),
1120///         version: "1.0.0".to_string(),
1121///     },
1122///     capabilities: ServerCapabilities::default(),
1123///     protocol_version: ProtocolVersion::current(),
1124///     instructions: Some("Custom server instructions".to_string()),
1125/// };
1126/// ```
1127#[derive(Debug, Clone, PartialEq)]
1128pub struct ServerConfig {
1129    /// Server information to send during initialization
1130    pub server_info: ServerInfo,
1131    /// Server capabilities to advertise
1132    pub capabilities: ServerCapabilities,
1133    /// Protocol version to support
1134    pub protocol_version: ProtocolVersion,
1135    /// Optional instructions to provide to clients during initialization
1136    pub instructions: Option<String>,
1137}
1138
1139impl Default for ServerConfig {
1140    fn default() -> Self {
1141        Self {
1142            server_info: ServerInfo {
1143                name: "airsprotocols-mcp-server".to_string(),
1144                version: env!("CARGO_PKG_VERSION").to_string(),
1145            },
1146            capabilities: ServerCapabilities::default(),
1147            protocol_version: ProtocolVersion::current(),
1148            instructions: Some(
1149                "MCP server with configurable capabilities. Use appropriate authentication method."
1150                    .to_string(),
1151            ),
1152        }
1153    }
1154}
1155
1156// ================================================================================
1157// MCP Response Types
1158// ================================================================================
1159
1160/// Result of calling a tool
1161#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1162pub struct CallToolResult {
1163    /// Content returned by the tool
1164    pub content: Vec<Content>,
1165    /// Whether the tool call failed
1166    #[serde(default)]
1167    pub is_error: bool,
1168}
1169
1170impl CallToolResult {
1171    /// Create a successful tool result
1172    pub fn success(content: Vec<Content>) -> Self {
1173        Self {
1174            content,
1175            is_error: false,
1176        }
1177    }
1178
1179    /// Create an error tool result
1180    pub fn error(content: Vec<Content>) -> Self {
1181        Self {
1182            content,
1183            is_error: true,
1184        }
1185    }
1186}
1187
1188/// Result of reading a resource
1189#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1190pub struct ReadResourceResult {
1191    /// Contents of the resource
1192    pub contents: Vec<Content>,
1193}
1194
1195impl ReadResourceResult {
1196    /// Create a new resource read result
1197    pub fn new(contents: Vec<Content>) -> Self {
1198        Self { contents }
1199    }
1200}
1201
1202/// Result of getting a prompt
1203#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1204pub struct GetPromptResult {
1205    /// Description of the prompt
1206    pub description: Option<String>,
1207    /// Prompt messages
1208    pub messages: Vec<PromptMessage>,
1209}
1210
1211impl GetPromptResult {
1212    /// Create a new prompt result
1213    pub fn new(description: Option<String>, messages: Vec<PromptMessage>) -> Self {
1214        Self { description, messages }
1215    }
1216}
1217
1218/// Result of listing resources
1219#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1220pub struct ListResourcesResult {
1221    /// List of resources
1222    pub resources: Vec<Resource>,
1223    /// Next page cursor if applicable
1224    pub next_cursor: Option<String>,
1225}
1226
1227impl ListResourcesResult {
1228    /// Create a new resource list result
1229    pub fn new(resources: Vec<Resource>) -> Self {
1230        Self {
1231            resources,
1232            next_cursor: None,
1233        }
1234    }
1235
1236    /// Create a new resource list result with pagination
1237    pub fn with_cursor(resources: Vec<Resource>, next_cursor: Option<String>) -> Self {
1238        Self {
1239            resources,
1240            next_cursor,
1241        }
1242    }
1243}
1244
1245/// Result of listing tools
1246#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1247pub struct ListToolsResult {
1248    /// List of tools
1249    pub tools: Vec<Tool>,
1250    /// Next page cursor if applicable
1251    pub next_cursor: Option<String>,
1252}
1253
1254impl ListToolsResult {
1255    /// Create a new tool list result
1256    pub fn new(tools: Vec<Tool>) -> Self {
1257        Self {
1258            tools,
1259            next_cursor: None,
1260        }
1261    }
1262
1263    /// Create a new tool list result with pagination
1264    pub fn with_cursor(tools: Vec<Tool>, next_cursor: Option<String>) -> Self {
1265        Self {
1266            tools,
1267            next_cursor,
1268        }
1269    }
1270}
1271
1272/// Result of listing prompts
1273#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1274pub struct ListPromptsResult {
1275    /// List of prompts
1276    pub prompts: Vec<Prompt>,
1277    /// Next page cursor if applicable
1278    pub next_cursor: Option<String>,
1279}
1280
1281impl ListPromptsResult {
1282    /// Create a new prompt list result
1283    pub fn new(prompts: Vec<Prompt>) -> Self {
1284        Self {
1285            prompts,
1286            next_cursor: None,
1287        }
1288    }
1289
1290    /// Create a new prompt list result with pagination
1291    pub fn with_cursor(prompts: Vec<Prompt>, next_cursor: Option<String>) -> Self {
1292        Self {
1293            prompts,
1294            next_cursor,
1295        }
1296    }
1297}
1298
1299/// Result of listing resource templates
1300#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1301pub struct ListResourceTemplatesResult {
1302    /// List of resource templates
1303    pub resource_templates: Vec<ResourceTemplate>,
1304    /// Next page cursor if applicable
1305    pub next_cursor: Option<String>,
1306}
1307
1308impl ListResourceTemplatesResult {
1309    /// Create a new resource templates list result
1310    pub fn new(resource_templates: Vec<ResourceTemplate>) -> Self {
1311        Self {
1312            resource_templates,
1313            next_cursor: None,
1314        }
1315    }
1316
1317    /// Create a new resource templates list result with pagination
1318    pub fn with_cursor(resource_templates: Vec<ResourceTemplate>, next_cursor: Option<String>) -> Self {
1319        Self {
1320            resource_templates,
1321            next_cursor,
1322        }
1323    }
1324}
1325
1326