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
- 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.json under permissions.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, with defaultMode: "plan" set globally.
- 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
Bug Description
Bug: Allowlisted MCP tool still triggers permission prompt on a fresh session
Environment
defaultMode: "plan"in global settings)Summary
An MCP tool (
mcp__plane__list_work_items, from a custom MCP server namedplane) is present verbatim in a project'spermissions.allowlist, in a workspace where trust has already been accepted, with no conflictingdeny/askrules 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.jsonadditionally has a server-level allow entry (mcp__plane__*, and previously the bare formmcp__plane— both documented as equivalent server-wide matches) plus:{ "permissions": { "defaultMode": "plan" }, "skipAutoPermissionPrompt": true }denyoraskentries exist in any scope (globalsettings.json, globalsettings.local.json, projectsettings.json, projectsettings.local.json).managed-settings.jsonpolicy file present on the machine..mcp.jsonoverriding the server definition.json.loadsucceeds).hasTrustDialogAccepted: truein~/.claude.jsonunder the project's entry.Steps to reproduce
plane) configured with several tools.mcp__plane__list_work_items) to a project's.claude/settings.local.jsonunderpermissions.allow.hasTrustDialogAccepted: true).claude, not--resume/--continue) in that project directory, withdefaultMode: "plan"set globally./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.allowand nodeny/askrule exists anywhere.Actual
Claude Code prompts:
What I ruled out before filing
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.deny/askoverride — none present in any scope.hasTrustDialogAccepted: true).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
Errors