Hmbown/CodeWhale · error · anyhow::Error
MCP tool '{tool_name}' is disabled for server '{server_name}
Error message
MCP tool '{tool_name}' is disabled for server '{server_name}' What it means
Before executing a tool, call_tool re-validates the live connection against the resolved route: the reviewed plugin's authority must match route.plugin_authority, is_tool_enabled must allow the tool (if enabled_tools is non-empty the tool must be listed, and disabled_tools must not list it), and the tool must still appear in the server's advertised tools list (mcp.rs:1053-1063). If any check fails, the call is refused as 'disabled' even though the tool name resolved earlier.
Source
Thrown at crates/tui/src/mcp.rs:3325
let route = self.resolve_advertised_tool(prefixed_name).await?;
let server_name = route.server_name.clone();
let tool_name = route.tool_name.clone();
// Copy the global timeouts to avoid borrow conflict
let global_timeouts = self.config.timeouts;
let conn = self.get_or_connect(&server_name).await?;
if conn.catalog_generation != route.catalog_generation {
anyhow::bail!("MCP catalog changed after tool resolution; retry the call");
}
if conn
.config()
.reviewed_plugin
.as_ref()
.map(|source| &source.authority)
!= route.plugin_authority.as_ref()
|| !conn.config().is_tool_enabled(&tool_name)
|| !conn.tools().iter().any(|tool| tool.name == tool_name)
{
anyhow::bail!("MCP tool '{tool_name}' is disabled for server '{server_name}'");
}
let timeout = conn.config().effective_execute_timeout(&global_timeouts);
match conn.call_tool(&tool_name, arguments.clone(), timeout).await {
Ok(result) => Ok(result),
Err(err) if is_mcp_stale_session_error(&err) => {
tracing::debug!(
target: "mcp",
server = server_name,
tool = tool_name,
error = %err,
"retrying MCP tool call after stale session"
);
self.drop_connection(&server_name, "stale session retry");
let conn = self.get_or_connect(&server_name).await?;
if conn.catalog_generation != route.catalog_generation
|| conn
.config()
.reviewed_pluginView on GitHub (pinned to 8880682c63)
Solutions
- Check enabled_tools/disabled_tools for the server in mcp.json and add (or remove) the tool name accordingly
- Refresh the tool catalog and confirm the tool still appears in the server's tools/list
- If a reviewed plugin is involved, re-review/re-approve it so its authority matches, then reconnect
- If the server renamed the tool, update the calling code to the new name
Example fix
// before (.codewhale/mcp.json)
"my-server": { "command": "npx", "args": ["-y", "some-server"], "enabled_tools": ["old_tool"] }
// after
"my-server": { "command": "npx", "args": ["-y", "some-server"], "enabled_tools": ["old_tool", "new_tool"] } Defensive patterns
Strategy: validation
Validate before calling
// Before calling, confirm the tool is still enabled and advertised on the live connection:
if let Some(conn) = manager.connection(server_name) {
let cfg = conn.config();
if !cfg.is_tool_enabled(&tool_name) || !conn.tools().iter().any(|t| t.name == tool_name) {
anyhow::bail!("tool '{tool_name}' is not currently enabled/advertised; fix config first");
}
}
manager.call_tool(prefixed_name, args).await?; Try / catch
match manager.call_tool(prefixed_name, args).await {
Err(e) if e.to_string().contains("is disabled for server") => {
// inspect enabled_tools/disabled_tools and the refreshed catalog, then surface a config error
}
other => other,
} Prevention
- Keep enabled_tools in mcp.json explicit and in sync with the tools your prompts actually call
- After upgrading or restarting an MCP server, refresh the catalog and verify tool names before invoking them
- Re-review plugins after re-staging so their authority matches the advertised routes
When it happens
Trigger: enabled_tools is set for the server and the tool is not in it; the tool is listed in disabled_tools; the server no longer advertises the tool after a restart; the reviewed_plugin authority changed (plugin re-reviewed/re-staged) so it no longer equals the authority captured when the tool was advertised.
Common situations: Editing mcp.json to add enabled_tools filtering; a server upgrade that renamed or removed a tool; a reviewed plugin re-staged so its authority digest differs from the advertised route.
Related errors
- disabled_tools must use Codewhale catalog identifiers: ${",
- 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
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/2ba5a0bef99a2264.
Report an issue: GitHub.