Where does the bug appear (feature/product)?
Cursor IDE
Describe the Bug
my hook returns ALLOW for all paths (confirmed by looking at the hooks log) but i’m still being asked to approve the tool call. mcp protection is off.
Steps to Reproduce
Setup: user-level hooks at ~/.cursor/hooks.json with both preToolUse and beforeMCPExecution using the same Python script
Issue:
Hook decisions observed in logs show preToolUse=ALLOW and beforeMCPExecution=ALLOW for MCP call user-google-drive-search
Tool call still requires manual approval
Expected behavior:
MCP call executes without manual prompt when hooks return ALLOW
Actual behavior:
Tool call fails with:
User rejected MCP: user-google-drive-search - User chose to skip
or Aborted
This happens despite hooks returning ALLOW
Repro steps:
Configure hooks to return ALLOW for the call
Invoke MCP tool user-google-drive search with query “trashed = false and viewedByMe = true”
Observe approval prompt still appears and skip/abort blocks execution despite hook ALLOW
Sample config:
{
“version”: 1,
“hooks”: {
“preToolUse”: [{ “command”: “./hooks/approval-policy.py” }],
“beforeMCPExecution”: [{ “command”: “./hooks/approval-policy.py” }]
}
}
Expected Behavior
i expected the tool calls to go through, but the ui still asks me to approve it.
Operating System
MacOS
Version Information
Version: 2.6.19 (Universal)
VSCode Version: 1.105.1
Commit: 224838f96445be37e3db643a163a817c15b36060
Date: 2026-03-12T04:07:27.435Z (1 wk ago)
Build Type: Stable
Release Track: Default
Electron: 39.4.0
Chromium: 142.0.7444.265
Node.js: 22.22.0
V8: 14.2.231.22-electron.0
OS: Darwin arm64 24.6.0
Additional Information
here is the approval-policy.py file:
#!/usr/bin/env python3
import json
import sys
from typing import Any, Dict
ALLOW: Dict[str, str] = {“permission”: “allow”}
ASK: Dict[str, str] = {“permission”: “ask”}
def _handle_before_mcp_execution(payload: Dict[str, Any]) → Dict[str, Any]:
command = payload.get(“command”, “”)
if "google-drive" in command:
return ALLOW
return ASK
def _handle_pre_tool_use(payload: Dict[str, Any]) → Dict[str, Any]:
tool_name = str(payload.get(“tool_name”, “”))
tool_input = payload.get(“tool_input”) or {}
command = str(tool_input.get(“command”, “”))
if tool_name == "Shell":
# Auto-allow git commands, except anything that includes push.
if "git" in command:
if "push" in command:
return ASK
return ALLOW
return ASK
return ALLOW
def main() → int:
try:
payload = json.load(sys.stdin)
except Exception:
print(json.dumps(ASK))
return 0
event_name = str(payload.get("hook_event_name", ""))
if event_name == "beforeMCPExecution":
response = _handle_before_mcp_execution(payload)
elif event_name == "preToolUse":
response = _handle_pre_tool_use(payload)
else:
response = ALLOW
print(json.dumps(response))
return 0
if name == “main”:
raise SystemExit(main())
Does this stop you from using Cursor
Sometimes - I can sometimes use Cursor