Govern GitHub MCP tool calls from the Cursor agent using Agent Control
Cursor hooks run external commands around the agent loop. This guide wires beforeMCPExecution to Agent Control’s evaluation API to govern what the Cursor agent can do through the GitHub MCP server.Cursor has a built-in MCP allowlist, but it is per-machine and per-developer; there is no central place to manage policy across an organization. Agent Control adds that central layer, giving you one place to manage rules for Cursor, your own agents, and any other Agent Control-integrated tool.By the end of this guide you will have:
A hook script that evaluates every GitHub MCP call against Agent Control before it runs
A control that blocks write operations while leaving read tools open
A working end-to-end test you can trigger with a natural language prompt in Cursor
Cursor passes the hook payload as JSON on stdin. The script maps it to a tool step and calls POST /api/v1/evaluation. Agent Control evaluates the step against the controls linked to your cursor-agent and returns is_safe. The script writes {"permission": "allow"} or {"permission": "deny"} to stdout.
Replace YOUR_GITHUB_PAT with a GitHub Personal Access Token that has repository permissions. Restart Cursor and confirm the server shows a green indicator under Settings → Tools & Integrations → MCP Tools.See the GitHub MCP installation guide for more detail.
For team or repo-specific behavior, use project hooks: <project>/.cursor/hooks.json with paths relative to the project root (e.g. .cursor/hooks/ac_evaluate.py).
The response includes the new control’s control_id. Copy it and use it in the next step.Link the control to the agent:
# Associates the control with cursor-agent so it is enforced on evaluationcurl -X POST http://localhost:8000/api/v1/agents/cursor-agent/controls/{control_id}
Creating controls and linking them to an agent requires an admin API key when authentication is enabled. Add -H "X-API-Key: your-admin-key" to the curl commands above.
Hook subprocesses inherit the environment of the Cursor app. On macOS, set these in ~/.zshenv (not ~/.zshrc) so GUI apps pick them up:
export AGENT_CONTROL_AGENT_NAME="cursor-agent"export AGENT_CONTROL_URL="http://localhost:8000"# If authentication is enabled:export AGENT_CONTROL_API_KEY="your-api-key"
Restart Cursor after updating env — hooks and environment variables are only picked up on launch.
Before restarting, make sure your Agent Control server is running. Once hooks are active, every MCP call the agent attempts will be evaluated — confirm the server is up first with curl http://localhost:8000/health.
Variable
Purpose
AGENT_CONTROL_AGENT_NAME
Must match the agent name registered above (default: cursor-agent)
Verify the plumbing first by piping a sample payload directly to the script:
# Should return {"permission": "deny", ...}echo '{"tool_name":"push_files","tool_input":"{}","serverName":"github"}' \ | python3 ~/.cursor/hooks/ac_evaluate.py# Should return {"permission": "allow"}echo '{"tool_name":"list_pull_requests","tool_input":"{}","serverName":"github"}' \ | python3 ~/.cursor/hooks/ac_evaluate.py
Then try it end-to-end in Cursor. Ask the agent something that would trigger a write operation:
“Create a pull request for these changes using the GitHub MCP.”
Agent Control will deny the create_pull_request callFor comparison, a read request like “show me the open pull requests” will call list_pull_requests and pass through without interruption.