[Bug] MCP allowlisted tools still trigger permission prompt on fresh session
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
denyoraskentries exist in any scope (globalsettings.json, globalsettings.local.json, projectsettings.json, projectsettings.local.json). - No
managed-settings.jsonpolicy file present on the machine. - No project-local
.mcp.jsonoverriding the server definition. - Both settings files parse as valid JSON (
json.loadsucceeds). - Workspace trust is confirmed accepted for the project:
hasTrustDialogAccepted: truein~/.claude.jsonunder the project's entry.
Steps to reproduce
- Have an MCP server (
plane) configured with several tools. - Add an exact tool name (
mcp__plane__list_work_items) to a project's.claude/settings.local.jsonunderpermissions.allow. - Confirm workspace trust is already accepted for that project (
hasTrustDialogAccepted: true). - Start a brand-new Claude Code session (
claude, not--resume/--continue) in that project directory, withdefaultMode: "plan"set globally. - Prompt Claude to call the allowlisted tool (e.g. via
/whats-nextor any flow that invokeslist_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) andmcp__<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/askoverride — 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
[]
3 Comments
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 inallow) suppresses the cards — details in https://github.com/anthropics/claude-code/issues/73587#issuecomment-4975856651.Same regression family: #73587 (desktop ignores
permissions.allowrules, Windows + macOS) and #74715 (Claude-in-Chrome "Always allow" persisted asduration:once).Reproduced on Linux, Claude Code 2.1.211, in
default/acceptEditsmode (notauto) — 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.allowin 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:No
deny/askrule for this tool anywhere (theasklist only covers the server's write tools —add_observations,create_entities, etc. — a deliberate separate rule, not this one). Nomanaged-settings.jsonpresent. NoPreToolUsehooks registered (Hooks: Found 0 total hooks in registrythroughout the session). Workspace trust already accepted.What the debug log shows at call time:
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.
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:
planein the project's.mcp.jsonexposing a toollist_work_itemswithout areadOnlyHint: trueannotation..claude/settings.local.json:``
json
``{"permissions":{"allow":["mcp__plane__list_work_items"],"defaultMode":"plan"},"enableAllProjectMcpServers":true}
claudesession in that directory and accept the workspace-trust dialog (it even listsmcp__plane__list_work_itemsas pre-approved).Observed (plan mode):
Expected (per the report): no prompt, since the exact tool name is in
permissions.allowand there is no deny/ask rule.Variations on the same build:
defaultMode: "default"-> runs silently, no prompt.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
readOnlyHintannotation) 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'sdefaultMode: "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 setreadOnlyHint: trueon read-only tools — that annotation is what plan mode keys off. Note that the Linux report in the comments (prompting indefault/acceptEditsmode) is a different cause; that one did not reproduce here and is better tracked separately.🤖 Generated with Claude Code