Hmbown/CodeWhale · error

MCP server ' ' not found

Error message

MCP server '{name}' not found

What it means

Raised in handle_mcp_ui_action when an OAuth token deletion (logout) targets a server name that is not present in the loaded MCP config. `cfg.servers.get(&name)` yields None and an anyhow error with the literal message is returned before delete_oauth_tokens_for_server can run. Unlike the login path (2193), this message is a hardcoded English string, not localized.

Solutions

  1. Reload/refresh the MCP server list in the TUI so it reflects the current config, then retry.
  2. Check the server name against the `servers` map in the active MCP config file.
  3. Re-add the server to the config (or re-enable its plugin) if you still need to revoke its stored tokens.
  4. If stale tokens must be removed regardless, delete them from the OAuth token store directly once the name is corrected.

Example fix

// before
let server = cfg.servers.get(&name)
    .ok_or_else(|| anyhow::anyhow!("MCP server '{name}' not found"))?;
mcp::oauth::delete_oauth_tokens_for_server(&name, server)
// after: tolerate already-absent servers on logout
match cfg.servers.get(&name) {
    Some(server) => mcp::oauth::delete_oauth_tokens_for_server(&name, server),
    None => Ok(false), // nothing stored; treat as already-deleted
}
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!("cannot log out: server '{name}' not configured");
    return Ok(());
}

Try / catch

match handle_mcp_ui_action(app, McpUiAction::Logout { name }).await {
    Err(e) if e.to_string().contains("not found") => {
        status("Server removed from config — nothing to log out");
    }
    Err(e) => status(format!("logout failed: {e:#}")),
    Ok(_) => {},
}

Prevention

When it happens

Trigger: Invoking the MCP UI action that deletes OAuth tokens for `{name}` when the name is missing from cfg.servers — stale UI snapshot after config edit, typo, or a server registered only by a currently-disabled plugin.

Common situations: Clicking logout on an MCP server entry rendered from a cached snapshot while the underlying config file changed; removing a server from config in another editor while the TUI stays open; running logout for a server whose plugin was disabled.

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/730ccd573c2a9823. Report an issue: GitHub.

Appendix: source

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

                .map(|()| message = Some(format!("Removed MCP server '{name}'")))
        }
        crate::tui::app::McpUiAction::Login { name, scopes } => {
            start_mcp_login(app, config, name, scopes);
            // Login owns its background discovery. Do not start a second
            // discovery here or await network work on the input loop.
            return;
        }
        crate::tui::app::McpUiAction::Logout { name } => {
            let result = (|| {
                let cfg = mcp::load_config_with_workspace_and_plugins(
                    &path,
                    &app.workspace,
                    app.plugin_registry.as_ref(),
                )?;
                let server = cfg
                    .servers
                    .get(&name)
                    .ok_or_else(|| anyhow::anyhow!("MCP server '{name}' not found"))?;
                mcp::oauth::delete_oauth_tokens_for_server(&name, server)
            })();
            result.map(|deleted| {
                changed = deleted;
                message = Some(if deleted {
                    format!(
                        "Deleted locally stored OAuth credentials for MCP server '{name}'. That clears this machine only — the provider may keep its grant; the next /mcp login re-prompts for consent. Run /mcp reload to reconnect."
                    )
                } else {
                    format!("No stored OAuth credentials found for MCP server '{name}'.")
                });
            })
        }
        crate::tui::app::McpUiAction::ImportList => {
            let path = path.clone();
            let workspace = app.workspace.clone();
            let plugins = app.plugin_registry.clone();
            #[cfg(test)]

View on GitHub (pinned to 73e0f67d83)