turbomcp_protocol/
capabilities.rs

1//! # Capability Negotiation
2//!
3//! This module provides sophisticated capability negotiation and feature detection
4//! for MCP protocol implementations.
5
6use serde::{Deserialize, Serialize};
7use std::collections::{HashMap, HashSet};
8
9use crate::types::{ClientCapabilities, ServerCapabilities};
10
11/// Capability matcher for negotiating features between client and server
12///
13/// # Examples
14///
15/// ```
16/// use turbomcp_protocol::capabilities::{CapabilityMatcher, CompatibilityRule};
17/// use turbomcp_protocol::types::{ClientCapabilities, ServerCapabilities};
18///
19/// let mut matcher = CapabilityMatcher::new();
20///
21/// // Add custom compatibility rules
22/// matcher.add_rule("custom_feature", CompatibilityRule::RequireBoth);
23/// matcher.set_default("progress", true);
24///
25/// // Negotiate capabilities
26/// let client = ClientCapabilities::default();
27/// let server = ServerCapabilities::default();
28/// let result = matcher.negotiate(&client, &server);
29/// ```
30#[derive(Debug, Clone)]
31pub struct CapabilityMatcher {
32    /// Feature compatibility rules
33    compatibility_rules: HashMap<String, CompatibilityRule>,
34    /// Default feature states
35    defaults: HashMap<String, bool>,
36}
37
38/// Compatibility rule for a feature
39#[derive(Debug, Clone)]
40pub enum CompatibilityRule {
41    /// Feature requires both client and server support
42    RequireBoth,
43    /// Feature requires only client support
44    RequireClient,
45    /// Feature requires only server support  
46    RequireServer,
47    /// Feature is optional (either side can enable)
48    Optional,
49    /// Custom compatibility function
50    Custom(fn(&ClientCapabilities, &ServerCapabilities) -> bool),
51}
52
53/// Negotiated capability set
54///
55/// # Examples
56///
57/// ```
58/// use turbomcp_protocol::capabilities::CapabilitySet;
59///
60/// let mut caps = CapabilitySet::empty();
61/// caps.enable_feature("tools".to_string());
62/// caps.enable_feature("prompts".to_string());
63///
64/// assert!(caps.has_feature("tools"));
65/// assert_eq!(caps.feature_count(), 2);
66///
67/// let summary = caps.summary();
68/// println!("{:?}", summary);
69/// ```
70#[derive(Debug, Clone, Serialize, Deserialize)]
71pub struct CapabilitySet {
72    /// Enabled features
73    pub enabled_features: HashSet<String>,
74    /// Negotiated client capabilities
75    pub client_capabilities: ClientCapabilities,
76    /// Negotiated server capabilities
77    pub server_capabilities: ServerCapabilities,
78    /// Additional metadata from negotiation
79    pub metadata: HashMap<String, serde_json::Value>,
80}
81
82/// Capability negotiator for handling the negotiation process
83#[derive(Debug, Clone)]
84pub struct CapabilityNegotiator {
85    /// Capability matcher
86    matcher: CapabilityMatcher,
87    /// Strict mode (fail on incompatible features)
88    strict_mode: bool,
89}
90
91impl Default for CapabilityMatcher {
92    fn default() -> Self {
93        Self::new()
94    }
95}
96
97impl CapabilityMatcher {
98    /// Create a new capability matcher with default MCP rules
99    pub fn new() -> Self {
100        let mut matcher = Self {
101            compatibility_rules: HashMap::new(),
102            defaults: HashMap::new(),
103        };
104
105        // Set up default MCP capability rules
106        matcher.add_rule("tools", CompatibilityRule::RequireServer);
107        matcher.add_rule("prompts", CompatibilityRule::RequireServer);
108        matcher.add_rule("resources", CompatibilityRule::RequireServer);
109        matcher.add_rule("logging", CompatibilityRule::RequireServer);
110        matcher.add_rule("sampling", CompatibilityRule::RequireClient);
111        matcher.add_rule("roots", CompatibilityRule::RequireClient);
112        matcher.add_rule("progress", CompatibilityRule::Optional);
113
114        // Set defaults
115        matcher.set_default("progress", true);
116
117        matcher
118    }
119
120    /// Add a compatibility rule for a feature
121    pub fn add_rule(&mut self, feature: &str, rule: CompatibilityRule) {
122        self.compatibility_rules.insert(feature.to_string(), rule);
123    }
124
125    /// Set default state for a feature
126    pub fn set_default(&mut self, feature: &str, enabled: bool) {
127        self.defaults.insert(feature.to_string(), enabled);
128    }
129
130    /// Check if a feature is compatible between client and server
131    pub fn is_compatible(
132        &self,
133        feature: &str,
134        client: &ClientCapabilities,
135        server: &ServerCapabilities,
136    ) -> bool {
137        self.compatibility_rules.get(feature).map_or_else(
138            || {
139                // Unknown feature - check if either side supports it
140                Self::client_has_feature(feature, client)
141                    || Self::server_has_feature(feature, server)
142            },
143            |rule| match rule {
144                CompatibilityRule::RequireBoth => {
145                    Self::client_has_feature(feature, client)
146                        && Self::server_has_feature(feature, server)
147                }
148                CompatibilityRule::RequireClient => Self::client_has_feature(feature, client),
149                CompatibilityRule::RequireServer => Self::server_has_feature(feature, server),
150                CompatibilityRule::Optional => true,
151                CompatibilityRule::Custom(func) => func(client, server),
152            },
153        )
154    }
155
156    /// Check if client has a specific feature
157    fn client_has_feature(feature: &str, client: &ClientCapabilities) -> bool {
158        match feature {
159            "sampling" => client.sampling.is_some(),
160            "roots" => client.roots.is_some(),
161            _ => {
162                // Check experimental features
163                client
164                    .experimental
165                    .as_ref()
166                    .is_some_and(|experimental| experimental.contains_key(feature))
167            }
168        }
169    }
170
171    /// Check if server has a specific feature
172    fn server_has_feature(feature: &str, server: &ServerCapabilities) -> bool {
173        match feature {
174            "tools" => server.tools.is_some(),
175            "prompts" => server.prompts.is_some(),
176            "resources" => server.resources.is_some(),
177            "logging" => server.logging.is_some(),
178            _ => {
179                // Check experimental features
180                server
181                    .experimental
182                    .as_ref()
183                    .is_some_and(|experimental| experimental.contains_key(feature))
184            }
185        }
186    }
187
188    /// Get all features from both client and server
189    fn get_all_features(
190        &self,
191        client: &ClientCapabilities,
192        server: &ServerCapabilities,
193    ) -> HashSet<String> {
194        let mut features = HashSet::new();
195
196        // Standard client features
197        if client.sampling.is_some() {
198            features.insert("sampling".to_string());
199        }
200        if client.roots.is_some() {
201            features.insert("roots".to_string());
202        }
203
204        // Standard server features
205        if server.tools.is_some() {
206            features.insert("tools".to_string());
207        }
208        if server.prompts.is_some() {
209            features.insert("prompts".to_string());
210        }
211        if server.resources.is_some() {
212            features.insert("resources".to_string());
213        }
214        if server.logging.is_some() {
215            features.insert("logging".to_string());
216        }
217
218        // Experimental features
219        if let Some(experimental) = &client.experimental {
220            features.extend(experimental.keys().cloned());
221        }
222        if let Some(experimental) = &server.experimental {
223            features.extend(experimental.keys().cloned());
224        }
225
226        // Add default features
227        features.extend(self.defaults.keys().cloned());
228
229        features
230    }
231
232    /// Negotiate capabilities between client and server
233    ///
234    /// # Errors
235    ///
236    /// Returns [`CapabilityError::IncompatibleFeatures`] if any features have
237    /// incompatible requirements between client and server.
238    pub fn negotiate(
239        &self,
240        client: &ClientCapabilities,
241        server: &ServerCapabilities,
242    ) -> Result<CapabilitySet, CapabilityError> {
243        let all_features = self.get_all_features(client, server);
244        let mut enabled_features = HashSet::new();
245        let mut incompatible_features = Vec::new();
246
247        for feature in &all_features {
248            if self.is_compatible(feature, client, server) {
249                enabled_features.insert(feature.clone());
250            } else {
251                incompatible_features.push(feature.clone());
252            }
253        }
254
255        if !incompatible_features.is_empty() {
256            return Err(CapabilityError::IncompatibleFeatures(incompatible_features));
257        }
258
259        // Apply defaults for features not explicitly enabled
260        for (feature, enabled) in &self.defaults {
261            if *enabled && !enabled_features.contains(feature) && all_features.contains(feature) {
262                enabled_features.insert(feature.clone());
263            }
264        }
265
266        Ok(CapabilitySet {
267            enabled_features,
268            client_capabilities: client.clone(),
269            server_capabilities: server.clone(),
270            metadata: HashMap::new(),
271        })
272    }
273}
274
275impl CapabilityNegotiator {
276    /// Create a new capability negotiator
277    pub const fn new(matcher: CapabilityMatcher) -> Self {
278        Self {
279            matcher,
280            strict_mode: false,
281        }
282    }
283
284    /// Enable strict mode (fail on any incompatible feature)
285    pub const fn with_strict_mode(mut self) -> Self {
286        self.strict_mode = true;
287        self
288    }
289
290    /// Negotiate capabilities between client and server
291    ///
292    /// # Errors
293    ///
294    /// Returns [`CapabilityError`] if capability negotiation fails.
295    /// In strict mode, incompatible features cause an error.
296    /// In non-strict mode, incompatible features are logged and disabled.
297    pub fn negotiate(
298        &self,
299        client: &ClientCapabilities,
300        server: &ServerCapabilities,
301    ) -> Result<CapabilitySet, CapabilityError> {
302        match self.matcher.negotiate(client, server) {
303            Ok(capability_set) => Ok(capability_set),
304            Err(CapabilityError::IncompatibleFeatures(features)) if !self.strict_mode => {
305                // In non-strict mode, just log the incompatible features and continue
306                tracing::warn!(
307                    "Some features are incompatible and will be disabled: {:?}",
308                    features
309                );
310
311                // Create a capability set with only compatible features
312                let all_features = self.matcher.get_all_features(client, server);
313                let mut enabled_features = HashSet::new();
314
315                for feature in &all_features {
316                    if self.matcher.is_compatible(feature, client, server) {
317                        enabled_features.insert(feature.clone());
318                    }
319                }
320
321                Ok(CapabilitySet {
322                    enabled_features,
323                    client_capabilities: client.clone(),
324                    server_capabilities: server.clone(),
325                    metadata: HashMap::new(),
326                })
327            }
328            Err(err) => Err(err),
329        }
330    }
331
332    /// Check if a specific feature is enabled in the capability set
333    pub fn is_feature_enabled(capability_set: &CapabilitySet, feature: &str) -> bool {
334        capability_set.enabled_features.contains(feature)
335    }
336
337    /// Get all enabled features as a sorted vector
338    pub fn get_enabled_features(capability_set: &CapabilitySet) -> Vec<String> {
339        let mut features: Vec<String> = capability_set.enabled_features.iter().cloned().collect();
340        features.sort();
341        features
342    }
343}
344
345impl Default for CapabilityNegotiator {
346    fn default() -> Self {
347        Self::new(CapabilityMatcher::new())
348    }
349}
350
351impl CapabilitySet {
352    /// Create a new empty capability set
353    pub fn empty() -> Self {
354        Self {
355            enabled_features: HashSet::new(),
356            client_capabilities: ClientCapabilities::default(),
357            server_capabilities: ServerCapabilities::default(),
358            metadata: HashMap::new(),
359        }
360    }
361
362    /// Check if a feature is enabled
363    pub fn has_feature(&self, feature: &str) -> bool {
364        self.enabled_features.contains(feature)
365    }
366
367    /// Add a feature to the enabled set
368    pub fn enable_feature(&mut self, feature: String) {
369        self.enabled_features.insert(feature);
370    }
371
372    /// Remove a feature from the enabled set
373    pub fn disable_feature(&mut self, feature: &str) {
374        self.enabled_features.remove(feature);
375    }
376
377    /// Get the number of enabled features
378    pub fn feature_count(&self) -> usize {
379        self.enabled_features.len()
380    }
381
382    /// Add metadata
383    pub fn add_metadata(&mut self, key: String, value: serde_json::Value) {
384        self.metadata.insert(key, value);
385    }
386
387    /// Get metadata
388    pub fn get_metadata(&self, key: &str) -> Option<&serde_json::Value> {
389        self.metadata.get(key)
390    }
391
392    /// Create a summary of enabled capabilities
393    pub fn summary(&self) -> CapabilitySummary {
394        CapabilitySummary {
395            total_features: self.enabled_features.len(),
396            client_features: self.count_client_features(),
397            server_features: self.count_server_features(),
398            enabled_features: self.enabled_features.iter().cloned().collect(),
399        }
400    }
401
402    fn count_client_features(&self) -> usize {
403        let mut count = 0;
404        if self.client_capabilities.sampling.is_some() {
405            count += 1;
406        }
407        if self.client_capabilities.roots.is_some() {
408            count += 1;
409        }
410        if let Some(experimental) = &self.client_capabilities.experimental {
411            count += experimental.len();
412        }
413        count
414    }
415
416    fn count_server_features(&self) -> usize {
417        let mut count = 0;
418        if self.server_capabilities.tools.is_some() {
419            count += 1;
420        }
421        if self.server_capabilities.prompts.is_some() {
422            count += 1;
423        }
424        if self.server_capabilities.resources.is_some() {
425            count += 1;
426        }
427        if self.server_capabilities.logging.is_some() {
428            count += 1;
429        }
430        if let Some(experimental) = &self.server_capabilities.experimental {
431            count += experimental.len();
432        }
433        count
434    }
435}
436
437/// Capability negotiation errors
438#[derive(Debug, Clone, thiserror::Error)]
439pub enum CapabilityError {
440    /// Features are incompatible between client and server
441    #[error("Incompatible features: {0:?}")]
442    IncompatibleFeatures(Vec<String>),
443    /// Required feature is missing
444    #[error("Required feature missing: {0}")]
445    RequiredFeatureMissing(String),
446    /// Protocol version mismatch
447    #[error("Protocol version mismatch: client={client}, server={server}")]
448    VersionMismatch {
449        /// Client version string
450        client: String,
451        /// Server version string
452        server: String,
453    },
454    /// Capability negotiation failed
455    #[error("Capability negotiation failed: {0}")]
456    NegotiationFailed(String),
457}
458
459/// Summary of capability negotiation results
460#[derive(Debug, Clone, Serialize, Deserialize)]
461pub struct CapabilitySummary {
462    /// Total number of enabled features
463    pub total_features: usize,
464    /// Number of client-side features
465    pub client_features: usize,
466    /// Number of server-side features
467    pub server_features: usize,
468    /// List of enabled features
469    pub enabled_features: Vec<String>,
470}
471
472/// Utility functions for capability management
473pub mod utils {
474    use super::*;
475
476    /// Create a minimal client capability set
477    pub fn minimal_client_capabilities() -> ClientCapabilities {
478        ClientCapabilities::default()
479    }
480
481    /// Create a minimal server capability set
482    pub fn minimal_server_capabilities() -> ServerCapabilities {
483        ServerCapabilities::default()
484    }
485
486    /// Create a full-featured client capability set
487    pub fn full_client_capabilities() -> ClientCapabilities {
488        ClientCapabilities {
489            sampling: Some(Default::default()),
490            roots: Some(Default::default()),
491            elicitation: Some(Default::default()),
492            experimental: None,
493        }
494    }
495
496    /// Create a full-featured server capability set
497    pub fn full_server_capabilities() -> ServerCapabilities {
498        ServerCapabilities {
499            tools: Some(Default::default()),
500            prompts: Some(Default::default()),
501            resources: Some(Default::default()),
502            completions: Some(Default::default()),
503            logging: Some(Default::default()),
504            experimental: None,
505        }
506    }
507
508    /// Check if two capability sets are compatible
509    pub fn are_compatible(client: &ClientCapabilities, server: &ServerCapabilities) -> bool {
510        let matcher = CapabilityMatcher::new();
511        matcher.negotiate(client, server).is_ok()
512    }
513}
514
515#[cfg(test)]
516mod tests {
517    use super::*;
518    use crate::types::*;
519
520    #[test]
521    fn test_capability_matcher() {
522        let matcher = CapabilityMatcher::new();
523
524        let client = ClientCapabilities {
525            sampling: Some(SamplingCapabilities),
526            roots: None,
527            elicitation: None,
528            experimental: None,
529        };
530
531        let server = ServerCapabilities {
532            tools: Some(ToolsCapabilities::default()),
533            prompts: None,
534            resources: None,
535            logging: None,
536            completions: None,
537            experimental: None,
538        };
539
540        assert!(matcher.is_compatible("sampling", &client, &server));
541        assert!(matcher.is_compatible("tools", &client, &server));
542        assert!(!matcher.is_compatible("roots", &client, &server));
543    }
544
545    #[test]
546    fn test_capability_negotiation() {
547        let negotiator = CapabilityNegotiator::default();
548
549        let client = utils::full_client_capabilities();
550        let server = utils::full_server_capabilities();
551
552        let result = negotiator.negotiate(&client, &server);
553        assert!(result.is_ok());
554
555        let capability_set = result.unwrap();
556        assert!(capability_set.has_feature("sampling"));
557        assert!(capability_set.has_feature("tools"));
558        assert!(capability_set.has_feature("roots"));
559    }
560
561    #[test]
562    fn test_strict_mode() {
563        let negotiator = CapabilityNegotiator::default().with_strict_mode();
564
565        let client = ClientCapabilities::default();
566        let server = ServerCapabilities::default();
567
568        let result = negotiator.negotiate(&client, &server);
569        assert!(result.is_ok()); // Should still work with minimal capabilities
570    }
571
572    #[test]
573    fn test_capability_summary() {
574        let mut capability_set = CapabilitySet::empty();
575        capability_set.enable_feature("tools".to_string());
576        capability_set.enable_feature("prompts".to_string());
577
578        let summary = capability_set.summary();
579        assert_eq!(summary.total_features, 2);
580        assert!(summary.enabled_features.contains(&"tools".to_string()));
581    }
582}
583
584// ============================================================================
585// TYPE-STATE CAPABILITY BUILDERS - TURBOMCP LEAPFROG IMPLEMENTATION
586// ============================================================================
587
588/// Type-state capability builders for compile-time validation
589///
590/// This module provides const-generic builders that ensure capabilities
591/// are configured correctly at compile time with zero-cost abstractions
592/// and advanced compile-time safety features.
593pub mod builders {
594    use crate::types::{
595        ClientCapabilities, CompletionCapabilities, ElicitationCapabilities, LoggingCapabilities,
596        PromptsCapabilities, ResourcesCapabilities, RootsCapabilities, SamplingCapabilities,
597        ServerCapabilities, ToolsCapabilities,
598    };
599    use serde_json;
600    use std::collections::HashMap;
601    use std::marker::PhantomData;
602
603    // ========================================================================
604    // SERVER CAPABILITIES BUILDER - TYPE-STATE SYSTEM
605    // ========================================================================
606
607    /// Type-state for ServerCapabilitiesBuilder
608    ///
609    /// Each const generic represents whether a capability is enabled:
610    /// - EXPERIMENTAL: Experimental capabilities
611    /// - LOGGING: Logging capabilities
612    /// - COMPLETIONS: Completion capabilities
613    /// - PROMPTS: Prompt capabilities
614    /// - RESOURCES: Resource capabilities
615    /// - TOOLS: Tool capabilities
616    #[derive(Debug, Clone)]
617    pub struct ServerCapabilitiesBuilderState<
618        const EXPERIMENTAL: bool = false,
619        const LOGGING: bool = false,
620        const COMPLETIONS: bool = false,
621        const PROMPTS: bool = false,
622        const RESOURCES: bool = false,
623        const TOOLS: bool = false,
624    >;
625
626    /// Const-generic ServerCapabilities builder with compile-time validation
627    ///
628    /// This builder ensures that capability-specific methods are only available
629    /// when the corresponding capability is enabled, providing compile-time safety
630    /// with compile-time validation.
631    #[derive(Debug, Clone)]
632    pub struct ServerCapabilitiesBuilder<S = ServerCapabilitiesBuilderState> {
633        experimental: Option<HashMap<String, serde_json::Value>>,
634        logging: Option<LoggingCapabilities>,
635        completions: Option<CompletionCapabilities>,
636        prompts: Option<PromptsCapabilities>,
637        resources: Option<ResourcesCapabilities>,
638        tools: Option<ToolsCapabilities>,
639
640        // TurboMCP Extensions
641        negotiator: Option<super::CapabilityNegotiator>,
642        strict_validation: bool,
643
644        _state: PhantomData<S>,
645    }
646
647    impl ServerCapabilities {
648        /// Create a new ServerCapabilities builder with type-state validation
649        ///
650        /// Returns a builder that ensures capabilities are configured correctly
651        /// at compile time, preventing runtime configuration errors.
652        pub fn builder() -> ServerCapabilitiesBuilder {
653            ServerCapabilitiesBuilder::new()
654        }
655    }
656
657    impl Default for ServerCapabilitiesBuilder {
658        fn default() -> Self {
659            Self::new()
660        }
661    }
662
663    impl ServerCapabilitiesBuilder {
664        /// Create a new ServerCapabilities builder
665        pub fn new() -> Self {
666            Self {
667                experimental: None,
668                logging: None,
669                completions: None,
670                prompts: None,
671                resources: None,
672                tools: None,
673                negotiator: None,
674                strict_validation: false,
675                _state: PhantomData,
676            }
677        }
678    }
679
680    // Generic implementation for all states
681    impl<S> ServerCapabilitiesBuilder<S> {
682        /// Build the final ServerCapabilities
683        ///
684        /// Consumes the builder and returns the configured ServerCapabilities.
685        /// All compile-time validations have been enforced during building.
686        pub fn build(self) -> ServerCapabilities {
687            ServerCapabilities {
688                experimental: self.experimental,
689                logging: self.logging,
690                completions: self.completions,
691                prompts: self.prompts,
692                resources: self.resources,
693                tools: self.tools,
694            }
695        }
696
697        /// TurboMCP Extension: Enable strict validation mode
698        ///
699        /// When enabled, the builder will perform additional runtime validations
700        /// on top of the compile-time guarantees.
701        pub fn with_strict_validation(mut self) -> Self {
702            self.strict_validation = true;
703            self
704        }
705
706        /// TurboMCP Extension: Set capability negotiator
707        ///
708        /// Integrates with TurboMCP's sophisticated capability negotiation system
709        /// for advanced client-server capability matching.
710        pub fn with_negotiator(mut self, negotiator: super::CapabilityNegotiator) -> Self {
711            self.negotiator = Some(negotiator);
712            self
713        }
714
715        /// TurboMCP Extension: Validate capability configuration
716        ///
717        /// Performs additional runtime validation to ensure the capability
718        /// configuration makes sense in the current context.
719        pub fn validate(&self) -> Result<(), String> {
720            if self.strict_validation {
721                // Perform additional validation when strict mode is enabled
722                if self.tools.is_none() && self.prompts.is_none() && self.resources.is_none() {
723                    return Err("Server must provide at least one capability (tools, prompts, or resources)".to_string());
724                }
725
726                // Validate experimental capabilities if present
727                if let Some(ref experimental) = self.experimental {
728                    for (key, value) in experimental {
729                        if key.starts_with("turbomcp_") {
730                            // Validate TurboMCP-specific experimental capabilities
731                            match key.as_str() {
732                                "turbomcp_simd_level" => {
733                                    if !value.is_string() {
734                                        return Err(
735                                            "turbomcp_simd_level must be a string".to_string()
736                                        );
737                                    }
738                                    let level = value.as_str().unwrap_or("");
739                                    if !["none", "sse2", "sse4", "avx2", "avx512"].contains(&level)
740                                    {
741                                        return Err(format!("Invalid SIMD level: {}", level));
742                                    }
743                                }
744                                "turbomcp_enterprise_security" => {
745                                    if !value.is_boolean() {
746                                        return Err(
747                                            "turbomcp_enterprise_security must be a boolean"
748                                                .to_string(),
749                                        );
750                                    }
751                                }
752                                _ => {
753                                    // Allow other TurboMCP experimental features
754                                }
755                            }
756                        }
757                    }
758                }
759            }
760            Ok(())
761        }
762
763        /// Get a summary of enabled capabilities
764        ///
765        /// Returns a human-readable summary of which capabilities are enabled.
766        pub fn summary(&self) -> String {
767            let mut capabilities = Vec::new();
768            if self.experimental.is_some() {
769                capabilities.push("experimental");
770            }
771            if self.logging.is_some() {
772                capabilities.push("logging");
773            }
774            if self.completions.is_some() {
775                capabilities.push("completions");
776            }
777            if self.prompts.is_some() {
778                capabilities.push("prompts");
779            }
780            if self.resources.is_some() {
781                capabilities.push("resources");
782            }
783            if self.tools.is_some() {
784                capabilities.push("tools");
785            }
786
787            if capabilities.is_empty() {
788                "No capabilities enabled".to_string()
789            } else {
790                format!("Enabled capabilities: {}", capabilities.join(", "))
791            }
792        }
793    }
794
795    // ========================================================================
796    // CAPABILITY ENABLEMENT METHODS
797    // ========================================================================
798
799    // Enable Experimental Capabilities
800    impl<const L: bool, const C: bool, const P: bool, const R: bool, const T: bool>
801        ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<false, L, C, P, R, T>>
802    {
803        /// Enable experimental capabilities
804        ///
805        /// Transitions the builder to a state where experimental capability methods
806        /// become available at compile time.
807        pub fn enable_experimental(
808            self,
809        ) -> ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<true, L, C, P, R, T>>
810        {
811            ServerCapabilitiesBuilder {
812                experimental: Some(HashMap::new()),
813                logging: self.logging,
814                completions: self.completions,
815                prompts: self.prompts,
816                resources: self.resources,
817                tools: self.tools,
818                negotiator: self.negotiator,
819                strict_validation: self.strict_validation,
820                _state: PhantomData,
821            }
822        }
823
824        /// Enable experimental capabilities with specific values
825        pub fn enable_experimental_with(
826            self,
827            experimental: HashMap<String, serde_json::Value>,
828        ) -> ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<true, L, C, P, R, T>>
829        {
830            ServerCapabilitiesBuilder {
831                experimental: Some(experimental),
832                logging: self.logging,
833                completions: self.completions,
834                prompts: self.prompts,
835                resources: self.resources,
836                tools: self.tools,
837                negotiator: self.negotiator,
838                strict_validation: self.strict_validation,
839                _state: PhantomData,
840            }
841        }
842    }
843
844    // Enable Logging Capabilities
845    impl<const E: bool, const C: bool, const P: bool, const R: bool, const T: bool>
846        ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<E, false, C, P, R, T>>
847    {
848        /// Enable logging capabilities
849        pub fn enable_logging(
850            self,
851        ) -> ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<E, true, C, P, R, T>>
852        {
853            ServerCapabilitiesBuilder {
854                experimental: self.experimental,
855                logging: Some(LoggingCapabilities),
856                completions: self.completions,
857                prompts: self.prompts,
858                resources: self.resources,
859                tools: self.tools,
860                negotiator: self.negotiator,
861                strict_validation: self.strict_validation,
862                _state: PhantomData,
863            }
864        }
865    }
866
867    // Enable Completion Capabilities
868    impl<const E: bool, const L: bool, const P: bool, const R: bool, const T: bool>
869        ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<E, L, false, P, R, T>>
870    {
871        /// Enable completion capabilities
872        pub fn enable_completions(
873            self,
874        ) -> ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<E, L, true, P, R, T>>
875        {
876            ServerCapabilitiesBuilder {
877                experimental: self.experimental,
878                logging: self.logging,
879                completions: Some(CompletionCapabilities),
880                prompts: self.prompts,
881                resources: self.resources,
882                tools: self.tools,
883                negotiator: self.negotiator,
884                strict_validation: self.strict_validation,
885                _state: PhantomData,
886            }
887        }
888    }
889
890    // Enable Prompts Capabilities
891    impl<const E: bool, const L: bool, const C: bool, const R: bool, const T: bool>
892        ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<E, L, C, false, R, T>>
893    {
894        /// Enable prompts capabilities
895        pub fn enable_prompts(
896            self,
897        ) -> ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<E, L, C, true, R, T>>
898        {
899            ServerCapabilitiesBuilder {
900                experimental: self.experimental,
901                logging: self.logging,
902                completions: self.completions,
903                prompts: Some(PromptsCapabilities { list_changed: None }),
904                resources: self.resources,
905                tools: self.tools,
906                negotiator: self.negotiator,
907                strict_validation: self.strict_validation,
908                _state: PhantomData,
909            }
910        }
911    }
912
913    // Enable Resources Capabilities
914    impl<const E: bool, const L: bool, const C: bool, const P: bool, const T: bool>
915        ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<E, L, C, P, false, T>>
916    {
917        /// Enable resources capabilities
918        pub fn enable_resources(
919            self,
920        ) -> ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<E, L, C, P, true, T>>
921        {
922            ServerCapabilitiesBuilder {
923                experimental: self.experimental,
924                logging: self.logging,
925                completions: self.completions,
926                prompts: self.prompts,
927                resources: Some(ResourcesCapabilities {
928                    subscribe: None,
929                    list_changed: None,
930                }),
931                tools: self.tools,
932                negotiator: self.negotiator,
933                strict_validation: self.strict_validation,
934                _state: PhantomData,
935            }
936        }
937    }
938
939    // Enable Tools Capabilities
940    impl<const E: bool, const L: bool, const C: bool, const P: bool, const R: bool>
941        ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<E, L, C, P, R, false>>
942    {
943        /// Enable tools capabilities
944        pub fn enable_tools(
945            self,
946        ) -> ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<E, L, C, P, R, true>>
947        {
948            ServerCapabilitiesBuilder {
949                experimental: self.experimental,
950                logging: self.logging,
951                completions: self.completions,
952                prompts: self.prompts,
953                resources: self.resources,
954                tools: Some(ToolsCapabilities { list_changed: None }),
955                negotiator: self.negotiator,
956                strict_validation: self.strict_validation,
957                _state: PhantomData,
958            }
959        }
960    }
961
962    // ========================================================================
963    // SUB-CAPABILITY METHODS (ONLY AVAILABLE WHEN PARENT CAPABILITY ENABLED)
964    // ========================================================================
965
966    // Tools sub-capabilities (only available when TOOLS = true)
967    impl<const E: bool, const L: bool, const C: bool, const P: bool, const R: bool>
968        ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<E, L, C, P, R, true>>
969    {
970        /// Enable tool list changed notifications
971        ///
972        /// This method is only available when tools capabilities are enabled,
973        /// providing advanced compile-time validation.
974        pub fn enable_tool_list_changed(mut self) -> Self {
975            if let Some(ref mut tools) = self.tools {
976                tools.list_changed = Some(true);
977            }
978            self
979        }
980    }
981
982    // Prompts sub-capabilities (only available when PROMPTS = true)
983    impl<const E: bool, const L: bool, const C: bool, const R: bool, const T: bool>
984        ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<E, L, C, true, R, T>>
985    {
986        /// Enable prompts list changed notifications
987        pub fn enable_prompts_list_changed(mut self) -> Self {
988            if let Some(ref mut prompts) = self.prompts {
989                prompts.list_changed = Some(true);
990            }
991            self
992        }
993    }
994
995    // Resources sub-capabilities (only available when RESOURCES = true)
996    impl<const E: bool, const L: bool, const C: bool, const P: bool, const T: bool>
997        ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<E, L, C, P, true, T>>
998    {
999        /// Enable resources list changed notifications
1000        pub fn enable_resources_list_changed(mut self) -> Self {
1001            if let Some(ref mut resources) = self.resources {
1002                resources.list_changed = Some(true);
1003            }
1004            self
1005        }
1006
1007        /// Enable resources subscribe capability
1008        pub fn enable_resources_subscribe(mut self) -> Self {
1009            if let Some(ref mut resources) = self.resources {
1010                resources.subscribe = Some(true);
1011            }
1012            self
1013        }
1014    }
1015
1016    // Experimental sub-capabilities (only available when EXPERIMENTAL = true)
1017    impl<const L: bool, const C: bool, const P: bool, const R: bool, const T: bool>
1018        ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<true, L, C, P, R, T>>
1019    {
1020        /// Add experimental capability
1021        ///
1022        /// This method is only available when experimental capabilities are enabled.
1023        pub fn add_experimental_capability<K, V>(mut self, key: K, value: V) -> Self
1024        where
1025            K: Into<String>,
1026            V: Into<serde_json::Value>,
1027        {
1028            if let Some(ref mut experimental) = self.experimental {
1029                experimental.insert(key.into(), value.into());
1030            }
1031            self
1032        }
1033
1034        /// TurboMCP Extension: Add SIMD optimization hint
1035        ///
1036        /// Unique to TurboMCP - hints about SIMD capabilities for performance optimization.
1037        pub fn with_simd_optimization(mut self, level: &str) -> Self {
1038            if let Some(ref mut experimental) = self.experimental {
1039                experimental.insert(
1040                    "turbomcp_simd_level".to_string(),
1041                    serde_json::Value::String(level.to_string()),
1042                );
1043            }
1044            self
1045        }
1046
1047        /// TurboMCP Extension: Add enterprise security metadata
1048        ///
1049        /// Unique to TurboMCP - metadata about security capabilities.
1050        pub fn with_enterprise_security(mut self, enabled: bool) -> Self {
1051            if let Some(ref mut experimental) = self.experimental {
1052                experimental.insert(
1053                    "turbomcp_enterprise_security".to_string(),
1054                    serde_json::Value::Bool(enabled),
1055                );
1056            }
1057            self
1058        }
1059    }
1060
1061    // ========================================================================
1062    // CLIENT CAPABILITIES BUILDER - TYPE-STATE SYSTEM
1063    // ========================================================================
1064
1065    /// Type-state for ClientCapabilitiesBuilder
1066    ///
1067    /// Each const generic represents whether a capability is enabled:
1068    /// - EXPERIMENTAL: Experimental capabilities
1069    /// - ROOTS: Roots capabilities
1070    /// - SAMPLING: Sampling capabilities
1071    /// - ELICITATION: Elicitation capabilities
1072    #[derive(Debug, Clone)]
1073    pub struct ClientCapabilitiesBuilderState<
1074        const EXPERIMENTAL: bool = false,
1075        const ROOTS: bool = false,
1076        const SAMPLING: bool = false,
1077        const ELICITATION: bool = false,
1078    >;
1079
1080    /// Const-generic ClientCapabilities builder with compile-time validation
1081    ///
1082    /// This builder ensures that capability-specific methods are only available
1083    /// when the corresponding capability is enabled, providing compile-time safety
1084    /// with comprehensive compile-time validation.
1085    #[derive(Debug, Clone)]
1086    pub struct ClientCapabilitiesBuilder<S = ClientCapabilitiesBuilderState> {
1087        experimental: Option<HashMap<String, serde_json::Value>>,
1088        roots: Option<RootsCapabilities>,
1089        sampling: Option<SamplingCapabilities>,
1090        elicitation: Option<ElicitationCapabilities>,
1091
1092        // TurboMCP Extensions
1093        negotiator: Option<super::CapabilityNegotiator>,
1094        strict_validation: bool,
1095
1096        _state: PhantomData<S>,
1097    }
1098
1099    impl ClientCapabilities {
1100        /// Create a new ClientCapabilities builder with type-state validation
1101        ///
1102        /// Returns a builder that ensures capabilities are configured correctly
1103        /// at compile time, preventing runtime configuration errors.
1104        ///
1105        /// By default, all capabilities are enabled (opt-out model).
1106        pub fn builder()
1107        -> ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<true, true, true, true>>
1108        {
1109            ClientCapabilitiesBuilder::new()
1110        }
1111    }
1112
1113    impl Default for ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<true, true, true, true>> {
1114        fn default() -> Self {
1115            Self::new()
1116        }
1117    }
1118
1119    impl ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<true, true, true, true>> {
1120        /// Create a new ClientCapabilities builder with all capabilities enabled (opt-out model)
1121        ///
1122        /// By default, all capabilities are enabled. Use `.without_*()` methods to disable
1123        /// specific capabilities if needed.
1124        ///
1125        /// This design provides forward compatibility - when new MCP capabilities are added,
1126        /// existing clients automatically support them without code changes.
1127        ///
1128        /// For clients that need explicit opt-in behavior, use `ClientCapabilitiesBuilder::minimal()`.
1129        pub fn new() -> Self {
1130            Self {
1131                experimental: Some(HashMap::new()),
1132                roots: Some(RootsCapabilities::default()),
1133                sampling: Some(SamplingCapabilities),
1134                elicitation: Some(ElicitationCapabilities::default()),
1135                negotiator: None,
1136                strict_validation: false,
1137                _state: PhantomData,
1138            }
1139        }
1140    }
1141
1142    impl ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<false, false, false, false>> {
1143        /// Create a minimal ClientCapabilities builder with no capabilities enabled (opt-in model)
1144        ///
1145        /// Starts with all capabilities disabled. Use `.enable_*()` methods to opt-in
1146        /// to specific capabilities.
1147        ///
1148        /// Most users should use `ClientCapabilitiesBuilder::new()` instead, which provides
1149        /// an opt-out model with all capabilities enabled by default.
1150        ///
1151        /// Use this constructor when:
1152        /// - You need explicit control over which capabilities are enabled
1153        /// - You're building a restricted client (embedded, CLI-only, etc.)
1154        /// - You want to minimize the attack surface
1155        pub fn minimal() -> Self {
1156            Self {
1157                experimental: None,
1158                roots: None,
1159                sampling: None,
1160                elicitation: None,
1161                negotiator: None,
1162                strict_validation: false,
1163                _state: PhantomData,
1164            }
1165        }
1166    }
1167
1168    // Generic implementation for all states
1169    impl<S> ClientCapabilitiesBuilder<S> {
1170        /// Build the final ClientCapabilities
1171        ///
1172        /// Consumes the builder and returns the configured ClientCapabilities.
1173        /// All compile-time validations have been enforced during building.
1174        pub fn build(self) -> ClientCapabilities {
1175            ClientCapabilities {
1176                experimental: self.experimental,
1177                roots: self.roots,
1178                sampling: self.sampling,
1179                elicitation: self.elicitation,
1180            }
1181        }
1182
1183        /// TurboMCP Extension: Enable strict validation mode
1184        ///
1185        /// When enabled, the builder will perform additional runtime validations
1186        /// on top of the compile-time guarantees.
1187        pub fn with_strict_validation(mut self) -> Self {
1188            self.strict_validation = true;
1189            self
1190        }
1191
1192        /// TurboMCP Extension: Set capability negotiator
1193        ///
1194        /// Integrates with TurboMCP's sophisticated capability negotiation system
1195        /// for advanced client-server capability matching.
1196        pub fn with_negotiator(mut self, negotiator: super::CapabilityNegotiator) -> Self {
1197            self.negotiator = Some(negotiator);
1198            self
1199        }
1200
1201        /// TurboMCP Extension: Validate capability configuration
1202        ///
1203        /// Performs additional runtime validation to ensure the capability
1204        /// configuration makes sense in the current context.
1205        pub fn validate(&self) -> Result<(), String> {
1206            if self.strict_validation {
1207                // Validate experimental capabilities if present
1208                if let Some(ref experimental) = self.experimental {
1209                    for key in experimental.keys() {
1210                        if key.starts_with("turbomcp_") {
1211                            // Allow all TurboMCP experimental features
1212                            // Removed validation for deprecated methods:
1213                            // - turbomcp_llm_provider (removed)
1214                            // - turbomcp_ui_capabilities (removed)
1215                        }
1216                    }
1217                }
1218            }
1219            Ok(())
1220        }
1221
1222        /// Get a summary of enabled capabilities
1223        ///
1224        /// Returns a human-readable summary of which capabilities are enabled.
1225        pub fn summary(&self) -> String {
1226            let mut capabilities = Vec::new();
1227            if self.experimental.is_some() {
1228                capabilities.push("experimental");
1229            }
1230            if self.roots.is_some() {
1231                capabilities.push("roots");
1232            }
1233            if self.sampling.is_some() {
1234                capabilities.push("sampling");
1235            }
1236            if self.elicitation.is_some() {
1237                capabilities.push("elicitation");
1238            }
1239
1240            if capabilities.is_empty() {
1241                "No capabilities enabled".to_string()
1242            } else {
1243                format!("Enabled capabilities: {}", capabilities.join(", "))
1244            }
1245        }
1246    }
1247
1248    // ========================================================================
1249    // CLIENT CAPABILITY ENABLEMENT METHODS
1250    // ========================================================================
1251
1252    // Enable Experimental Capabilities
1253    impl<const R: bool, const S: bool, const E: bool>
1254        ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<false, R, S, E>>
1255    {
1256        /// Enable experimental capabilities
1257        ///
1258        /// Transitions the builder to a state where experimental capability methods
1259        /// become available at compile time.
1260        pub fn enable_experimental(
1261            self,
1262        ) -> ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<true, R, S, E>> {
1263            ClientCapabilitiesBuilder {
1264                experimental: Some(HashMap::new()),
1265                roots: self.roots,
1266                sampling: self.sampling,
1267                elicitation: self.elicitation,
1268                negotiator: self.negotiator,
1269                strict_validation: self.strict_validation,
1270                _state: PhantomData,
1271            }
1272        }
1273
1274        /// Enable experimental capabilities with specific values
1275        pub fn enable_experimental_with(
1276            self,
1277            experimental: HashMap<String, serde_json::Value>,
1278        ) -> ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<true, R, S, E>> {
1279            ClientCapabilitiesBuilder {
1280                experimental: Some(experimental),
1281                roots: self.roots,
1282                sampling: self.sampling,
1283                elicitation: self.elicitation,
1284                negotiator: self.negotiator,
1285                strict_validation: self.strict_validation,
1286                _state: PhantomData,
1287            }
1288        }
1289    }
1290
1291    // Enable Roots Capabilities
1292    impl<const X: bool, const S: bool, const E: bool>
1293        ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, false, S, E>>
1294    {
1295        /// Enable roots capabilities
1296        pub fn enable_roots(
1297            self,
1298        ) -> ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, true, S, E>> {
1299            ClientCapabilitiesBuilder {
1300                experimental: self.experimental,
1301                roots: Some(RootsCapabilities { list_changed: None }),
1302                sampling: self.sampling,
1303                elicitation: self.elicitation,
1304                negotiator: self.negotiator,
1305                strict_validation: self.strict_validation,
1306                _state: PhantomData,
1307            }
1308        }
1309    }
1310
1311    // Enable Sampling Capabilities
1312    impl<const X: bool, const R: bool, const E: bool>
1313        ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, R, false, E>>
1314    {
1315        /// Enable sampling capabilities
1316        pub fn enable_sampling(
1317            self,
1318        ) -> ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, R, true, E>> {
1319            ClientCapabilitiesBuilder {
1320                experimental: self.experimental,
1321                roots: self.roots,
1322                sampling: Some(SamplingCapabilities),
1323                elicitation: self.elicitation,
1324                negotiator: self.negotiator,
1325                strict_validation: self.strict_validation,
1326                _state: PhantomData,
1327            }
1328        }
1329    }
1330
1331    // Enable Elicitation Capabilities
1332    impl<const X: bool, const R: bool, const S: bool>
1333        ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, R, S, false>>
1334    {
1335        /// Enable elicitation capabilities
1336        pub fn enable_elicitation(
1337            self,
1338        ) -> ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, R, S, true>> {
1339            ClientCapabilitiesBuilder {
1340                experimental: self.experimental,
1341                roots: self.roots,
1342                sampling: self.sampling,
1343                elicitation: Some(ElicitationCapabilities::default()),
1344                negotiator: self.negotiator,
1345                strict_validation: self.strict_validation,
1346                _state: PhantomData,
1347            }
1348        }
1349
1350        /// Enable elicitation with schema validation
1351        pub fn enable_elicitation_with_schema_validation(
1352            self,
1353        ) -> ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, R, S, true>> {
1354            ClientCapabilitiesBuilder {
1355                experimental: self.experimental,
1356                roots: self.roots,
1357                sampling: self.sampling,
1358                elicitation: Some(ElicitationCapabilities::default().with_schema_validation()),
1359                negotiator: self.negotiator,
1360                strict_validation: self.strict_validation,
1361                _state: PhantomData,
1362            }
1363        }
1364    }
1365
1366    // ========================================================================
1367    // CLIENT SUB-CAPABILITY METHODS
1368    // ========================================================================
1369
1370    // Roots sub-capabilities (only available when ROOTS = true)
1371    impl<const X: bool, const S: bool, const E: bool>
1372        ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, true, S, E>>
1373    {
1374        /// Enable roots list changed notifications
1375        ///
1376        /// This method is only available when roots capabilities are enabled,
1377        /// providing compile-time safety.
1378        pub fn enable_roots_list_changed(mut self) -> Self {
1379            if let Some(ref mut roots) = self.roots {
1380                roots.list_changed = Some(true);
1381            }
1382            self
1383        }
1384    }
1385
1386    // ========================================================================
1387    // CLIENT CAPABILITY DISABLEMENT METHODS (OPT-OUT API)
1388    // ========================================================================
1389
1390    // Disable Experimental Capabilities
1391    impl<const R: bool, const S: bool, const E: bool>
1392        ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<true, R, S, E>>
1393    {
1394        /// Disable experimental capabilities (opt-out)
1395        ///
1396        /// Transitions the builder to a state where experimental capability methods
1397        /// are no longer available at compile time.
1398        pub fn without_experimental(
1399            self,
1400        ) -> ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<false, R, S, E>> {
1401            ClientCapabilitiesBuilder {
1402                experimental: None,
1403                roots: self.roots,
1404                sampling: self.sampling,
1405                elicitation: self.elicitation,
1406                negotiator: self.negotiator,
1407                strict_validation: self.strict_validation,
1408                _state: PhantomData,
1409            }
1410        }
1411    }
1412
1413    // Disable Roots Capabilities
1414    impl<const X: bool, const S: bool, const E: bool>
1415        ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, true, S, E>>
1416    {
1417        /// Disable roots capabilities (opt-out)
1418        ///
1419        /// Transitions the builder to a state where roots capability methods
1420        /// are no longer available at compile time.
1421        pub fn without_roots(
1422            self,
1423        ) -> ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, false, S, E>> {
1424            ClientCapabilitiesBuilder {
1425                experimental: self.experimental,
1426                roots: None,
1427                sampling: self.sampling,
1428                elicitation: self.elicitation,
1429                negotiator: self.negotiator,
1430                strict_validation: self.strict_validation,
1431                _state: PhantomData,
1432            }
1433        }
1434    }
1435
1436    // Disable Sampling Capabilities
1437    impl<const X: bool, const R: bool, const E: bool>
1438        ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, R, true, E>>
1439    {
1440        /// Disable sampling capabilities (opt-out)
1441        ///
1442        /// Transitions the builder to a state where sampling capability methods
1443        /// are no longer available at compile time.
1444        pub fn without_sampling(
1445            self,
1446        ) -> ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, R, false, E>> {
1447            ClientCapabilitiesBuilder {
1448                experimental: self.experimental,
1449                roots: self.roots,
1450                sampling: None,
1451                elicitation: self.elicitation,
1452                negotiator: self.negotiator,
1453                strict_validation: self.strict_validation,
1454                _state: PhantomData,
1455            }
1456        }
1457    }
1458
1459    // Disable Elicitation Capabilities
1460    impl<const X: bool, const R: bool, const S: bool>
1461        ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, R, S, true>>
1462    {
1463        /// Disable elicitation capabilities (opt-out)
1464        ///
1465        /// Transitions the builder to a state where elicitation capability methods
1466        /// are no longer available at compile time.
1467        pub fn without_elicitation(
1468            self,
1469        ) -> ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, R, S, false>> {
1470            ClientCapabilitiesBuilder {
1471                experimental: self.experimental,
1472                roots: self.roots,
1473                sampling: self.sampling,
1474                elicitation: None,
1475                negotiator: self.negotiator,
1476                strict_validation: self.strict_validation,
1477                _state: PhantomData,
1478            }
1479        }
1480    }
1481
1482    // Experimental sub-capabilities (only available when EXPERIMENTAL = true)
1483    impl<const R: bool, const S: bool, const E: bool>
1484        ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<true, R, S, E>>
1485    {
1486        /// Add experimental capability
1487        ///
1488        /// This method is only available when experimental capabilities are enabled.
1489        pub fn add_experimental_capability<K, V>(mut self, key: K, value: V) -> Self
1490        where
1491            K: Into<String>,
1492            V: Into<serde_json::Value>,
1493        {
1494            if let Some(ref mut experimental) = self.experimental {
1495                experimental.insert(key.into(), value.into());
1496            }
1497            self
1498        }
1499    }
1500
1501    #[cfg(test)]
1502    mod type_state_tests {
1503        use super::*;
1504
1505        #[test]
1506        fn test_server_capabilities_builder_type_state() {
1507            // Test basic builder construction
1508            let builder = ServerCapabilities::builder();
1509            assert!(format!("{:?}", builder).contains("ServerCapabilitiesBuilder"));
1510
1511            // Test enabling capabilities changes the type
1512            let builder_with_tools = builder.enable_tools();
1513
1514            // This should compile - enable_tool_list_changed is available when tools are enabled
1515            let _final_builder = builder_with_tools.enable_tool_list_changed();
1516
1517            // Test building a server with multiple capabilities
1518            let full_capabilities = ServerCapabilitiesBuilder::new()
1519                .enable_experimental()
1520                .enable_logging()
1521                .enable_completions()
1522                .enable_prompts()
1523                .enable_resources()
1524                .enable_tools()
1525                .enable_tool_list_changed()
1526                .enable_prompts_list_changed()
1527                .enable_resources_list_changed()
1528                .enable_resources_subscribe()
1529                .build();
1530
1531            assert!(full_capabilities.experimental.is_some());
1532            assert!(full_capabilities.logging.is_some());
1533            assert!(full_capabilities.completions.is_some());
1534            assert!(full_capabilities.prompts.is_some());
1535            assert!(full_capabilities.resources.is_some());
1536            assert!(full_capabilities.tools.is_some());
1537
1538            // Validate sub-capabilities are set correctly
1539            if let Some(ref tools) = full_capabilities.tools {
1540                assert_eq!(tools.list_changed, Some(true));
1541            }
1542
1543            if let Some(ref resources) = full_capabilities.resources {
1544                assert_eq!(resources.list_changed, Some(true));
1545                assert_eq!(resources.subscribe, Some(true));
1546            }
1547        }
1548
1549        #[test]
1550        fn test_client_capabilities_builder_type_state() {
1551            // Test basic builder construction - now returns all-enabled state
1552            let builder = ClientCapabilities::builder();
1553            assert!(format!("{:?}", builder).contains("ClientCapabilitiesBuilder"));
1554
1555            // Test opt-out: disabling capabilities changes the type
1556            let builder_without_roots = builder.without_roots();
1557
1558            // After disabling roots, we can re-enable it
1559            let builder_with_roots = builder_without_roots.enable_roots();
1560
1561            // This should compile - enable_roots_list_changed is available when roots are enabled
1562            let _final_builder = builder_with_roots.enable_roots_list_changed();
1563
1564            // Test the opt-out default (new() has everything enabled)
1565            let full_capabilities = ClientCapabilitiesBuilder::new()
1566                .enable_roots_list_changed()
1567                .build();
1568
1569            assert!(full_capabilities.experimental.is_some());
1570            assert!(full_capabilities.roots.is_some());
1571            assert!(full_capabilities.sampling.is_some());
1572            assert!(full_capabilities.elicitation.is_some());
1573
1574            // Validate sub-capabilities are set correctly
1575            if let Some(ref roots) = full_capabilities.roots {
1576                assert_eq!(roots.list_changed, Some(true));
1577            }
1578        }
1579
1580        #[test]
1581        fn test_opt_out_model() {
1582            // Default builder has everything enabled
1583            let caps = ClientCapabilitiesBuilder::new().build();
1584            assert!(caps.experimental.is_some());
1585            assert!(caps.roots.is_some());
1586            assert!(caps.sampling.is_some());
1587            assert!(caps.elicitation.is_some());
1588
1589            // Can selectively disable capabilities
1590            let caps_without_elicitation = ClientCapabilitiesBuilder::new()
1591                .without_elicitation()
1592                .build();
1593
1594            assert!(caps_without_elicitation.experimental.is_some());
1595            assert!(caps_without_elicitation.roots.is_some());
1596            assert!(caps_without_elicitation.sampling.is_some());
1597            assert!(caps_without_elicitation.elicitation.is_none());
1598
1599            // Can disable multiple capabilities
1600            let minimal_caps = ClientCapabilitiesBuilder::new()
1601                .without_experimental()
1602                .without_roots()
1603                .without_elicitation()
1604                .build();
1605
1606            assert!(minimal_caps.experimental.is_none());
1607            assert!(minimal_caps.roots.is_none());
1608            assert!(minimal_caps.sampling.is_some());
1609            assert!(minimal_caps.elicitation.is_none());
1610        }
1611
1612        #[test]
1613        fn test_opt_in_with_minimal() {
1614            // Minimal builder starts with nothing enabled
1615            let caps = ClientCapabilitiesBuilder::minimal().build();
1616            assert!(caps.experimental.is_none());
1617            assert!(caps.roots.is_none());
1618            assert!(caps.sampling.is_none());
1619            assert!(caps.elicitation.is_none());
1620
1621            // Can selectively enable capabilities
1622            let caps_with_sampling = ClientCapabilitiesBuilder::minimal()
1623                .enable_sampling()
1624                .build();
1625
1626            assert!(caps_with_sampling.experimental.is_none());
1627            assert!(caps_with_sampling.roots.is_none());
1628            assert!(caps_with_sampling.sampling.is_some());
1629            assert!(caps_with_sampling.elicitation.is_none());
1630
1631            // Can enable multiple capabilities
1632            let full_caps = ClientCapabilitiesBuilder::minimal()
1633                .enable_experimental()
1634                .enable_roots()
1635                .enable_sampling()
1636                .enable_elicitation()
1637                .build();
1638
1639            assert!(full_caps.experimental.is_some());
1640            assert!(full_caps.roots.is_some());
1641            assert!(full_caps.sampling.is_some());
1642            assert!(full_caps.elicitation.is_some());
1643        }
1644
1645        #[test]
1646        fn test_turbomcp_extensions() {
1647            // Test TurboMCP-specific server extensions (still use enable for servers)
1648            let server_caps = ServerCapabilities::builder()
1649                .enable_experimental()
1650                .with_simd_optimization("avx2")
1651                .with_enterprise_security(true)
1652                .build();
1653
1654            if let Some(ref experimental) = server_caps.experimental {
1655                assert!(experimental.contains_key("turbomcp_simd_level"));
1656                assert!(experimental.contains_key("turbomcp_enterprise_security"));
1657                assert_eq!(
1658                    experimental.get("turbomcp_simd_level").unwrap().as_str(),
1659                    Some("avx2")
1660                );
1661                assert_eq!(
1662                    experimental
1663                        .get("turbomcp_enterprise_security")
1664                        .unwrap()
1665                        .as_bool(),
1666                    Some(true)
1667                );
1668            } else {
1669                panic!("Expected experimental capabilities to be set");
1670            }
1671
1672            // Test client experimental capabilities using add_experimental_capability
1673            let client_caps = ClientCapabilities::builder()
1674                .add_experimental_capability("custom_feature", true)
1675                .build();
1676
1677            if let Some(ref experimental) = client_caps.experimental {
1678                assert!(experimental.contains_key("custom_feature"));
1679            } else {
1680                panic!("Expected experimental capabilities to be set");
1681            }
1682        }
1683
1684        #[test]
1685        fn test_minimal_constructor() {
1686            // Test client minimal() constructor - starts with nothing enabled
1687            let minimal_client_caps = ClientCapabilitiesBuilder::minimal().build();
1688            assert!(minimal_client_caps.experimental.is_none());
1689            assert!(minimal_client_caps.roots.is_none());
1690            assert!(minimal_client_caps.sampling.is_none());
1691            assert!(minimal_client_caps.elicitation.is_none());
1692
1693            // Test that we can selectively enable from minimal
1694            let sampling_only = ClientCapabilitiesBuilder::minimal()
1695                .enable_sampling()
1696                .build();
1697            assert!(sampling_only.experimental.is_none());
1698            assert!(sampling_only.roots.is_none());
1699            assert!(sampling_only.sampling.is_some());
1700            assert!(sampling_only.elicitation.is_none());
1701
1702            // Test enabling multiple capabilities from minimal
1703            let sampling_focused_client = ClientCapabilitiesBuilder::minimal()
1704                .enable_experimental()
1705                .enable_sampling()
1706                .build();
1707            assert!(sampling_focused_client.experimental.is_some());
1708            assert!(sampling_focused_client.roots.is_none());
1709            assert!(sampling_focused_client.sampling.is_some());
1710            assert!(sampling_focused_client.elicitation.is_none());
1711        }
1712
1713        #[test]
1714        fn test_builder_default_implementations() {
1715            // Test that default implementations work - now defaults to all-enabled
1716            let default_server_builder = ServerCapabilitiesBuilder::default();
1717            let server_caps = default_server_builder.build();
1718            assert!(server_caps.tools.is_none()); // Server builder still opts in
1719
1720            let default_client_builder = ClientCapabilitiesBuilder::default();
1721            let client_caps = default_client_builder.build();
1722            // Client default now has everything enabled
1723            assert!(client_caps.experimental.is_some());
1724            assert!(client_caps.roots.is_some());
1725            assert!(client_caps.sampling.is_some());
1726            assert!(client_caps.elicitation.is_some());
1727        }
1728
1729        #[test]
1730        fn test_builder_chaining() {
1731            // Test that builder method chaining works correctly
1732            let server_caps = ServerCapabilities::builder()
1733                .enable_experimental()
1734                .enable_tools()
1735                .enable_prompts()
1736                .enable_resources()
1737                .enable_tool_list_changed()
1738                .enable_prompts_list_changed()
1739                .enable_resources_list_changed()
1740                .enable_resources_subscribe()
1741                .add_experimental_capability("custom_feature", true)
1742                .build();
1743
1744            assert!(server_caps.experimental.is_some());
1745            assert!(server_caps.tools.is_some());
1746            assert!(server_caps.prompts.is_some());
1747            assert!(server_caps.resources.is_some());
1748
1749            // Verify custom experimental capability
1750            if let Some(ref experimental) = server_caps.experimental {
1751                assert!(experimental.contains_key("custom_feature"));
1752            }
1753        }
1754
1755        #[test]
1756        fn test_with_negotiator_integration() {
1757            // Test TurboMCP capability negotiator integration
1758            let negotiator = super::super::CapabilityNegotiator::default();
1759
1760            let server_caps = ServerCapabilities::builder()
1761                .enable_tools()
1762                .with_negotiator(negotiator.clone())
1763                .with_strict_validation()
1764                .build();
1765
1766            assert!(server_caps.tools.is_some());
1767            // Note: negotiator and strict_validation are internal to the builder
1768            // and don't appear in the final ServerCapabilities struct
1769        }
1770
1771        #[test]
1772        fn test_builder_validation_methods() {
1773            // Test server builder validation
1774            let server_builder = ServerCapabilities::builder()
1775                .enable_experimental()
1776                .enable_tools()
1777                .with_simd_optimization("avx2")
1778                .with_enterprise_security(true)
1779                .with_strict_validation();
1780
1781            // Validation should pass for well-configured builder
1782            assert!(server_builder.validate().is_ok());
1783
1784            // Test summary method
1785            let summary = server_builder.summary();
1786            assert!(summary.contains("experimental"));
1787            assert!(summary.contains("tools"));
1788
1789            // Test client builder validation - now uses new() which starts all-enabled
1790            let client_builder = ClientCapabilities::builder()
1791                .add_experimental_capability("custom_feature", true)
1792                .with_strict_validation();
1793
1794            // Validation should pass for well-configured builder
1795            assert!(client_builder.validate().is_ok());
1796
1797            // Test summary method
1798            let summary = client_builder.summary();
1799            assert!(summary.contains("experimental"));
1800            assert!(summary.contains("sampling"));
1801        }
1802
1803        #[test]
1804        fn test_builder_validation_errors() {
1805            // Test server validation errors
1806            let server_builder = ServerCapabilities::builder()
1807                .enable_experimental()
1808                .with_strict_validation();
1809
1810            // Should fail validation - no actual capabilities enabled
1811            assert!(server_builder.validate().is_err());
1812            let error = server_builder.validate().unwrap_err();
1813            assert!(error.contains("at least one capability"));
1814
1815            // Test invalid SIMD level
1816            let invalid_server_builder = ServerCapabilities::builder()
1817                .enable_experimental()
1818                .enable_tools()
1819                .add_experimental_capability("turbomcp_simd_level", "invalid_level")
1820                .with_strict_validation();
1821
1822            assert!(invalid_server_builder.validate().is_err());
1823            let error = invalid_server_builder.validate().unwrap_err();
1824            assert!(error.contains("Invalid SIMD level"));
1825
1826            // Client validation should always pass now (removed strict validation for UI/LLM)
1827            let client_builder = ClientCapabilities::builder()
1828                .add_experimental_capability("custom_feature", true)
1829                .with_strict_validation();
1830
1831            assert!(client_builder.validate().is_ok());
1832        }
1833
1834        #[test]
1835        fn test_builder_clone_support() {
1836            // Test that builders can be cloned
1837            let original_server_builder = ServerCapabilities::builder()
1838                .enable_tools()
1839                .enable_prompts();
1840
1841            let cloned_server_builder = original_server_builder.clone();
1842
1843            // Both should produce equivalent capabilities
1844            let original_caps = original_server_builder.build();
1845            let cloned_caps = cloned_server_builder.build();
1846
1847            assert_eq!(original_caps.tools.is_some(), cloned_caps.tools.is_some());
1848            assert_eq!(
1849                original_caps.prompts.is_some(),
1850                cloned_caps.prompts.is_some()
1851            );
1852
1853            // Test client builder clone - use without_*() since default is all-enabled
1854            let original_client_builder = ClientCapabilities::builder()
1855                .without_experimental()
1856                .without_roots();
1857
1858            let cloned_client_builder = original_client_builder.clone();
1859
1860            let original_caps = original_client_builder.build();
1861            let cloned_caps = cloned_client_builder.build();
1862
1863            assert_eq!(
1864                original_caps.experimental.is_some(),
1865                cloned_caps.experimental.is_some()
1866            );
1867            assert_eq!(original_caps.roots.is_some(), cloned_caps.roots.is_some());
1868            assert_eq!(
1869                original_caps.sampling.is_some(),
1870                cloned_caps.sampling.is_some()
1871            );
1872            assert_eq!(
1873                original_caps.elicitation.is_some(),
1874                cloned_caps.elicitation.is_some()
1875            );
1876        }
1877    }
1878}