turbomcp_protocol/
config.rs

1//! Configuration types and utilities for MCP core
2//!
3//! This module provides configuration management for `TurboMCP` applications
4//! with builder pattern support and validation.
5//!
6//! # Examples
7//!
8//! ## Creating a default configuration
9//!
10//! ```
11//! # #[cfg(feature = "fancy-errors")]
12//! # {
13//! use turbomcp_protocol::config::CoreConfig;
14//!
15//! let config = CoreConfig::default();
16//! assert_eq!(config.max_message_size, 64 * 1024 * 1024);
17//! assert_eq!(config.timeout_ms, 30_000);
18//! assert!(config.tracing_enabled);
19//! # }
20//! ```
21//!
22//! ## Using the configuration builder
23//!
24//! ```
25//! # #[cfg(feature = "fancy-errors")]
26//! # {
27//! use turbomcp_protocol::config::ConfigBuilder;
28//!
29//! let config = ConfigBuilder::new()
30//!     .max_message_size(1024 * 1024).unwrap() // 1MB
31//!     .timeout_ms(10_000).unwrap() // 10 seconds
32//!     .tracing_enabled(false)
33//!     .option("env", "production").unwrap()
34//!     .build();
35//!
36//! assert_eq!(config.max_message_size, 1024 * 1024);
37//! assert_eq!(config.timeout_ms, 10_000);
38//! assert!(!config.tracing_enabled);
39//! # }
40//! ```
41
42use serde::{Deserialize, Serialize};
43use std::collections::HashMap;
44
45/// Core configuration for MCP operations
46#[derive(Debug, Clone, Serialize, Deserialize)]
47pub struct CoreConfig {
48    /// Maximum message size in bytes
49    pub max_message_size: usize,
50    /// Timeout for operations in milliseconds
51    pub timeout_ms: u64,
52    /// Enable tracing
53    pub tracing_enabled: bool,
54    /// Additional configuration options
55    pub options: HashMap<String, serde_json::Value>,
56}
57
58impl Default for CoreConfig {
59    fn default() -> Self {
60        Self {
61            max_message_size: 64 * 1024 * 1024, // 64MB
62            timeout_ms: 30_000,                 // 30 seconds
63            tracing_enabled: true,
64            options: HashMap::new(),
65        }
66    }
67}
68
69/// Configuration builder for core settings
70#[derive(Debug)]
71pub struct ConfigBuilder {
72    config: CoreConfig,
73}
74
75impl ConfigBuilder {
76    /// Create a new configuration builder
77    #[must_use]
78    pub fn new() -> Self {
79        Self {
80            config: CoreConfig::default(),
81        }
82    }
83
84    /// Set maximum message size
85    ///
86    /// # Examples
87    ///
88    /// ```
89    /// # #[cfg(feature = "fancy-errors")]
90    /// # {
91    /// use turbomcp_protocol::config::ConfigBuilder;
92    ///
93    /// let config = ConfigBuilder::new()
94    ///     .max_message_size(1024 * 1024).unwrap()
95    ///     .build();
96    /// assert_eq!(config.max_message_size, 1024 * 1024);
97    ///
98    /// // Validation errors
99    /// assert!(ConfigBuilder::new().max_message_size(0).is_err());
100    /// assert!(ConfigBuilder::new().max_message_size(2 * 1024 * 1024 * 1024).is_err());
101    /// # }
102    /// ```
103    pub fn max_message_size(mut self, size: usize) -> Result<Self, String> {
104        if size == 0 {
105            return Err("Maximum message size cannot be zero".to_string());
106        }
107        if size > 1024 * 1024 * 1024 {
108            // 1GB limit
109            return Err("Maximum message size cannot exceed 1GB".to_string());
110        }
111        self.config.max_message_size = size;
112        Ok(self)
113    }
114
115    /// Set operation timeout
116    pub fn timeout_ms(mut self, timeout: u64) -> Result<Self, String> {
117        if timeout == 0 {
118            return Err("Timeout cannot be zero".to_string());
119        }
120        if timeout > 10 * 60 * 1000 {
121            // 10 minutes max
122            return Err("Timeout cannot exceed 10 minutes".to_string());
123        }
124        self.config.timeout_ms = timeout;
125        Ok(self)
126    }
127
128    /// Enable or disable tracing
129    #[must_use]
130    pub const fn tracing_enabled(mut self, enabled: bool) -> Self {
131        self.config.tracing_enabled = enabled;
132        self
133    }
134
135    /// Add a configuration option
136    pub fn option<V: serde::Serialize>(
137        mut self,
138        key: &str,
139        value: V,
140    ) -> Result<Self, serde_json::Error> {
141        let json_value = serde_json::to_value(value)?;
142        self.config.options.insert(key.to_string(), json_value);
143        Ok(self)
144    }
145
146    /// Build the configuration
147    #[must_use]
148    pub fn build(self) -> CoreConfig {
149        self.config
150    }
151}
152
153impl Default for ConfigBuilder {
154    fn default() -> Self {
155        Self::new()
156    }
157}