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}