[BUG] macOS: custom/self-hosted MCP connector tools blocked by stale enabledMcpTools dual-key scheme — regression since v1.24012.11 (2026-08-03)

Status Open
Maintainer reply None cached
Activity 0 comments · opened Aug 8, 2026

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-remotemcp.exa.ai) | remote, third-party but well-known | No |
| context7 (mcp-remotemcp.context7.com) | remote, well-known | No |
| jmdb (mcp-remotehttp://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)

  1. Toggling the connector off then on in Settings → Connectors — no change to session state (only local:-prefixed keys got rewritten, unprefixed ones untouched).
  2. Removing the connector's declaration from claude_desktop_config.json entirely, quitting the app, confirming the declaration was gone, then relaunching — the very next new session still seeded the unprefixed keys as false. 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.
  3. 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 false entries ~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-remote wrapping a local http://127.0.0.1:<port>/mcp streamable-HTTP server (also reproduced with a different custom connector using a local wrapper script instead of mcp-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.

View original on GitHub ↗