Skip to content

Refactor Kubernetes Remediation MCP: approval-based tool separation - #2148

Merged
arikalon1 merged 11 commits into
masterfrom
claude/k8s-remediation-mcp-BTz5W
Jun 24, 2026
Merged

arikalon1 merged 11 commits into
masterfrom
claude/k8s-remediation-mcp-BTz5W

Conversation

@aantn

@aantn aantn commented Jun 7, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Replaces the legacy restricted_tools mechanism with a cleaner approval-based model for the Kubernetes Remediation MCP server. Tools are now categorized as either auto-approved (read-only diagnostics) or approval-gated (mutations), eliminating the need for dual-layer authorization and making approval intent explicit in the toolset configuration.

Key Changes

Core Tool Framework (holmes/core/tools.py)

  • Removed Tool.restricted field and _is_restricted() method
  • Removed Toolset.restricted_tools list field
  • Added backwards-compatibility validator to warn on deprecated restricted_tools config and silently ignore it
  • Approval logic now relies solely on approval_required_tools patterns

Tool Execution (holmes/core/tool_calling_llm.py, holmes/core/tools_utils/tool_executor.py)

  • Removed _skill_in_use transient state tracking (no longer needed)
  • Removed _should_include_restricted_tools() and include_restricted parameter
  • Removed skill authorization filtering from get_all_tools_openai_format()
  • Simplified reset_interaction_state() to a no-op hook

Kubernetes Remediation MCP Documentation & Helm

  • Updated docs/data-sources/builtin-toolsets/kubernetes-remediation-mcp.md:

    • Clarified tool separation: four auto-approved read-only tools + one approval-gated mutation fallback
    • Added tool reference table with approval status and descriptions
    • Emphasized "prefer no-approval tools" guidance
    • Removed references to restricted_tools and dual-layer authorization
  • Helm values (helm/holmes/values.yaml):

    • Removed restrictedTools configuration
    • Updated approvalRequiredTools to only list ["run_kubectl_command"]
    • Added new config keys: preapprovedCommands, diagnosticImages, fileReadAllowedPaths, fileReadDeniedPaths, allowArbitraryKubectlCommands
    • Changed default clusterRole from "cluster-admin" to "" (chart creates scoped role)
    • Enabled networkPolicy by default
    • Updated image to 1.1.0
  • New Helm template helm/holmes/templates/mcp-servers/kubernetes-remediation/rbac.yaml:

    • Scoped, least-privilege ClusterRole (no cluster-admin, no secrets access)
    • Grants only necessary verbs for remediation: scale, rollout, drain, cordon, patch, delete, exec, eviction
    • Conditionally created when serviceAccount.clusterRole is empty
  • Updated Helm deployment (helm/holmes/templates/mcp-servers/kubernetes-remediation/deployment.yaml):

    • Wired new environment variables for policy configuration
    • Removed KUBECTL_ALLOWED_IMAGES (replaced by KUBECTL_DIAGNOSTIC_IMAGES)
    • Updated ClusterRoleBinding to use scoped role instead of cluster-admin
  • Updated LLM instructions (helm/holmes/templates/mcp-servers/kubernetes-remediation/_helpers.tpl):

    • Reframed as "diagnose AND act" rather than just remediation
    • Emphasized tool separation and approval model
    • Provided clear guidance on when to use each tool

CLI Documentation

  • Updated docs/data-sources/builtin-toolsets/kubernetes-remediation-mcp.md with:
    • Scoped RBAC example (no cluster-admin)
    • New environment variables for policy configuration
    • Simplified configuration guidance for both CLI and Helm deployments

Tests

  • Added tests/test_approval_required_tools.py: Validates approval-based tool separation model
    • Tests that approval-gated tools require approval
    • Tests that read-only tools auto-approve
    • Tests backwards compatibility with deprecated restricted_tools config

https://claude.ai/code/session_01FoqM3sjnrRgPjdqYdqutzK

Summary by CodeRabbit

  • New Features

    • Image bumped to 1.1.0; new config keys: preapproved commands, diagnostic images, file-read allow/deny paths, allow-arbitrary-kubectl toggle.
  • Security Improvements

    • Ingress-only NetworkPolicy scoped to the release namespace; chart emits a scoped, least-privilege ClusterRole by default; approval model now splits auto-approved read/diagnostic tools from approval-required mutating kubectl.
  • Documentation

    • Revamped MCP guide with policy/control tables, configuration reference, and clearer approval guidance.
  • Tests

    • Added tests covering approval gating and Helm chart wiring.

claude added 2 commits June 5, 2026 13:38
Approval is now purely tool-name based via approval_required_tools. The legacy
restricted_tools / skill-gating coupling (skills unlocking restricted tools) is
removed entirely — it is no longer needed.

Core:
- tools.py: drop Tool.restricted, Tool._is_restricted(), and the
  restricted_tools fields on Toolset and ToolsetYamlFromConfig. The
  approval_required_tools / _check_approval_config / requires_approval path is
  kept as-is (this is what gates run_kubectl_command).
- tool_calling_llm.py: drop _skill_in_use and _should_include_restricted_tools;
  stop passing include_restricted. Skill fetching itself is untouched.
- tool_executor.py / frontend_tools.py: drop the include_restricted param/filter
  and the _is_restricted override.

Helm (mcpAddons.kubernetesRemediation):
- values: drop restrictedTools; approvalRequiredTools -> ["run_kubectl_command"];
  clusterRole "" (chart creates a scoped role); networkPolicy on by default;
  image 1.1.0; new config keys (preapproved commands, diagnostic images,
  file-read paths, allowArbitraryKubectlCommands).
- new rbac.yaml: scoped least-privilege ClusterRole (no cluster-admin, no
  secret access), gated on serviceAccount.create and empty clusterRole.
- deployment: wire the new env vars; binding no longer defaults to cluster-admin.
- networkpolicy: ingress-only, scoped to Holmes pods in the release namespace.
- _helpers.tpl: rewrite llm_instructions around the auto-approved vs
  approval-gated tool split.
- toolset-config: emit approval_required_tools instead of restricted_tools.

Docs: rewrite kubernetes-remediation-mcp.md (5-tool table with approval column,
scoped RBAC sample, plug-and-play defaults, CLI config without restricted_tools).

Tests: tool-name approval gating, and a helm values/template regression check.
Signed-off-by: Claude <noreply@anthropic.com>
Backwards compatibility: old configs carrying the removed restricted_tools
key now load with a deprecation warning instead of silently dropping it,
guiding users to approval_required_tools.

Signed-off-by: Claude <noreply@anthropic.com>

@claude claude 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.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

@github-actions

