Skip to main content

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