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            sampling: Some(Default::default()),
524            roots: Some(Default::default()),
525            elicitation: Some(Default::default()),
526            tasks: Some(Default::default()),
527            extensions: None,
528            experimental: None,
529        }
530    }
531
532    /// Create a full-featured server capability set
533    pub fn full_server_capabilities() -> ServerCapabilities {
534        ServerCapabilities {
535            tools: Some(Default::default()),
536            prompts: Some(Default::default()),
537            resources: Some(Default::default()),
538            completions: Some(Default::default()),
539            logging: Some(Default::default()),
540            tasks: Some(Default::default()),
541            extensions: None,
542            experimental: None,
543        }
544    }
545
546    /// Check if two capability sets are compatible
547    pub fn are_compatible(client: &ClientCapabilities, server: &ServerCapabilities) -> bool {
548        let matcher = CapabilityMatcher::new();
549        matcher.negotiate(client, server).is_ok()
550    }
551}
552
553#[cfg(test)]
554mod tests {
555    use super::*;
556    use crate::types::*;
557
558    #[test]
559    fn test_capability_matcher() {
560        let matcher = CapabilityMatcher::new();
561
562        let client = ClientCapabilities {
563            sampling: Some(SamplingCapabilities::default()),
564            ..Default::default()
565        };
566
567        let server = ServerCapabilities {
568            tools: Some(ToolsCapabilities::default()),
569            ..Default::default()
570        };
571
572        assert!(matcher.is_compatible("sampling", &client, &server));
573        assert!(matcher.is_compatible("tools", &client, &server));
574        assert!(!matcher.is_compatible("roots", &client, &server));
575    }
576
577    #[test]
578    fn test_capability_negotiation() {
579        let negotiator = CapabilityNegotiator::default();
580
581        let client = utils::full_client_capabilities();
582        let server = utils::full_server_capabilities();
583
584        let result = negotiator.negotiate(&client, &server);
585        assert!(result.is_ok());
586
587        let capability_set = result.unwrap();
588        assert!(capability_set.has_feature("sampling"));
589        assert!(capability_set.has_feature("tools"));
590        assert!(capability_set.has_feature("roots"));
591    }
592
593    #[test]
594    fn test_strict_mode() {
595        let negotiator = CapabilityNegotiator::default().with_strict_mode();
596
597        let client = ClientCapabilities::default();
598        let server = ServerCapabilities::default();
599
600        let result = negotiator.negotiate(&client, &server);
601        assert!(result.is_ok()); // Should still work with minimal capabilities
602    }
603
604    #[test]
605    fn test_capability_summary() {
606        let mut capability_set = CapabilitySet::empty();
607        capability_set.enable_feature("tools".to_string());
608        capability_set.enable_feature("prompts".to_string());
609
610        let summary = capability_set.summary();
611        assert_eq!(summary.total_features, 2);
612        assert!(summary.enabled_features.contains(&"tools".to_string()));
613    }
614}
615
616// ============================================================================
617// TYPE-STATE CAPABILITY BUILDERS - TURBOMCP LEAPFROG IMPLEMENTATION
618// ============================================================================
619
620/// Type-state capability builders for compile-time validation
621///
622/// This module provides const-generic builders that ensure capabilities
623/// are configured correctly at compile time with zero-cost abstractions
624/// and advanced compile-time safety features.
625pub mod builders {
626    use crate::types::{
627        ClientCapabilities, ClientTasksCapabilities, CompletionCapabilities,
628        ElicitationCapabilities, LoggingCapabilities, PromptsCapabilities, ResourcesCapabilities,
629        RootsCapabilities, SamplingCapabilities, ServerCapabilities, ServerTasksCapabilities,
630        ToolsCapabilities,
631    };
632    use serde_json;
633    use std::collections::HashMap;
634    use std::marker::PhantomData;
635
636    /// Extension trait that adds `ServerCapabilities::builder()`.
637    ///
638    /// `ServerCapabilities` lives in [`turbomcp_types`], so the inherent `impl`
639    /// has to be reached through this trait (Rust's orphan rules).
640    pub trait ServerCapabilitiesBuilderExt {
641        /// Create a new [`ServerCapabilitiesBuilder`] with type-state validation.
642        fn builder() -> ServerCapabilitiesBuilder;
643    }
644
645    impl ServerCapabilitiesBuilderExt for ServerCapabilities {
646        fn builder() -> ServerCapabilitiesBuilder {
647            ServerCapabilitiesBuilder::new()
648        }
649    }
650
651    /// Extension trait that adds `ClientCapabilities::builder()`.
652    ///
653    /// `ClientCapabilities` lives in [`turbomcp_types`], so the inherent `impl`
654    /// has to be reached through this trait (Rust's orphan rules).
655    pub trait ClientCapabilitiesBuilderExt {
656        /// Create a new [`ClientCapabilitiesBuilder`] with all capabilities enabled (opt-out model).
657        fn builder()
658        -> ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<true, true, true, true>>;
659    }
660
661    impl ClientCapabilitiesBuilderExt for ClientCapabilities {
662        fn builder()
663        -> ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<true, true, true, true>>
664        {
665            ClientCapabilitiesBuilder::new()
666        }
667    }
668
669    // ========================================================================
670    // SERVER CAPABILITIES BUILDER - TYPE-STATE SYSTEM
671    // ========================================================================
672
673    /// Type-state for ServerCapabilitiesBuilder
674    ///
675    /// Each const generic represents whether a capability is enabled:
676    /// - EXPERIMENTAL: Experimental capabilities
677    /// - LOGGING: Logging capabilities
678    /// - COMPLETIONS: Completion capabilities
679    /// - PROMPTS: Prompt capabilities
680    /// - RESOURCES: Resource capabilities
681    /// - TOOLS: Tool capabilities
682    #[derive(Debug, Clone)]
683    pub struct ServerCapabilitiesBuilderState<
684        const EXPERIMENTAL: bool = false,
685        const LOGGING: bool = false,
686        const COMPLETIONS: bool = false,
687        const PROMPTS: bool = false,
688        const RESOURCES: bool = false,
689        const TOOLS: bool = false,
690    >;
691
692    /// Const-generic ServerCapabilities builder with compile-time validation
693    ///
694    /// This builder ensures that capability-specific methods are only available
695    /// when the corresponding capability is enabled, providing compile-time safety
696    /// with compile-time validation.
697    #[derive(Debug, Clone)]
698    pub struct ServerCapabilitiesBuilder<S = ServerCapabilitiesBuilderState> {
699        extensions: Option<HashMap<String, serde_json::Value>>,
700        experimental: Option<HashMap<String, serde_json::Value>>,
701        logging: Option<LoggingCapabilities>,
702        completions: Option<CompletionCapabilities>,
703        prompts: Option<PromptsCapabilities>,
704        resources: Option<ResourcesCapabilities>,
705        tools: Option<ToolsCapabilities>,
706        tasks: Option<ServerTasksCapabilities>,
707
708        // TurboMCP Extensions
709        negotiator: Option<super::CapabilityNegotiator>,
710        strict_validation: bool,
711
712        _state: PhantomData<S>,
713    }
714
715    impl Default for ServerCapabilitiesBuilder {
716        fn default() -> Self {
717            Self::new()
718        }
719    }
720
721    impl ServerCapabilitiesBuilder {
722        /// Create a new ServerCapabilities builder
723        pub fn new() -> Self {
724            Self {
725                extensions: None,
726                experimental: None,
727                logging: None,
728                completions: None,
729                prompts: None,
730                resources: None,
731                tools: None,
732                tasks: None,
733                negotiator: None,
734                strict_validation: false,
735                _state: PhantomData,
736            }
737        }
738    }
739
740    // Generic implementation for all states
741    impl<S> ServerCapabilitiesBuilder<S> {
742        /// Build the final ServerCapabilities
743        ///
744        /// Consumes the builder and returns the configured ServerCapabilities.
745        /// All compile-time validations have been enforced during building.
746        pub fn build(self) -> ServerCapabilities {
747            ServerCapabilities {
748                extensions: self.extensions,
749                experimental: self.experimental,
750                logging: self.logging,
751                completions: self.completions,
752                prompts: self.prompts,
753                resources: self.resources,
754                tools: self.tools,
755                tasks: self.tasks,
756            }
757        }
758
759        /// TurboMCP Extension: Enable strict validation mode
760        ///
761        /// When enabled, the builder will perform additional runtime validations
762        /// on top of the compile-time guarantees.
763        pub fn with_strict_validation(mut self) -> Self {
764            self.strict_validation = true;
765            self
766        }
767
768        /// TurboMCP Extension: Set capability negotiator
769        ///
770        /// Integrates with TurboMCP's sophisticated capability negotiation system
771        /// for advanced client-server capability matching.
772        pub fn with_negotiator(mut self, negotiator: super::CapabilityNegotiator) -> Self {
773            self.negotiator = Some(negotiator);
774            self
775        }
776
777        /// TurboMCP Extension: Validate capability configuration
778        ///
779        /// Performs additional runtime validation to ensure the capability
780        /// configuration makes sense in the current context.
781        pub fn validate(&self) -> Result<(), String> {
782            if self.strict_validation {
783                // Perform additional validation when strict mode is enabled
784                if self.tools.is_none() && self.prompts.is_none() && self.resources.is_none() {
785                    return Err("Server must provide at least one capability (tools, prompts, or resources)".to_string());
786                }
787
788                // Validate experimental capabilities if present
789                if let Some(ref experimental) = self.experimental {
790                    for (key, value) in experimental {
791                        if key.starts_with("turbomcp_") {
792                            // Validate TurboMCP-specific experimental capabilities
793                            match key.as_str() {
794                                "turbomcp_simd_level" => {
795                                    if !value.is_string() {
796                                        return Err(
797                                            "turbomcp_simd_level must be a string".to_string()
798                                        );
799                                    }
800                                    let level = value.as_str().unwrap_or("");
801                                    if !["none", "sse2", "sse4", "avx2", "avx512"].contains(&level)
802                                    {
803                                        return Err(format!("Invalid SIMD level: {}", level));
804                                    }
805                                }
806                                "turbomcp_enterprise_security" if !value.is_boolean() => {
807                                    return Err("turbomcp_enterprise_security must be a boolean"
808                                        .to_string());
809                                }
810                                _ => {
811                                    // Allow other TurboMCP experimental features
812                                }
813                            }
814                        }
815                    }
816                }
817            }
818            Ok(())
819        }
820
821        /// Get a summary of enabled capabilities
822        ///
823        /// Returns a human-readable summary of which capabilities are enabled.
824        pub fn summary(&self) -> String {
825            let mut capabilities = Vec::new();
826            if self.extensions.is_some() {
827                capabilities.push("extensions");
828            }
829            if self.experimental.is_some() {
830                capabilities.push("experimental");
831            }
832            if self.logging.is_some() {
833                capabilities.push("logging");
834            }
835            if self.completions.is_some() {
836                capabilities.push("completions");
837            }
838            if self.prompts.is_some() {
839                capabilities.push("prompts");
840            }
841            if self.resources.is_some() {
842                capabilities.push("resources");
843            }
844            if self.tools.is_some() {
845                capabilities.push("tools");
846            }
847
848            if capabilities.is_empty() {
849                "No capabilities enabled".to_string()
850            } else {
851                format!("Enabled capabilities: {}", capabilities.join(", "))
852            }
853        }
854
855        /// Set draft extensions directly.
856        pub fn with_extensions(mut self, extensions: HashMap<String, serde_json::Value>) -> Self {
857            self.extensions = Some(extensions);
858            self
859        }
860
861        /// Add a single draft extension.
862        pub fn add_extension<K, V>(mut self, key: K, value: V) -> Self
863        where
864            K: Into<String>,
865            V: Into<serde_json::Value>,
866        {
867            self.extensions
868                .get_or_insert_with(HashMap::new)
869                .insert(key.into(), value.into());
870            self
871        }
872    }
873
874    // ========================================================================
875    // CAPABILITY ENABLEMENT METHODS
876    // ========================================================================
877
878    // Enable Experimental Capabilities
879    impl<const L: bool, const C: bool, const P: bool, const R: bool, const T: bool>
880        ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<false, L, C, P, R, T>>
881    {
882        /// Enable experimental capabilities
883        ///
884        /// Transitions the builder to a state where experimental capability methods
885        /// become available at compile time.
886        pub fn enable_experimental(
887            self,
888        ) -> ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<true, L, C, P, R, T>>
889        {
890            ServerCapabilitiesBuilder {
891                extensions: self.extensions,
892                experimental: Some(HashMap::new()),
893                logging: self.logging,
894                completions: self.completions,
895                prompts: self.prompts,
896                resources: self.resources,
897                tools: self.tools,
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                tasks: self.tasks,
920                negotiator: self.negotiator,
921                strict_validation: self.strict_validation,
922                _state: PhantomData,
923            }
924        }
925    }
926
927    // Enable Logging Capabilities
928    impl<const E: bool, const C: bool, const P: bool, const R: bool, const T: bool>
929        ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<E, false, C, P, R, T>>
930    {
931        /// Enable logging capabilities
932        pub fn enable_logging(
933            self,
934        ) -> ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<E, true, C, P, R, T>>
935        {
936            ServerCapabilitiesBuilder {
937                extensions: self.extensions,
938                experimental: self.experimental,
939                logging: Some(LoggingCapabilities {}),
940                completions: self.completions,
941                prompts: self.prompts,
942                resources: self.resources,
943                tools: self.tools,
944                tasks: self.tasks,
945                negotiator: self.negotiator,
946                strict_validation: self.strict_validation,
947                _state: PhantomData,
948            }
949        }
950    }
951
952    // Enable Completion Capabilities
953    impl<const E: bool, const L: bool, const P: bool, const R: bool, const T: bool>
954        ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<E, L, false, P, R, T>>
955    {
956        /// Enable completion capabilities
957        pub fn enable_completions(
958            self,
959        ) -> ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<E, L, true, P, R, T>>
960        {
961            ServerCapabilitiesBuilder {
962                extensions: self.extensions,
963                experimental: self.experimental,
964                logging: self.logging,
965                completions: Some(CompletionCapabilities {}),
966                prompts: self.prompts,
967                resources: self.resources,
968                tools: self.tools,
969                tasks: self.tasks,
970                negotiator: self.negotiator,
971                strict_validation: self.strict_validation,
972                _state: PhantomData,
973            }
974        }
975    }
976
977    // Enable Prompts Capabilities
978    impl<const E: bool, const L: bool, const C: bool, const R: bool, const T: bool>
979        ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<E, L, C, false, R, T>>
980    {
981        /// Enable prompts capabilities
982        pub fn enable_prompts(
983            self,
984        ) -> ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<E, L, C, true, R, T>>
985        {
986            ServerCapabilitiesBuilder {
987                extensions: self.extensions,
988                experimental: self.experimental,
989                logging: self.logging,
990                completions: self.completions,
991                prompts: Some(PromptsCapabilities { list_changed: None }),
992                resources: self.resources,
993                tools: self.tools,
994                tasks: self.tasks,
995                negotiator: self.negotiator,
996                strict_validation: self.strict_validation,
997                _state: PhantomData,
998            }
999        }
1000    }
1001
1002    // Enable Resources Capabilities
1003    impl<const E: bool, const L: bool, const C: bool, const P: bool, const T: bool>
1004        ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<E, L, C, P, false, T>>
1005    {
1006        /// Enable resources capabilities
1007        pub fn enable_resources(
1008            self,
1009        ) -> ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<E, L, C, P, true, T>>
1010        {
1011            ServerCapabilitiesBuilder {
1012                extensions: self.extensions,
1013                experimental: self.experimental,
1014                logging: self.logging,
1015                completions: self.completions,
1016                prompts: self.prompts,
1017                resources: Some(ResourcesCapabilities {
1018                    subscribe: None,
1019                    list_changed: None,
1020                }),
1021                tools: self.tools,
1022                tasks: self.tasks,
1023                negotiator: self.negotiator,
1024                strict_validation: self.strict_validation,
1025                _state: PhantomData,
1026            }
1027        }
1028    }
1029
1030    // Enable Tools Capabilities
1031    impl<const E: bool, const L: bool, const C: bool, const P: bool, const R: bool>
1032        ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<E, L, C, P, R, false>>
1033    {
1034        /// Enable tools capabilities
1035        pub fn enable_tools(
1036            self,
1037        ) -> ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<E, L, C, P, R, true>>
1038        {
1039            ServerCapabilitiesBuilder {
1040                extensions: self.extensions,
1041                experimental: self.experimental,
1042                logging: self.logging,
1043                completions: self.completions,
1044                prompts: self.prompts,
1045                resources: self.resources,
1046                tools: Some(ToolsCapabilities { list_changed: None }),
1047                tasks: self.tasks,
1048                negotiator: self.negotiator,
1049                strict_validation: self.strict_validation,
1050                _state: PhantomData,
1051            }
1052        }
1053    }
1054
1055    // ========================================================================
1056    // SUB-CAPABILITY METHODS (ONLY AVAILABLE WHEN PARENT CAPABILITY ENABLED)
1057    // ========================================================================
1058
1059    // Tools sub-capabilities (only available when TOOLS = true)
1060    impl<const E: bool, const L: bool, const C: bool, const P: bool, const R: bool>
1061        ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<E, L, C, P, R, true>>
1062    {
1063        /// Enable tool list changed notifications
1064        ///
1065        /// This method is only available when tools capabilities are enabled,
1066        /// providing advanced compile-time validation.
1067        pub fn enable_tool_list_changed(mut self) -> Self {
1068            if let Some(ref mut tools) = self.tools {
1069                tools.list_changed = Some(true);
1070            }
1071            self
1072        }
1073    }
1074
1075    // Prompts sub-capabilities (only available when PROMPTS = true)
1076    impl<const E: bool, const L: bool, const C: bool, const R: bool, const T: bool>
1077        ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<E, L, C, true, R, T>>
1078    {
1079        /// Enable prompts list changed notifications
1080        pub fn enable_prompts_list_changed(mut self) -> Self {
1081            if let Some(ref mut prompts) = self.prompts {
1082                prompts.list_changed = Some(true);
1083            }
1084            self
1085        }
1086    }
1087
1088    // Resources sub-capabilities (only available when RESOURCES = true)
1089    impl<const E: bool, const L: bool, const C: bool, const P: bool, const T: bool>
1090        ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<E, L, C, P, true, T>>
1091    {
1092        /// Enable resources list changed notifications
1093        pub fn enable_resources_list_changed(mut self) -> Self {
1094            if let Some(ref mut resources) = self.resources {
1095                resources.list_changed = Some(true);
1096            }
1097            self
1098        }
1099
1100        /// Enable resources subscribe capability
1101        pub fn enable_resources_subscribe(mut self) -> Self {
1102            if let Some(ref mut resources) = self.resources {
1103                resources.subscribe = Some(true);
1104            }
1105            self
1106        }
1107    }
1108
1109    // Experimental sub-capabilities (only available when EXPERIMENTAL = true)
1110    impl<const L: bool, const C: bool, const P: bool, const R: bool, const T: bool>
1111        ServerCapabilitiesBuilder<ServerCapabilitiesBuilderState<true, L, C, P, R, T>>
1112    {
1113        /// Add experimental capability
1114        ///
1115        /// This method is only available when experimental capabilities are enabled.
1116        pub fn add_experimental_capability<K, V>(mut self, key: K, value: V) -> Self
1117        where
1118            K: Into<String>,
1119            V: Into<serde_json::Value>,
1120        {
1121            if let Some(ref mut experimental) = self.experimental {
1122                experimental.insert(key.into(), value.into());
1123            }
1124            self
1125        }
1126
1127        /// TurboMCP Extension: Add SIMD optimization hint
1128        ///
1129        /// Unique to TurboMCP - hints about SIMD capabilities for performance optimization.
1130        pub fn with_simd_optimization(mut self, level: &str) -> Self {
1131            if let Some(ref mut experimental) = self.experimental {
1132                experimental.insert(
1133                    "turbomcp_simd_level".to_string(),
1134                    serde_json::Value::String(level.to_string()),
1135                );
1136            }
1137            self
1138        }
1139
1140        /// TurboMCP Extension: Add enterprise security metadata
1141        ///
1142        /// Unique to TurboMCP - metadata about security capabilities.
1143        pub fn with_enterprise_security(mut self, enabled: bool) -> Self {
1144            if let Some(ref mut experimental) = self.experimental {
1145                experimental.insert(
1146                    "turbomcp_enterprise_security".to_string(),
1147                    serde_json::Value::Bool(enabled),
1148                );
1149            }
1150            self
1151        }
1152    }
1153
1154    // ========================================================================
1155    // CLIENT CAPABILITIES BUILDER - TYPE-STATE SYSTEM
1156    // ========================================================================
1157
1158    /// Type-state for ClientCapabilitiesBuilder
1159    ///
1160    /// Each const generic represents whether a capability is enabled:
1161    /// - EXPERIMENTAL: Experimental capabilities
1162    /// - ROOTS: Roots capabilities
1163    /// - SAMPLING: Sampling capabilities
1164    /// - ELICITATION: Elicitation capabilities
1165    #[derive(Debug, Clone)]
1166    pub struct ClientCapabilitiesBuilderState<
1167        const EXPERIMENTAL: bool = false,
1168        const ROOTS: bool = false,
1169        const SAMPLING: bool = false,
1170        const ELICITATION: bool = false,
1171    >;
1172
1173    /// Const-generic ClientCapabilities builder with compile-time validation
1174    ///
1175    /// This builder ensures that capability-specific methods are only available
1176    /// when the corresponding capability is enabled, providing compile-time safety
1177    /// with comprehensive compile-time validation.
1178    #[derive(Debug, Clone)]
1179    pub struct ClientCapabilitiesBuilder<S = ClientCapabilitiesBuilderState> {
1180        extensions: Option<HashMap<String, serde_json::Value>>,
1181        experimental: Option<HashMap<String, serde_json::Value>>,
1182        roots: Option<RootsCapabilities>,
1183        sampling: Option<SamplingCapabilities>,
1184        elicitation: Option<ElicitationCapabilities>,
1185        tasks: Option<ClientTasksCapabilities>,
1186
1187        // TurboMCP Extensions
1188        negotiator: Option<super::CapabilityNegotiator>,
1189        strict_validation: bool,
1190
1191        _state: PhantomData<S>,
1192    }
1193
1194    impl Default for ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<true, true, true, true>> {
1195        fn default() -> Self {
1196            Self::new()
1197        }
1198    }
1199
1200    impl ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<true, true, true, true>> {
1201        /// Create a new ClientCapabilities builder with all capabilities enabled (opt-out model)
1202        ///
1203        /// By default, all capabilities are enabled. Use `.without_*()` methods to disable
1204        /// specific capabilities if needed.
1205        ///
1206        /// This design provides forward compatibility - when new MCP capabilities are added,
1207        /// existing clients automatically support them without code changes.
1208        ///
1209        /// For clients that need explicit opt-in behavior, use `ClientCapabilitiesBuilder::minimal()`.
1210        pub fn new() -> Self {
1211            Self {
1212                extensions: None,
1213                experimental: Some(HashMap::new()),
1214                roots: Some(RootsCapabilities::default()),
1215                sampling: Some(SamplingCapabilities::default()),
1216                elicitation: Some(ElicitationCapabilities::full()),
1217                tasks: Some(ClientTasksCapabilities::default()),
1218                negotiator: None,
1219                strict_validation: false,
1220                _state: PhantomData,
1221            }
1222        }
1223    }
1224
1225    impl ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<false, false, false, false>> {
1226        /// Create a minimal ClientCapabilities builder with no capabilities enabled (opt-in model)
1227        ///
1228        /// Starts with all capabilities disabled. Use `.enable_*()` methods to opt-in
1229        /// to specific capabilities.
1230        ///
1231        /// Most users should use `ClientCapabilitiesBuilder::new()` instead, which provides
1232        /// an opt-out model with all capabilities enabled by default.
1233        ///
1234        /// Use this constructor when:
1235        /// - You need explicit control over which capabilities are enabled
1236        /// - You're building a restricted client (embedded, CLI-only, etc.)
1237        /// - You want to minimize the attack surface
1238        pub fn minimal() -> Self {
1239            Self {
1240                extensions: None,
1241                experimental: None,
1242                roots: None,
1243                sampling: None,
1244                elicitation: None,
1245                tasks: None,
1246                negotiator: None,
1247                strict_validation: false,
1248                _state: PhantomData,
1249            }
1250        }
1251    }
1252
1253    // Generic implementation for all states
1254    impl<S> ClientCapabilitiesBuilder<S> {
1255        /// Build the final ClientCapabilities
1256        ///
1257        /// Consumes the builder and returns the configured ClientCapabilities.
1258        /// All compile-time validations have been enforced during building.
1259        pub fn build(self) -> ClientCapabilities {
1260            ClientCapabilities {
1261                extensions: self.extensions,
1262                experimental: self.experimental,
1263                roots: self.roots,
1264                sampling: self.sampling,
1265                elicitation: self.elicitation,
1266                tasks: self.tasks,
1267            }
1268        }
1269
1270        /// TurboMCP Extension: Enable strict validation mode
1271        ///
1272        /// When enabled, the builder will perform additional runtime validations
1273        /// on top of the compile-time guarantees.
1274        pub fn with_strict_validation(mut self) -> Self {
1275            self.strict_validation = true;
1276            self
1277        }
1278
1279        /// TurboMCP Extension: Set capability negotiator
1280        ///
1281        /// Integrates with TurboMCP's sophisticated capability negotiation system
1282        /// for advanced client-server capability matching.
1283        pub fn with_negotiator(mut self, negotiator: super::CapabilityNegotiator) -> Self {
1284            self.negotiator = Some(negotiator);
1285            self
1286        }
1287
1288        /// TurboMCP Extension: Validate capability configuration
1289        ///
1290        /// Performs additional runtime validation to ensure the capability
1291        /// configuration makes sense in the current context.
1292        pub fn validate(&self) -> Result<(), String> {
1293            if self.strict_validation {
1294                // Validate experimental capabilities if present
1295                if let Some(ref experimental) = self.experimental {
1296                    for key in experimental.keys() {
1297                        if key.starts_with("turbomcp_") {
1298                            // Allow all TurboMCP experimental features
1299                            // Removed validation for deprecated methods:
1300                            // - turbomcp_llm_provider (removed)
1301                            // - turbomcp_ui_capabilities (removed)
1302                        }
1303                    }
1304                }
1305            }
1306            Ok(())
1307        }
1308
1309        /// Get a summary of enabled capabilities
1310        ///
1311        /// Returns a human-readable summary of which capabilities are enabled.
1312        pub fn summary(&self) -> String {
1313            let mut capabilities = Vec::new();
1314            if self.extensions.is_some() {
1315                capabilities.push("extensions");
1316            }
1317            if self.experimental.is_some() {
1318                capabilities.push("experimental");
1319            }
1320            if self.roots.is_some() {
1321                capabilities.push("roots");
1322            }
1323            if self.sampling.is_some() {
1324                capabilities.push("sampling");
1325            }
1326            if self.elicitation.is_some() {
1327                capabilities.push("elicitation");
1328            }
1329
1330            if capabilities.is_empty() {
1331                "No capabilities enabled".to_string()
1332            } else {
1333                format!("Enabled capabilities: {}", capabilities.join(", "))
1334            }
1335        }
1336
1337        /// Set draft extensions directly.
1338        pub fn with_extensions(mut self, extensions: HashMap<String, serde_json::Value>) -> Self {
1339            self.extensions = Some(extensions);
1340            self
1341        }
1342
1343        /// Add a single draft extension.
1344        pub fn add_extension<K, V>(mut self, key: K, value: V) -> Self
1345        where
1346            K: Into<String>,
1347            V: Into<serde_json::Value>,
1348        {
1349            self.extensions
1350                .get_or_insert_with(HashMap::new)
1351                .insert(key.into(), value.into());
1352            self
1353        }
1354    }
1355
1356    // ========================================================================
1357    // CLIENT CAPABILITY ENABLEMENT METHODS
1358    // ========================================================================
1359
1360    // Enable Experimental Capabilities
1361    impl<const R: bool, const S: bool, const E: bool>
1362        ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<false, R, S, E>>
1363    {
1364        /// Enable experimental capabilities
1365        ///
1366        /// Transitions the builder to a state where experimental capability methods
1367        /// become available at compile time.
1368        pub fn enable_experimental(
1369            self,
1370        ) -> ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<true, R, S, E>> {
1371            ClientCapabilitiesBuilder {
1372                extensions: self.extensions,
1373                experimental: Some(HashMap::new()),
1374                roots: self.roots,
1375                sampling: self.sampling,
1376                elicitation: self.elicitation,
1377                tasks: self.tasks,
1378                negotiator: self.negotiator,
1379                strict_validation: self.strict_validation,
1380                _state: PhantomData,
1381            }
1382        }
1383
1384        /// Enable experimental capabilities with specific values
1385        pub fn enable_experimental_with(
1386            self,
1387            experimental: HashMap<String, serde_json::Value>,
1388        ) -> ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<true, R, S, E>> {
1389            ClientCapabilitiesBuilder {
1390                extensions: self.extensions,
1391                experimental: Some(experimental),
1392                roots: self.roots,
1393                sampling: self.sampling,
1394                elicitation: self.elicitation,
1395                tasks: self.tasks,
1396                negotiator: self.negotiator,
1397                strict_validation: self.strict_validation,
1398                _state: PhantomData,
1399            }
1400        }
1401    }
1402
1403    // Enable Roots Capabilities
1404    impl<const X: bool, const S: bool, const E: bool>
1405        ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, false, S, E>>
1406    {
1407        /// Enable roots capabilities
1408        pub fn enable_roots(
1409            self,
1410        ) -> ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, true, S, E>> {
1411            ClientCapabilitiesBuilder {
1412                extensions: self.extensions,
1413                experimental: self.experimental,
1414                roots: Some(RootsCapabilities { list_changed: None }),
1415                sampling: self.sampling,
1416                elicitation: self.elicitation,
1417                tasks: self.tasks,
1418                negotiator: self.negotiator,
1419                strict_validation: self.strict_validation,
1420                _state: PhantomData,
1421            }
1422        }
1423    }
1424
1425    // Enable Sampling Capabilities
1426    impl<const X: bool, const R: bool, const E: bool>
1427        ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, R, false, E>>
1428    {
1429        /// Enable sampling capabilities
1430        pub fn enable_sampling(
1431            self,
1432        ) -> ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, R, true, E>> {
1433            ClientCapabilitiesBuilder {
1434                extensions: self.extensions,
1435                experimental: self.experimental,
1436                roots: self.roots,
1437                sampling: Some(SamplingCapabilities::default()),
1438                elicitation: self.elicitation,
1439                tasks: self.tasks,
1440                negotiator: self.negotiator,
1441                strict_validation: self.strict_validation,
1442                _state: PhantomData,
1443            }
1444        }
1445    }
1446
1447    // Enable Elicitation Capabilities
1448    impl<const X: bool, const R: bool, const S: bool>
1449        ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, R, S, false>>
1450    {
1451        /// Enable elicitation capabilities (form + URL modes)
1452        pub fn enable_elicitation(
1453            self,
1454        ) -> ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, R, S, true>> {
1455            ClientCapabilitiesBuilder {
1456                extensions: self.extensions,
1457                experimental: self.experimental,
1458                roots: self.roots,
1459                sampling: self.sampling,
1460                elicitation: Some(ElicitationCapabilities::full()),
1461                tasks: self.tasks,
1462                negotiator: self.negotiator,
1463                strict_validation: self.strict_validation,
1464                _state: PhantomData,
1465            }
1466        }
1467
1468        /// Enable elicitation with form mode only
1469        pub fn enable_elicitation_form_only(
1470            self,
1471        ) -> ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, R, S, true>> {
1472            ClientCapabilitiesBuilder {
1473                extensions: self.extensions,
1474                experimental: self.experimental,
1475                roots: self.roots,
1476                sampling: self.sampling,
1477                elicitation: Some(ElicitationCapabilities::form_only()),
1478                tasks: self.tasks,
1479                negotiator: self.negotiator,
1480                strict_validation: self.strict_validation,
1481                _state: PhantomData,
1482            }
1483        }
1484
1485        /// Enable elicitation with schema validation (TurboMCP extension)
1486        pub fn enable_elicitation_with_schema_validation(
1487            self,
1488        ) -> ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, R, S, true>> {
1489            ClientCapabilitiesBuilder {
1490                extensions: self.extensions,
1491                experimental: self.experimental,
1492                roots: self.roots,
1493                sampling: self.sampling,
1494                elicitation: Some(ElicitationCapabilities::full().with_schema_validation()),
1495                tasks: self.tasks,
1496                negotiator: self.negotiator,
1497                strict_validation: self.strict_validation,
1498                _state: PhantomData,
1499            }
1500        }
1501    }
1502
1503    // ========================================================================
1504    // CLIENT SUB-CAPABILITY METHODS
1505    // ========================================================================
1506
1507    // Roots sub-capabilities (only available when ROOTS = true)
1508    impl<const X: bool, const S: bool, const E: bool>
1509        ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, true, S, E>>
1510    {
1511        /// Enable roots list changed notifications
1512        ///
1513        /// This method is only available when roots capabilities are enabled,
1514        /// providing compile-time safety.
1515        pub fn enable_roots_list_changed(mut self) -> Self {
1516            if let Some(ref mut roots) = self.roots {
1517                roots.list_changed = Some(true);
1518            }
1519            self
1520        }
1521    }
1522
1523    // ========================================================================
1524    // CLIENT CAPABILITY DISABLEMENT METHODS (OPT-OUT API)
1525    // ========================================================================
1526
1527    // Disable Experimental Capabilities
1528    impl<const R: bool, const S: bool, const E: bool>
1529        ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<true, R, S, E>>
1530    {
1531        /// Disable experimental capabilities (opt-out)
1532        ///
1533        /// Transitions the builder to a state where experimental capability methods
1534        /// are no longer available at compile time.
1535        pub fn without_experimental(
1536            self,
1537        ) -> ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<false, R, S, E>> {
1538            ClientCapabilitiesBuilder {
1539                extensions: self.extensions,
1540                experimental: None,
1541                roots: self.roots,
1542                sampling: self.sampling,
1543                elicitation: self.elicitation,
1544                tasks: self.tasks,
1545                negotiator: self.negotiator,
1546                strict_validation: self.strict_validation,
1547                _state: PhantomData,
1548            }
1549        }
1550    }
1551
1552    // Disable Roots Capabilities
1553    impl<const X: bool, const S: bool, const E: bool>
1554        ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, true, S, E>>
1555    {
1556        /// Disable roots capabilities (opt-out)
1557        ///
1558        /// Transitions the builder to a state where roots capability methods
1559        /// are no longer available at compile time.
1560        pub fn without_roots(
1561            self,
1562        ) -> ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, false, S, E>> {
1563            ClientCapabilitiesBuilder {
1564                extensions: self.extensions,
1565                experimental: self.experimental,
1566                roots: None,
1567                sampling: self.sampling,
1568                elicitation: self.elicitation,
1569                tasks: self.tasks,
1570                negotiator: self.negotiator,
1571                strict_validation: self.strict_validation,
1572                _state: PhantomData,
1573            }
1574        }
1575    }
1576
1577    // Disable Sampling Capabilities
1578    impl<const X: bool, const R: bool, const E: bool>
1579        ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, R, true, E>>
1580    {
1581        /// Disable sampling capabilities (opt-out)
1582        ///
1583        /// Transitions the builder to a state where sampling capability methods
1584        /// are no longer available at compile time.
1585        pub fn without_sampling(
1586            self,
1587        ) -> ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, R, false, E>> {
1588            ClientCapabilitiesBuilder {
1589                extensions: self.extensions,
1590                experimental: self.experimental,
1591                roots: self.roots,
1592                sampling: None,
1593                elicitation: self.elicitation,
1594                tasks: self.tasks,
1595                negotiator: self.negotiator,
1596                strict_validation: self.strict_validation,
1597                _state: PhantomData,
1598            }
1599        }
1600    }
1601
1602    // Disable Elicitation Capabilities
1603    impl<const X: bool, const R: bool, const S: bool>
1604        ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, R, S, true>>
1605    {
1606        /// Disable elicitation capabilities (opt-out)
1607        ///
1608        /// Transitions the builder to a state where elicitation capability methods
1609        /// are no longer available at compile time.
1610        pub fn without_elicitation(
1611            self,
1612        ) -> ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<X, R, S, false>> {
1613            ClientCapabilitiesBuilder {
1614                extensions: self.extensions,
1615                experimental: self.experimental,
1616                roots: self.roots,
1617                sampling: self.sampling,
1618                elicitation: None,
1619                tasks: self.tasks,
1620                negotiator: self.negotiator,
1621                strict_validation: self.strict_validation,
1622                _state: PhantomData,
1623            }
1624        }
1625    }
1626
1627    // Experimental sub-capabilities (only available when EXPERIMENTAL = true)
1628    impl<const R: bool, const S: bool, const E: bool>
1629        ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<true, R, S, E>>
1630    {
1631        /// Add experimental capability
1632        ///
1633        /// This method is only available when experimental capabilities are enabled.
1634        pub fn add_experimental_capability<K, V>(mut self, key: K, value: V) -> Self
1635        where
1636            K: Into<String>,
1637            V: Into<serde_json::Value>,
1638        {
1639            if let Some(ref mut experimental) = self.experimental {
1640                experimental.insert(key.into(), value.into());
1641            }
1642            self
1643        }
1644    }
1645
1646    #[cfg(test)]
1647    mod type_state_tests {
1648        use super::*;
1649
1650        #[test]
1651        fn test_server_capabilities_builder_type_state() {
1652            // Test basic builder construction
1653            let builder = ServerCapabilities::builder();
1654            assert!(format!("{:?}", builder).contains("ServerCapabilitiesBuilder"));
1655
1656            // Test enabling capabilities changes the type
1657            let builder_with_tools = builder.enable_tools();
1658
1659            // This should compile - enable_tool_list_changed is available when tools are enabled
1660            let _final_builder = builder_with_tools.enable_tool_list_changed();
1661
1662            // Test building a server with multiple capabilities
1663            let full_capabilities = ServerCapabilitiesBuilder::new()
1664                .enable_experimental()
1665                .enable_logging()
1666                .enable_completions()
1667                .enable_prompts()
1668                .enable_resources()
1669                .enable_tools()
1670                .enable_tool_list_changed()
1671                .enable_prompts_list_changed()
1672                .enable_resources_list_changed()
1673                .enable_resources_subscribe()
1674                .build();
1675
1676            assert!(full_capabilities.experimental.is_some());
1677            assert!(full_capabilities.logging.is_some());
1678            assert!(full_capabilities.completions.is_some());
1679            assert!(full_capabilities.prompts.is_some());
1680            assert!(full_capabilities.resources.is_some());
1681            assert!(full_capabilities.tools.is_some());
1682
1683            // Validate sub-capabilities are set correctly
1684            if let Some(ref tools) = full_capabilities.tools {
1685                assert_eq!(tools.list_changed, Some(true));
1686            }
1687
1688            if let Some(ref resources) = full_capabilities.resources {
1689                assert_eq!(resources.list_changed, Some(true));
1690                assert_eq!(resources.subscribe, Some(true));
1691            }
1692        }
1693
1694        #[test]
1695        fn test_client_capabilities_builder_type_state() {
1696            // Test basic builder construction - now returns all-enabled state
1697            let builder = ClientCapabilities::builder();
1698            assert!(format!("{:?}", builder).contains("ClientCapabilitiesBuilder"));
1699
1700            // Test opt-out: disabling capabilities changes the type
1701            let builder_without_roots = builder.without_roots();
1702
1703            // After disabling roots, we can re-enable it
1704            let builder_with_roots = builder_without_roots.enable_roots();
1705
1706            // This should compile - enable_roots_list_changed is available when roots are enabled
1707            let _final_builder = builder_with_roots.enable_roots_list_changed();
1708
1709            // Test the opt-out default (new() has everything enabled)
1710            let full_capabilities = ClientCapabilitiesBuilder::new()
1711                .enable_roots_list_changed()
1712                .build();
1713
1714            assert!(full_capabilities.experimental.is_some());
1715            assert!(full_capabilities.roots.is_some());
1716            assert!(full_capabilities.sampling.is_some());
1717            assert!(full_capabilities.elicitation.is_some());
1718
1719            // Validate sub-capabilities are set correctly
1720            if let Some(ref roots) = full_capabilities.roots {
1721                assert_eq!(roots.list_changed, Some(true));
1722            }
1723        }
1724
1725        #[test]
1726        fn test_opt_out_model() {
1727            // Default builder has everything enabled
1728            let caps = ClientCapabilitiesBuilder::new().build();
1729            assert!(caps.experimental.is_some());
1730            assert!(caps.roots.is_some());
1731            assert!(caps.sampling.is_some());
1732            assert!(caps.elicitation.is_some());
1733
1734            // Can selectively disable capabilities
1735            let caps_without_elicitation = ClientCapabilitiesBuilder::new()
1736                .without_elicitation()
1737                .build();
1738
1739            assert!(caps_without_elicitation.experimental.is_some());
1740            assert!(caps_without_elicitation.roots.is_some());
1741            assert!(caps_without_elicitation.sampling.is_some());
1742            assert!(caps_without_elicitation.elicitation.is_none());
1743
1744            // Can disable multiple capabilities
1745            let minimal_caps = ClientCapabilitiesBuilder::new()
1746                .without_experimental()
1747                .without_roots()
1748                .without_elicitation()
1749                .build();
1750
1751            assert!(minimal_caps.experimental.is_none());
1752            assert!(minimal_caps.roots.is_none());
1753            assert!(minimal_caps.sampling.is_some());
1754            assert!(minimal_caps.elicitation.is_none());
1755        }
1756
1757        #[test]
1758        fn test_opt_in_with_minimal() {
1759            // Minimal builder starts with nothing enabled
1760            let caps = ClientCapabilitiesBuilder::minimal().build();
1761            assert!(caps.experimental.is_none());
1762            assert!(caps.roots.is_none());
1763            assert!(caps.sampling.is_none());
1764            assert!(caps.elicitation.is_none());
1765
1766            // Can selectively enable capabilities
1767            let caps_with_sampling = ClientCapabilitiesBuilder::minimal()
1768                .enable_sampling()
1769                .build();
1770
1771            assert!(caps_with_sampling.experimental.is_none());
1772            assert!(caps_with_sampling.roots.is_none());
1773            assert!(caps_with_sampling.sampling.is_some());
1774            assert!(caps_with_sampling.elicitation.is_none());
1775
1776            // Can enable multiple capabilities
1777            let full_caps = ClientCapabilitiesBuilder::minimal()
1778                .enable_experimental()
1779                .enable_roots()
1780                .enable_sampling()
1781                .enable_elicitation()
1782                .build();
1783
1784            assert!(full_caps.experimental.is_some());
1785            assert!(full_caps.roots.is_some());
1786            assert!(full_caps.sampling.is_some());
1787            assert!(full_caps.elicitation.is_some());
1788        }
1789
1790        #[test]
1791        fn test_turbomcp_extensions() {
1792            // Test TurboMCP-specific server extensions (still use enable for servers)
1793            let server_caps = ServerCapabilities::builder()
1794                .enable_experimental()
1795                .with_simd_optimization("avx2")
1796                .with_enterprise_security(true)
1797                .build();
1798
1799            if let Some(ref experimental) = server_caps.experimental {
1800                assert!(experimental.contains_key("turbomcp_simd_level"));
1801                assert!(experimental.contains_key("turbomcp_enterprise_security"));
1802                assert_eq!(
1803                    experimental.get("turbomcp_simd_level").unwrap().as_str(),
1804                    Some("avx2")
1805                );
1806                assert_eq!(
1807                    experimental
1808                        .get("turbomcp_enterprise_security")
1809                        .unwrap()
1810                        .as_bool(),
1811                    Some(true)
1812                );
1813            } else {
1814                panic!("Expected experimental capabilities to be set");
1815            }
1816
1817            // Test client experimental capabilities using add_experimental_capability
1818            let client_caps = ClientCapabilities::builder()
1819                .add_experimental_capability("custom_feature", true)
1820                .build();
1821
1822            if let Some(ref experimental) = client_caps.experimental {
1823                assert!(experimental.contains_key("custom_feature"));
1824            } else {
1825                panic!("Expected experimental capabilities to be set");
1826            }
1827        }
1828
1829        #[test]
1830        fn test_draft_extensions_round_trip() {
1831            let client_caps = ClientCapabilities::builder()
1832                .add_extension("trace", serde_json::json!({"version": "1"}))
1833                .build();
1834            let server_caps = ServerCapabilities::builder()
1835                .add_extension("trace", serde_json::json!({"version": "1"}))
1836                .build();
1837
1838            let negotiated = crate::CapabilityMatcher::new()
1839                .negotiate(&client_caps, &server_caps)
1840                .expect("extensions should negotiate");
1841
1842            assert!(negotiated.has_feature("trace"));
1843            let extensions = negotiated
1844                .client_capabilities
1845                .extensions
1846                .as_ref()
1847                .expect("extensions should be preserved");
1848            assert_eq!(
1849                extensions
1850                    .get("trace")
1851                    .and_then(|v| v.get("version"))
1852                    .and_then(serde_json::Value::as_str),
1853                Some("1")
1854            );
1855        }
1856
1857        #[test]
1858        fn test_draft_extensions_require_both_sides() {
1859            let client_caps = ClientCapabilities::builder()
1860                .add_extension("trace", serde_json::json!({"version": "1"}))
1861                .build();
1862            let server_caps = ServerCapabilities::builder().build();
1863
1864            let negotiated = crate::CapabilityMatcher::new()
1865                .negotiate(&client_caps, &server_caps)
1866                .expect("negotiation should succeed with extension disabled");
1867
1868            assert!(!negotiated.has_feature("trace"));
1869        }
1870
1871        #[test]
1872        fn test_minimal_constructor() {
1873            // Test client minimal() constructor - starts with nothing enabled
1874            let minimal_client_caps = ClientCapabilitiesBuilder::minimal().build();
1875            assert!(minimal_client_caps.experimental.is_none());
1876            assert!(minimal_client_caps.roots.is_none());
1877            assert!(minimal_client_caps.sampling.is_none());
1878            assert!(minimal_client_caps.elicitation.is_none());
1879
1880            // Test that we can selectively enable from minimal
1881            let sampling_only = ClientCapabilitiesBuilder::minimal()
1882                .enable_sampling()
1883                .build();
1884            assert!(sampling_only.experimental.is_none());
1885            assert!(sampling_only.roots.is_none());
1886            assert!(sampling_only.sampling.is_some());
1887            assert!(sampling_only.elicitation.is_none());
1888
1889            // Test enabling multiple capabilities from minimal
1890            let sampling_focused_client = ClientCapabilitiesBuilder::minimal()
1891                .enable_experimental()
1892                .enable_sampling()
1893                .build();
1894            assert!(sampling_focused_client.experimental.is_some());
1895            assert!(sampling_focused_client.roots.is_none());
1896            assert!(sampling_focused_client.sampling.is_some());
1897            assert!(sampling_focused_client.elicitation.is_none());
1898        }
1899
1900        #[test]
1901        fn test_builder_default_implementations() {
1902            // Test that default implementations work - now defaults to all-enabled
1903            let default_server_builder = ServerCapabilitiesBuilder::default();
1904            let server_caps = default_server_builder.build();
1905            assert!(server_caps.tools.is_none()); // Server builder still opts in
1906
1907            let default_client_builder = ClientCapabilitiesBuilder::default();
1908            let client_caps = default_client_builder.build();
1909            // Client default now has everything enabled
1910            assert!(client_caps.experimental.is_some());
1911            assert!(client_caps.roots.is_some());
1912            assert!(client_caps.sampling.is_some());
1913            assert!(client_caps.elicitation.is_some());
1914        }
1915
1916        #[test]
1917        fn test_builder_chaining() {
1918            // Test that builder method chaining works correctly
1919            let server_caps = ServerCapabilities::builder()
1920                .enable_experimental()
1921                .enable_tools()
1922                .enable_prompts()
1923                .enable_resources()
1924                .enable_tool_list_changed()
1925                .enable_prompts_list_changed()
1926                .enable_resources_list_changed()
1927                .enable_resources_subscribe()
1928                .add_experimental_capability("custom_feature", true)
1929                .build();
1930
1931            assert!(server_caps.experimental.is_some());
1932            assert!(server_caps.tools.is_some());
1933            assert!(server_caps.prompts.is_some());
1934            assert!(server_caps.resources.is_some());
1935
1936            // Verify custom experimental capability
1937            if let Some(ref experimental) = server_caps.experimental {
1938                assert!(experimental.contains_key("custom_feature"));
1939            }
1940        }
1941
1942        #[test]
1943        fn test_with_negotiator_integration() {
1944            // Test TurboMCP capability negotiator integration
1945            let negotiator = super::super::CapabilityNegotiator::default();
1946
1947            let server_caps = ServerCapabilities::builder()
1948                .enable_tools()
1949                .with_negotiator(negotiator.clone())
1950                .with_strict_validation()
1951                .build();
1952
1953            assert!(server_caps.tools.is_some());
1954            // Note: negotiator and strict_validation are internal to the builder
1955            // and don't appear in the final ServerCapabilities struct
1956        }
1957
1958        #[test]
1959        fn test_builder_validation_methods() {
1960            // Test server builder validation
1961            let server_builder = ServerCapabilities::builder()
1962                .enable_experimental()
1963                .enable_tools()
1964                .with_simd_optimization("avx2")
1965                .with_enterprise_security(true)
1966                .with_strict_validation();
1967
1968            // Validation should pass for well-configured builder
1969            assert!(server_builder.validate().is_ok());
1970
1971            // Test summary method
1972            let summary = server_builder.summary();
1973            assert!(summary.contains("experimental"));
1974            assert!(summary.contains("tools"));
1975
1976            // Test client builder validation - now uses new() which starts all-enabled
1977            let client_builder = ClientCapabilities::builder()
1978                .add_experimental_capability("custom_feature", true)
1979                .with_strict_validation();
1980
1981            // Validation should pass for well-configured builder
1982            assert!(client_builder.validate().is_ok());
1983
1984            // Test summary method
1985            let summary = client_builder.summary();
1986            assert!(summary.contains("experimental"));
1987            assert!(summary.contains("sampling"));
1988        }
1989
1990        #[test]
1991        fn test_builder_validation_errors() {
1992            // Test server validation errors
1993            let server_builder = ServerCapabilities::builder()
1994                .enable_experimental()
1995                .with_strict_validation();
1996
1997            // Should fail validation - no actual capabilities enabled
1998            assert!(server_builder.validate().is_err());
1999            let error = server_builder.validate().unwrap_err();
2000            assert!(error.contains("at least one capability"));
2001
2002            // Test invalid SIMD level
2003            let invalid_server_builder = ServerCapabilities::builder()
2004                .enable_experimental()
2005                .enable_tools()
2006                .add_experimental_capability("turbomcp_simd_level", "invalid_level")
2007                .with_strict_validation();
2008
2009            assert!(invalid_server_builder.validate().is_err());
2010            let error = invalid_server_builder.validate().unwrap_err();
2011            assert!(error.contains("Invalid SIMD level"));
2012
2013            // Client validation should always pass now (removed strict validation for UI/LLM)
2014            let client_builder = ClientCapabilities::builder()
2015                .add_experimental_capability("custom_feature", true)
2016                .with_strict_validation();
2017
2018            assert!(client_builder.validate().is_ok());
2019        }
2020
2021        #[test]
2022        fn test_builder_clone_support() {
2023            // Test that builders can be cloned
2024            let original_server_builder = ServerCapabilities::builder()
2025                .enable_tools()
2026                .enable_prompts();
2027
2028            let cloned_server_builder = original_server_builder.clone();
2029
2030            // Both should produce equivalent capabilities
2031            let original_caps = original_server_builder.build();
2032            let cloned_caps = cloned_server_builder.build();
2033
2034            assert_eq!(original_caps.tools.is_some(), cloned_caps.tools.is_some());
2035            assert_eq!(
2036                original_caps.prompts.is_some(),
2037                cloned_caps.prompts.is_some()
2038            );
2039
2040            // Test client builder clone - use without_*() since default is all-enabled
2041            let original_client_builder = ClientCapabilities::builder()
2042                .without_experimental()
2043                .without_roots();
2044
2045            let cloned_client_builder = original_client_builder.clone();
2046
2047            let original_caps = original_client_builder.build();
2048            let cloned_caps = cloned_client_builder.build();
2049
2050            assert_eq!(
2051                original_caps.experimental.is_some(),
2052                cloned_caps.experimental.is_some()
2053            );
2054            assert_eq!(original_caps.roots.is_some(), cloned_caps.roots.is_some());
2055            assert_eq!(
2056                original_caps.sampling.is_some(),
2057                cloned_caps.sampling.is_some()
2058            );
2059            assert_eq!(
2060                original_caps.elicitation.is_some(),
2061                cloned_caps.elicitation.is_some()
2062            );
2063        }
2064    }
2065}