github-actions Bot commented Jun 7, 2026 •

Copy link
Copy Markdown
Contributor

📂 Previous Runs

⚠️ 1 older run truncated

Older runs were omitted to stay under GitHub's 64KB comment size limit.


✅ Results of HolmesGPT evals

Automatically triggered by commit 7c7c35c on branch claude/k8s-remediation-mcp-BTz5W

View workflow logs

Results of HolmesGPT evals

  • ask_holmes: 14/14 test cases were successful, 0 regressions
Status Test case Time Turns Tools Cost Total tokens Input Max input Output Max output Cached Non-cached Reasoning Compactions Denied commands Src
✅ 09_crashpod 26.2s 4 8 $0.2108 70,075 68,386 19,583 1,689 739 48,230 20,156 125 — — src
✅ 101_loki_historical_logs_pod_deleted 38.5s 4 8 $0.2275 69,722 67,284 19,358 2,438 867 47,637 19,647 430 — — src
✅ 112_find_pvcs_by_uuid 14.4s 2 2 $0.1563 33,188 32,266 17,944 922 480 14,319 17,947 294 — — src
✅ 12_job_crashing 34.1s 5 10 $0.2488 95,048 93,219 21,345 1,829 539 69,397 23,822 172 — — src
✅ 176_network_policy_blocking_traffic_no_skills 31.5s 4 10 $0.2268 71,162 69,319 20,595 1,843 587 47,164 22,155 369 — — src
✅ 227_count_configmaps_per_namespace[0] 14.6s 3 6 $0.1488 46,361 45,651 16,667 710 437 28,980 16,671 29 — — src
✅ 243_pod_names_contain_service 29.8s 3 7 $0.1912 49,606 47,802 18,079 1,804 677 29,445 18,357 301 — — src
✅ 24_misconfigured_pvc 29.2s 5 11 $0.2191 86,578 84,848 19,114 1,730 412 64,925 19,923 42 — — src
✅ 254_elasticsearch_dr_test_log_check 48.0s 7 11 $0.2580 96,445 93,206 18,428 3,239 842 74,134 19,072 130 — — src
✅ 259_wrong_cluster_logs_confusion 62.9s 7 12 $0.2969 103,554 99,267 18,652 4,287 1,592 79,319 19,948 683 — — src
✅ 260_global_es_remote_cluster_logs 53.8s 5 9 $0.2480 74,722 71,253 17,561 3,469 820 53,218 18,035 630 — — src
✅ 43_current_datetime_from_prompt 3.8s 1 — $0.1017 14,428 14,306 14,306 122 122 0 14,306 78 — — src
✅ 51_logs_summarize_errors 17.7s 3 2 $0.1546 46,888 46,151 17,219 737 360 28,928 17,223 33 — — src
✅ 61_exact_match_counting 7.4s 2 1 $0.1146 29,148 28,927 14,641 221 152 14,283 14,644 34 — — src
Total 29.4s avg 3.9 avg 7.5 avg $2.8032 886,925 861,885 21,345 25,040 1,592 599,979 261,906 3,350 — —
Benchmark Comparison Details

Master baseline: latest master-* experiment (post-merge regression eval)
Status: 14 test/model combinations loaded

Benchmark baseline: latest ci-benchmark experiment on master
Status: 17 test/model combinations loaded

Time comparison (seconds):

Test case This branch master (2h ago) Δ vs master benchmark (3h ago) Δ vs benchmark
09_crashpod (opus-4.6) 📄 26.2s 21.9s ↑19% — —
101_loki_historical_logs_pod_deleted (opus-4.6) 📄 38.5s 47.4s ↓19% — —
112_find_pvcs_by_uuid (opus-4.6) 📄 14.4s 14.1s ±0% — —
12_job_crashing (opus-4.6) 📄 34.1s 28.3s ↑20% — —
176_network_policy_blocking_traffic_no_skills (opus-4.6) 📄 31.5s 31.1s ±0% — —
227_count_configmaps_per_namespace[0] (opus-4.6) 📄 14.6s 14.4s ±0% — —
243_pod_names_contain_service (opus-4.6) 📄 29.8s 28.7s ±0% — —
24_misconfigured_pvc (opus-4.6) 📄 29.2s 28.0s ±0% — —
254_elasticsearch_dr_test_log_check (opus-4.6) 📄 48.0s 54.1s ↓11% — —
259_wrong_cluster_logs_confusion (opus-4.6) 📄 62.9s 63.4s ±0% — —
260_global_es_remote_cluster_logs (opus-4.6) 📄 53.8s 65.1s ↓17% — —
43_current_datetime_from_prompt (opus-4.6) 📄 3.8s 3.9s ±0% — —
51_logs_summarize_errors (opus-4.6) 📄 17.7s 17.1s ±0% — —
61_exact_match_counting (opus-4.6) 📄 7.4s 7.1s ±0% — —
Total (all, n=14) 29.4s 30.3s — — —
Comparable (m=14, b=0) 29.4s 30.3s ±0% — —

Cost comparison:

Test case This branch master (2h ago) Δ vs master benchmark (3h ago) Δ vs benchmark
09_crashpod (opus-4.6) 📄 $0.2108 $0.1800 ↑17% — —
101_loki_historical_logs_pod_deleted (opus-4.6) 📄 $0.2275 $0.2682 ↓15% — —
112_find_pvcs_by_uuid (opus-4.6) 📄 $0.1563 $0.1567 ±0% — —
12_job_crashing (opus-4.6) 📄 $0.2488 $0.2165 ↑15% — —
176_network_policy_blocking_traffic_no_skills (opus-4.6) 📄 $0.2268 $0.2276 ±0% — —
227_count_configmaps_per_namespace[0] (opus-4.6) 📄 $0.1488 $0.1492 ±0% — —
243_pod_names_contain_service (opus-4.6) 📄 $0.1912 $0.1916 ±0% — —
24_misconfigured_pvc (opus-4.6) 📄 $0.2191 $0.2136 ±0% — —
254_elasticsearch_dr_test_log_check (opus-4.6) 📄 $0.2580 $0.2668 ±0% — —
259_wrong_cluster_logs_confusion (opus-4.6) 📄 $0.2969 $0.2996 ±0% — —
260_global_es_remote_cluster_logs (opus-4.6) 📄 $0.2480 $0.3025 ↓18% — —
43_current_datetime_from_prompt (opus-4.6) 📄 $0.1017 $0.1017 ±0% — —
51_logs_summarize_errors (opus-4.6) 📄 $0.1546 $0.1546 ±0% — —
61_exact_match_counting (opus-4.6) 📄 $0.1146 $0.1148 ±0% — —
Total (all, n=14) $0.2002 $0.2031 — — —
Comparable (m=14, b=0) $0.2002 $0.2031 ±0% — —

