Skip to content

fix: align skill parameters with actual MCP tool schemas#323

Merged
luis5tb merged 10 commits into
RHEcosystemAppEng:mainfrom
luis5tb:fix/multi-severity-cve-tool-selection
Jul 10, 2026
Merged

fix: align skill parameters with actual MCP tool schemas#323
luis5tb merged 10 commits into
RHEcosystemAppEng:mainfrom
luis5tb:fix/multi-severity-cve-tool-selection

Conversation

@luis5tb

@luis5tb luis5tb commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Summary

Skills documented wrong parameter names that don't exist in the MCP tool schemas. The LLM followed skill instructions, sent invalid params (e.g., severity="Critical"), and the MCP server rejected them — causing the Error calling tool 'get_cves' failures in production.

Root cause: parameter names in skills were guessed, not verified against the actual MCP tool schemas. Production logs with AGENT_LOGGING_DETAIL=detailed revealed the actual call args, and the schema debug logging confirmed the real parameter names.

Parameter corrections

Tool Skill had (wrong) MCP schema has (correct)
vulnerability__get_cves severity (Critical/Important) impact (numeric: 7=Critical, 5=Important, 4=Moderate, 2=Low)
vulnerability__get_cves affecting (boolean) advisory_available (string "true")
vulnerability__get_cves known_exploit (boolean) known_exploit (string "true"/"false")
inventory__list_hosts limit / offset per_page (default 10) / page (starts at 1)
inventory__list_hosts operating_system does not exist
vulnerability__get_system_cves severity, status, remediation only system_uuid, filter_, limit, offset, sort

Changes

Skills modified (5):

  • tool-invocation-rules v1.6 — correct parameter names, types, enum values; recommended default argument sets for common queries; string-typed boolean guidance; pushy skill description for reliable loading
  • multi-step-workflows v1.2 — updated workflows to use impact, advisory_available, system_uuid
  • response-formatting v1.1 — added Synopsis + CVSS Score to CVE tables, sort hosts by display_name
  • efficient-counting v1.1 — corrected per_page/page for inventory counting
  • error-handling v1.2 — corrected retry example to use impact="7" and advisory_available="true"

Debug logging added:

  • schema_sanitizer.py — logs all tool parameter types and $ref usage at startup
  • agent.py — logs each skill name and version at startup for deployment verification

Eval workspace:

  • 3 eval cases (IDs 4-6): multi-severity CVEs, advisor recommendations, system listing
  • iteration-5 results: 16/17 (94.1%) vs baseline 11/17 (64.7%) = +29.4%
  • 5 discriminating assertions, 0 regressions

Test plan

  • Deploy to staging and test: "Show me the top critical and important CVEs affecting my systems"
  • Verify single vulnerability__get_cves call with sort="-cvss_score", advisory_available="true", impact="5,7" (no severity or affecting param)
  • Test "List my registered systems" — verify per_page, sorted by order_by="display_name"
  • Test "What are the top advisor recommendations?" — verify impacting="true" (string, not boolean), sort="-total_risk"

🤖 Generated with Claude Code

@luis5tb luis5tb changed the title fix: prevent multi-severity parameter error in CVE queries [WIP] fix: prevent multi-severity parameter error in CVE queries Jul 9, 2026
@luis5tb luis5tb force-pushed the fix/multi-severity-cve-tool-selection branch from 713e7f6 to 26bc875 Compare July 9, 2026 21:08
@luis5tb luis5tb changed the title [WIP] fix: prevent multi-severity parameter error in CVE queries fix: align skill parameters with actual MCP tool schemas Jul 9, 2026
dmartinol
dmartinol previously approved these changes Jul 10, 2026

@dmartinol dmartinol left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

/LGTM

@dmartinol

Copy link
Copy Markdown
Collaborator

Review: parameter name corrections look good — but 4 issues remain

Great direction on this PR. The core fixes (severityimpact, affectingadvisory_available, limit/offsetper_page/page) are all confirmed correct against the live MCP schema. However, there are 4 bugs that need addressing before merge.


Bug 1 — tool-invocation-rules/SKILL.md: wrong impact numeric values for Moderate and Low

The skill documents "3" as Moderate and "1" as Low, but the actual MCP schema for vulnerability__get_cves maps:

(0, 'NotSet'), (1, 'None'), (2, 'Low'), (3, 'Medium'), (4, 'Moderate'),
(5, 'Important'), (6, 'High'), (7, 'Critical')

