Appearance
Hooks with MCP Tools
Claude Code hooks work seamlessly with Model Context Protocol (MCP) tools. When MCP servers provide tools, they appear with a special naming pattern.
MCP Tool Naming
MCP tools follow the pattern mcp__{server}__{tool}:
mcp__memory__create_entities— Memory server's create entities toolmcp__filesystem__read_file— Filesystem server's read file toolmcp__github__search_repositories— GitHub server's search toolmcp__playwright__screenshot— Playwright server's screenshot tool
Targeting MCP Tools in Hooks
You can target specific MCP tools or entire MCP servers:
json
{
"hooks": {
"PreToolUse": [
{
"matcher": "mcp__memory__.*",
"hooks": [
{
"type": "command",
"command": "echo 'Memory operation initiated' >> ~/mcp-operations.log"
}
]
},
{
"matcher": "mcp__.*__write.*",
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/validate-mcp-write.py"
}
]
}
]
}
}Log All MCP Calls
Track which MCP tools are being used:
python
#!/usr/bin/env python3
import json
import sys
from datetime import datetime
try:
data = json.load(sys.stdin)
except:
sys.exit(0)
tool_name = data.get("tool_name", "")
# Only log MCP tools
if not tool_name.startswith("mcp__"):
sys.exit(0)
timestamp = datetime.utcnow().isoformat()
log_line = f"{timestamp} MCP: {tool_name}\n"
try:
with open("/tmp/mcp-usage.log", "a") as f:
f.write(log_line)
except:
pass
sys.exit(0)Validate Playwright Operations
The adw_review.py phase uses Playwright MCP for screenshots. Add validation:
json
{
"hooks": {
"PreToolUse": [
{
"matcher": "mcp__playwright__.*",
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/validate-playwright.sh",
"timeout": 30
}
]
}
]
}
}Block Specific MCP Servers
If you want to prevent Claude from using a particular MCP server:
python
#!/usr/bin/env python3
import json
import sys
try:
data = json.load(sys.stdin)
except:
sys.exit(0)
tool_name = data.get("tool_name", "")
# Block filesystem MCP server except for reads
if tool_name.startswith("mcp__filesystem__") and "read" not in tool_name:
output = {
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "Filesystem MCP server is restricted to read operations in this project."
}
}
print(json.dumps(output))
sys.exit(0)
sys.exit(0)Debugging MCP Hook Issues
If your MCP tool hooks aren't firing:
- Check the tool name pattern:
claude --debugshows exact tool names - MCP tool names are case-sensitive and include double underscores
- Use
"matcher": "mcp__.*"to catch all MCP tools and log them first - Verify the MCP server is registered in your
settings.jsonor~/.claude/settings.json