Total tokens comparison:

Test case This branch master (2h ago) Δ vs master benchmark (3h ago) Δ vs benchmark
09_crashpod (opus-4.6) 📄 70,075 49,629 ↑41% — —
101_loki_historical_logs_pod_deleted (opus-4.6) 📄 69,722 91,718 ↓24% — —
112_find_pvcs_by_uuid (opus-4.6) 📄 33,188 33,198 ±0% — —
12_job_crashing (opus-4.6) 📄 95,048 71,809 ↑32% — —
176_network_policy_blocking_traffic_no_skills (opus-4.6) 📄 71,162 73,590 ±0% — —
227_count_configmaps_per_namespace[0] (opus-4.6) 📄 46,361 46,352 ±0% — —
243_pod_names_contain_service (opus-4.6) 📄 49,606 50,018 ±0% — —
24_misconfigured_pvc (opus-4.6) 📄 86,578 85,995 ±0% — —
254_elasticsearch_dr_test_log_check (opus-4.6) 📄 96,445 119,075 ↓19% — —
259_wrong_cluster_logs_confusion (opus-4.6) 📄 103,554 104,919 ±0% — —
260_global_es_remote_cluster_logs (opus-4.6) 📄 74,722 139,543 ↓46% — —
43_current_datetime_from_prompt (opus-4.6) 📄 14,428 14,429 ±0% — —
51_logs_summarize_errors (opus-4.6) 📄 46,888 46,815 ±0% — —
61_exact_match_counting (opus-4.6) 📄 29,148 29,162 ±0% — —
Total (all, n=14) 63,352 68,304 — — —
Comparable (m=14, b=0) 63,352 68,304 ±0% — —

Cached tokens comparison:

Test case This branch master (2h ago) Δ vs master benchmark (3h ago) Δ vs benchmark
09_crashpod (opus-4.6) 📄 48,230 29,359 ↑64% — —
101_loki_historical_logs_pod_deleted (opus-4.6) 📄 47,637 66,827 ↓29% — —
112_find_pvcs_by_uuid (opus-4.6) 📄 14,319 14,319 ±0% — —
12_job_crashing (opus-4.6) 📄 69,397 48,821 ↑42% — —
176_network_policy_blocking_traffic_no_skills (opus-4.6) 📄 47,164 50,301 ±0% — —
227_count_configmaps_per_namespace[0] (opus-4.6) 📄 28,980 28,979 ±0% — —
243_pod_names_contain_service (opus-4.6) 📄 29,445 29,440 ±0% — —
24_misconfigured_pvc (opus-4.6) 📄 64,925 64,473 ±0% — —
254_elasticsearch_dr_test_log_check (opus-4.6) 📄 74,134 97,757 ↓24% — —
259_wrong_cluster_logs_confusion (opus-4.6) 📄 79,319 81,004 ±0% — —
260_global_es_remote_cluster_logs (opus-4.6) 📄 53,218 116,916 ↓54% — —
43_current_datetime_from_prompt (opus-4.6) 📄 — — — — —
51_logs_summarize_errors (opus-4.6) 📄 28,928 28,928 ±0% — —
61_exact_match_counting (opus-4.6) 📄 14,283 14,283 ±0% — —
Total (all, n=14) 42,856 47,958 — — —
Comparable (m=13, b=0) 46,152 51,647 ↓11% — —

Turns comparison:

Test case This branch master (2h ago) Δ vs master benchmark (3h ago) Δ vs benchmark
09_crashpod (opus-4.6) 📄 4 3 ↑33% — —
101_loki_historical_logs_pod_deleted (opus-4.6) 📄 4 5 ↓20% — —
112_find_pvcs_by_uuid (opus-4.6) 📄 2 2 ±0% — —
12_job_crashing (opus-4.6) 📄 5 4 ↑25% — —
176_network_policy_blocking_traffic_no_skills (opus-4.6) 📄 4 4 ±0% — —
227_count_configmaps_per_namespace[0] (opus-4.6) 📄 3 3 ±0% — —
243_pod_names_contain_service (opus-4.6) 📄 3 3 ±0% — —
24_misconfigured_pvc (opus-4.6) 📄 5 5 ±0% — —
254_elasticsearch_dr_test_log_check (opus-4.6) 📄 7 9 ↓22% — —
259_wrong_cluster_logs_confusion (opus-4.6) 📄 7 7 ±0% — —
260_global_es_remote_cluster_logs (opus-4.6) 📄 5 10 ↓50% — —
43_current_datetime_from_prompt (opus-4.6) 📄 1 1 ±0% — —
51_logs_summarize_errors (opus-4.6) 📄 3 3 ±0% — —
61_exact_match_counting (opus-4.6) 📄 2 2 ±0% — —
Total (all, n=14) 3.9 4.4 — — —
Comparable (m=14, b=0) 3.9 4.4 ±0% — —

Tool calls comparison:

Test case This branch master (2h ago) Δ vs master benchmark (3h ago) Δ vs benchmark
09_crashpod (opus-4.6) 📄 8 6 ↑33% — —
101_loki_historical_logs_pod_deleted (opus-4.6) 📄 8 10 ↓20% — —
112_find_pvcs_by_uuid (opus-4.6) 📄 2 2 ±0% — —
12_job_crashing (opus-4.6) 📄 10 9 ↑11% — —
176_network_policy_blocking_traffic_no_skills (opus-4.6) 📄 10 11 ±0% — —
227_count_configmaps_per_namespace[0] (opus-4.6) 📄 6 6 ±0% — —
243_pod_names_contain_service (opus-4.6) 📄 7 7 ±0% — —
24_misconfigured_pvc (opus-4.6) 📄 11 10 ↑10% — —
254_elasticsearch_dr_test_log_check (opus-4.6) 📄 11 12 ±0% — —
259_wrong_cluster_logs_confusion (opus-4.6) 📄 12 13 ±0% — —
260_global_es_remote_cluster_logs (opus-4.6) 📄 9 12 ↓25% — —
43_current_datetime_from_prompt (opus-4.6) 📄 — — — — —
51_logs_summarize_errors (opus-4.6) 📄 2 2 ±0% — —
61_exact_match_counting (opus-4.6) 📄 1 1 ±0% — —
Total (all, n=14) 6.9 7.8 — — —
Comparable (m=13, b=0) 7.5 7.8 ±0% — —

Comparison indicators:

  • ±0% — diff under 10% (within noise threshold)
  • ↑N%/↓N% — diff 10-25%
  • ↑N%/↓N% — diff over 25% (significant)
