Hmbown/CodeWhale · error · anyhow::Error
Invalid MCP URL
Error message
Invalid MCP URL
What it means
Remote entries supply a `url` string parsed with reqwest::Url::parse; if the string is not a parseable URL at all, this error is thrown before any scheme/host checks. The bad URL's contents are not echoed.
Solutions
- Add an explicit scheme: `https://mcp.example.com` or `http://localhost:3000`
- URL-encode or remove stray spaces and characters from the value
- Test the string in a URL parser before saving the config
Example fix
// before
{"mcpServers":{"api":{"url":"mcp.example.com:8080"}}}
// after
{"mcpServers":{"api":{"url":"http://mcp.example.com:8080"}}} Defensive patterns
Strategy: validation
Validate before calling
try { new URL(u); } catch { throw new Error(`not a URL: ${u}`); } Type guard
function isParseableUrl(u) { try { new URL(u); return true; } catch { return false; } } Try / catch
catch, then run the string through a URL parser locally to see the real parse error
Prevention
- Always include the scheme (http:// or https://) in url fields
- Trim whitespace/quotes when pasting URLs
- Prefer http://127.0.0.1:<port> for local dev servers
When it happens
Trigger: `url` is missing the scheme ("mcp.example.com/sse"), contains spaces, or is otherwise malformed so Url::parse fails.
Common situations: Omitting `https://` when copying a server address; trailing quotes or whitespace pasted into the field; using a bare host:port for a local dev server.
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
- MCP HTTP requires an http:// or https:// URL with a host
- MCP server URL ' ' must include a host
- reviewed plugin MCP endpoint has an unsafe origin
- Unsupported MCP URL
- bad_target
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/c59ffef4941479c3.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/mcp/external_import.rs:208
.is_some_and(|map| map.keys().all(|key| key == "client_id")),
"Source contains unsupported OAuth fields"
);
}
let server: McpServerConfig = serde_json::from_value(config)
.map_err(|_| anyhow::anyhow!("Invalid MCP entry; contents omitted"))?;
anyhow::ensure!(
server.command.is_some() != server.url.is_some(),
"MCP entry must have one target"
);
if let Some(command) = &server.command {
anyhow::ensure!(
!command.trim().is_empty() && !command.chars().any(char::is_control),
"Invalid MCP command"
);
}
if let Some(url) = &server.url {
let parsed =
reqwest::Url::parse(url).map_err(|_| anyhow::anyhow!("Invalid MCP URL"))?;
anyhow::ensure!(
matches!(parsed.scheme(), "http" | "https")
&& parsed.host_str().is_some()
&& parsed.username().is_empty()
&& parsed.password().is_none(),
"Unsupported MCP URL"
);
}
super::validate_mcp_transport(server.transport.as_deref())
.map_err(|_| anyhow::anyhow!("Unsupported MCP transport"))?;
let hard_blocked = !server.is_enabled();
out.push(ImportCandidate {
summary: server_summary(&name, &server),
name,
source_kind: kind.clone(),
source_path: path.to_path_buf(),
content_hash: hash.clone(),
hard_blocked,View on GitHub (pinned to 73e0f67d83)