PreToolUse hook not enforced for MCP tool calls (mutating query bypasses "ask" permission)
Bug
PreToolUse hook (matcher mcp__.*) that returns permissionDecision:"ask" is
correctly triggered when the hook script is tested directly via stdin, but is
NOT enforced when the actual MCP tool call happens — the mutating call runs
through with no permission prompt at all.
Comparable Bash-tool hook (same repo, PreToolUse matcher on Bash) works
correctly and blocks as expected — only MCP tool calls are affected.
Repro
- Configure a PreToolUse hook in
.claude/settings.jsonwith matcher
mcp__.* (or a specific MCP server pattern) that returns
{"permissionDecision":"ask"} for mutating calls.
- Call an MCP tool directly that the matcher covers (e.g. Supabase
execute_sql with an UPDATE query).
- Expected: permission prompt appears before the call executes.
- Actual: no prompt — the call runs immediately.
Isolation
- Ran the hook script directly via stdin with the exact payload the MCP call
would send (tool_name/tool_input matching the real call) — hook script
returns the correct ask decision 100% of the time.
- Regex matcher tested standalone — matches the MCP tool name correctly.
- Confirmed not a pre-allow/settings.local.json cache issue — retested in a
fresh session with no pre-allow entries present, bug still reproduces.
- Conclusion: the harness either does not invoke the hook for MCP tool calls,
or invokes it but ignores the returned decision for this tool type.
Impact
A hook written specifically to gate dangerous MCP calls (DB mutations,
production secret rotation, etc.) provides no actual protection — silently.
Environment
Claude Code CLI, Windows 11 (win32), MCP server: Supabase
(mcp__claude_ai_Supabase__execute_sql tested specifically)
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