📖 Legend
Icon Meaning
✅ The test was successful
➖ The test was skipped
⚠️ The test failed but is known to be flaky or known to fail
🚧 The test had a setup failure (not a code regression)
🔧 The test failed due to mock data issues (not a code regression)
🚫 The test was throttled by API rate limits/overload
❌ The test failed and should be fixed before merging the PR
🔄 Re-run evals manually

⚠️ Warning: /eval comments always run using the workflow from master, not from this PR branch. If you modified the GitHub Action (e.g., added secrets or env vars), those changes won't take effect.

To test workflow changes, use the GitHub CLI or Actions UI instead:

gh workflow run eval-regression.yaml --repo HolmesGPT/holmesgpt --ref claude/k8s-remediation-mcp-BTz5W -f markers=regression -f filter=

Option 1: Comment on this PR with /eval:

/eval
tags: regression

Or with more options (one per line):

/eval
model: gpt-4o
tags: regression
id: 09_crashpod
iterations: 5

Run evals on a different branch (e.g., master) for comparison:

/eval
branch: master
tags: regression
Option Description
model Model(s) to test (default: same as automatic runs)
tags Pytest tags / markers (no default - runs all tests!)
id Eval ID / pytest -k filter (use /list to see valid eval names)
iterations Number of runs, max 10
branch Run evals on a different branch (for cross-branch comparison)

Quick re-run: Use /rerun to re-run the most recent /eval on this PR with the same parameters.

Option 2: Trigger via GitHub Actions UI → "Run workflow"

Option 3: Add PR labels to include extra evals (applies to both automatic runs and /eval comments):

Label Effect
evals-tag-<name> Run tests with tag <name> alongside regression
evals-id-<name> Run a specific eval by test ID
evals-model-<name> Override the model (use model list name, e.g. sonnet-4.5)

Examples: evals-tag-easy, evals-id-09_crashpod, evals-model-sonnet-4.5

🏷️ Valid tags

benchmark, chain-of-causation, compaction, confluence, context_window, conversation_worker, coralogix, counting, database, datadog, datetime, db-connectors, easy, elasticsearch, embeds, fast, frontend, grafana, hard, images, integration, kafka, kubernetes, leaked-information, logs, loki, manual, mcp, medium, metrics, multi-cluster, network, newrelic, no-cicd, numerical, one-test, port-forward, prometheus, question-answer, regression, skills, slackbot, storage, token-limit, toolset-limitation, traces, transparency, victorialogs

🤖 Valid models

deepseek-chat, deepseek-r1-reasoner, deepseek-reasoner, deepseek-v3.2-chat, fable-5, gemini-3-flash-preview, gemini-3-pro-preview, gemini-3.1-pro-preview, gpt-4.1, gpt-5.2-high-reasoning, gpt-5.3-codex, gpt-5.4, gpt-5.5, haiku-4.5, kimi-2.5, kimi-2.5-openrouter, opus-4.5, opus-4.6, opus-4.7, opus-4.8, qwen-next-80B-instruct, qwen-next-80B-thinking, sonnet-4.5, sonnet-4.6


Commands: /eval · /rerun · /list

CLI: gh workflow run eval-regression.yaml --repo HolmesGPT/holmesgpt --ref claude/k8s-remediation-mcp-BTz5W -f markers=regression -f filter=

@coderabbitai

coderabbitai Bot commented Jun 7, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

This PR centralizes approval gating on approval_required_tools, removes legacy restricted flags and _skill_in_use runtime gating, threads user context into tool listing, updates the Kubernetes Remediation Helm chart (scoped RBAC, new ConfigMap/env keys, ingress-only NetworkPolicy), rewrites docs/specs, and adds tests for approval behavior, Helm wiring, and OAuth persistence.

Changes

Approval-Based Tool Gating Migration

Layer / File(s) Summary
Tool model refactor - Remove legacy restricted mechanism
holmes/core/tools.py
Tool.restricted and Tool._is_restricted() removed. Toolset and ToolsetYamlFromConfig no longer declare restricted_tools. Added a Toolset "before" model validator that strips incoming restricted_tools keys and logs a warning.
Tool executor refactor - Unconditional base tool listing and frontend approval hook
holmes/core/tools_utils/tool_executor.py, holmes/core/tools_utils/frontend_tools.py
ToolExecutor.get_all_tools_openai_format() and _get_base_tools() removed the include_restricted filtering and now return base tools unconditionally, applying per-user OAuth replacements afterward. _FrontendToolBase replaces _is_restricted() with _get_approval_requirement() returning None.
Tool calling layer refactor - Thread user context for approval
holmes/core/tool_calling_llm.py
Removed _skill_in_use state and _should_include_restricted_tools() logic. with_executor() no longer preserves _skill_in_use. reset_interaction_state() is now a no-op. _get_tools() derives user_id from _request_context and calls get_all_tools_openai_format(user_id=...). Removed post-success path that set _skill_in_use = True.
Multi-instance wrapper - forward approval overrides
holmes/plugins/toolsets/multi_instance.py
Wrapper no longer propagates deprecated restricted_tools into child toolsets; it continues forwarding approval_required_tools and updated docstring wording.
Kubernetes Remediation Helm configuration
helm/holmes/values.yaml, helm/holmes/templates/mcp-servers/kubernetes-remediation/rbac.yaml, helm/holmes/templates/mcp-servers/kubernetes-remediation/deployment.yaml, helm/holmes/templates/mcp-servers/kubernetes-remediation/networkpolicy.yaml, helm/holmes/templates/mcp-servers/kubernetes-remediation/_helpers.tpl, helm/holmes/templates/toolset-config.yaml
Bumped image to 1.1.0, removed hardcoded cluster-admin default and added a conditional/chart-generated scoped ClusterRole template, extended ConfigMap/env wiring with preapprovedCommands, diagnosticImages, fileReadAllowedPaths, fileReadDeniedPaths, and allowArbitraryKubectlCommands. Enabled ingress-only NetworkPolicy scoped to the release namespace. Removed restrictedTools and narrowed approvalRequiredTools to ["run_kubectl_command"]. Rewrote LLM instructions to reflect tool split and updated toolset-config to drop restricted_tools.
Documentation & Specs
docs/data-sources/builtin-toolsets/kubernetes-remediation-mcp.md, specs/kubernetes-remediation-mcp.md
Rewrote guidance to frame the MCP as additive, clarified tool separation and approval legibility, added an Available Tools table distinguishing auto-approved read/diagnostic tools from human-approval run_kubectl_command, replaced CLI RBAC example with a scoped ClusterRole, updated deployment example and Helm notes, and overhauled Security Controls and a Configuration Reference. Added a detailed design/spec for server-side hardening and acceptance criteria.
Tests - Approval mechanism and Helm wiring
tests/test_approval_required_tools.py, tests/test_kubernetes_remediation_helm.py, tests/test_mcp_oauth.py
Added tests validating approval gating behavior (approval-gated tool returns APPROVAL_REQUIRED without user approval; read-only tools return SUCCESS; user_approved=True suppresses re-prompt). Added Helm regression tests asserting values/templates drop restricted_tools, map approval to approvalRequiredTools: ["run_kubectl_command"], scoped RBAC (no cluster-admin), ingress-only NetworkPolicy scoped to release namespace, new ConfigMap env vars present, old allowedImages removed, and LLM helper text mentions the tool split. Updated OAuth test to assert returned oauth_tools are persisted per-user.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • HolmesGPT/holmesgpt#2056: Documentation updates overlapping the remediation MCP guidance and additive usage messaging.
  • HolmesGPT/holmesgpt#1626: Earlier Kubernetes Remediation MCP integration that introduced restrictedTools/approval knobs now removed/rewired.
  • HolmesGPT/holmesgpt#2115: Changes touching multi-instance toolset wrapper behavior and approval propagation.

