Hmbown/CodeWhale · error · anyhow::Error
MCP entry must have one target
Error message
MCP entry must have one target
What it means
An imported MCP server must specify exactly one target: either a local `command` or a remote `url`, never both and never neither. The invariant `command.is_some() != url.is_some()` is enforced with XOR; violating it rejects the entry.
Solutions
- Delete either the `command` or the `url` key so exactly one target remains
- If the server is remote, remove command/args; if local, remove url/transport
- Split genuinely dual-mode servers into two distinct named entries
Example fix
// before
{"mcpServers":{"api":{"command":"npx","url":"https://mcp.example.com"}}}
// after
{"mcpServers":{"api":{"url":"https://mcp.example.com"}}} Defensive patterns
Strategy: validation
Validate before calling
function oneTargetOk(e) { return ("command" in e) !== ("url" in e); } Try / catch
catch, then check whether the offending entry has 0 or 2 targets and fix accordingly
Prevention
- Never add `command` to an existing url entry (or vice versa) without deleting the other
- Diff config merges so dual-target entries can't survive
- One entry = one target; model dual-mode servers as two entries
When it happens
Trigger: An entry has both `command` and `url` set, or an entry has neither (only optional fields like transport, env, or headers).
Common situations: Merging two config files by hand so both keys survive; converting a remote entry to local by adding `command` without removing `url`; an empty stub entry with only metadata fields.
Related errors
- MCP consent history must be an object
- Source contains unsupported OAuth fields
- Unsupported MCP transport
- A managed, project or plugin connector already uses this…
- Absolute path should not warn
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/9b2bf02b0a70081e.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/mcp/external_import.rs:196
"scopes",
"oauth",
"oauth_resource",
];
anyhow::ensure!(
fields.keys().all(|key| ALLOWED.contains(&key.as_str())),
"Source contains unsupported MCP fields; review it at its source"
);
if let Some(oauth) = fields.get("oauth").filter(|v| !v.is_null()) {
anyhow::ensure!(
oauth
.as_object()
.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"View on GitHub (pinned to 73e0f67d83)