The default value "1,2,4,5,7" in the schema confirms this: Moderate=4, Low=2. If the agent follows the skill and sends impact="3" for "Moderate", it gets Medium CVEs instead.

Fix — in tool-invocation-rules/SKILL.md, update the impact description:

-`impact` (string — comma-separated numeric impact IDs: `"7"` for Critical,
-`"5"` for Important, `"3"` for Moderate, `"1"` for Low; combine as `"5,7"`
-for Important+Critical),
+`impact` (string — comma-separated numeric impact IDs: `"7"` for Critical,
+`"5"` for Important, `"4"` for Moderate, `"2"` for Low; combine as `"5,7"`
+for Important+Critical),

Same fix in the "Multi-impact queries" section at the bottom of the same file:

-For example, to get both Critical and Important CVEs: `impact="5,7"`.
+For example, to get both Critical and Important CVEs: `impact="5,7"`.
+For Moderate and above: `impact="4,5,7"`. For all actionable severities: `impact="2,4,5,7"`.

Bug 2 — evals.json Eval ID 4: wrong impact values in expected_output

The new eval asserts the correct call uses '3,4' for Important+Critical, but per the schema Important=5, Critical=7.

Fix — in adk-skills-workspace/evals/evals.json, Eval ID 4:

-"expected_output": "Should use vulnerability__get_cves with the correct MCP parameter names: impact (numeric string like '3,4' for Important+Critical), sort=-cvss_score, advisory_available='true'. ..."
+"expected_output": "Should use vulnerability__get_cves with the correct MCP parameter names: impact (numeric string like '5,7' for Important+Critical), sort=-cvss_score, advisory_available='true'. ..."

And the corresponding assertion description:

-{"name": "uses_impact_not_severity", "description": "Uses the 'impact' parameter (numeric string like '3,4') instead of the nonexistent 'severity' parameter..."}
+{"name": "uses_impact_not_severity", "description": "Uses the 'impact' parameter (numeric string like '5,7' for Important+Critical, or '7' for Critical-only) instead of the nonexistent 'severity' parameter..."}

Bug 3 — error-handling/SKILL.md: severity=Critical still used as example

The oversized-response retry section was updated to v1.1 but still contains the old wrong parameter:

"Add filters: Apply severity, date range, status, or other filters to narrow the result set (e.g., severity=Critical, status=Applicable)."

severity is the exact wrong parameter this PR removes everywhere else.

Fix — in src/lightspeed_agent/core/skills/error-handling/SKILL.md:

-2. **Add filters**: Apply severity, date range, status, or other filters to narrow
-   the result set (e.g., `severity=Critical`, `status=Applicable`).
+2. **Add filters**: Apply impact level, date range, or other filters to narrow
+   the result set (e.g., `impact="7"` for Critical-only, `advisory_available="true"`).

Bug 4 — PR test plan: uses affecting=true (the old wrong parameter)

In the PR description's test checklist:

"Verify single vulnerability__get_cves call with sort=-cvss_score, affecting=true (no severity param)"

affecting does not exist on get_cves — this is the parameter name the PR is fixing. The test plan should verify the correct form.

Fix — update the test plan item in the PR description:

-- [ ]  Verify single `vulnerability__get_cves` call with `sort=-cvss_score, affecting=true` (no severity param)
+- [ ]  Verify single `vulnerability__get_cves` call with `sort="-cvss_score", advisory_available="true"` (no `severity` or `affecting` param)

The impact value confusion (bugs 1 & 2) is the most impactful — it would cause the agent to silently return wrong severity-tier results without any tool error, making it hard to catch in testing.

luis5tb and others added 8 commits July 10, 2026 09:35
Root cause: skills documented wrong parameter names that don't exist
in the MCP tool schemas. The LLM followed skill instructions, sent
invalid params (e.g. severity='Critical'), and the MCP server rejected
them. Meanwhile vulnerability__get_system_cves worked because the LLM
read its simpler schema directly.

Parameter corrections verified from MCP schema dump + production logs:
- vulnerability__get_cves: severity→impact (numeric string: 7=Critical,
  5=Important, 3=Moderate, 1=Low), affecting→advisory_available,
  known_exploit is string not boolean, add cvss_from/cvss_to
- vulnerability__get_system_cves: only has system_uuid, filter_,
  limit, offset, sort (no severity/status/remediation)
