{"record":{"id":"74c482570c8167d7","repo":"Hmbown/CodeWhale","slug":"qualified-mcp-tool-name-is-ambiguous-across-servers","errorCode":null,"errorMessage":"qualified MCP tool name '{}' is ambiguous across servers: {}","messagePattern":"qualified MCP tool name '(.+?)' is ambiguous across servers: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/mcp/src/lib.rs","lineNumber":519,"sourceCode":"            }\n        }\n        match matches.len() {\n            0 => {}\n            1 => {\n                let (server_name, tool_name) = &matches[0];\n                let client = self\n                    .clients\n                    .get(*server_name)\n                    .with_context(|| format!(\"MCP server '{server_name}' not available\"))?;\n                return client.call_tool(tool_name, arguments);\n            }\n            _ => {\n                matches.sort();\n                let servers: Vec<&str> = matches\n                    .iter()\n                    .map(|(server_name, _)| server_name.as_str())\n                    .collect();\n                bail!(\n                    \"qualified MCP tool name '{qualified_tool_name}' is ambiguous across servers: \\\n                     {}\",\n                    servers.join(\", \")\n                );\n            }\n        }\n\n        let (server_name, tool_name) = parsed?;\n        self.call_tool(&server_name, &tool_name, arguments)\n    }\n\n    /// List all resources from all running servers.\n    pub fn list_resources(&self) -> Result<Vec<McpResourceDescriptor>> {\n        Ok(self\n            .list_resources_with_metadata()?\n            .into_iter()\n            .map(|(resource, _)| resource)\n            .collect())","sourceCodeStart":501,"sourceCodeEnd":537,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/mcp/src/lib.rs#L501-L537","documentation":"call_qualified_tool resolves an mcp__<server>__<tool> name to (server, tool). When the server segment is missing or resolves to multiple running servers exposing the same tool, the qualified name is ambiguous and the call fails closed listing the candidate servers.","triggerScenarios":"Calling call_qualified_tool with a qualified name whose tool name matches tools on multiple running servers, or a truncated/partial name that matches more than one server.","commonSituations":"Two servers ship a tool with the same name and the caller used a short/unqualified form; a legacy caller building names without the server segment; name truncation in UI-generated tool calls.","solutions":["Use the fully qualified mcp__<specific-server>__<tool> name","Rename the tool on one server to remove the collision","Apply a tool filter on one server so only one match remains"],"exampleFix":"// before\nmanager.call_qualified_tool(\"mcp__search__find\")?\n// after\nmanager.call_qualified_tool(\"mcp__docs__search__find\")?","handlingStrategy":"validation","validationCode":"if !name.starts_with(\"mcp__\") || name.matches(\"__\").count() < 2 { return Err(\"need fully qualified name\"); }","typeGuard":null,"tryCatchPattern":"match manager.call_qualified_tool(name) { Err(e) if e.to_string().contains(\"ambiguous across servers\") => /* retry with explicit server segment */, other => other }","preventionTips":["Always construct full mcp__server__tool names","Detect server-wide duplicate tool names at registration time"],"tags":["mcp","ambiguity","naming-collision"],"backgroundTag":"invalid-argument-value","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}