Skip to content

fix(claude-code): catch up to v2.1.118 (mcp_tool hook type) - #767

Merged
avifenesh merged 2 commits into
mainfrom
chore/triage-claude-code-2-1-118
Apr 23, 2026
Merged

fix(claude-code): catch up to v2.1.118 (mcp_tool hook type)#767
avifenesh merged 2 commits into
mainfrom
chore/triage-claude-code-2-1-118

Conversation

@avifenesh

Copy link
Copy Markdown
Collaborator

Summary

Triage of Claude Code v2.1.117 -> v2.1.118 (issue #764). The release added type: "mcp_tool" so hooks can invoke MCP tools directly. Without this PR, agnix would false-positive CC-HK-016 on every v2.1.118+ user that follows the release notes.

The fix

Added "mcp_tool" to BOTH allow-lists in crates/agnix-core/src/rules/hooks/helpers.rs:

  • valid_types (lines 607, 973): used by CC-HK-016 strict check
  • known_non_command (lines 532, 974): used to flag async on non-command types

Plus a regression test (test_cc_hk_016_mcp_tool_type_valid).

Doc gap caveat

As of 2026-04-23 the official docs at code.claude.com/docs/en/hooks still only list 4 types (command, prompt, agent, http). The v2.1.118 release notes explicitly add mcp_tool and are authoritative until the docs catch up. Will revisit the structural validation (required fields for the mcp_tool type, e.g., a tool reference) in a future PR once the docs document them.

Other v2.1.118 changes — NO agnix change

Change Why no impact
Vim visual mode, /cost+/stats -> /usage, custom themes, plugin themes/ directory UI/CLI; agnix's plugin.rs has no strict-fields check
DISABLE_UPDATES env var Not a config file
wslInheritsWindowsSettings policy key settings.json field; agnix doesn't validate settings.json directly
autoMode.* "$defaults" token settings.json field
claude plugin tag (CLI), OAuth/credential bug fixes Runtime

Doc bumps

  • Bumped verified_on to 2026-04-23 for all 25 CC-HK-* rules
  • Regenerated website/docs/rules/generated/*.md

Test plan

  • cargo clippy --workspace --all-targets --all-features -- -D warnings clean
  • cargo test -p agnix-core --lib: passes (+1 new regression test)
  • Pre-push hook passes
  • CI: Verify Changelog
  • CI: Tests
  • CI: claude-review

Closes #764.

Closes #764.

Triage of Claude Code v2.1.117 -> v2.1.118. The release added
`type: "mcp_tool"` so hooks can invoke MCP tools directly. Without
this fix, agnix would false-positive CC-HK-016 (unknown hook type)
on every v2.1.118+ user following the release notes.

Added `"mcp_tool"` to BOTH allow-lists in
crates/agnix-core/src/rules/hooks/helpers.rs:
  - `valid_types` (lines 607, 973): used by CC-HK-016 strict check
  - `known_non_command` (lines 532, 974): used to flag async on
    non-command hook types

Plus a regression test (`test_cc_hk_016_mcp_tool_type_valid`)
asserting `mcp_tool` doesn't trigger CC-HK-016.

Doc gap caveat: as of 2026-04-23 the docs at
code.claude.com/docs/en/hooks only list 4 types (command, prompt,
agent, http). The v2.1.118 release notes explicitly mention mcp_tool
and are authoritative until the docs catch up.

Other v2.1.118 changes need no agnix change:
  - Vim visual mode, /cost+/stats -> /usage, custom themes (UI/CLI)
  - Plugin themes/ directory: agnix's plugin.rs has no strict
    fields check, no false positive
  - DISABLE_UPDATES env var: not a config file
  - wslInheritsWindowsSettings policy key: settings.json field;
    agnix doesn't validate settings.json fields directly
  - autoMode.* '\$defaults' token: settings.json field
  - claude plugin tag (CLI), OAuth/credential bug fixes (runtime)

Documentation:
  - Bumped verified_on to 2026-04-23 for all 25 CC-HK-* rules in
    knowledge-base/rules.json + synced crates/agnix-rules/rules.json
  - Regenerated website/docs/rules/generated/*.md

Verified locally:
  - cargo clippy --workspace --all-targets --all-features -- -D warnings clean
  - cargo test -p agnix-core --lib: passes (+1 new regression test)
Copilot AI review requested due to automatic review settings April 23, 2026 09:35

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for the mcp_tool hook type in Claude Code v2.1.118, updating validation logic, regression tests, and documentation verification dates. Feedback recommends refactoring duplicated hook type arrays into shared constants to ensure a single source of truth.

Comment on lines +973 to +974
let valid_types = ["command", "prompt", "agent", "http", "mcp_tool"];
let known_non_command = ["prompt", "agent", "http", "mcp_tool"];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The valid_types and known_non_command arrays are duplicated across multiple functions in this file (lines 532, 607, 973, and 974). Following the 'Single Source of Truth' general rule, these should be refactored into shared constants (e.g., at the module level) to ensure consistency and simplify future updates when new hook types are introduced.

References
  1. Instead of merging and deduplicating data from multiple sources, refactor the code to have a single source of truth to avoid duplication in the first place.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates agnix’s Claude Code hooks validation to account for Claude Code v2.1.118 introducing a new hook type: "mcp_tool", and refreshes CC-HK rule documentation metadata.

Changes:

  • Add "mcp_tool" to hook-type allow-lists used by CC-HK-016 and async-on-non-command handling.
  • Add a regression unit test for mcp_tool not triggering CC-HK-016.
  • Bump verified_on for CC-HK-* rules and regenerate generated rule docs; update changelog.

Reviewed changes

Copilot reviewed 5 out of 30 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
crates/agnix-core/src/rules/hooks/helpers.rs Extends raw hook-type allow-lists to include mcp_tool.
crates/agnix-core/src/rules/hooks/tests.rs Adds regression test covering mcp_tool vs CC-HK-016.
knowledge-base/rules.json Bumps verified_on dates for CC-HK-* rules.
crates/agnix-rules/rules.json Mirrors verified_on bumps for CC-HK-* rules.
CHANGELOG.md Adds release catch-up note for Claude Code v2.1.118.
website/docs/rules/generated/cc-hk-001.md Regenerated doc with updated Verified On date.
website/docs/rules/generated/cc-hk-002.md Regenerated doc with updated Verified On date.
website/docs/rules/generated/cc-hk-003.md Regenerated doc with updated Verified On date.
website/docs/rules/generated/cc-hk-004.md Regenerated doc with updated Verified On date.
website/docs/rules/generated/cc-hk-005.md Regenerated doc with updated Verified On date.
website/docs/rules/generated/cc-hk-006.md Regenerated doc with updated Verified On date.
website/docs/rules/generated/cc-hk-007.md Regenerated doc with updated Verified On date.
website/docs/rules/generated/cc-hk-008.md Regenerated doc with updated Verified On date.
website/docs/rules/generated/cc-hk-009.md Regenerated doc with updated Verified On date.
website/docs/rules/generated/cc-hk-010.md Regenerated doc with updated Verified On date.
website/docs/rules/generated/cc-hk-011.md Regenerated doc with updated Verified On date.
website/docs/rules/generated/cc-hk-012.md Regenerated doc with updated Verified On date.
website/docs/rules/generated/cc-hk-013.md Regenerated doc with updated Verified On date.
website/docs/rules/generated/cc-hk-014.md Regenerated doc with updated Verified On date.
website/docs/rules/generated/cc-hk-015.md Regenerated doc with updated Verified On date.
website/docs/rules/generated/cc-hk-016.md Regenerated doc with updated Verified On date.
website/docs/rules/generated/cc-hk-017.md Regenerated doc with updated Verified On date.
website/docs/rules/generated/cc-hk-018.md Regenerated doc with updated Verified On date.
website/docs/rules/generated/cc-hk-019.md Regenerated doc with updated Verified On date.
website/docs/rules/generated/cc-hk-020.md Regenerated doc with updated Verified On date.
website/docs/rules/generated/cc-hk-021.md Regenerated doc with updated Verified On date.
website/docs/rules/generated/cc-hk-022.md Regenerated doc with updated Verified On date.
website/docs/rules/generated/cc-hk-023.md Regenerated doc with updated Verified On date.
website/docs/rules/generated/cc-hk-024.md Regenerated doc with updated Verified On date.
website/docs/rules/generated/cc-hk-025.md Regenerated doc with updated Verified On date.
Comments suppressed due to low confidence (1)

crates/agnix-core/src/rules/hooks/helpers.rs:537

  • The comment above says this rule only flags known non-command types “(prompt/agent)”, but the allow-list now includes http and mcp_tool as well. Please update the comment to match the actual behavior (or reword it to avoid enumerating types) so future changes don’t accidentally miss updating documentation around this list.
    let known_non_command = ["prompt", "agent", "http", "mcp_tool"];
    for_each_raw_hook(raw_value, |event, matcher_idx, hook_idx, hook| {
        if hook.get("async").is_some() {
            if let Some(hook_type) = hook.get("type").and_then(|t| t.as_str()) {
                // Only flag async on known non-command types.
                // Unknown/invalid types are handled by CC-HK-016.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

diagnostics: &mut Vec<Diagnostic>,
) {
let valid_types = ["command", "prompt", "agent", "http"];
let valid_types = ["command", "prompt", "agent", "http", "mcp_tool"];

Copilot AI Apr 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mcp_tool is added to the raw JSON allow-list, but typed parsing still uses schemas::hooks::Hook (internally-tagged enum) which currently only supports command|prompt|agent|http. That means configs containing {"type":"mcp_tool"...} will still fail serde_json::from_value and emit CC-HK-012, so this change likely shifts the failure from CC-HK-016 to CC-HK-012 rather than fully supporting v2.1.118. Consider adding an mcp_tool variant to Hook (with at least a tool field and a #[serde(flatten)] _extra map if you want to avoid strict-field coupling) or otherwise adjusting typed parsing to accept this new type.

Suggested change
let valid_types = ["command", "prompt", "agent", "http", "mcp_tool"];
// Keep this list aligned with the currently supported typed hook variants.
// Until `schemas::hooks::Hook` accepts `mcp_tool`, raw validation must not
// allow it here or the config will fail later during typed deserialization.
let valid_types = ["command", "prompt", "agent", "http"];

Copilot uses AI. Check for mistakes.
Comment on lines +2972 to +2977
let cc_hk_016: Vec<_> = diagnostics
.iter()
.filter(|d| d.rule == "CC-HK-016")
.collect();

assert_eq!(cc_hk_016.len(), 0, "mcp_tool should be a valid hook type (Claude Code v2.1.118+)");

Copilot AI Apr 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This regression test only asserts that CC-HK-016 doesn’t fire. Since Hook’s typed schema currently doesn’t include an mcp_tool variant, validation may still emit CC-HK-012 (schema mismatch) for the same input, and this test would pass anyway. Please strengthen the test to assert there are no diagnostics (or at least that CC-HK-012 is also absent) once mcp_tool is fully supported.

Suggested change
let cc_hk_016: Vec<_> = diagnostics
.iter()
.filter(|d| d.rule == "CC-HK-016")
.collect();
assert_eq!(cc_hk_016.len(), 0, "mcp_tool should be a valid hook type (Claude Code v2.1.118+)");
assert!(
diagnostics.is_empty(),
"mcp_tool should be fully supported and produce no diagnostics (including CC-HK-012 schema mismatch or CC-HK-016 unknown hook type), got: {:?}",
diagnostics
);

Copilot uses AI. Check for mistakes.
Comment on lines +2957 to +2958
// CC-HK-016 (unknown hook type) on every v2.1.118+ user that follows
// the docs.

Copilot AI Apr 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: the test comment says “user that follows the docs”, but the PR description notes the docs page hasn’t been updated yet and the source of truth is the v2.1.118 release notes. Consider rewording this comment to avoid confusion about which upstream reference introduced mcp_tool.

Suggested change
// CC-HK-016 (unknown hook type) on every v2.1.118+ user that follows
// the docs.
// CC-HK-016 (unknown hook type) for users on v2.1.118+ following
// the release notes that introduced `mcp_tool`.

Copilot uses AI. Check for mistakes.
@avifenesh

Copy link
Copy Markdown
Collaborator Author

Per-comment reply table for round 1

# Reviewer File Status Resolution
1 Gemini MEDIUM helpers.rs:974 (KNOWN_KEYS dedup) Won't fix (intentional pattern) Same answer as PR #757/#763: the duplicate `valid_types` arrays are local to each pass intentionally — refactoring them to a shared const would be a generic refactor of the existing project-wide pattern, out of scope for a triage PR. The per-pass arrays exist because the two passes have slightly different scopes (one for strict-fields detection, one for async-on-non-command detection — `known_non_command` is a strict subset of `valid_types` minus `"command"`). Happy to take a separate refactor PR for this.
2 Copilot helpers.rs:607 (typed Hook enum still rejects mcp_tool) CRITICAL CATCH — Fixed Right — without this fix the raw-JSON allow-list change would unblock CC-HK-016 but leave CC-HK-012 (typed-schema parse failure) firing on every `mcp_tool` hook. Added a new `Hook::McpTool` variant to the `schemas::hooks::Hook` enum (with `tool`, `if`, `timeout` fields per release notes), updated all match arms (`command()`, `prompt()`, `type_name()`, the per-variant typed-validation block in `rules/hooks/mod.rs`), and added `is_mcp_tool()` for symmetry with `is_command`/`is_prompt`/`is_agent`/`is_http`.
3 Copilot tests.rs:2977 (test was vacuous) Fixed Right — the test only checked CC-HK-016 absence, would have passed even with CC-HK-012 still firing. Strengthened to assert `diagnostics.is_empty()` (zero diagnostics of any rule). Now genuinely fails without #2's typed-enum addition.
4 Copilot tests.rs:2958 (comment about "follows the docs") Fixed Reworded comment to "follows the release notes" since the docs page hasn't been updated yet.

Plus the fmt drift CI caught (forgot `cargo fmt --all` after the round-1 test edit, same lesson as PR #758/#762). Pushing now.

…view)

Reviewer feedback (PR #767 round 1):

- Copilot CRITICAL: typed Hook enum still rejected mcp_tool, so even
  with the raw-JSON allow-list fix, CC-HK-012 (schema mismatch) would
  fire on every mcp_tool hook. Added Hook::McpTool variant with tool,
  if, timeout fields (per release notes). Updated all match arms
  (command(), prompt(), type_name(), the per-variant typed-validation
  block in rules/hooks/mod.rs); added is_mcp_tool() for symmetry.

- Copilot: test was vacuous (only checked CC-HK-016 absence; would have
  passed with CC-HK-012 still firing). Strengthened to assert
  diagnostics.is_empty() (zero diagnostics of any rule). Now genuinely
  fails without the typed-enum addition.

- Copilot: comment said 'follows the docs' but docs page hasn't been
  updated yet; reworded to 'follows the release notes' with a caveat
  about the doc gap as of 2026-04-23.

- Gemini MEDIUM: KNOWN_KEYS dedup -> won't fix (project-wide pattern,
  same answer as PR #757/#763).

Plus fmt drift caught by CI (cargo fmt forgotten after round-1 edit;
same lesson as PR #758/#762).
@avifenesh
avifenesh merged commit 1eb1991 into main Apr 23, 2026
9 checks passed
@avifenesh
avifenesh deleted the chore/triage-claude-code-2-1-118 branch April 23, 2026 10:13
@avifenesh avifenesh mentioned this pull request Apr 23, 2026
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tool release: Claude Code v2.1.118 (was v2.1.117)

2 participants