Skip to main content

rustapi_mcp/
config.rs

1//! Configuration for the MCP server / integration.
2
3use std::collections::HashSet;
4
5/// Configuration for the native MCP server.
6///
7/// This is the primary way users control what gets exposed as tools,
8/// authentication for MCP clients, transport behavior, etc.
9#[derive(Debug, Clone)]
10pub struct McpConfig {
11    /// Human-friendly name of this MCP server (shown to agents).
12    pub name: String,
13    /// Version string.
14    pub version: String,
15    /// Optional description.
16    pub description: Option<String>,
17
18    /// Whether tool discovery and calling is enabled.
19    pub tools_enabled: bool,
20
21    /// Explicitly allowed tags. Only routes that have at least one of these tags
22    /// (via OpenAPI `tags` or future route metadata) will be exposed as tools.
23    ///
24    /// Empty set + no other allow rules = nothing is exposed (safe default).
25    pub allowed_tags: HashSet<String>,
26
27    /// Explicit path prefixes that are allowed to become tools.
28    /// Example: `["/api/public", "/agent"]`
29    pub allowed_path_prefixes: Vec<String>,
30
31    /// Admin / MCP client token.
32    ///
33    /// When set, MCP clients must present this (via header or query param,
34    /// transport dependent) to use discovery or invocation.
35    pub admin_token: Option<String>,
36
37    /// Whether to include detailed error information in tool responses.
38    /// In production you usually want this `false` (similar to RUSTAPI_ENV=production).
39    pub expose_detailed_errors: bool,
40
41    /// Maximum number of tools to advertise in one `tools/list` response.
42    /// Helps protect against very large route sets.
43    pub max_tools: usize,
44}
45
46impl Default for McpConfig {
47    fn default() -> Self {
48        Self {
49            name: "rustapi-mcp".to_string(),
50            version: "0.0.0".to_string(),
51            description: None,
52            tools_enabled: true,
53            allowed_tags: HashSet::new(),
54            allowed_path_prefixes: vec![],
55            admin_token: None,
56            expose_detailed_errors: false,
57            max_tools: 256,
58        }
59    }
60}
61
62impl McpConfig {
63    /// Create a new config with reasonable defaults.
64    pub fn new() -> Self {
65        Self::default()
66    }
67
68    /// Set the name advertised to MCP clients.
69    pub fn name(mut self, name: impl Into<String>) -> Self {
70        self.name = name.into();
71        self
72    }
73
74    /// Set the version advertised to MCP clients.
75    pub fn version(mut self, version: impl Into<String>) -> Self {
76        self.version = version.into();
77        self
78    }
79
80    /// Set a human description.
81    pub fn description(mut self, desc: impl Into<String>) -> Self {
82        self.description = Some(desc.into());
83        self
84    }
85
86    /// Enable or disable the tools capability entirely.
87    pub fn enable_tools(mut self, enabled: bool) -> Self {
88        self.tools_enabled = enabled;
89        self
90    }
91
92    /// Allow tools only for routes that carry at least one of the given tags.
93    ///
94    /// This is the recommended way to safely expose a curated surface to agents.
95    pub fn allowed_tags<I, S>(mut self, tags: I) -> Self
96    where
97        I: IntoIterator<Item = S>,
98        S: Into<String>,
99    {
100        self.allowed_tags = tags.into_iter().map(Into::into).collect();
101        self
102    }
103
104    /// Add a path prefix that is allowed to be exposed as tools.
105    pub fn allow_path_prefix(mut self, prefix: impl Into<String>) -> Self {
106        self.allowed_path_prefixes.push(prefix.into());
107        self
108    }
109
110    /// Require this token for MCP clients (discovery + calls).
111    pub fn admin_token(mut self, token: impl Into<String>) -> Self {
112        self.admin_token = Some(token.into());
113        self
114    }
115
116    /// Control whether tool responses include full internal error details.
117    pub fn expose_detailed_errors(mut self, expose: bool) -> Self {
118        self.expose_detailed_errors = expose;
119        self
120    }
121
122    /// Set the maximum number of tools to list.
123    pub fn max_tools(mut self, max: usize) -> Self {
124        self.max_tools = max;
125        self
126    }
127}