Hmbown/CodeWhale · error
No external MCP candidate named
Error message
No external MCP candidate named '{name}'. Run /mcp import to list sources with provenance. What it means
Thrown by mcp_import_apply when the named external MCP candidate cannot be found among the sources discovered by discover_external_sources (home dir, workspace, and market paths). Import works only on candidates the discovery pass enumerated, so an unknown name is rejected with a pointer to /mcp import for a provenance listing. Case-insensitive match is used but the name must still exist.
Solutions
- Run /mcp import to list candidate names with provenance and copy the exact name
- Check that the source file (e.g. claude desktop config, marketplace JSON) is in a scanned path
- Re-run import discovery after adding or fixing market paths in config
Defensive patterns
Strategy: validation
Validate before calling
let candidates = discover_external_sources(&home, &workspace, &markets);
if !candidates.iter().any(|c| c.name.eq_ignore_ascii_case(name)) { return Err(anyhow!("no candidate '{name}'")); } Prevention
- Always derive import names from /mcp import output, never from memory
- Keep market paths configured before importing
- Refresh discovery after editing external source files
When it happens
Trigger: Calling the apply/import UI action with a name never produced by discovery; discovery ran before a new market file was added; name casing differs beyond ASCII case-fold.
Common situations: User typed a server name from memory instead of the /mcp import listing; external source file moved or renamed; marketplace path not configured so discovery never saw the candidate.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- A managed, project or plugin connector already uses this…
- Invalid MCP entry; contents omitted
- MCP import failed
- MCP import preview failed
- Refusing to import ' ': (enabled=false is a hard block)
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/cef4c4eba828acec.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tui/ui/provider_routes.rs:967
) -> anyhow::Result<String> {
use crate::mcp::external_import::{
ImportDecision, apply_approved, discover_external_sources, load_consent_store,
merge_approved_into_config, record_decisions, save_consent_store,
};
use std::collections::HashMap;
use std::time::{SystemTime, UNIX_EPOCH};
let home = crate::config::effective_home_dir().unwrap_or_else(|| PathBuf::from("."));
let market_path = codewhale_config::codewhale_home()
.ok()
.map(|h| h.join("mcp-marketplace.json"));
let markets: Vec<PathBuf> = market_path.into_iter().collect();
let all = discover_external_sources(&home, workspace, &markets);
let candidate = all
.iter()
.find(|c| c.name.eq_ignore_ascii_case(name))
.ok_or_else(|| {
anyhow::anyhow!(
"No external MCP candidate named '{name}'. Run /mcp import to list sources with provenance."
)
})?;
if approve && candidate.hard_blocked {
anyhow::bail!(
"Refusing to import '{}': {} (enabled=false is a hard block)",
candidate.name,
candidate.block_reason.as_deref().unwrap_or("hard blocked")
);
}
let mut decisions = HashMap::new();
decisions.insert(
candidate.name.clone(),
if approve {
ImportDecision::Approve
} else {View on GitHub (pinned to 433685b202)