Hmbown/CodeWhale · error
MCP server ' ' config must have either 'command' or 'url
Error message
MCP server '{name}' config must have either 'command' or 'url' What it means
Every MCP server config must specify exactly one launch mechanism: a local 'command' (stdio transport) or a remote 'url' (HTTP/SSE transport). When neither field is present the server cannot be constructed, and the setup bails naming the server.
Solutions
- Add a 'command' array for a local stdio server
- Add a 'url' string for a remote HTTP/SSE server
- Validate the mcpServers config structure (each entry needs exactly one of command/url)
- Check nesting/indentation so the field actually lands on the server entry
Example fix
// before
[config.mcpServers.myserver]
env = { API_KEY = "..." }
// after
[config.mcpServers.myserver]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-xyz"]
env = { API_KEY = "..." } Defensive patterns
Strategy: validation
Validate before calling
for (name, cfg) in &config.mcpServers {
if cfg.command.is_none() && cfg.url.is_none() {
return Err(format!("MCP server '{name}' needs either 'command' or 'url'"));
}
} Type guard
fn is_launchable(cfg: &McpServerConfig) -> bool {
cfg.command.is_some() || cfg.url.is_some()
} Prevention
- Validate mcpServers entries at config load
- Template new server entries with command/url pre-filled
- Watch for indentation mistakes in TOML/YAML configs
When it happens
Trigger: Defining an MCP server entry that lacks both 'command' and 'url'; e.g. an entry with only 'name'/'headers'/'env' or an empty object in the mcpServers map.
Common situations: Copy-pasting a config fragment and dropping the command/url line; YAML/TOML nesting mistakes that put command under the wrong key; a partially edited config saved mid-way.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- .inputSchema is required for an advertised MCP tool
- {error}
- Failed to parse MCP config
- Failed to parse MCP config
- Failed to parse MCP config; file contents were omitted
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/1eeefce162ddcf19.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/mcp.rs:1816
if let Err(e) = http.try_establish_session().await {
tracing::debug!(
target: "mcp",
server = %name,
error = %e,
"session-establishment GET skipped; proceeding with POST initialize"
);
}
Box::new(http)
}
} else if let Some(command) = &config.command {
Box::new(StdioTransport::spawn(
&name,
command,
&config,
cancel_token.clone(),
)?)
} else {
anyhow::bail!("MCP server '{name}' config must have either 'command' or 'url'");
};
// Revalidate after transport construction as well: remote setup may
// await DNS/TLS/SSE preflight, and a concurrent process can revoke the
// receipt during that interval. Initialization and catalog discovery
// never start under a stale generation.
if let Some(source) = config.reviewed_plugin.as_ref() {
source.validate_before_use(&name, "initialize")?;
}
let authority_watch = authority_watch.map(PendingAuthorityWatch::disarm);
let mut conn = Self {
name: name.clone(),
transport,
tools: Vec::new(),
resources: Vec::new(),
resource_templates: Vec::new(),
prompts: Vec::new(),
request_id: AtomicU64::new(1),View on GitHub (pinned to 73e0f67d83)