[BUG] macOS: custom/self-hosted MCP connector tools blocked by stale enabledMcpTools dual-key scheme — regression since v1.24012.11 (2026-08-03)
Description
Custom (self-hosted) MCP connector tools are silently blocked in Claude Code / Cowork sessions launched from Claude Desktop, even though the connector shows "enabled" and every individual tool is set to "Always allow" in Settings → Connectors. Every tool call fails with:
This tool has been disabled in your connector settings.
Toggling the connector off/on, and even fully removing + re-adding the connector's declaration, does not clear the block.
Root cause found in app.asar
The permission gate (in Contents/Resources/app.asar) is:
function qn(e,t){
var i;
if(!e) return {decision:"block", reason:"Session state unavailable; cannot verify tool permissions."};
const n=t.match(u1t); // u1t = /^mcp__(.+?)__(.+)$/
if(!n) return {decision:"allow"};
const r = `${n[1]}:${n[2]}`; // UNPREFIXED key: "<server>:<tool>"
return ((i=e.enabledMcpTools)==null?void 0:i[r]) === !1
? {decision:"block", reason:"This tool has been disabled in your connector settings."}
: {decision:"allow"};
}
Each session's enabledMcpTools map (stored per-session in ~/Library/Application Support/Claude/claude-code-sessions/<acct>/<org>/local_<uuid>.json on macOS) contains two competing key schemes for the same server:
"local:jmdb:jmdb_campagnes": true, // written by Settings → Connectors UI ("Always allow")
"jmdb:jmdb_campagnes": false // read by qn() above — always false for custom connectors
The gate reads the unprefixed key (<server>:<tool>). The Settings UI writes the local:-prefixed key. They never reconcile, so the UI can show "Always allow" while every call is denied.
What distinguishes blocked vs. working connectors
Across 6 personally-configured MCP servers (all declared identically, in both claude_desktop_config.json and the Claude Code global ~/.claude.json):
| Server | Type | Blocked? |
|---|---|---|
| github (@modelcontextprotocol/server-github) | official npm package | No |
| gitlab (community npm package) | official-style npm package | No |
| exa (mcp-remote → mcp.exa.ai) | remote, third-party but well-known | No |
| context7 (mcp-remote → mcp.context7.com) | remote, well-known | No |
| jmdb (mcp-remote → http://127.0.0.1:7791/mcp, self-hosted) | custom/self-hosted | Yes — 7/7 tools blocked |
| hostinger-api (custom wrapper script) | custom/self-hosted | Yes — tools blocked (281 false entries across session history) |
Only the two self-hosted/custom connectors are affected. This suggests the app treats custom connectors as requiring some additional per-session confirmation gate that official/catalog connectors skip — and that gate silently fails (or is simply unreachable) for headless/non-interactive Claude Code sessions, leaving the unprefixed key stuck at false.
Regression window
Scanned 953 local session-state files spanning several months. Every session referencing the jmdb connector before 2026-08-03 has a clean enabledMcpTools map (only the local:-prefixed keys, no unprefixed false entries). From 2026-08-03 onward (the day Claude Desktop updated to 1.24012.11), every session has both key schemes, with the unprefixed one at false. Same connector config on both sides of that date — only the app version changed.
What was tried (all failed to unblock)
- Toggling the connector off then on in Settings → Connectors — no change to session state (only
local:-prefixed keys got rewritten, unprefixed ones untouched). - Removing the connector's declaration from
claude_desktop_config.jsonentirely, quitting the app, confirming the declaration was gone, then relaunching — the very next new session still seeded the unprefixed keys asfalse. This rules out "duplicate declaration" as the cause: the only remaining declaration (the Claude Code–side one in the global~/.claude.json, required for the tools to exist at all) is sufficient on its own to reproduce the block. - Manually deleting the stale unprefixed keys from the session JSON on disk while the app was closed — confirmed the file was correctly purged, but the app regenerated the same
falseentries ~38 seconds after the next launch, on the first new session.
Expected behavior
A custom/self-hosted MCP connector, once enabled with all tools set to "Always allow" in Settings → Connectors, should have its tools usable from Claude Code / Cowork sessions — matching the behavior of official/catalog connectors, and matching the app's own pre-2026-08-03 behavior with the identical configuration.
Environment
- OS: macOS 27.0.0 (Darwin)
- Claude Desktop: 1.24012.11
- Connector transport:
mcp-remotewrapping a localhttp://127.0.0.1:<port>/mcpstreamable-HTTP server (also reproduced with a different custom connector using a local wrapper script instead ofmcp-remote)
Related reports
This looks like the same underlying enabledMcpTools dual-key defect reported (and closed without a fix) in:
- #24433 — "Claude Desktop Cowork: 'Always allow' for MCP tools does not persist across sessions" (macOS, closed not-planned, stale)
- #38811 — "Claude in Chrome: 18 of 20 MCP tools blocked by enabledMcpTools despite connector being enabled" (Windows, closed as duplicate)
Reopening with the above: exact code path in app.asar, the two-key-scheme mechanism, and — new information — the fact that this is isolated to custom/self-hosted connectors specifically, and a precise regression date (2026-08-03, v1.24012.11) with a same-config before/after comparison across 953 sessions.