Feature Request: Enhance Hooks with Integrated Types (MCP Tool, Inline Script, API Call)
Title: Feature Request: Enhance Hooks with Integrated Types (MCP Tool, Inline Script, API Call)
Labels: enhancement, feature-request, hooks, developer-experience
Is your feature request related to a problem? Please describe.
The current implementation of Hooks, as detailed in the documentation, is a powerful feature for extending Claude Code's behavior. However, it is limited to a single hook type: "type": "command".
This forces all custom logic into external shell scripts. While flexible, this approach introduces several developer experience challenges:
- File Management Overhead: For simple validation or logging, developers must create, manage, and distribute separate script files alongside their
.claude/settings.json, increasing project complexity. - Boilerplate Code: Every hook script must manually handle reading JSON from
stdin, parsing it, and carefully formatting JSON output tostdoutorstderr. This is repetitive and error-prone. - Shell Scripting Complexity: Reliably handling argument parsing, string escaping, and cross-platform compatibility within shell scripts can be brittle and difficult to maintain, especially for teams working across different environments (e.g., macOS, Linux, WSL).
The current system is functional but could be significantly more ergonomic and powerful.
Describe the solution you'd like
I propose enhancing the Hooks system by introducing new, more integrated hook types directly within the .claude/settings.json configuration. This would streamline common workflows and enable more powerful integrations with less boilerplate.
Here are three suggested new types:
1. mcp_tool Hook
Directly invoke a configured Model Context Protocol (MCP) tool. The hook's input JSON would be available to populate the tool's input parameters, perhaps using a variable substitution syntax.
Example Use Case: Logging every Write operation to a custom auditing MCP server.
// in .claude/settings.json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write",
"hooks": [{
"type": "mcp_tool",
"tool": "mcp__auditor__log_write_event",
"input": {
"session_id": "${session_id}",
"file_path": "${tool_input.file_path}",
"content_length": "${#tool_input.content}"
}
}]
}
]
}
}
- Benefit: Promotes code reuse by leveraging the existing MCP ecosystem. Simplifies tasks like logging, notifications, or pre-flight checks that are already exposed as MCP tools.
2. inline_script Hook
Execute a short, self-contained script (e.g., Python, JavaScript) directly from the settings file. The hook's input JSON would be passed via stdin, just like with the command type.
Example Use Case: A simple, project-specific validation rule that blocks writing to configuration files.
// in .claude/settings.json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write",
"hooks": [{
"type": "inline_script",
"language": "python",
"script": "import json, sys; data=json.load(sys.stdin); path=data.get('tool_input',{}).get('file_path',''); exit(2) if 'prod.config' in path else exit(0)"
}]
}
]
}
}
- Benefit: Perfect for simple, project-specific logic (validation, data transformation, conditional checks) without the overhead of creating and maintaining separate script files.
3. api_call Hook
Make a direct HTTP(S) request to a webhook or API endpoint. The hook's input JSON would be sent as the request body. This could support variable expansion for secrets from the environment.
Example Use Case: Sending a notification to a Slack webhook whenever a complex Task is completed.
// in .claude/settings.json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Task",
"hooks": [{
"type": "api_call",
"url": "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX",
"method": "POST",
"headers": {
"Authorization": "Bearer ${SLACK_TOKEN}"
}
}]
}
]
}
}
- Benefit: Enables powerful, direct integrations with external services (Slack, Jira, CI/CD systems, serverless functions), turning Claude Code into a first-class event source for automated workflows.
Describe alternatives you've considered
The current alternative is to write wrapper shell scripts for all desired logic. For example, to call an MCP tool, one would write a script that parses stdin, constructs the claude mcp command-line arguments, executes it, and then formats the output. For an API call, the script would use curl or a similar utility.
While this works, it's precisely the friction and boilerplate that this feature request aims to eliminate.
Additional context
This proposal aligns with the highly agentic and extensible nature of Claude Code. By making the Hooks system more capable and easier to use, you empower developers to more deeply integrate Claude Code into their existing toolchains and workflows, transforming it from a powerful assistant into a true automation platform.
I can second this. My use case is using a jetbrains MCP to invoke IDE actions, which would save tens of thousands of tokens on
- Auto importing
- Auto fixing formatting and lint issues
- Auto running tests (with better output than what console gives)
- Auto-running and sending preview images for UI. and many more
+1 It's ridiculous hooks (nor the SDK) don't have baked-in MCP integration. It should be trivial to make MCP tool calls programmatically, particularly for hooks but really this should come standard in the developer kit.
This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.
Don't close this issue. This is an automatic message by Fresh - a bot against stale bots.
Strong +1 for the mcp_tool hook type.
My use case: I use Serena MCP for semantic code tools and project memory. Every session, I need Claude to call mcp__serena__activate_project before doing anything else.
Current workaround (doesn't work):
{ "hooks": { "SessionStart": [{ "matcher": "", "hooks": [{ "type": "command", "command": "echo '🚨 IMMEDIATELY call: mcp__serena__activate_project(project="my-project")'" }] }] } }
I've also added instructions in CLAUDE.md. But this relies on Claude's compliance with text instructions - it often responds to my message before calling the tool.
What I need:
{ "hooks": { "SessionStart": [{ "matcher": "", "hooks": [{ "type": "mcp_tool", "tool": "mcp__serena__activate_project", "input": { "project": "my-project" } }] }] } }
This would guarantee the MCP tool runs before Claude processes any user input - no more hoping Claude follows the instruction.
Other MCPs that would benefit: Any MCP requiring session initialization (memory servers, context loaders, project activators).