From f55dac69582000f0bfdae6dbed2d33f2e48087b2 Mon Sep 17 00:00:00 2001 From: centdix <40307056+centdix@users.noreply.github.com> Date: Mon, 19 Jan 2026 21:24:12 +0100 Subject: [PATCH] fix(mcp): fix empty args format + sanitize tool name (#7615) * fix empty args format + sanitize tool name * cleaning --- backend/windmill-mcp/src/client/mod.rs | 4 ++-- backend/windmill-worker/src/ai/utils.rs | 16 +++++++++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/backend/windmill-mcp/src/client/mod.rs b/backend/windmill-mcp/src/client/mod.rs index 2364571486..2cac061c5e 100644 --- a/backend/windmill-mcp/src/client/mod.rs +++ b/backend/windmill-mcp/src/client/mod.rs @@ -190,7 +190,7 @@ impl McpClient { args_str: &str, ) -> Result>> { if args_str.trim().is_empty() { - return Ok(None); + return Ok(Some(serde_json::Map::new())); } let args_value: serde_json::Value = @@ -198,7 +198,7 @@ impl McpClient { match args_value { serde_json::Value::Object(map) => Ok(Some(map)), - serde_json::Value::Null => Ok(None), + serde_json::Value::Null => Ok(Some(serde_json::Map::new())), _ => Ok(Some( vec![("value".to_string(), args_value)] .into_iter() diff --git a/backend/windmill-worker/src/ai/utils.rs b/backend/windmill-worker/src/ai/utils.rs index 5f017a4e75..7bd02af4ff 100644 --- a/backend/windmill-worker/src/ai/utils.rs +++ b/backend/windmill-worker/src/ai/utils.rs @@ -351,6 +351,19 @@ pub async fn cleanup_mcp_clients(mcp_clients: HashMap>) { } } +#[cfg(feature = "mcp")] +fn sanitize_tool_name_part(s: &str) -> String { + s.chars() + .map(|c| { + if c.is_ascii_alphanumeric() || c == '_' || c == '-' { + c + } else { + '_' + } + }) + .collect() +} + /// Convert raw MCP tools to Windmill Tool format with source tracking #[cfg(feature = "mcp")] fn convert_mcp_tools_to_windmill_tools( @@ -361,7 +374,8 @@ fn convert_mcp_tools_to_windmill_tools( mcp_tools .iter() .map(|mcp_tool| { - let tool_name = format!("mcp_{}_{}", resource_name, mcp_tool.name); + let sanitized_resource_name = sanitize_tool_name_part(resource_name); + let tool_name = format!("mcp_{}_{}", sanitized_resource_name, mcp_tool.name); let mut schema_value = serde_json::to_value(&*mcp_tool.input_schema) .context("Failed to convert MCP schema to JSON value")?;