[Bug] MCP allowlisted tools still trigger permission prompt on fresh session

Status Open
Reported on v2.1.206
Maintainer reply ✓ Yes — bcherny
Activity 3 comments · opened Jul 10, 2026
💡 Likely answer: A maintainer (bcherny, collaborator) responded on this thread — see the highlighted reply below.

Bug Description

Bug: Allowlisted MCP tool still triggers permission prompt on a fresh session

Environment

  • Claude Code version: 2.1.206
  • OS: macOS (Darwin)
  • Model/mode at time of repro: Opus Plan (defaultMode: "plan" in global settings)

Summary

An MCP tool (mcp__plane__list_work_items, from a custom MCP server named plane) is present verbatim in a project's permissions.allow list, in a workspace where trust has already been accepted, with no conflicting deny/ask rules anywhere — and it still triggers a permission confirmation prompt on a brand-new session, instead of executing silently.

Config at time of repro

Project-level .claude/settings.local.json (gitignored, not committed) has had this entry since 5 days before the repro:

{
  "permissions": {
    "allow": [
      "mcp__plane__list_work_items",
      "mcp__plane__retrieve_work_item_by_identifier",
      "mcp__plane__create_work_item",
      "mcp__plane__list_work_item_comments",
      "mcp__plane__search_work_items"
    ]
  }
}

Global ~/.claude/settings.json additionally has a server-level allow entry (mcp__plane__*, and previously the bare form mcp__plane — both documented as equivalent server-wide matches) plus:

{
  "permissions": {
    "defaultMode": "plan"
  },
  "skipAutoPermissionPrompt": true
}
  • No deny or ask entries exist in any scope (global settings.json, global settings.local.json, project settings.json, project settings.local.json).
  • No managed-settings.json policy file present on the machine.
  • No project-local .mcp.json overriding the server definition.
  • Both settings files parse as valid JSON (json.load succeeds).
  • Workspace trust is confirmed accepted for the project: hasTrustDialogAccepted: true in ~/.claude.json under the project's entry.

Steps to reproduce

  1. Have an MCP server (plane) configured with several tools.
  2. Add an exact tool name (mcp__plane__list_work_items) to a project's .claude/settings.local.json under permissions.allow.
  3. Confirm workspace trust is already accepted for that project (hasTrustDialogAccepted: true).
  4. Start a brand-new Claude Code session (claude, not --resume/--continue) in that project directory, with defaultMode: "plan" set globally.
  5. Prompt Claude to call the allowlisted tool (e.g. via /whats-next or any flow that invokes list_work_items).

Expected

The tool call executes silently — no permission prompt — since the exact tool name is present in permissions.allow and no deny/ask rule exists anywhere.

Actual

Claude Code prompts:

plane - list_work_items(project_id: "...", expand: "state", fields: "sequence_id,name,priority,state", per_page: 100) (MCP)
List work items in a project or search across the workspace.

Do you want to proceed?
> 1. Yes
  2. Yes, and don't ask again for plane - list_work_items commands in /Users/vic/Repos/<project>
  3. No

What I ruled out before filing

  • Stale/cached permission set from an already-running session — confirmed this was a fresh session start, not a resumed one.
  • Malformed allowlist pattern — both mcp__<server> (bare) and mcp__<server>__* (wildcard) are documented to match all tools from that server; neither should be needed since the exact tool name was also present.
  • Invalid JSON silently voiding the permissions file — both settings files parse cleanly.
  • deny/ask override — none present in any scope.
  • Workspace trust not accepted — confirmed accepted (hasTrustDialogAccepted: true).
  • Plan mode overriding/bypassing the allowlist for MCP tools — per docs, permission prompts in Plan Mode behave identically to Manual mode; the allowlist should still be honored.
  • Outdated client — version matches (2.1.206) what's installed.

Given all of the above, the exact-match allow rule for this MCP tool does not appear to be honored on a fresh session, despite meeting every documented condition for it to apply.

Additional note

This may be specific to MCP tools (as opposed to built-in tools like Bash/Read, which reliably honor allowlist entries in the same environment) — worth checking whether MCP permission matching has a separate code path from built-in tool permission matching that might have a regression.

Environment Info

  • Platform: darwin
  • Terminal: ghostty
  • Version: 2.1.201
  • Feedback ID: 3932e642-4860-4f21-9e6b-d1f35e027f09

Errors

[]

View original on GitHub ↗

3 Comments

PropellerHead23 · 1 month ago

Same behavior here on macOS, desktop 1.20186.1 — allowlisted MCP tools re-prompt on every fresh desktop-spawned session. Regression onset for me was the 2026-07-11 desktop auto-update; allow rules were honored before it.

Workaround that holds: permissions.defaultMode: "dontAsk" in ~/.claude/settings.json (with the tools in allow) suppresses the cards — details in https://github.com/anthropics/claude-code/issues/73587#issuecomment-4975856651.

Same regression family: #73587 (desktop ignores permissions.allow rules, Windows + macOS) and #74715 (Claude-in-Chrome "Always allow" persisted as duration:once).

