mcp_tools/config/
mod.rs

1//! Configuration management for MCP Tools
2
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5use std::path::Path;
6
7/// Global MCP Tools configuration
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct McpToolsConfig {
10    /// Default server configurations
11    pub servers: HashMap<String, crate::common::ServerConfig>,
12
13    /// Default client configurations  
14    pub clients: HashMap<String, crate::common::ClientConfig>,
15
16    /// Global settings
17    pub global: GlobalConfig,
18}
19
20/// Global configuration settings
21#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct GlobalConfig {
23    /// Default log level
24    pub log_level: String,
25
26    /// Enable metrics collection
27    pub enable_metrics: bool,
28
29    /// Metrics collection interval in seconds
30    pub metrics_interval_secs: u64,
31
32    /// Default session timeout in seconds
33    pub session_timeout_secs: u64,
34}
35
36impl Default for McpToolsConfig {
37    fn default() -> Self {
38        Self {
39            servers: HashMap::new(),
40            clients: HashMap::new(),
41            global: GlobalConfig::default(),
42        }
43    }
44}
45
46impl Default for GlobalConfig {
47    fn default() -> Self {
48        Self {
49            log_level: "info".to_string(),
50            enable_metrics: true,
51            metrics_interval_secs: 60,
52            session_timeout_secs: 3600, // 1 hour
53        }
54    }
55}
56
57/// Load configuration from file
58pub async fn load_config<P: AsRef<Path>>(path: P) -> Result<McpToolsConfig, Box<dyn std::error::Error + Send + Sync>> {
59    let content = tokio::fs::read_to_string(path).await?;
60
61    // Try TOML first, then JSON
62    if let Ok(config) = toml::from_str::<McpToolsConfig>(&content) {
63        Ok(config)
64    } else {
65        serde_json::from_str::<McpToolsConfig>(&content)
66            .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)
67    }
68}
69
70/// Save configuration to file
71pub async fn save_config<P: AsRef<Path>>(config: &McpToolsConfig, path: P) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
72    let content = toml::to_string_pretty(config)
73        .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?;
74
75    tokio::fs::write(path, content).await?;
76    Ok(())
77}
78
79#[cfg(test)]
80mod tests {
81    use super::*;
82    use tempfile::NamedTempFile;
83
84    #[test]
85    fn test_default_config() {
86        let config = McpToolsConfig::default();
87        assert_eq!(config.global.log_level, "info");
88        assert!(config.global.enable_metrics);
89    }
90
91    #[tokio::test]
92    async fn test_config_serialization() {
93        let config = McpToolsConfig::default();
94
95        let toml_str = toml::to_string(&config).unwrap();
96        let parsed: McpToolsConfig = toml::from_str(&toml_str).unwrap();
97
98        assert_eq!(config.global.log_level, parsed.global.log_level);
99    }
100}