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