- inventory__list_hosts: limit→per_page (default 10), offset→page,
  operating_system does not exist, add staleness/order_by enums
- Cross-referenced with upstream agentic-plugins parameter reference

Also includes:
- response-formatting: add Synopsis + CVSS to CVE tables, sort hosts
  by display_name, per_page=10 default
- Debug logging: tool schema props at startup, skill versions at startup

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add 3 new eval cases (IDs 4-6) testing:
- Multi-severity CVE queries (impact param, advisory_available)
- Advisor recommendations (correct tool selection)
- System listing (per_page/page params, sort by display_name)

Update skill-snapshot/ to pre-fix baseline for comparison.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
iteration-3: initial eval with wrong severity→impact mapping
iteration-4: final eval with correct MCP parameter names

5 discriminating assertions improved, 0 regressions:
- uses_impact_not_severity (impact='5,7' not severity='Critical')
- uses_correct_param_names (advisory_available not affecting)
- uses_advisory_available (string 'true' not boolean)
- uses_correct_inventory_params (per_page not limit)
- sorts_by_display_name (order_by guidance added)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
advisor__get_active_rules has many params with MISSING types in the MCP
schema. The schema sanitizer defaults them to string, but the LLM
passes boolean True instead of string 'true', causing MCP server
rejection. Document all advisor params with explicit string types and
add a 'String-typed booleans' section warning against this pattern.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… v1.4

- CVE queries: emphasize always including sort and advisory_available
- Inventory listings: emphasize always including order_by=display_name
- Fix multi-impact example: 3,4 → 5,7 (correct numeric IDs)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ggering v1.5

- Description: make triggering more assertive (ALWAYS load before MCP calls)
- Argument Formatting: remove contradicting boolean guidance, add early
  warning about string-typed booleans
- String-typed booleans section: add CRITICAL label, add explicit
  correct/wrong examples with concrete param names

Root cause: Argument Formatting said 'booleans as true/false' which
contradicted the String-typed booleans section, causing the LLM to
pass impacting=True (boolean) instead of impacting="true" (string).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a 'Recommended defaults for common queries' section with full
argument templates for top CVEs, system listings, and advisor queries.
Provides copy-ready JSON that includes sort, limit, and all required
params — more effective than bolded hints within parameter descriptions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Bug 1: Moderate=4 (not 3), Low=2 (not 1) per actual MCP schema enum
Bug 2: evals.json expected_output/assertions updated to '5,7'
Bug 3: error-handling retry example now uses impact="7" instead of
       severity=Critical (the exact wrong param this PR removes)
Bug 4: PR description test plan updated (via gh pr edit)

Also adds multi-impact examples: impact="4,5,7" for Moderate+,
impact="2,4,5,7" for all actionable severities.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@luis5tb luis5tb force-pushed the fix/multi-severity-cve-tool-selection branch from 738a730 to fe387e7 Compare July 10, 2026 07:35
luis5tb and others added 2 commits July 10, 2026 10:19
…e 11/17)

Skill-creator evaluation results for tool-invocation-rules v1.5:
- 94.1% pass rate (16/17) vs 64.7% baseline (11/17) = +29.4%
- 5 discriminating assertions all pass: uses_impact_not_severity,
  uses_correct_param_names, uses_advisory_available,
  uses_impacting_as_string, uses_correct_inventory_params
- 0 regressions
- 1 shared failure: flags_stale_checkins (neither version flags it)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Gemini consistently loads only guardrails-safety via load_skill and
skips tool-invocation-rules, so the recommended defaults, string-typed
boolean rules, and correct parameter names were never in context.

This change reads the SKILL.md bodies of STRICT skills at startup and
injects them directly into the system prompt (static_instruction).
The LLM no longer needs to call load_skill for these — the content is
always available. External skill overrides via SKILLS_DIR are respected.

The Skills section in AGENT_INSTRUCTION now tells the LLM not to call
load_skill for the two STRICT skills since they are pre-loaded.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

@dmartinol dmartinol left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

/lgtm all issues fixed and by pre-injecting STRICT skills into the system prompt at startup you addressed the root cause: Gemini was consistently skipping load_skill for tool-invocation-rules, meaning the correct parameter names were never in context at all.
👍

@luis5tb luis5tb merged commit dee2cd5 into RHEcosystemAppEng:main Jul 10, 2026
15 checks passed
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.

2 participants