Hmbown/CodeWhale · error

MCP server ' ' was not found.

Error message

MCP server '{server}' was not found.

What it means

Thrown by start_mcp_login when the MCP server name given for an OAuth login does not exist in the loaded MCP configuration. The config is loaded via load_config_with_workspace_and_plugins (including plugin-registered servers) and `cfg.servers.get(&name)` returns None. The message is produced from the localized McpLoginServerNotFound template with `{server}` substituted.

Solutions

  1. Verify the server name matches a `servers` entry in your MCP config (check spelling/case).
  2. Confirm the TUI is loading the config file you edited (workspace path / plugin registry).
  3. Re-run discovery or reload MCP config so the server list is fresh, then retry login.
  4. If the server comes from a plugin, enable that plugin so its servers appear in the merged config.

Example fix

// before
begin_oauth_login_for_server_tool(&name, ...)?;
// after: validate first
if !cfg.servers.contains_key(&name) {
    eprintln!("server '{name}' not in config; available: {:?}",
        cfg.servers.keys().collect::<Vec<_>>());
    return Ok(());
}
begin_oauth_login_for_server_tool(&name, ...)?;
Defensive patterns

Strategy: validation

Validate before calling

let cfg = crate::mcp::load_config_with_workspace_and_plugins(&path, &workspace, plugin_registry.as_ref())?;
if !cfg.servers.contains_key(&name) {
    eprintln!("unknown server '{name}'; known: {:?}", cfg.servers.keys().collect::<Vec<_>>());
    return Ok(());
}

Try / catch

match start_mcp_login(app, &name).await {
    Ok(()) => {},
    Err(e) if e.to_string().contains("was not found") => {
        status(format!("Server '{name}' not in config — reload the server list"));
    }
    Err(e) => status(format!("MCP login failed: {e:#}")),
}

Prevention

When it happens

Trigger: Calling the MCP UI login action (handle_mcp_ui_action -> start_mcp_login) with a server name that is absent from the mcp config file at `path` and from any plugin registry servers — e.g. a typo'd name, a server removed from config, or the wrong config path being loaded.

Common situations: Renaming or deleting a server in the MCP config while the TUI still shows a stale snapshot; passing a name from a different config file than the one loaded; plugin providing the server not enabled so the merged config lacks it.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at crates/tui/src/tui/ui/handlers.rs:555

    let progress = Arc::clone(&pending.progress);
    app.mcp_login = Some(pending);
    report_mcp_login(
        app,
        app.tr(MessageId::McpLoginStarting)
            .replace("{server}", &name)
            .replace("{cancel_key}", "Esc"),
        StatusToastLevel::Info,
    );

    tokio::spawn(async move {
        let handshake = async {
            let cfg = crate::mcp::load_config_with_workspace_and_plugins(
                &path,
                &workspace,
                plugin_registry.as_ref(),
            )?;
            let server = cfg.servers.get(&name).ok_or_else(|| {
                anyhow::anyhow!(
                    codewhale_localization::tr(locale, MessageId::McpLoginServerNotFound)
                        .replace("{server}", &name)
                )
            })?;
            crate::mcp::oauth::begin_oauth_login_for_server_tool(
                &name,
                server,
                (!scopes.is_empty()).then_some(scopes),
                callback_port,
                callback_url.as_deref(),
                network_policy.as_ref(),
            )
            .await
        };
        let operation = async {
            // Bound the whole handshake as well as each guarded HTTP request.
            // The timeout is in the background: even an unresponsive issuer
            // cannot delay redraw, input or cancellation.

View on GitHub (pinned to 73e0f67d83)