Hmbown/CodeWhale · error

MCP server ' ' already has bearer/static Authorization…

Error message

MCP server '{name}' already has bearer/static Authorization configured

What it means

After confirming the server is URL-based, resolve_oauth_login rejects servers that already carry manual authorization — a static bearer token or Authorization header in their config. Running an OAuth flow would overwrite or conflict with the explicitly configured credential, so the library refuses instead of guessing which auth should win.

Solutions

  1. Remove the static Authorization header / bearer token from the server config, then run the OAuth login
  2. Or keep the static credential and skip OAuth entirely — the current token may be all you need
  3. If both are wanted, split into two server entries with different names
  4. Check env-var substitution in the config in case a header is being injected without your realizing it

Example fix

// before
{ "my-server": { "url": "https://mcp.example.com/mcp", "headers": { "Authorization": "Bearer sk-..." } } }
// after (OAuth takes over)
{ "my-server": { "url": "https://mcp.example.com/mcp" } }
Defensive patterns

Strategy: validation

Validate before calling

fn has_manual_auth(server: &McpServerConfig) -> bool {
    server_has_manual_authorization(server)
}
// gate: if has_manual_auth(server) { skip OAuth }

Try / catch

match perform_oauth_login_for_server(&server).await {
    Err(e) if e.to_string().contains("already has bearer/static Authorization") => {
        eprintln!("server uses a static credential; removing OAuth attempt");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling perform_oauth_login_for_server for a server whose McpServerConfig has a bearer token or Authorization header set (detected by server_has_manual_authorization), typically via /mcp login or the authenticate tool.

Common situations: A user configures an API-key header, later hears the server supports OAuth and tries /mcp login; infra-managed configs that ship static tokens; config templates that include a placeholder Authorization header.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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

Appendix: source

Thrown at crates/tui/src/mcp/oauth.rs:1115

        _ = cancellation_token.cancelled() => bail!("OAuth login was cancelled"),
        result = future => result,
    }
}

/// Shared gate + scope resolution for `/mcp login` and the model-driven
/// authenticate tool: URL-based servers only, no manual Authorization config,
/// scopes from explicit argument, config, or discovery (in that order).
async fn resolve_oauth_login(
    name: &str,
    server: &McpServerConfig,
    explicit_scopes: Option<Vec<String>>,
    network_policy: Option<&NetworkPolicyDecider>,
) -> Result<(String, ResolvedMcpOAuthScopes)> {
    let Some(url) = server.url.as_deref() else {
        bail!("OAuth login is only supported for URL-based MCP servers");
    };
    if server_has_manual_authorization(server) {
        bail!("MCP server '{name}' already has bearer/static Authorization configured");
    }

    let discovery = if explicit_scopes.is_none() && server.scopes.is_empty() {
        oauth_login_support(server, network_policy).await?
    } else {
        None
    };
    let resolved_scopes = resolve_oauth_scopes(
        explicit_scopes,
        server.scopes.clone(),
        discovery.and_then(|discovery| discovery.scopes_supported),
    );
    Ok((url.to_string(), resolved_scopes))
}

async fn perform_oauth_login_for_server_inner(
    name: &str,
    server: &McpServerConfig,

View on GitHub (pinned to 73e0f67d83)