diff --git a/hooks/hooks.json b/hooks/hooks.json index 8ec470673..ea3960496 100644 --- a/hooks/hooks.json +++ b/hooks/hooks.json @@ -70,7 +70,7 @@ ] }, { - "matcher": ".*", + "matcher": "^mcp__", "hooks": [ { "type": "command", @@ -145,7 +145,7 @@ ], "PostToolUseFailure": [ { - "matcher": ".*", + "matcher": "^mcp__", "hooks": [ { "type": "command", diff --git a/hooks/hooks.metadata.json b/hooks/hooks.metadata.json index 1c3a54c8a..c5986e44c 100644 --- a/hooks/hooks.metadata.json +++ b/hooks/hooks.metadata.json @@ -40,7 +40,7 @@ { "id": "pre:mcp-health-check", "description": "Check MCP server health before MCP tool execution and block unhealthy MCP calls", - "fingerprint": "922686364d01" + "fingerprint": "a68881c27a83" }, { "id": "pre:edit-write:gateguard-fact-force", @@ -83,7 +83,7 @@ { "id": "post:mcp-health-check", "description": "Track failed MCP tool calls, mark unhealthy servers, and attempt reconnect", - "fingerprint": "9e25549c1229" + "fingerprint": "edbf5346288f" }, { "id": "post:skill:track", diff --git a/tests/hooks/hooks.test.js b/tests/hooks/hooks.test.js index e9ca3ebfa..a1e53d737 100644 --- a/tests/hooks/hooks.test.js +++ b/tests/hooks/hooks.test.js @@ -2748,6 +2748,31 @@ async function runTests() { passed++; else failed++; + if ( + test('MCP health-check hooks use anchored ^mcp__ matcher (no wildcard spawns)', () => { + const hooksPath = path.join(__dirname, '..', '..', 'hooks', 'hooks.json'); + const hooks = readHooksConfig(hooksPath); + + const preMcp = hooks.hooks.PreToolUse.filter(entry => JSON.stringify(entry).includes('pre:mcp-health-check')); + assert.strictEqual(preMcp.length, 1, 'Should define exactly one PreToolUse mcp-health-check entry'); + assert.strictEqual( + preMcp[0].matcher, + '^mcp__', + `PreToolUse mcp-health-check matcher must be anchored '^mcp__' so it only spawns on genuine MCP tool names (got ${preMcp[0].matcher})` + ); + + const postMcp = hooks.hooks.PostToolUseFailure.filter(entry => JSON.stringify(entry).includes('post:mcp-health-check')); + assert.strictEqual(postMcp.length, 1, 'Should define exactly one PostToolUseFailure mcp-health-check entry'); + assert.strictEqual( + postMcp[0].matcher, + '^mcp__', + `PostToolUseFailure mcp-health-check matcher must be anchored '^mcp__' so it only spawns on genuine MCP tool failures (got ${postMcp[0].matcher})` + ); + }) + ) + passed++; + else failed++; + if ( test('hooks.json gives PowerShell dedicated GateGuard and governance routes', () => { const hooksPath = path.join(__dirname, '..', '..', 'hooks', 'hooks.json');