Hmbown/CodeWhale · error · anyhow::Error
Failed to connect MCP server '{server_name}': server is disa
Error message
Failed to connect MCP server '{server_name}': server is disabled What it means
get_or_connect found the server in static config or dynamic_servers, but McpServerConfig::is_enabled() returned false, so it refuses to spawn/connect. The server exists but was explicitly disabled (an enabled: false style flag in the server entry, or however the config expresses opt-out), and the pool treats that as a hard stop rather than silently connecting.
Source
Thrown at crates/tui/src/mcp.rs:2672
return self
.connections
.get_mut(server_name)
.ok_or_else(|| anyhow::anyhow!("MCP connection disappeared for {server_name}"));
}
self.drop_connection(server_name, "reconnect");
// Check static config first, then dynamic servers
let server_config = self
.config
.servers
.get(server_name)
.cloned()
.or_else(|| self.dynamic_servers.read().get(server_name).cloned())
.ok_or_else(|| anyhow::anyhow!("Failed to find MCP server: {server_name}"))?;
if !server_config.is_enabled() {
anyhow::bail!("Failed to connect MCP server '{server_name}': server is disabled");
}
let mut connection = McpConnection::connect_with_policy(
server_name.to_string(),
server_config,
&self.config.timeouts,
self.network_policy.as_ref(),
)
.await?;
connection.catalog_generation = self.catalog_generation.load(Ordering::SeqCst);
self.connections.insert(server_name.to_string(), connection);
self.connections
.get_mut(server_name)
.ok_or_else(|| anyhow::anyhow!("Failed to store MCP connection for {server_name}"))
}
/// Connect to all enabled servers, returning errors for failed connectionsView on GitHub (pinned to 8880682c63)
Solutions
- Set the server's enabled flag to true in the MCP config (or remove the disabling override) and save, then retry — the lazy reload picks up the mtime change.
- Filter call sites on is_enabled() so disabled servers are skipped instead of erroring.
- If it should stay disabled, remove or stop calling the code path that references it.
- For dynamic servers, register with the enabled state you actually want.
Example fix
# before (.mcp.json)
{"servers": {"github": {"command": "gh-mcp", "enabled": false}}}
# after
{"servers": {"github": {"command": "gh-mcp", "enabled": true}}} Defensive patterns
Strategy: validation
Validate before calling
// Rust: check enablement before dispatch
if let Some(cfg) = pool.config().servers.get(name) {
if !cfg.is_enabled() {
bail!("server '{name}' is disabled in config; enable it or skip the call");
}
}
let conn = pool.get_or_connect(name).await?; Try / catch
// Rust: catch and route around disabled servers
match pool.get_or_connect(name).await {
Err(e) if e.to_string().contains("server is disabled") => {
return Ok(fallback_without(name)); // skip feature relying on this server
}
o => o,
} Prevention
- Filter iteration over config.servers on is_enabled() before issuing calls.
- Keep disabled servers out of model-visible tool catalogs.
- When toggling enabled, expect one reload cycle before the change takes effect.
When it happens
Trigger: Any access path (tool call, resource read, prompt get, connect_all) naming a server whose config sets the enabled flag to false; also dynamic registrations created in a disabled state.
Common situations: Users temporarily disabling a broken server in config and forgetting to re-enable; config templates that ship servers disabled by default; programmatic callers enumerating all keys in the file without filtering on enabled; flip-flopping the flag while a session holds old state.
Related errors
- invalid JSON payload at key {MCP_SERVER_DEFINITIONS_KEY}; co
- invalid MCP server definition list in key {MCP_SERVER_DEFINI
- Failed to write MCP config {}: {}
- MCP config path cannot be empty
- MCP config path cannot contain '..' components
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/bd020ca3328f77d1.
Report an issue: GitHub.