Suggested reviewers

  • RoiGlinik
  • Avi-Robusta
  • naomi-robusta
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Refactor Kubernetes Remediation MCP: approval-based tool separation' accurately describes the main change: replacing the legacy restricted_tools mechanism with an approval-based model.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jun 7, 2026 •

Copy link
Copy Markdown
Contributor

✅ Docker images ready for 014415ee3 (built in 5m 57s)

⚠️ Warning: does not support ARM (ARM images are built on release only - not on every PR)

Use these tags to pull the images for testing.

📋 Copy commands

⚠️ Temporary images are deleted after 30 days. Copy to a permanent registry before using them:

gcloud auth configure-docker us-central1-docker.pkg.dev
docker pull us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes:014415ee3
docker tag us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes:014415ee3 me-west1-docker.pkg.dev/robusta-development/development/holmes-dev:014415ee3
docker push me-west1-docker.pkg.dev/robusta-development/development/holmes-dev:014415ee3
docker pull us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes-operator:014415ee3
docker tag us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes-operator:014415ee3 me-west1-docker.pkg.dev/robusta-development/development/holmes-operator-dev:014415ee3
docker push me-west1-docker.pkg.dev/robusta-development/development/holmes-operator-dev:014415ee3

Patch Helm values in one line (choose the chart you use):

HolmesGPT chart:

helm upgrade --install holmesgpt ./helm/holmes \
  --set registry=me-west1-docker.pkg.dev/robusta-development/development \
  --set image=holmes-dev:014415ee3 \
  --set operator.registry=me-west1-docker.pkg.dev/robusta-development/development \
  --set operator.image=holmes-operator-dev:014415ee3

Robusta wrapper chart:

helm upgrade --install robusta robusta/robusta \
  --reuse-values \
  --set holmes.registry=me-west1-docker.pkg.dev/robusta-development/development \
  --set holmes.image=holmes-dev:014415ee3 \
  --set holmes.operator.registry=me-west1-docker.pkg.dev/robusta-development/development \
  --set holmes.operator.image=holmes-operator-dev:014415ee3

@netlify

netlify Bot commented Jun 7, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for holmes-docs ready!

Name Link
🔨 Latest commit c87b5a1
🔍 Latest deploy log https://app.netlify.com/projects/holmes-docs/deploys/6a3c670f197105000839ea2d
😎 Deploy Preview https://deploy-preview-2148--holmes-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (1)
tests/test_approval_required_tools.py (1)

100-103: ⚡ Quick win

Move ToolsetYamlFromConfig import to module scope.

Line 102 imports inside the test function; move it to the top import block for consistency and simpler static analysis.

Suggested fix
 from holmes.core.models import StructuredToolResult, StructuredToolResultStatus
+from holmes.core.tools import ToolsetYamlFromConfig
@@
 def test_deprecated_restricted_tools_is_ignored_with_warning(caplog):
     """Old configs carrying the removed restricted_tools key load without error."""
-    from holmes.core.tools import ToolsetYamlFromConfig
-
     with caplog.at_level("WARNING"):

As per coding guidelines, "**/*.py: Always place Python imports at the top of the file, not inside functions or methods."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_approval_required_tools.py` around lines 100 - 103, The test
currently imports ToolsetYamlFromConfig inside the test function
test_deprecated_restricted_tools_is_ignored_with_warning; move the import
statement for ToolsetYamlFromConfig to the module-level import block at the top
of the file so it is imported once for the module (not inside the function),
updating any existing top imports to include ToolsetYamlFromConfig from
holmes.core.tools and removing the inline import in
test_deprecated_restricted_tools_is_ignored_with_warning.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/test_approval_required_tools.py`:
- Around line 100-103: The test currently imports ToolsetYamlFromConfig inside
the test function test_deprecated_restricted_tools_is_ignored_with_warning; move
the import statement for ToolsetYamlFromConfig to the module-level import block
at the top of the file so it is imported once for the module (not inside the
function), updating any existing top imports to include ToolsetYamlFromConfig
from holmes.core.tools and removing the inline import in
test_deprecated_restricted_tools_is_ignored_with_warning.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 58f064c9-eccb-45ac-b554-6f5f09063ef8

📥 Commits

Reviewing files that changed from the base of the PR and between 7b97462 and a505786.

📒 Files selected for processing (14)
  • docs/data-sources/builtin-toolsets/kubernetes-remediation-mcp.md
  • helm/holmes/templates/mcp-servers/kubernetes-remediation/_helpers.tpl
  • helm/holmes/templates/mcp-servers/kubernetes-remediation/deployment.yaml
  • helm/holmes/templates/mcp-servers/kubernetes-remediation/networkpolicy.yaml
  • helm/holmes/templates/mcp-servers/kubernetes-remediation/rbac.yaml
  • helm/holmes/templates/toolset-config.yaml
  • helm/holmes/values.yaml
  • holmes/core/tool_calling_llm.py
  • holmes/core/tools.py
  • holmes/core/tools_utils/frontend_tools.py
  • holmes/core/tools_utils/tool_executor.py
  • tests/test_approval_required_tools.py
  • tests/test_kubernetes_remediation_helm.py
  • tests/test_mcp_oauth.py
💤 Files with no reviewable changes (2)
  • tests/test_mcp_oauth.py
  • holmes/core/tools_utils/frontend_tools.py

claude added 3 commits June 7, 2026 09:00
Addresses CodeRabbit nitpick / repo guideline to keep imports at file top.

