[Bug] MCP tools with requiresUserInteraction not suppressing "don't ask again" option

Status Open
Reported on v2.1.241
Maintainer reply None cached
Activity 1 comment · opened Aug 23, 2026

Bug Description
Claude Code still offers "Yes, and don't ask again" for an MCP tool whose
tools/list entry sets _meta["anthropic/requiresUserInteraction"]: true.
Choosing it writes an allow rule into .claude/settings.local.json that the
tool then permanently ignores — the prompt still appears on every call.

Verified on 2.1.241 against a local Spring AI MCP server (tools/list confirmed
to emit the _meta on the tool entry).

Repro:

  1. MCP server exposes tool write with _meta["anthropic/requiresUserInteraction"]: true
  2. Call it; the dialog shows "Yes, and don't ask again for <server> — Write commands in <dir>"
  3. Select that row -> {"permissions":{"allow":["mcp__<server>__write"]}} is written
  4. Call the tool again -> still prompted (correct per docs, but the rule is now dead)

But the prompt should not include:

2. Yes, and don't ask again for mcprui — Write commands in /repo/folder   

only

1. Yes

Should be shown because the idea is that the user must answer that every time due to _meta["anthropic/requiresUserInteraction"]: true.

Expected: per the docs,

Claude Code shows that tool’s permission prompt on every call, even in acceptEdits, auto, and bypassPermissions permission modes, and _doesn’t offer a “don’t ask again” option for it._

Cause (from the 2.1.241 bundle): the meta is read as
U = M._meta?.["anthropic/requiresUserInteraction"] === true
and used for behavior: U ? "ask" : "passthrough" and suggestions: U ? [] : [...],
but checkPermissions never sets suppressAlwaysAllowRule on the returned ask result.
The row is gated on a different predicate:
!(permissionResult.behavior === "ask" && permissionResult.suppressAlwaysAllowRule === true)
&& tool.suppressesAlwaysAllowRule?.(input) !== true
For MCP tools the latter is anl(kLf(config), name) — driven by server config, not _meta.
Empty suggestions doesn't prevent persistence either, because handleUserAllow
synthesizes the whole-tool rule from the tool name.

Impact: the dead rule becomes silently live if the server ever stops sending the
_meta — a permission the user was shown as inapplicable, later granted for real.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