Hmbown/CodeWhale · error

MCP HTTP URL must not contain credentials; use configured…

Error message

MCP HTTP URL must not contain credentials; use configured headers

What it means

The MCP HTTP client constructor rejects endpoint URLs that embed credentials (user:password@) when the endpoint was added at runtime or comes from a reviewed plugin. Credentials in URLs leak into logs and proxies; the library requires them to be sent as configured headers instead.

Solutions

  1. Strip the userinfo from the URL and supply credentials via the headers argument instead
  2. If you are the operator (not runtime-added/reviewed-plugin), configure the endpoint through the operator config path where credentials in URL are permitted
  3. Use an Authorization header in configured headers, e.g. Authorization: Basic <base64> or Bearer <token>

Example fix

// before
McpHttpClient::new("https://user:secret@example.com/mcp", true, false, ...)
// after
let headers = [("Authorization", format!("Basic {}", base64("user:secret")))];
McpHttpClient::new("https://example.com/mcp", true, false, ...).with_headers(headers)
Defensive patterns

Strategy: validation

Validate before calling

fn url_has_credentials(url: &Url) -> bool {
    !url.username().is_empty() || url.password().is_some()
}
let parsed = Url::parse(endpoint)?;
if runtime_added && url_has_credentials(&parsed) {
    // move credentials to headers before constructing the client
}

Type guard

fn is_credential_free_http_url(s: &str) -> Option<Url> {
    let u = Url::parse(s).ok()?;
    (matches!(u.scheme(), "http" | "https")
        && !u.username().is_empty() == false
        && u.password().is_none()).then_some(u)
}

Prevention

When it happens

Trigger: Calling McpHttpClient::new with a URL like https://user:pass@example.com/mcp while runtime_added==true or reviewed_plugin==true, so url_has_credentials(&url) is true.

Common situations: Pasting a provider URL that includes an API key as basic-auth userinfo; a plugin manifest carrying credentials in its endpoint URL; migrating a curl-style URL (which commonly embeds auth) into an MCP config.

Related errors


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

Appendix: source

Thrown at crates/tui/src/mcp/http_client.rs:49

    request_builder: reqwest::Client,
    clients: Arc<Mutex<HashMap<String, reqwest::Client>>>,
}

impl McpHttpClient {
    pub(super) fn new(
        url: &str,
        runtime_added: bool,
        reviewed_plugin: bool,
        allow_private_network: bool,
        network_policy: Option<&NetworkPolicyDecider>,
        connect_timeout: Duration,
        read_timeout: Duration,
    ) -> Result<Self> {
        let url = Url::parse(url).context("invalid MCP HTTP endpoint")?;
        validate_url(&url)?;
        validate_network_policy(&url, network_policy)?;
        if (runtime_added || reviewed_plugin) && url_has_credentials(&url) {
            bail!("MCP HTTP URL must not contain credentials; use configured headers");
        }
        Ok(Self {
            origin: url.origin().ascii_serialization(),
            operator_configured: !runtime_added,
            private_origin_allowed: !runtime_added
                && (allow_private_network || explicit_local_target(&url)),
            #[cfg(test)]
            dns_answers: Arc::new(Mutex::new(None)),
            reviewed_plugin,
            network_policy: network_policy.cloned(),
            connect_timeout,
            read_timeout,
            default_headers: header::HeaderMap::new(),
            request_builder: guarded_reqwest_client_builder().build()?,
            clients: Arc::new(Mutex::new(HashMap::new())),
        })
    }

View on GitHub (pinned to 73e0f67d83)