Hmbown/CodeWhale · error · anyhow::Error

Failed to find MCP server

Error message

Failed to find MCP server: {server}

What it means

require_server() checks the requested MCP server name against the allow rules (server_allowed) and fails with this message when the name is not permitted. The wording deliberately mirrors "server not found" so the model cannot probe which servers exist; the real cause is a disallow rule, not a missing server.

Solutions

  1. Check the server name spelling against the configured MCP servers.
  2. Confirm the server is in the allow rules (not in disallowed_tools) in the MCP config.
  3. List available servers via the MCP listing tooling before dispatching a call.
  4. Reconnect or reload config if the server was recently enabled.

Example fix

// before
conn.call("db-server", "query", input)?
// after: guard with the same allow rule the pool uses
if !pool.server_allowed("db-server") { return Err(...); }
conn.call("db-server", "query", input)?
Defensive patterns

Strategy: validation

Validate before calling

// Resolve the server list and check before calling
let servers: Vec<String> = pool.list_server_names();
assert!(servers.iter().any(|s| s == server), "unknown MCP server: {server}");

Type guard

fn server_in_list(servers: &[String], name: &str) -> bool {
    servers.iter().any(|s| s == name)
}

Try / catch

match pool.call_tool(server, tool, input) {
    Err(e) if e.to_string().contains("Failed to find MCP server") => {
        eprintln!("server '{server}' is not available; check spelling and config");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Invoking an MCP tool whose input names a server that does not match any allowed server rule — i.e. tool_matches_any_rule matched the disallowed_tools/server-deny configuration for that server name.

Common situations: Typo in the server name in a tools/call; calling an MCP server that was removed from or never added to the allowlist; stale session referencing a server disabled in config.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/21ff8a4ad0677659. Report an issue: GitHub.

Appendix: source

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

    pub(crate) fn server_denied_by(rules: &[String], server: &str) -> bool {
        let namespace = format!("mcp_{server}_").to_ascii_lowercase();
        rules.iter().any(|rule| {
            rule.to_ascii_lowercase()
                .strip_suffix('*')
                .is_some_and(|prefix| namespace.starts_with(prefix))
        })
    }

    fn server_allowed(&self, server: &str) -> bool {
        !Self::server_denied_by(&self.disallowed_tools, server)
    }

    pub(crate) fn tool_allowed(&self, name: &str) -> bool {
        !crate::core::engine::tool_catalog::tool_matches_any_rule(&self.disallowed_tools, name)
    }

    fn require_server(&self, server: &str) -> Result<()> {
        anyhow::ensure!(
            self.server_allowed(server),
            "Failed to find MCP server: {server}"
        );
        Ok(())
    }

    pub(crate) fn authorize_call(
        rules: &[String],
        name: &str,
        input: &serde_json::Value,
    ) -> Result<()> {
        anyhow::ensure!(
            !crate::core::engine::tool_catalog::tool_matches_any_rule(rules, name),
            "Unknown MCP tool name: {name}"
        );
        if matches!(
            name,
            "list_mcp_resources"

View on GitHub (pinned to 73e0f67d83)