Simonmaignan · 1 month ago

Reproduced on Linux, Claude Code 2.1.211, in default/acceptEdits mode (not auto) — so this isn't confined to the auto-mode classifier gate; it hits the standard interactive permission flow too.

Tool: mcp__kg-memory__search_nodes, from a self-hosted stdio MCP server (kg-memory, custom Python/FastMCP).

Config: the exact tool name is in permissions.allow in both ~/.claude/settings.json (user) and the project's .claude/settings.local.json — confirmed via the startup debug log, which shows both destinations receiving the rule:

10:01:32.269Z [DEBUG] Applying permission update: Adding 154 allow rule(s) to destination 'userSettings': [...,"mcp__kg-memory__search_nodes",...]
10:01:32.270Z [DEBUG] Applying permission update: Adding 3 allow rule(s) to destination 'localSettings': [...,"mcp__kg-memory__search_nodes"]

No deny/ask rule for this tool anywhere (the ask list only covers the server's write tools — add_observations, create_entities, etc. — a deliberate separate rule, not this one). No managed-settings.json present. No PreToolUse hooks registered (Hooks: Found 0 total hooks in registry throughout the session). Workspace trust already accepted.

What the debug log shows at call time:

10:05:11.458Z tool_dispatch_start tool=mcp__atlassian__getJiraIssue permissionDecisionMs=2      <- allow-listed, no prompt
10:05:12.514Z executePermissionRequestHooks called for tool: mcp__kg-memory__search_nodes
10:05:16.292Z tool_dispatch_start tool=mcp__kg-memory__search_nodes permissionDecisionMs=3780   <- ~3.8s human decision gap
10:05:16.321Z executePermissionRequestHooks called for tool: mcp__kg-memory__search_nodes        <- SAME tool, next call, same session
10:05:17.914Z tool_dispatch_start tool=mcp__kg-memory__search_nodes permissionDecisionMs=1594   <- prompted AGAIN

Notably, this isn't just a fresh-session issue — the second call to the identical tool, seconds later in the same session, prompted again too. Every other allow-listed MCP tool call in the same session (Atlassian, etc.) dispatched in ~2ms with no prompt, so the allow-list mechanism is clearly working in general — it's specifically this tool (and per other comments here, MCP tools broadly) that falls through to a prompt despite the matching rule.

Happy to share the full sanitized debug log if useful for triage.

bcherny collaborator · 15 days ago

Reproduced on v2.1.233 (macOS). The prompt appears specifically when the session is in plan mode and the MCP tool does not advertise itself as read-only. In default (manual) mode the same allow rule is honored and the tool runs silently.

Minimal steps:

  1. Register a stdio MCP server named plane in the project's .mcp.json exposing a tool list_work_items without a readOnlyHint: true annotation.
  2. Project .claude/settings.local.json:

``json
{"permissions":{"allow":["mcp__plane__list_work_items"],"defaultMode":"plan"},"enableAllProjectMcpServers":true}
``

  1. Start a fresh claude session in that directory and accept the workspace-trust dialog (it even lists mcp__plane__list_work_items as pre-approved).
  2. Ask: "Call the plane MCP tool list_work_items with project_id abc."

Observed (plan mode):

 Tool use
   plane - list_work_items(project_id: "abc") (MCP)
   List work items in a project.
 Do you want to proceed?
 ❯ 1. Yes
   2. Yes, and don't ask again for plane - list_work_items commands in <project>
   3. No

Expected (per the report): no prompt, since the exact tool name is in permissions.allow and there is no deny/ask rule.

Variations on the same build:

  • Same tool and allow rule, defaultMode: "default" -> runs silently, no prompt.
  • Same setup in plan mode, but the tool annotated with readOnlyHint: true -> runs silently, no prompt.

Assessment: Intended today, but the expectation is reasonable and this should be made clearer. Since roughly v2.1.204, plan mode treats any MCP tool that isn't marked read-only (via the MCP readOnlyHint annotation) as a potential write and always prompts for it, even when an allow rule matches — the same way plan mode gates file edits and non-read-only shell commands. That is why an exact-name allow rule that works in default mode is ignored in plan mode, and why the second commenter's defaultMode: "dontAsk" workaround suppresses it (it isn't plan mode). Three things make this confusing: (1) the plan-mode docs only mention edits and shell commands, not MCP tools; (2) the prompt reads like an ordinary permission request and never says plan mode is the reason; and (3) "Yes, and don't ask again" writes an allow rule that plan mode then keeps ignoring, so it appears to have no effect on the next fresh session. Reasonable fixes: show a plan-mode-specific message (and hide or reword the "don't ask again" option there), document the MCP behavior on the plan-mode page, and/or ask MCP server authors to set readOnlyHint: true on read-only tools — that annotation is what plan mode keys off. Note that the Linux report in the comments (prompting in default/acceptEdits mode) is a different cause; that one did not reproduce here and is better tracked separately.

🤖 Generated with Claude Code