CherryHQ/cherry-studio · warning · Error
MCP tool is disabled: ${name}
Error message
MCP tool is disabled: ${name} What it means
Thrown before invoking an MCP tool when the latest source policy marks the tool as disabled. The check `isMcpToolDisabledBySource(sourcePolicy, { name })` evaluates the server's current disabled-tools configuration. This is a policy enforcement guard, not a transport or connection error.
Source
Thrown at src/main/ai/mcp/McpRuntimeService.ts:1232
getServerLogger(server, { tool: name, callId: toolCallId }).debug(`Calling tool`, {
args: redactSensitive(args)
})
if (typeof args === 'string') {
if (args.trim() === '') {
args = {}
} else {
try {
args = JSON.parse(args)
} catch (e) {
// Fail fast instead of forwarding malformed JSON as a raw string — the MCP
// server expects an object/record, so a bare string yields opaque downstream errors.
throw new Error(`Invalid JSON tool arguments for ${name}: ${(e as Error).message}`)
}
}
}
const sourcePolicy = this.getLatestSourcePolicy(server)
if (isMcpToolDisabledBySource(sourcePolicy, { name })) {
throw new Error(`MCP tool is disabled: ${name}`)
}
// Client init (ping probe, transport connect, OAuth) has no unified timeout at this
// layer — release this call's wait on abort instead of blocking until it settles.
// The shared `pendingClients` init keeps running (only this caller's wait is released),
// and both racers are consumed, so the loser's late rejection is never unhandled.
// The listener is removed once the race settles: `once` only cleans up after an
// abort fires, and the composed signal is retained by the long-lived stream signal —
// leaving it installed would accumulate a closure per tool call.
let handleAbort: (() => void) | undefined
const client = await Promise.race([
this.getOrCreateClient(server),
new Promise<never>((_, reject) => {
handleAbort = (): void => reject(getAbortReason(effectiveSignal))
if (effectiveSignal.aborted) return handleAbort()
effectiveSignal.addEventListener('abort', handleAbort, { once: true })
})
]).finally(() => {
if (handleAbort) effectiveSignal.removeEventListener('abort', handleAbort)View on GitHub (pinned to 726446b54c)
Solutions
- Re-enable the tool in MCP settings → server details → tools list
- Check the server's `disabledTools` array in the database to confirm which tools are disabled
- If using source policies, review the policy configuration that disabled the tool
- In the calling layer, check `isMcpToolDisabledBySource` before attempting the call to provide a cleaner error message
Defensive patterns
Strategy: validation
Validate before calling
import { isMcpToolDisabledBySource } from '...'
const sourcePolicy = runtime.getLatestSourcePolicy(server)
if (isMcpToolDisabledBySource(sourcePolicy, { name: toolName })) {
throw new Error(`Tool '${toolName}' is disabled for server '${server.name}'`)
}
await runtime.callToolByServer({ server, name: toolName, args }) Type guard
function isToolEnabled(server: McpServer, toolName: string, policy: SourcePolicy): boolean {
return !isMcpToolDisabledBySource(policy, { name: toolName })
} Try / catch
try {
await runtime.callToolByServer({ server, name, args })
} catch (e) {
if (e instanceof Error && e.message.startsWith('MCP tool is disabled')) {
// Skip this tool or inform the user it needs to be enabled
logger.info(`Tool ${name} is disabled, skipping`)
return null
}
throw e
} Prevention
- Filter tool lists by the source policy before presenting them to the LLM
- Keep the disabledTools array and source policy in sync with the UI state
- Log which tools are disabled to aid debugging when calls fail unexpectedly
When it happens
Trigger: Calling `callToolByServer` or `callToolById` for a tool whose name appears in the server's `disabledTools` array or is disabled by the current source policy snapshot. The policy is fetched via `getLatestSourcePolicy(server)` at call time.
Common situations: User disabled specific tools in the MCP settings UI (per-tool toggle); an admin policy disabled certain tools; the tool was disabled by a security/compliance rule; the source policy was updated after the tool list was cached.
Related errors
- Invalid manifest: missing server.mcp_config.command
- Invalid manifest: server.mcp_config.args must be an array
- Invalid tool ID format: ${toolId}
- MCP server ${server.name} is disabled
- Invalid server type
AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12).
Data as JSON: /api/errors/8b5945d1fa3c7918.
Report an issue: GitHub.