Signed-off-by: Claude <noreply@anthropic.com>
- specs/kubernetes-remediation-mcp.md: full design + security review across both
  repos (tool taxonomy, RBAC/NetworkPolicy, the agent-core removal, the actual
  security boundaries, residual risks, test/eval coverage) to ease team review.
- docs: path-policy row now reflects in-container symlink resolution and the
  hard /proc,/sys,/dev denial (server PR robusta-dev/holmes-mcp-integrations#24).

Signed-off-by: Claude <noreply@anthropic.com>

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🧹 Nitpick comments (2)
specs/kubernetes-remediation-mcp.md (2)

192-199: ⚡ Quick win

Consider documenting resource exhaustion risks and mitigations.

§6.3 documents diagnostic pod hardening including memory limits, but does not address:

  • Risk of multiple concurrent diagnostic pods consuming cluster resources
  • Rate limiting or concurrency controls
  • Resource quota interactions in the target namespace

While the 60s timeout (line 94) and per-pod memory caps provide some protection, an LLM could still launch many diagnostic pods in parallel. Consider adding a risk note in §6.4 about resource exhaustion and potential mitigations (e.g., server-side concurrency limits, resource quotas in the MCP server's own namespace).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@specs/kubernetes-remediation-mcp.md` around lines 192 - 199, Add a short risk
note referencing §6.3's run_diagnostic_image hardening that explains the
potential for resource exhaustion if many diagnostic pods are launched
concurrently and lists mitigations to include in §6.4 — mention the existing 60s
timeout and per-pod memory caps, and recommend server-side concurrency/rate
limits, namespace ResourceQuota usage, and limiting total concurrent diagnostic
pods (or queuing) in the MCP server; tie these recommendations to the
run_diagnostic_image behavior so readers can correlate mitigations with the
implemented limits.

210-215: ⚡ Quick win

The approval sync dependency is clearly documented but architecturally significant.

The acknowledgment that "the server has no notion of approval and will run run_kubectl_command if called directly" (lines 211-212) highlights a fundamental architectural limitation: the security boundary relies on correct configuration across two systems.

The documented mitigations are appropriate:

  • NetworkPolicy restricts direct access (§3.4)
  • Image pinning prevents drift (line 213)
  • allowArbitraryKubectlCommands toggle provides a killswitch (lines 214-215)

However, consider adding:

  • A recommendation to monitor for direct MCP server calls that bypass HolmesGPT (if logging permits)
  • A note about the implications if NetworkPolicy is not enforced by the CNI (already noted as "inert where the CNI doesn't enforce" in line 123, but the security implication could be more explicit here)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@specs/kubernetes-remediation-mcp.md` around lines 210 - 215, The doc
currently notes the cross-system approval sync risk and mitigations but should
explicitly add two points: (1) recommend operational monitoring for direct MCP
server invocations that bypass HolmesGPT—eg. log/alert on calls to
run_kubectl_command or unauthenticated access patterns so operators can detect
direct MCP server calls; (2) explicitly call out the security impact if
NetworkPolicy is not enforced by the CNI (i.e., that NetworkPolicy becomes inert
and the approval boundary can be bypassed), and advise mitigations such as
enforcing CNI compliance or adding host-level firewall rules; reference
HolmesGPT, approval_required_tools, run_kubectl_command and
allowArbitraryKubectlCommands when adding these notes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@specs/kubernetes-remediation-mcp.md`:
- Around line 157-223: Add a new subsection under "6. Security model — what's
actually enforced" (e.g., 6.6 Audit logging) that documents audit logging
requirements: state whether kubectl executions are logged by HolmesGPT, the MCP
server, and/or rely on Kubernetes audit logs; enumerate captured events (command
invocation, tool name, user/actor, approval decisions, policy/deny hits,
container/pod targets, and execution outcomes); specify retention and
access/monitoring recommendations (retention period, alerting for anomalous
patterns, and where logs are stored/forwarded); and note any gaps or
dependencies (e.g., server must forward to cluster audit or centralized logging)
so the existing sections like "6.4 Residual risks" and "6.5 Things that are
correct by construction" can reference audit mitigations.
- Around line 244-252: Document and track the missing LLM eval coverage
described in §8 by opening a tracking issue that (1) prioritizes writing evals
for the auto-approved tools first (they require no approval hook), (2) specifies
the harness enhancement needed to run approval-gated tools non-interactively (so
run_kubectl_command can be exercised in regression suites), and (3) adds a short
acceptance checklist to the spec listing required LLM checks (tool selection,
command safety, and mutation approval flow); include links to the existing unit
tests that validate authorization so the issue clearly separates auth tests from
desired LLM behavior tests.

---

Nitpick comments:
In `@specs/kubernetes-remediation-mcp.md`:
- Around line 192-199: Add a short risk note referencing §6.3's
run_diagnostic_image hardening that explains the potential for resource
exhaustion if many diagnostic pods are launched concurrently and lists
mitigations to include in §6.4 — mention the existing 60s timeout and per-pod
memory caps, and recommend server-side concurrency/rate limits, namespace
ResourceQuota usage, and limiting total concurrent diagnostic pods (or queuing)
in the MCP server; tie these recommendations to the run_diagnostic_image
behavior so readers can correlate mitigations with the implemented limits.
- Around line 210-215: The doc currently notes the cross-system approval sync
risk and mitigations but should explicitly add two points: (1) recommend
operational monitoring for direct MCP server invocations that bypass
HolmesGPT—eg. log/alert on calls to run_kubectl_command or unauthenticated
access patterns so operators can detect direct MCP server calls; (2) explicitly
call out the security impact if NetworkPolicy is not enforced by the CNI (i.e.,
that NetworkPolicy becomes inert and the approval boundary can be bypassed), and
advise mitigations such as enforcing CNI compliance or adding host-level
firewall rules; reference HolmesGPT, approval_required_tools,
run_kubectl_command and allowArbitraryKubectlCommands when adding these notes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f7b12ad7-a65a-403d-aa99-64e200989b4d

📥 Commits

Reviewing files that changed from the base of the PR and between 86b4ef3 and f3febaf.

📒 Files selected for processing (2)
  • docs/data-sources/builtin-toolsets/kubernetes-remediation-mcp.md
  • specs/kubernetes-remediation-mcp.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/data-sources/builtin-toolsets/kubernetes-remediation-mcp.md

Comment thread specs/kubernetes-remediation-mcp.md
Comment thread specs/kubernetes-remediation-mcp.md Outdated
claude added 2 commits June 10, 2026 09:32
Master's multi_instance.py (merged in) propagated the now-removed
Toolset.restricted_tools to child toolsets in _forward_overrides, which broke
all multi-instance toolset tests (azure_sql/datadog/elasticsearch/...) once this
branch's removal met it. Drop the restricted_tools propagation (keep
approval_required_tools) and fix the _RoutingTool docstring accordingly.

Signed-off-by: Claude <noreply@anthropic.com>
…ecklist

Addresses CodeRabbit review on specs/kubernetes-remediation-mcp.md:
- §6.6 Audit logging: what the server/HolmesGPT/k8s capture today and the
  forwarding/retention/alerting gaps.
- §6.4: resource-exhaustion risk from concurrent diagnostic pods (+ mitigations),
  and the NetworkPolicy-inert-without-CNI / direct-call monitoring implications
  of the cross-system approval boundary.
- §8: eval acceptance checklist separating authorization tests from LLM-behavior
  evals, prioritizing the auto-approved tools and noting the harness hook the
  gated tool needs.

Signed-off-by: Claude <noreply@anthropic.com>

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🧹 Nitpick comments (2)
specs/kubernetes-remediation-mcp.md (2)

223-230: Resource exhaustion mitigations documented as gap.

This section honestly documents that global concurrency/rate limits and ResourceQuota/LimitRange are "not yet implemented" and recommends them for multi-tenant or resource-constrained clusters. The risk is clearly described.

Unlike the eval coverage (§8), this section doesn't state whether these mitigations are tracked or planned. For a tool that can launch multiple diagnostic pods, this is a real operational concern for production deployments.

Consider adding a note indicating whether these mitigations are tracked (similar to the "(tracked separately — not blocking this PR)" note in §8) to help operators understand the roadmap.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@specs/kubernetes-remediation-mcp.md` around lines 223 - 230, The doc notes
global concurrency/rate limits and namespace ResourceQuota/LimitRange for
run_diagnostic_image are "not yet implemented" but doesn't state whether these
mitigations are tracked or planned; update the paragraph that mentions
run_diagnostic_image and the recommended ResourceQuota/LimitRange to include a
short status note (e.g. "(tracked separately — planned/issue #...)" or "(not
currently tracked)") matching the style used in §8 so operators know the roadmap
and whether this is blocking.

217-219: Consider adding more specific CNI guidance.

The text correctly documents that NetworkPolicy enforcement depends on CNI support and recommends "enforce a NetworkPolicy-capable CNI (or add host/firewall-level restrictions)". For operators evaluating this addon, it might be helpful to briefly enumerate which CNIs support NetworkPolicy (e.g., Calico, Cilium, Weave Net vs. Flannel without additional components) or provide a detection recommendation.

However, this level of detail may be out of scope for a design spec. The critical point—that the approval boundary can be bypassed where NetworkPolicy isn't enforced—is clearly stated.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@specs/kubernetes-remediation-mcp.md` around lines 217 - 219, Add a short,
optional paragraph after the sentence about "enforce a NetworkPolicy-capable CNI
(or add host/firewall-level restrictions)" that (1) lists common CNIs that do
and do not enforce NetworkPolicy by default (e.g., Calico, Cilium, Weave Net
support NetworkPolicy enforcement; Flannel does not without extra components)
and (2) suggests a lightweight detection method such as checking for known CNI
DaemonSets/Deployments (calico-node, cilium, weave-net) or performing a simple
NetworkPolicy enforcement test (create an isolated deny/allow policy and verify
connectivity) so operators can quickly validate whether their CNI enforces
NetworkPolicy.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@holmes/plugins/toolsets/multi_instance.py`:
- Around line 97-100: The current check uses "if not raw:" which treats an
explicit empty list for "instances" the same as a missing key and produces a
synthetic "default" instance; instead check for presence vs absence by using "if
raw is None:" (or "if 'instances' not in config:") so an explicit empty list is
preserved and will flow into _aggregate()'s "No instances configured" path;
update the conditional around raw/instances in multi_instance.py (the block that
builds flat and returns [("default", flat)]) to only run when raw is truly
missing, leaving raw == [] untouched.

---

Nitpick comments:
In `@specs/kubernetes-remediation-mcp.md`:
- Around line 223-230: The doc notes global concurrency/rate limits and
namespace ResourceQuota/LimitRange for run_diagnostic_image are "not yet
implemented" but doesn't state whether these mitigations are tracked or planned;
update the paragraph that mentions run_diagnostic_image and the recommended
ResourceQuota/LimitRange to include a short status note (e.g. "(tracked
separately — planned/issue #...)" or "(not currently tracked)") matching the
style used in §8 so operators know the roadmap and whether this is blocking.
- Around line 217-219: Add a short, optional paragraph after the sentence about
"enforce a NetworkPolicy-capable CNI (or add host/firewall-level restrictions)"
that (1) lists common CNIs that do and do not enforce NetworkPolicy by default
(e.g., Calico, Cilium, Weave Net support NetworkPolicy enforcement; Flannel does
not without extra components) and (2) suggests a lightweight detection method
such as checking for known CNI DaemonSets/Deployments (calico-node, cilium,
weave-net) or performing a simple NetworkPolicy enforcement test (create an
isolated deny/allow policy and verify connectivity) so operators can quickly
validate whether their CNI enforces NetworkPolicy.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 23ede510-55f1-49ed-8098-057273d8c4c7

📥 Commits

Reviewing files that changed from the base of the PR and between f3febaf and 8e5f8e9.

📒 Files selected for processing (3)
  • helm/holmes/values.yaml
  • holmes/plugins/toolsets/multi_instance.py
  • specs/kubernetes-remediation-mcp.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • helm/holmes/values.yaml

@coderabbitai coderabbitai 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.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 1

🧹 Nitpick comments (2)
specs/kubernetes-remediation-mcp.md (2)

223-230: Resource exhaustion mitigations documented as gap.

This section honestly documents that global concurrency/rate limits and ResourceQuota/LimitRange are "not yet implemented" and recommends them for multi-tenant or resource-constrained clusters. The risk is clearly described.

Unlike the eval coverage (§8), this section doesn't state whether these mitigations are tracked or planned. For a tool that can launch multiple diagnostic pods, this is a real operational concern for production deployments.

Consider adding a note indicating whether these mitigations are tracked (similar to the "(tracked separately — not blocking this PR)" note in §8) to help operators understand the roadmap.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@specs/kubernetes-remediation-mcp.md` around lines 223 - 230, The doc notes
global concurrency/rate limits and namespace ResourceQuota/LimitRange for
run_diagnostic_image are "not yet implemented" but doesn't state whether these
mitigations are tracked or planned; update the paragraph that mentions
run_diagnostic_image and the recommended ResourceQuota/LimitRange to include a
short status note (e.g. "(tracked separately — planned/issue #...)" or "(not
currently tracked)") matching the style used in §8 so operators know the roadmap
and whether this is blocking.

217-219: Consider adding more specific CNI guidance.

The text correctly documents that NetworkPolicy enforcement depends on CNI support and recommends "enforce a NetworkPolicy-capable CNI (or add host/firewall-level restrictions)". For operators evaluating this addon, it might be helpful to briefly enumerate which CNIs support NetworkPolicy (e.g., Calico, Cilium, Weave Net vs. Flannel without additional components) or provide a detection recommendation.

However, this level of detail may be out of scope for a design spec. The critical point—that the approval boundary can be bypassed where NetworkPolicy isn't enforced—is clearly stated.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@specs/kubernetes-remediation-mcp.md` around lines 217 - 219, Add a short,
optional paragraph after the sentence about "enforce a NetworkPolicy-capable CNI
(or add host/firewall-level restrictions)" that (1) lists common CNIs that do
and do not enforce NetworkPolicy by default (e.g., Calico, Cilium, Weave Net
support NetworkPolicy enforcement; Flannel does not without extra components)
and (2) suggests a lightweight detection method such as checking for known CNI
DaemonSets/Deployments (calico-node, cilium, weave-net) or performing a simple
NetworkPolicy enforcement test (create an isolated deny/allow policy and verify
connectivity) so operators can quickly validate whether their CNI enforces
NetworkPolicy.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@holmes/plugins/toolsets/multi_instance.py`:
- Around line 97-100: The current check uses "if not raw:" which treats an
explicit empty list for "instances" the same as a missing key and produces a
synthetic "default" instance; instead check for presence vs absence by using "if
raw is None:" (or "if 'instances' not in config:") so an explicit empty list is
preserved and will flow into _aggregate()'s "No instances configured" path;
update the conditional around raw/instances in multi_instance.py (the block that
builds flat and returns [("default", flat)]) to only run when raw is truly
missing, leaving raw == [] untouched.

---

Nitpick comments:
In `@specs/kubernetes-remediation-mcp.md`:
- Around line 223-230: The doc notes global concurrency/rate limits and
namespace ResourceQuota/LimitRange for run_diagnostic_image are "not yet
implemented" but doesn't state whether these mitigations are tracked or planned;
update the paragraph that mentions run_diagnostic_image and the recommended
ResourceQuota/LimitRange to include a short status note (e.g. "(tracked
separately — planned/issue #...)" or "(not currently tracked)") matching the
style used in §8 so operators know the roadmap and whether this is blocking.
- Around line 217-219: Add a short, optional paragraph after the sentence about
"enforce a NetworkPolicy-capable CNI (or add host/firewall-level restrictions)"
that (1) lists common CNIs that do and do not enforce NetworkPolicy by default
(e.g., Calico, Cilium, Weave Net support NetworkPolicy enforcement; Flannel does
not without extra components) and (2) suggests a lightweight detection method
such as checking for known CNI DaemonSets/Deployments (calico-node, cilium,
weave-net) or performing a simple NetworkPolicy enforcement test (create an
isolated deny/allow policy and verify connectivity) so operators can quickly
validate whether their CNI enforces NetworkPolicy.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 23ede510-55f1-49ed-8098-057273d8c4c7

📥 Commits

Reviewing files that changed from the base of the PR and between f3febaf and 8e5f8e9.

📒 Files selected for processing (3)
  • helm/holmes/values.yaml
  • holmes/plugins/toolsets/multi_instance.py
  • specs/kubernetes-remediation-mcp.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • helm/holmes/values.yaml
🛑 Comments failed to post (1)
holmes/plugins/toolsets/multi_instance.py (1)

97-100: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't collapse instances: [] into flat single-instance mode.

if not raw: treats an explicit empty list the same as a missing instances key, so instances: [] silently creates a synthetic "default" child from the top-level globals. That bypasses the "No instances configured" path in _aggregate() and can unexpectedly leave a routable endpoint enabled when the config explicitly declared zero instances.

Suggested fix
 def _parse_instances(config: Dict[str, Any]) -> List[Tuple[str, Dict[str, Any]]]:
     """Decompose a wrapper config into ordered (instance_name, flat_child_config) pairs.
 
     Flat config (no `instances:`) → one instance named `default`.
     """
     raw = config.get("instances")
-    if not raw:
+    if raw is None:
         flat = {k: v for k, v in config.items() if k != "instances"}
         return [("default", flat)]
     if not isinstance(raw, list):
         raise ValueError("`instances` must be a list")
+    if not raw:
+        return []
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@holmes/plugins/toolsets/multi_instance.py` around lines 97 - 100, The current
check uses "if not raw:" which treats an explicit empty list for "instances" the
same as a missing key and produces a synthetic "default" instance; instead check
for presence vs absence by using "if raw is None:" (or "if 'instances' not in
config:") so an explicit empty list is preserved and will flow into
_aggregate()'s "No instances configured" path; update the conditional around
raw/instances in multi_instance.py (the block that builds flat and returns
[("default", flat)]) to only run when raw is truly missing, leaving raw == []
untouched.

claude and others added 4 commits June 10, 2026 19:58
… note

Address CodeRabbit nitpicks on the k8s-remediation spec (§6.4):
- Enumerate which CNIs enforce NetworkPolicy (Calico/Cilium/Antrea/Weave Net
  vs plain Flannel) plus managed-cluster caveats and a quick detection method,
  so operators can validate the approval-boundary backstop.
- Add a tracking-status note to the resource-exhaustion mitigations matching
  the §8 style (ResourceQuota/LimitRange available today; server-side
  concurrency cap is a follow-up, not blocking this PR).

Signed-off-by: Claude <noreply@anthropic.com>
…uth/steer-away framing

The page was underselling the remediation MCP and steering readers toward the
default toolset:
- Dropped the shared kubernetes_toolset_picker snippet here (its OAuth/OIDC
  comparison is relevant on the kubernetes-mcp page, not this one) and replaced
  it with capability-first positioning.
- Lead with what this MCP adds over read-only access (act on the cluster +
  deeper in-container diagnostics), with a comparison table.
- Removed the 'Don't use this server for reads' / 'Prefer the no-approval tools'
  lines that read as discouragement; reframed the built-in toolset as
  complementary and the approval split as a positive design property.

Signed-off-by: Claude <noreply@anthropic.com>
…ostic_image

Track the server-side tool rename (#24) so the docs, spec, Helm LLM
instructions, and unit tests reference the tool by its new name, consistent
with run_preapproved_kubectl_command. 11 unit tests pass.

Signed-off-by: Claude <noreply@anthropic.com>
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.

3 participants