Add MCP tool handler support to the hooks engine (#38705)

## What changed

- Discover synchronous `mcp_tool` hook handlers and invoke their configured MCP server and tool through a supplied executor.
- Expand nested hook-event placeholders in MCP tool inputs while preserving JSON types, and process tool output through the existing hook output contract.
- Represent hook details as handler-specific metadata in `hooks/list`, including MCP server and tool fields, and show those details in the TUI hooks browser.
- Skip unsupported `SessionEnd` MCP hooks and runtimes without MCP invocation support with startup warnings.

## Testing

- Cover argument expansion, missing placeholders, MCP invocation and hook decisions, discovery warnings, `hooks/list` metadata, and TUI rendering.

GitOrigin-RevId: 295b845471fe92bd7ad7cd272fbcd2c3713912e0
This commit is contained in:
Abhinav authored and copyberry committed 2026-08-15 05:53:54 +00:00
1 parent 3685a61dad
commit 85fc4def35
33 files changed
+1351 -182

No files matched your search

@@ -8100,12 +8100,89 @@
"HookHandlerType": {
"enum": [
"command",
"mcpTool",
"prompt",
"agent"
],
"type": "string"
},
"HookMetadata": {
"oneOf": [
{
"properties": {
"async": {
"default": false,
"type": "boolean"
},
"command": {
"type": "string"
},
"handlerType": {
"enum": [
"command"
],
"type": "string"
}
},
"required": [
"command",
"handlerType"
],
"type": "object"
},
{
"properties": {
"handlerType": {
"enum": [
"mcpTool"
],
"type": "string"
},
"server": {
"type": "string"
},
"tool": {
"type": "string"
}
},
"required": [
"handlerType",
"server",
"tool"
],
"type": "object"
},
{
"properties": {
"handlerType": {
"enum": [
"prompt"
],
"type": "string"
}
},
"required": [
"handlerType"
],
"title": "PromptHookMetadata",
"type": "object"
},
{
"properties": {
"handlerType": {
"enum": [
"agent"
],
"type": "string"
}
},
"required": [
"handlerType"
],
"title": "AgentHookMetadata",
"type": "object"
}
],
"properties": {
"additionalContextLimit": {
"description": "Configured `additionalContext` spill threshold. `null` uses 2,500 tokens; `0` disables spilling.",
@@ -8116,12 +8193,6 @@
"null"
]
},
"command": {
"type": [
"string",
"null"
]
},
"currentHash": {
"type": "string"
},
@@ -8135,17 +8206,6 @@
"eventName": {
"$ref": "#/definitions/HookEventName"
},
"executionMode": {
"allOf": [
{
"$ref": "#/definitions/HookExecutionMode"
}
],
"default": "sync"
},
"handlerType": {
"$ref": "#/definitions/HookHandlerType"
},
"isManaged": {
"type": "boolean"
},
@@ -8190,7 +8250,6 @@
"displayOrder",
"enabled",
"eventName",
"handlerType",
"isManaged",
"key",
"source",