Skip to content

Commit a40e3fd

Browse files
committed
feat: add skip_tools in runtime_config to skip loading certain tools
Signed-off-by: Tuan Anh Tran <[email protected]>
1 parent 2cd407b commit a40e3fd

File tree

3 files changed

+38
-16
lines changed

3 files changed

+38
-16
lines changed

src/config.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@ pub struct PluginConfig {
1515
pub runtime_config: Option<RuntimeConfig>,
1616
}
1717

18-
#[derive(Debug, Serialize, Deserialize, Clone)]
18+
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
1919
pub struct RuntimeConfig {
20+
// List of tool names to skip loading at runtime.
21+
pub skip_tools: Option<Vec<String>>,
2022
pub allowed_hosts: Option<Vec<String>>,
2123
pub allowed_paths: Option<Vec<String>>,
2224
pub env_vars: Option<HashMap<String, String>>,

src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ async fn main() -> Result<()> {
150150
}
151151
"streamable-http" => {
152152
tracing::info!(
153-
"Starting hyper-mcp with streamable-http transport at {}",
153+
"Starting hyper-mcp with streamable-http transport at {}/mcp",
154154
cli.bind_address
155155
);
156156

src/plugins.rs

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ impl PluginService {
8383
} else {
8484
tokio::fs::read(&plugin_cfg.path).await?
8585
};
86-
8786
let mut manifest = Manifest::new([Wasm::data(wasm_content)]);
8887
if let Some(runtime_cfg) = &plugin_cfg.runtime_config {
8988
log::info!("runtime_cfg: {:?}", runtime_cfg);
@@ -129,7 +128,16 @@ impl PluginService {
129128
if let Ok(result) = plugin.call::<&str, &str>("describe", "") {
130129
if let Ok(parsed) = serde_json::from_str::<ListToolsResult>(result) {
131130
let mut cache = self.tool_plugin_map.write().await;
131+
let skip_tools = plugin_cfg
132+
.runtime_config
133+
.as_ref()
134+
.and_then(|rc| rc.skip_tools.clone())
135+
.unwrap_or_default();
132136
for tool in parsed.tools {
137+
if skip_tools.iter().any(|s| s == tool.name.as_ref() as &str) {
138+
log::info!("Skipping tool {} as requested in skip_tools", tool.name);
139+
continue;
140+
}
133141
log::info!("Saving tool {}/{} to cache", plugin_cfg.name, tool.name);
134142
// Check if the tool name already exists in another plugin
135143
if let Some(existing_plugin) = cache.get(&tool.name.to_string()) {
@@ -231,20 +239,32 @@ impl ServerHandler for PluginService {
231239
// Clear the existing cache when listing tools
232240
tool_cache.clear();
233241

234-
for (plugin_name, plugin) in plugins.iter_mut() {
235-
match plugin.call::<&str, &str>("describe", "") {
236-
Ok(result) => {
237-
let parsed: ListToolsResult = serde_json::from_str(result).unwrap();
238-
239-
// Update the tool-to-plugin cache
240-
for tool in &parsed.tools {
241-
tool_cache.insert(tool.name.to_string(), plugin_name.clone());
242+
for plugin_cfg in &self.config.plugins {
243+
if let Some(plugin) = plugins.get_mut(&plugin_cfg.name) {
244+
match plugin.call::<&str, &str>("describe", "") {
245+
Ok(result) => {
246+
if let Ok(parsed) = serde_json::from_str::<ListToolsResult>(result) {
247+
let skip_tools = plugin_cfg
248+
.runtime_config
249+
.as_ref()
250+
.and_then(|rc| rc.skip_tools.clone())
251+
.unwrap_or_default();
252+
for tool in parsed.tools {
253+
if skip_tools.iter().any(|s| s == tool.name.as_ref() as &str) {
254+
log::info!(
255+
"Skipping tool {} as requested in skip_tools",
256+
tool.name
257+
);
258+
continue;
259+
}
260+
tool_cache.insert(tool.name.to_string(), plugin_cfg.name.clone());
261+
payload.tools.push(tool);
262+
}
263+
}
264+
}
265+
Err(e) => {
266+
log::error!("tool {} describe() error: {}", plugin_cfg.name, e);
242267
}
243-
244-
payload.tools.extend(parsed.tools);
245-
}
246-
Err(e) => {
247-
log::error!("tool {} describe() error: {}", plugin_name, e);
248268
}
249269
}
250270
}

0 commit comments

Comments
 (0)