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
- Strip the userinfo from the URL and supply credentials via the headers argument instead
- If you are the operator (not runtime-added/reviewed-plugin), configure the endpoint through the operator config path where credentials in URL are permitted
- 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
- Store API credentials in header configuration, never in endpoint URLs
- Scan MCP config files for 'user:pass@' patterns during review
- Use a credential manager and inject Authorization headers at connect time
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
- MCP HTTP discovered URL must not contain credentials
- MCP HTTP redirect must not contain credentials
- reviewed plugin MCP endpoint must not contain user…
- returned a verification URI with embedded credentials
- MCP HTTP destination blocked by network policy
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)