Hmbown/CodeWhale · error · anyhow
MCP server URL ' ' must include a host
Error message
MCP server URL '{server_url}' must include a host What it means
callback_id_from_server_url derives a stable callback identifier by parsing the MCP server URL and hashing it; this requires the URL to have a host component. Url::parse can succeed for URLs without a host (e.g. relative or some non-special schemes), so host_str() returning None triggers this error. The URL is used to route the OAuth callback, so a hostless URL cannot be identified.
Solutions
- Set the MCP server URL to a valid absolute http(s) URL including a host, e.g. https://mcp.example.com
- Fix typos in the scheme (file://, missing scheme, etc.) in the server configuration
- If the server is local and hostless, do not enable OAuth for it
Example fix
// before "url": "file:///opt/mcp/server" // after "url": "https://mcp.example.com"
Defensive patterns
Strategy: validation
Validate before calling
fn has_host(url: &str) -> bool {
url::Url::parse(url).map(|u| u.host_str().is_some()).unwrap_or(false)
}
// call before OAuth setup: if !has_host(server_url) { fix config } Prevention
- Always configure MCP servers with absolute http(s) URLs including a host
- Only enable OAuth for servers that are actually reachable over http(s)
- Validate the server URL at config-load time so hostless URLs fail early
When it happens
Trigger: Calling callback_id_from_server_url with a server URL that parses but has no host — e.g. "file:///path/to/server", a malformed scheme-relative URL, or an empty/whitespace string that still parses.
Common situations: Configuring an MCP server entry with a local file or Unix-socket URL instead of an http(s) URL when OAuth is enabled; typos in the configured URL scheme; template variables left unsubstituted in config.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- returned an unusable verification URI
- Invalid MCP URL
- MCP HTTP requires an http:// or https:// URL with a host
- OAuth login is only supported for URL-based MCP servers
- reviewed plugin MCP endpoint has an unsafe origin
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/67e710bd719f4181.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/mcp/oauth.rs:2020
fn callback_bind_host(callback_url: Option<&str>) -> &'static str {
let Some(callback_url) = callback_url else {
return "127.0.0.1";
};
let Ok(parsed) = Url::parse(callback_url) else {
return "127.0.0.1";
};
match parsed.host_str() {
Some("localhost" | "127.0.0.1" | "::1") | None => "127.0.0.1",
Some(_) => "0.0.0.0",
}
}
fn callback_id_from_server_url(server_url: &str) -> Result<String> {
let mut parsed =
Url::parse(server_url).with_context(|| format!("invalid MCP server URL '{server_url}'"))?;
parsed
.host_str()
.ok_or_else(|| anyhow!("MCP server URL '{server_url}' must include a host"))?;
parsed.set_fragment(None);
let digest = Sha256::digest(parsed.as_str().as_bytes());
Ok(URL_SAFE_NO_PAD.encode(&digest[..9]))
}
fn append_callback_id_to_redirect_uri(redirect_uri: &str, callback_id: &str) -> Result<String> {
let mut parsed = Url::parse(redirect_uri)
.with_context(|| format!("invalid redirect URI '{redirect_uri}'"))?;
let path = parsed.path();
let new_path = if path.ends_with('/') {
format!("{path}{callback_id}")
} else {
format!("{path}/{callback_id}")
};
parsed.set_path(&new_path);
Ok(parsed.to_string())
}
View on GitHub (pinned to 73e0f67d83)