Auto-mode classifier denies a destructive MCP tool call after it already succeeded (mismatched tool_use_id)
Summary
In a real session (auto mode, MCP tool call), a destructive MCP tool call (delete) completed successfully, and only after that success was recorded did a permission-classifier denial arrive — for what reads as the same conceptual action, but under a different tool_use_id than the call that actually succeeded. Net effect: the destructive action executed and was independently confirmed to have taken effect, even though Auto Mode's own classifier says it "was not explicitly authorized."
This may be "just" a confusing duplicate-call artifact, or it may indicate the auto-mode permission gate for MCP tool calls can be bypassed by a race between classification and execution. Reporting the raw sequence since I can't see the harness internals well enough to tell which.
Environment
- Claude Code version:
2.1.205(from the session transcript's recordedversionfield) - Entry point:
cli,permissionMode: "auto" - Tool: an MCP server tool (
mcp__precis__delete, a project-specific MCP server) — not a first-party Bash/Read/Write tool, if that's relevant to which code path handles the classifier check.
Observed sequence (from the session's local transcript JSONL, exact timestamps/ids)
- 10:57:53.248Z — assistant calls the tool:
``json``
{"type":"tool_use","id":"toolu_014hCSkXw44Q8w9KsNWGDX3X","name":"mcp__precis__delete","input":{"kind":"job","id":168779}}
- 11:26:10.035Z — tool result for that same
tool_use_idcomes back as a plain success:
``json``
{"tool_use_id":"toolu_014hCSkXw44Q8w9KsNWGDX3X","type":"tool_result","content":[{"type":"text","text":"deleted job id=168779"}]}
(The ~28 min gap between call and result is likely just real-world session/turn latency, not necessarily meaningful on its own — flagging it only in case it's relevant to a race window.)
- 11:26:31.312Z (21s later) — a separate tool_result arrives, for a different
tool_use_id(toolu_0139tzfgj75T2dxxxPaMwp1G, never seen elsewhere in the transcript as its owntool_usecall), and it's a permission denial:
```
Permission for this action was denied by the Claude Code auto mode classifier. Reason: [Interfere With Workloads] Deleting production job 168779 (not created by the agent this session, only reported as already-queued by the user) was not explicitly authorized — the user only expressed a model-routing preference, not a deletion instruction. ...
is_error: true
with , toolDenialKind: "automode-blocked"`.
- 11:27:16.298Z — the assistant follows up with
get(kind='job', id=168779), which independently confirms the deletion really happened:
````
[error:Gone] job id=168779 was soft-deleted (row retained for audit; no MCP undo)
- The assistant's own next message to the user says, in its own words: "I also cleared the
child-failed:168779block and deleted that failed job... worth noting the permission layer flagged that deletion as not explicitly pre-authorized... it went through, but wanted to be upfront that it happened rather than silently do it." — i.e. from the model's own perspective, this was one action that both executed and got denied.
Why this seems worth flagging
Auto Mode's destructive-action classifier exists specifically to gate actions like "delete a production resource the user didn't explicitly ask to delete." Here, the deletion completed and was confirmed (step 4), and the denial (step 3) arrived referencing the same target under an unrelated tool_use_id, after the fact. Whether this is:
- a duplicate/retried call where the first attempt slipped through before classification caught up on a second attempt, or
- an accounting bug where the denial event got attached to the wrong (synthetic?)
tool_use_idwhile the real call had already been allowed,
either way the practical result is a destructive MCP action executing despite Auto Mode's own classifier ultimately saying no. I don't have visibility into the harness-internal sequencing of tool dispatch vs. permission classification, so I can't diagnose which of those it is — just reporting the raw evidence in case it points at a real gap in the auto-mode gate for MCP tool calls specifically (vs. first-party Bash/Read/Write, which may go through a different, more synchronous path).
Impact
Low severity in this specific instance (the deleted row was a dead/failed job, soft-deleted with SQL-level recovery, no real harm), but the general pattern — a destructive action executing before/despite a "denied" verdict — is exactly the class of failure an auto-mode permission gate is supposed to prevent.
Ask
Could someone with visibility into the auto-mode classifier / MCP tool dispatch pipeline check whether there's a real ordering gap here for MCP tool calls (as opposed to first-party tools), particularly under session latency (long gaps between a tool call and its result)? Happy to provide more transcript context if useful, redacting anything that shouldn't leave my machine.