From fb05c3cae6c92fc1ae0a633a57a197f4d4eff497 Mon Sep 17 00:00:00 2001 From: Dominik Simonik Date: Wed, 1 Jul 2026 15:05:31 +0200 Subject: [PATCH] fix: auto-allow Very Good CLI MCP tools in all run modes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit check-vgv-cli.sh now returns a PreToolUse "allow" decision on success, so Very Good CLI MCP tools are approved before the permission-mode check and never dead-end when they aren't on permissions.allow — including under skipAutoPermissionPrompt, where a non-allowlisted MCP tool otherwise fails closed and silently (#109). Also broaden the PreToolUse matcher to `mcp__.*very-good-cli__.*` so the guard fires for the plugin-namespaced tool name (`mcp__plugin__very-good-cli__*`) used on marketplace installs; the old `mcp__very-good-cli__.*` never matched that form. - Add allow() helper to vgv-cli-common.sh (mirrors deny()). - Keep deny-with-install-message when the CLI is missing or < 1.3.0. - Update README and CLAUDE.md hook docs. Co-Authored-By: Claude Opus 4.8 --- CLAUDE.md | 2 +- README.md | 2 +- hooks/hooks.json | 2 +- hooks/scripts/check-vgv-cli.sh | 12 ++++++++---- hooks/scripts/vgv-cli-common.sh | 17 +++++++++++++++++ 5 files changed, 28 insertions(+), 7 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index e9ba6f6..0328b54 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -113,7 +113,7 @@ These run **when a session begins**: These run **before** a tool call is executed: -- `mcp__very-good-cli__.*` matcher → `check-vgv-cli.sh` — validates that the Very Good CLI is installed and at version >= 1.3.0; exits 2 on failure (blocking) +- `mcp__.*very-good-cli__.*` matcher → `check-vgv-cli.sh` — auto-approves the Very Good CLI MCP tool call by returning a PreToolUse `allow` decision, so it is always permitted regardless of run mode (interactive, headless, or `skipAutoPermissionPrompt`) and never dead-ends when the tool isn't on `permissions.allow`; denies with an install/upgrade message if the CLI is missing or < 1.3.0. The `.*` in the matcher covers both the bare `mcp__very-good-cli__*` server (repo-root `.mcp.json`) and the plugin-namespaced `mcp__plugin__very-good-cli__*` form used when installed from a marketplace - `Bash` matcher → `block-cli-workarounds.sh` — prevents direct CLI bypass of VGV CLI commands through the Bash tool; exits 2 on failure (blocking) Both PreToolUse scripts share common utilities from `vgv-cli-common.sh`. diff --git a/README.md b/README.md index 8d143af..c090bcc 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ This plugin includes SessionStart, PreToolUse, and PostToolUse hooks that valida | Hook | Trigger | Behavior | | ---- | ------- | -------- | | **Warn Missing MCP** (`warn-missing-mcp.sh`) | SessionStart | Warns if the Very Good CLI is missing or older than 1.3.0; non-blocking | -| **Check VGV CLI** (`check-vgv-cli.sh`) | PreToolUse (`mcp__very-good-cli__.*`) | Validates the Very Good CLI is installed and ≥ 1.3.0; exits 2 on failure (blocking) | +| **Check VGV CLI** (`check-vgv-cli.sh`) | PreToolUse (`mcp__.*very-good-cli__.*`) | Auto-approves Very Good CLI MCP tool calls in every run mode via a PreToolUse `allow` decision, so they never dead-end when the tool isn't on `permissions.allow` (including under `skipAutoPermissionPrompt`); denies with an install/upgrade message if the CLI is missing or < 1.3.0 | | **Block CLI Workarounds** (`block-cli-workarounds.sh`) | PreToolUse (`Bash`) | Blocks direct CLI bypass of Very Good CLI commands through the Bash tool; exits 2 on failure (blocking) | | **Analyze** (`analyze.sh`) | PostToolUse (`Edit`/`Write`) | Runs `dart analyze` on the modified `.dart` file; exits 2 on failure (blocking — Claude must fix issues before continuing) | | **Format** (`format.sh`) | PostToolUse (`Edit`/`Write`) | Runs `dart format` on the modified `.dart` file; always exits 0 (non-blocking — formatting is applied silently) | diff --git a/hooks/hooks.json b/hooks/hooks.json index f006bdc..c97b65b 100644 --- a/hooks/hooks.json +++ b/hooks/hooks.json @@ -14,7 +14,7 @@ ], "PreToolUse": [ { - "matcher": "mcp__very-good-cli__.*", + "matcher": "mcp__.*very-good-cli__.*", "hooks": [ { "type": "command", diff --git a/hooks/scripts/check-vgv-cli.sh b/hooks/scripts/check-vgv-cli.sh index 1c016cf..979665d 100644 --- a/hooks/scripts/check-vgv-cli.sh +++ b/hooks/scripts/check-vgv-cli.sh @@ -1,6 +1,8 @@ #!/bin/bash -# PreToolUse hook: verify very_good_cli is installed before -# allowing Very Good CLI MCP tool calls. +# PreToolUse hook: gate Very Good CLI MCP tool calls. +# When the CLI is installed and new enough, auto-approve the call so it is +# always allowed regardless of run mode; otherwise deny with an install/ +# upgrade message instead of letting the call fail silently. if ! command -v jq &>/dev/null; then echo "jq is required for check-vgv-cli hook but not found" >&2 @@ -21,5 +23,7 @@ case "$cli_status" in ;; esac -# Version OK -exit 0 +# Version OK — auto-approve so the Very Good CLI MCP tool is always allowed, +# even under skipAutoPermissionPrompt where a non-allowlisted tool would +# otherwise fail closed and silently. +allow "Very Good CLI >= ${MIN_VERSION} verified; auto-approving Very Good CLI MCP tool call." diff --git a/hooks/scripts/vgv-cli-common.sh b/hooks/scripts/vgv-cli-common.sh index c894c7c..0c3d1fd 100755 --- a/hooks/scripts/vgv-cli-common.sh +++ b/hooks/scripts/vgv-cli-common.sh @@ -19,6 +19,23 @@ deny() { exit 0 } +# Auto-approve the tool call, skipping the interactive permission prompt. +# A PreToolUse "allow" fires before the permission-mode check, so the call +# proceeds in every run mode (interactive, headless, skipAutoPermissionPrompt). +# Explicit deny/ask rules and managed deny lists still take precedence. +allow() { + jq -n \ + --arg reason "$1" \ + '{ + hookSpecificOutput: { + hookEventName: "PreToolUse", + permissionDecision: "allow", + permissionDecisionReason: $reason + } + }' + exit 0 +} + # Check Very Good CLI availability and version. # Returns: "ok", "not_installed", or "outdated:" check_vgv_cli() {