From f19e03b3fa2d126c56a58ec0a23333c198d78ec0 Mon Sep 17 00:00:00 2001 From: Deepak kudi Date: Thu, 4 Jun 2026 14:47:13 +0530 Subject: [PATCH] fix: parse MCP server names with underscores --- crates/tui/src/mcp.rs | 58 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/crates/tui/src/mcp.rs b/crates/tui/src/mcp.rs index 08baea295f..85c30d80ec 100644 --- a/crates/tui/src/mcp.rs +++ b/crates/tui/src/mcp.rs @@ -2245,6 +2245,21 @@ impl McpPool { anyhow::bail!("Invalid MCP tool name: {prefixed_name}"); } let rest = &prefixed_name[4..]; + let mut resolved = None; + for (idx, _) in rest.match_indices('_') { + let server = &rest[..idx]; + let tool = &rest[idx + 1..]; + if server.is_empty() || tool.is_empty() { + continue; + } + if self.connections.contains_key(server) || self.config.servers.contains_key(server) { + resolved = Some((server, tool)); + } + } + if let Some((server, tool)) = resolved { + return Ok((server, tool)); + } + let Some((server, tool)) = rest.split_once('_') else { anyhow::bail!("Invalid MCP tool name format: {prefixed_name}"); }; @@ -3638,6 +3653,49 @@ mod tests { ); } + #[tokio::test] + async fn mcp_pool_call_tool_preserves_server_names_with_underscores() { + let sent = Arc::new(Mutex::new(Vec::new())); + let transport = ScriptedValueTransport { + sent: Arc::clone(&sent), + responses: VecDeque::from([json_frame(serde_json::json!({ + "jsonrpc": "2.0", + "id": 1, + "result": {"ok": true} + }))]), + }; + let mut conn = test_connection(Box::new(transport)); + conn.name = "my_db".to_string(); + conn.tools = vec![McpTool { + name: "execute_sql".to_string(), + description: None, + input_schema: serde_json::json!({}), + }]; + + let mut pool = McpPool::new(McpConfig { + timeouts: McpTimeouts::default(), + servers: HashMap::new(), + }); + pool.connections.insert("my_db".to_string(), conn); + + let result = pool + .call_tool( + "mcp_my_db_execute_sql", + serde_json::json!({"query": "select 1"}), + ) + .await + .unwrap(); + + assert_eq!(result, serde_json::json!({"ok": true})); + let sent = sent.lock().unwrap(); + assert_eq!(sent[0]["method"], "tools/call"); + assert_eq!(sent[0]["params"]["name"], "execute_sql"); + assert_eq!( + sent[0]["params"]["arguments"], + serde_json::json!({"query": "select 1"}) + ); + } + #[tokio::test] async fn json_rpc_session_error_is_marked_stale() { let sent = Arc::new(Mutex::new(Vec::new()));