Hmbown/CodeWhale · error · anyhow::Error

Unknown MCP tool name: {prefixed_name}

Error message

Unknown MCP tool name: {prefixed_name}

What it means

parse_prefixed_name's fallback: the name had the mcp_ prefix (and passed the shape check) but no connected, catalog-authorized server advertises a tool whose composed name equals the remainder, considering per-tool enablement (is_tool_enabled). It means 'well-formed but unknown' — distinct from the invalid-prefix and ambiguous cases.

Source

Thrown at crates/tui/src/mcp.rs:3043

            for tool in connection.tools() {
                if !connection.config().is_tool_enabled(&tool.name)
                    || format!("{server}_{}", tool.name) != rest
                {
                    continue;
                }
                if matched.is_some() {
                    anyhow::bail!(
                        "Ambiguous MCP tool name '{prefixed_name}' matches more than one server/tool authority"
                    );
                }
                matched = Some((server.clone(), tool.name.clone()));
            }
        }
        if let Some(matched) = matched {
            return Ok(matched);
        }

        Err(anyhow::anyhow!("Unknown MCP tool name: {prefixed_name}"))
    }

    /// Resolve an MCP tool through an exact advertised catalog. A configured
    /// but lazy server may be connected and asked for `tools/list`; the
    /// requested suffix is never treated as authority on its own.
    async fn resolve_advertised_tool(&mut self, prefixed_name: &str) -> Result<McpToolRoute> {
        if let Ok((server_name, tool_name)) = self.parse_prefixed_name(prefixed_name) {
            return self.capture_tool_route(server_name, tool_name);
        }
        let Some(rest) = prefixed_name.strip_prefix("mcp_") else {
            anyhow::bail!("Invalid MCP tool name: {prefixed_name}");
        };
        let mut candidates = {
            let dynamic = self.dynamic_servers.read();
            self.config
                .servers
                .iter()
                .filter_map(|(name, config)| {

View on GitHub (pinned to 8880682c63)

Solutions

  1. Compare the requested name against the current advertised list (all_tools / to_api_tools) and use an exact entry.
  2. If the tool is tool-level disabled, enable it in the server's tool config or stop calling it.
  3. Force a reconnect/refresh so lazy or stale servers publish their catalogs, then retry.
  4. Fix typos in the server or tool portion of the name.

Example fix

# before
# config removed server 'jira', model still calls mcp_jira_search
let route = pool.resolve_advertised_tool("mcp_jira_search").await?; // Unknown MCP tool name

# after
# re-add the server, or call a tool that is currently advertised:
let route = pool.resolve_advertised_tool("mcp_github_search").await?;
Defensive patterns

Strategy: validation

Validate before calling

// Rust: confirm the exact name is currently advertised
let advertised: Vec<String> = pool.all_tools().into_keys().collect();
ensure!(
    advertised.iter().any(|n| n == requested),
    "tool '{requested}' not advertised; available: {}",
    advertised.join(", ")
);

Type guard

// Rust
fn is_advertised_mcp_tool(pool: &McpPool, name: &str) -> bool {
    name.starts_with("mcp_") && pool.all_tools().contains_key(name)
}

Try / catch

// Rust: unknown tool — refresh and re-check once
match pool.resolve_advertised_tool(name).await {
    Err(e) if e.to_string().contains("Unknown MCP tool name") => {
        pool.connect_all().await; // refresh lazy catalogs
        pool.resolve_advertised_tool(name).await
    }
    r => r,
}

Prevention

When it happens

Trigger: Dispatching to a tool from a stale catalog after the server was removed or renamed; the tool exists on the server but is disabled via tool-level config (is_tool_enabled false); the connection exists but its reviewed-plugin catalog is not current (catalog_authorized false) so it is skipped; simple typos in the server or tool portion.

Common situations: Model uses a tool name remembered from an earlier turn after a config reload removed that server; tool filtered out by allow/deny tool lists in config; plugin catalog updated so the connection is skipped during matching; misspelled suffix.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/fc0951d105f1590d. Report an issue: GitHub.