vmware-harden
This server provides read-only VMware compliance scanning, violation tracking, drift detection, and remediation advisory capabilities.
list_baselines: List all available built-in and user-imported compliance baselines (e.g., CIS ESXi 8.0, PCI-DSS 4.0, EU NIS2, BSI IT-Grundschutz).scan_target: Trigger a compliance scan against a specified vCenter or host target using a chosen baseline (defaults tocis-vmware-esxi-8.0-subset).list_violations: View compliance violations from the latest scan snapshot, with optional filtering by severity (critical, high, medium, low).get_remediation: Retrieve a persisted remediation suggestion for a specific violation by its ID.list_drift_events: View configuration change/drift events from the latest snapshot, with a configurable result limit (default: 50).get_baseline_rules: Fetch all individual compliance rules defined within a specific baseline by its ID.
Enforces compliance baselines on VMware vSphere environments, including ESXi hosts and NSX DFW rules, with built-in baselines such as CIS, PCI-DSS, and 等保 2.0.
vmware-harden
Disclaimer: Community-maintained open-source project. Not affiliated with, endorsed by, or sponsored by VMware, Inc. or Broadcom Inc. "VMware", "vSphere", "ESXi", and "NSX" are trademarks of Broadcom. Source code is publicly auditable at github.com/vmware-skills/VMware-Harden under the MIT license.
English | 中文
AI-native VMware compliance and baseline enforcement. Sibling to the vmware-* skill family.
Read-only against vSphere: all 8 MCP tools carry the
[READ]marker and none mutate managed VMware infrastructure;scan_targetwrites only to the local twin DB (a cache of its own observations). See Read-only by design.
GA family member (since v1.5.18)
Production-ready compliance platform with 9 built-in baselines (CIS ESXi 8.0 + 9.0, vSphere SCG v8 + v9, vSphere 9 STIG-aligned, 等保 2.0 三级, PCI-DSS 4.0, EU NIS2, BSI IT-Grundschutz) carrying 99 rules, multi-vCenter Twin, drift detection, LLM Remediation Advisor, MCP server with 8 audited tools, web dashboard, and vmware-harden doctor environment diagnostics.
Related MCP server: vSphere-MCP-Pro
Quickstart
# The collectors extra is what makes `scan` work: harden reads inventory
# through vmware-aiops / vmware-storage / vmware-nsx-security, and `uv tool
# install` gives each tool its own environment — installing them separately
# puts them where harden cannot import them from.
uv tool install "vmware-harden[collectors]"
# Reporting on an existing twin DB needs no collectors:
# uv tool install vmware-harden
# List built-in baselines
vmware-harden baseline list
# Run a scan
vmware-harden scan --target <vcenter-name> --baseline cis-vmware-esxi-8.0-subset
# Or use 等保 2.0 三级 (国内合规独家)
vmware-harden scan --target <vc> --baseline dengbao-2.0-level3-vmware
# View results
vmware-harden report
vmware-harden drift
# Generate remediation suggestions
export ANTHROPIC_API_KEY=... # optional; falls back to mock without
vmware-harden advise --all-critical
# Web dashboard
vmware-harden web --port 8080 # → http://127.0.0.1:8080Reading a result: violations alone are not a verdict
A rule can only judge configuration that was actually gathered, and that fails
in two independent ways. A rule whose attribute no collector produces is not
executed at all. A rule that does run can still learn nothing about one
particular host, because there the value came back absent or as the N/A
sentinel — an unreachable host, an account without the privilege, a setting the
ESXi build does not have. Neither is reported as passing:
$ vmware-harden report
No violations among the checks that could be made.
16 of 20 rules could not be evaluated — no collector provides the data they
check, so their result is unknown, not compliant. 6 of 8 per-node checks could
not be made across 2 node(s): the rules ran, but the values they read were
missing on those nodes, so those nodes are unknown rather than compliant.
Not evaluated:
cis-esxi-2.1.1 no collector writes host.ntp_enabled
...
Not judged on these nodes (data missing):
cis-esxi-2.2.1 esx-02 esxi_build
...--format json returns {"violations": [...], "coverage": {...}}, and the MCP
tools return the same coverage block, so an agent reading violations: 0
cannot conclude "compliant" on its own. Before v1.9.0 the uncollected-attribute
rules matched zero rows and were silently counted as passes; before v1.10.0 the
per-node case was, too. See RELEASE_NOTES.md.
The two lists call for different work: the first is waiting on a collector, the second on that node's reachability and the scanning account's privileges.
Offline / Air-Gapped Install (from source)
This project uses the modern PEP 517 build system (hatchling), so there is no
setup.py by design — that is expected, not a missing file. If you cloned the
source and hit ERROR: File "setup.py" or "setup.cfg" not found ... editable mode currently requires a setuptools-based build, your pip is older than 21.3 and
cannot do an editable (-e) install with a non-setuptools backend. Editable
mode is a developer convenience, not needed to run the tool — do one of:
# From the source tree — a normal (non-editable) install builds a wheel:
pip install . # NOT pip install -e .
# ...or upgrade pip first, and editable works too:
pip install --upgrade pip && pip install -e .For a truly air-gapped host, build the wheels on a connected machine and copy them over — the target then needs no network:
# On a connected machine, collect this package + its dependencies as wheels:
pip wheel . -w dist # → dist/*.whl (or: uv build, for just this package)
# Copy dist/ to the air-gapped host, then install offline:
pip install --no-index --find-links dist vmware-hardenRead-Only by Design
vmware-harden is read-only against vSphere and NSX — all 8 MCP tools carry the [READ]
marker, and none mutate managed VMware infrastructure. scan_target writes only to the
local twin DB (~/.vmware-harden/twin.duckdb), a cache of its own observations rather than
managed infrastructure. Remediation is never applied by this skill; it is deferred to
vmware-pilot, which provides approval gating and audit trails for write operations.
Built-in baselines
Baseline | Rules | Applies to | Source |
| 20 | host | CIS Benchmark v1.0 |
| 15 | host, vm | |
| 20 | host, vm, datastore, dfw_rule | GB/T 22239-2019 三级 |
| 10 | host, dfw_rule | PCI-DSS v4.0 |
| 12 | host, dfw_rule | EU NIS2 Directive (Articles 21/23, Annex I) |
| 10 | host | BSI IT-Grundschutz (OPS.1.1.4 + SYS.1.1) |
| 20 | host | Inherits |
| 15 | host, vm | Inherits |
| 12 | host | vSphere 9 STIG-aligned host advanced settings (DoD/DISA STIG content) — collector verified on ESXi 8.0.3; not yet run against 9.x |
baseline list returns 9 IDs: the 7 rule-bearing baselines above (99 rules total) plus the
two v9 aliases, which carry no rules of their own and resolve to their v8 parent's.
VCF 9.0 / 9.1 Compatibility
The existing baselines (cis-vmware-esxi-8.0-subset, vsphere-scg-v8, dengbao-2.0-level3-vmware, pci-dss-4.0-vmware) scan VCF 9.0 / 9.1 clusters successfully — most rules target host advanced settings stable across 8.x → 9.x. cis-vmware-esxi-9.0-subset and vsphere-scg-v9-subset ship today as extends: aliases of their v8 parents — same rules, a v9-named ID to scan and report under. Rules specific to 9.x will be added to them as Broadcom publishes the v9 guides.
vsphere-stig-v9-subset is a rule-bearing STIG-aligned baseline: 12 host advanced-setting controls (account lockout, password policy, DCUI access, shell/DCUI timeouts, MOB, guest BPDU, remote syslog) mapped to the official open-source vSphere STIG content (MITRE InSpec / Cinc Auditor). Status: experimental. Its checks read ESXi host advanced settings the host collector fetches via a config.option PropertyCollector pass. That pass was verified end-to-end on 2026-08-13 against a live standalone ESXi 8.0.3 (build 24280767): all 12 attributes came back populated, with values in the shapes the rules expect (account_lock_failures=5, dcui_access='root', password_quality_control='retry=3 min=disabled,disabled,disabled,7,7', mob_enabled=False, syslog_remote_host=''), and the scan raised 3 genuine violations. Still unverified, and why the status stays experimental: ESXi 9.x, which is what this baseline actually targets, and any vCenter-managed multi-host inventory. Treat results on 9.x as non-authoritative. The v1.9.0 undetermined mechanism does not cover a failed fetch on its own: it refuses a rule when no collector declares the attribute, a static check against the vocabulary, and these STIG attributes are declared, so their rules do run. If the real PropertyCollector pass comes back empty on live hardware, the attribute is simply absent and the rule again matches zero rows. v1.10.0 catches that case — such a host is recorded as a per-node gap (coverage.undetermined_node_checks) rather than a pass, so an unverified collector shows up as unjudged hosts instead of a clean report. What remains unverified is whether the pass returns the right values, which no coverage mechanism can tell you. The baseline's status field is surfaced by list_baselines and describe_stig_content_sync so a scan self-declares this caveat. It is a content sync, not an API wrapper — VCF Operations 9.1 Automated Configuration Compliance (ACC) / Security Posture Management (SPM) is UI- and schedule-driven and exposes no public compliance REST API. For continuous, fleet-wide enforcement and automated remediation, use VCF Operations SPM/ACC (UI); vmware-harden is the API-scriptable, DuckDB-persisted, cross-target point-in-time scanner. See references/stig-content-sync.md and inspect the catalog with vmware-harden stig controls.
Official Broadcom References
Security Configuration Guides: https://core.vmware.com/security/ — vSphere SCG v8 / future v9
SDKs: https://developer.broadcom.com/sdks — VCF Python SDK (for fetching host config via REST)
CIS Benchmarks: https://www.cisecurity.org/cis-benchmarks/ — CIS VMware ESXi Benchmark v1.0 (8.0 / future 9.0)
Custom baselines
vmware-harden baseline validate ./my-strict.yaml
vmware-harden baseline import ./my-strict.yaml --name my-strict-cis
vmware-harden scan --target <vc> --baseline my-strict-cisYAML supports extends: for inheriting from a built-in baseline. See skills/vmware-harden/references/cli-reference.md.
MCP server
vmware-harden mcp # stdio MCP server (legacy alias: vmware-harden-mcp)Configure your MCP client with one of examples/mcp-configs/*.json. 8 read-only tools: list_baselines, get_baseline_rules, list_stig_controls, describe_stig_content_sync, list_violations, get_remediation, list_drift_events, scan_target.
Architecture
Estate Digital Twin — DuckDB single file at
~/.vmware-harden/twin.duckdb. Multi-target safe via target prefix on all node IDs.Collectors — lazy-import sibling vmware-* skills (no spawn overhead). All scans are READ; writes deferred to vmware-pilot.
Baseline schema — Pydantic v2, strict (
extra="forbid"),extends:inheritance, user-dir override.Drift — pure diff function with optional persistence; auto-runs after every scan.
Advisor — LLM-driven Suggestion generation; Anthropic provider with prompt caching; mock fallback for tests / no-API-key environments.
Audit — every MCP tool wrapped with
@vmware_toolfrom family vmware-policy.Web — FastAPI + Jinja2 + Tailwind/HTMX/ECharts CDN.
Lab regression
export VMWARE_HARDEN_LAB_TARGET=<your-vc>
pytest tests/eval/regression -v -m labFamily
vmware-aiops — host inventory + ops (used by harden's HostCollector)
vmware-monitor — read-only counterpart
vmware-storage — datastore inventory
vmware-nsx-security — DFW inventory
vmware-pilot — execute remediations (writes; out of scope for harden)
vmware-policy —
@vmware_toolaudit decorator
Acceptance criteria (v1.5.18 GA)
221 tests passing
Bandit: 0 issues at any severity
All 8 MCP tools audited
SKILL.md ≤ 3000 words, family-convention compliant
SECURITY.md with 6 elements + Broadcom disclaimer
9 built-in baselines (99 rules across 7 rule-bearing sets + 2 v9 aliases)
vmware-harden doctorfor environment diagnosticsGA member of vmware-* family (version-aligned at 1.5.28)
References
Family CLAUDE.md:
CLAUDE.mdat the monorepo root
License
MIT
Available Tools
8 toolsdescribe_stig_content_syncARead-onlyIdempotent
[READ] Explain harden's vSphere STIG integration and route continuous enforcement. Takes no parameters. Returns {compliance_api_available (always false — VCF Operations ACC/SPM exposes no public compliance REST API), why_no_api, content_sources (the open-source MITRE InSpec/Cinc STIG repos harden syncs against), mechanism (how upstream controls become harden rules), routing_note (use VCF Operations SPM/ACC UI for fleet-wide continuous enforcement; harden is the API-scriptable point-in-time scanner), importer_status}. Read-only, local static content — no database, network, or API call. Call this before assuming a compliance endpoint exists; use list_stig_controls to see the actual controls.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint, idempotentHint, destructiveHint), the description discloses meaningful behavioral detail: 'Read-only, local static content — no database, network, or API call.' It also reveals the key invariant that compliance_api_available is 'always false', which is critical for the agent to know before calling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Although the description is dense, every sentence earns its place: purpose, return field semantics, routing guidance, and behavioral guarantees. The most important usage instruction is front-loaded, and the output field breakdown compensates for the absent output schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description fully documents the return shape and key field meanings. It also covers behavioral aspects, prerequisites, and the relationship to sibling tools. Nothing critical is missing for an agent to decide when and how to call this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the baseline is 4. The description confirms 'Takes no parameters,' which fully covers the parameter dimension.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb-resource pair: 'Explain harden's vSphere STIG integration' and clearly states its routing role. It also distinguishes itself from the sibling tool list_stig_controls by noting that callers should use that tool to see actual controls.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides direct guidance: 'Call this before assuming a compliance endpoint exists; use list_stig_controls to see the actual controls.' This explicitly tells the agent when to invoke this tool and names the alternative, making the usage context unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_baseline_rulesARead-onlyIdempotent
[READ] Return every rule in one compliance baseline. Returns the family list envelope {items, returned, limit, total, truncated, hint}; each item is {id, title, severity, category}, where severity is one of 'critical', 'high', 'medium', 'low', 'info'. The whole baseline is returned, so truncated is always false and total is the exact rule count. Read-only — parses local baseline YAML only, no database or network access. Use after list_baselines to preview what scan_target will check; use list_violations for actual scan findings.
| Name | Required | Description | Default |
|---|---|---|---|
| baseline_id | Yes | A baseline id exactly as returned by list_baselines — e.g. 'cis-vmware-esxi-8.0-subset', 'vsphere-stig-v9-subset' — not the baseline's display name. Unknown ids raise a not-found error; re-run list_baselines for the valid set, which includes any YAML you dropped in ~/.vmware-harden/baselines/. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint and idempotentHint annotations, the description discloses that the tool parses local baseline YAML only with no database or network access, always returns the whole baseline, and guarantees truncated is false and total is exact. It also documents severity values and the error behavior for unknown ids in the schema description, giving the agent a strong behavioral model.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Every sentence adds value: the main action, the exact return envelope, the severity vocabulary, the guaranteed truncation behavior, the read-only/local nature, and the sibling routing. The description is slightly longer than minimal, but the extra details are necessary because there is no output schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read-only tool with no output schema, the description explains the return shape, field semantics, severity values, uniqueness guarantees, input requirements, error behavior, and when to use sibling tools. Nothing needed for correct selection or invocation appears to be missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the baseline_id property in the schema already provides rich guidance: exact format, examples, the caution against display names, and behavior on unknown ids. The tool description reinforces the single-baseline scope, but the schema already carries the parameter-semantics burden, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with '[READ] Return every rule in one compliance baseline,' which names a specific verb and resource and clarifies the tool returns the full rule set for a single baseline. This clearly distinguishes it from siblings like list_baselines and list_violations by stating the scope and object of the operation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Use after list_baselines to preview what scan_target will check; use list_violations for actual scan findings' explicitly tells the agent when to call this tool and which sibling to use for a different purpose. The baseline_id schema description also reinforces the relationship to list_baselines and warns against using display names.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_remediationARead-onlyIdempotent
[READ] Fetch the persisted LLM-generated remediation Suggestion for one violation. Returns {summary, execution_plan.steps, impact_prediction (workload impact, maintenance window, rollback plan), confidence (0.0-1.0), human_review_required}, or None when no advisor suggestion has been generated for that violation yet (generate one via the vmware-harden CLI advisor). Read-only lookup in the local twin DB (~/.vmware-harden/twin.duckdb); no network calls and nothing is executed — suggestions are advisory only.
| Name | Required | Description | Default |
|---|---|---|---|
| violation_id | Yes | The 'id' field of a row returned by list_violations (the violation's own id, not its rule_id or node_id). An id with no stored suggestion returns None rather than an error, so None means "not generated yet", not "not found". |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint annotation, the description discloses that the call is a read-only local DB lookup, makes no network calls, executes nothing, and returns advisory content only. It also explains the None-vs-error behavior, providing meaningful behavioral context that annotations alone would not convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with '[READ]' and a direct action statement, then efficiently lists return fields, the None edge case, and execution constraints. Every sentence carries useful information without redundancy or padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter read tool with a rich output schema, the description covers the input source, the missing-suggestion case, the storage location, and execution safety. Nothing an agent needs to invoke it correctly is left out.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The schema already details that violation_id must be the violation's own id and that missing suggestions return None; the tool description repeats and reinforces this rather than adding entirely new parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Fetch') and resource ('persisted LLM-generated remediation Suggestion for one violation'), and it enumerates the return fields. This clearly identifies the tool's action and distinguishes it from sibling list/get tools targeting baselines, rules, or violations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clarifies that the violation_id must come from list_violations and explains that None means the suggestion has not been generated, with an explicit pointer to the vmware-harden CLI advisor for generation. It does not explicitly contrast against sibling tools, but the usage context is clear and includes a generation pathway.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_baselinesARead-onlyIdempotent
[READ] List all available compliance baselines: built-in (CIS ESXi 8.0, vSphere SCG v8, PCI-DSS 4.0, DengBao 2.0 L3, EU NIS2, BSI ITGS) plus any user-imported YAML baselines from ~/.vmware-harden/baselines/. Takes no parameters. Returns the family list envelope {items, returned, limit, total, truncated, hint}; each item is {id, name, version, applies_to (node types covered), rule_count}, and entries that fail to load carry an 'error' field instead. Every baseline is listed, so truncated is always false and total is exact — this is the complete set, not a page of it. Read-only — parses local baseline YAML only, no database or network access. Start here to discover valid baseline ids for get_baseline_rules and scan_target.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as read-only and idempotent, and the description adds substantial context: it parses local YAML onl, has no database or network access, returns the complete set with exact totals, and reports failed entries via an error field. This goes well beyond structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is detailed but every sentence earns its place: the builtin list removes ambiguity, the return format compensates for the missing output schema, and the read-onl/source note adds safety context. It is front-loaded with the [READ] tag and the core purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Since there is no output schema, the description fully explains the return envelope and item fields, including the error case and truncation behavior for the complete set. It also covers the data source and the downstream use for baseline ids. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters and the schema already exhaustively covers this. The description confirms there are no parameters, which is appropriate, but there is no additional semantic detail needed. Baseline for 0 params is 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'List all available compliance baselines', enumerates built-in sources and the local YAML path. It also positions itself as the discovery entry point for get_baseline_ules and scan_target, which helps distinguish it from sibling toools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear context with 'Start here to discover valid baseline ids for get_baseline_ules and scan_target.' This is strong usage guidance, but it does not explicitly state when not to use this tool or contrast it with all alternatives, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_drift_eventsARead-onlyIdempotent
[READ] List configuration drift events from the most recent scan snapshot — fields whose values changed since the prior scan of the same target. Returns the family list envelope {items, returned, limit, total, truncated, hint}; each item is {node_id, field, old_value, new_value, detected_at}. total is the snapshot's exact change-event count, so truncated tells you definitively whether rows were left behind — raise limit when it is true. Returns an empty envelope (total 0) when no snapshot exists or there was no prior snapshot to diff against (a target must be scanned at least twice). Read-only query of the local twin DB (~/.vmware-harden/twin.duckdb); no network calls. Use for change tracking; use list_violations for compliance failures.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum rows returned, ordered by node_id then field (default 50). There is no offset or cursor here — this tool cannot page, so when the envelope's 'truncated' is true the only way to see the rest is to re-call with a larger limit. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, but the description adds meaningful behavior beyond them: read-only query of the local twin DB path, no network calls, exact total count semantics, definitive truncated behavior, and empty-envelope behavior when no prior snapshot exists. This is substantial context, not just annotation repetition.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but well-ordered: purpose first, then response envelope, item shape, pagination/count semantics, edge cases, storage/network behavior, and usage routing. Every sentence carries load-bearing information; there is no filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, yet the description fully documents the envelope fields, item fields, total/truncated semantics, empty-envelope conditions, storage location, read-only nature, and routing to list_violations. An agent has everything needed to invoke the tool and interpret its results correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema covers 'limit' at 100%, but the description adds crucial actionable semantics: ordering by node_id then field, no offset/cursor, and explicit guidance to re-call with a larger limit when truncated is true. This goes well beyond the schema's 'Maximum rows returned' definition.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description starts with '[READ] List configuration drift events' and immediately scopes to the most recent scan snapshot, defining drift as fields whose values changed since the prior scan. It also explicitly distinguishes this tool from list_violations, so an agent can tell sibling tools apart without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says 'Use for change tracking; use list_violations for compliance failures,' naming the sibling alternative and the selection condition. It also states the precondition that a target must be scanned at least twice, which is critical for knowing when this tool will return empty data.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_stig_controlsARead-onlyIdempotent
[READ] List the built-in vSphere 9 / VCF 9 STIG-aligned host baseline's controls (baseline id 'vsphere-stig-v9-subset'). Returns the family list envelope {items, returned, limit, total, truncated, hint}; each item is {id, title, severity (one of critical/high/medium/low/info), category, advanced_setting} where advanced_setting names the ESXi advanced setting the control governs (e.g. 'Security.AccountLockFailures'). total is the exact catalog size, so truncated tells you definitively whether to raise offset. Read-only — parses local baseline YAML only, no database, network, or compliance API (VCF Operations ACC/SPM has none). Use scan_target with baseline 'vsphere-stig-v9-subset' to evaluate these controls against a target; use describe_stig_content_sync for how this catalog is kept in sync.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum rows in this page, must be >= 1 (default 50). The whole catalog is loaded and paged locally, so 'total' stays exact whatever you pass. | |
| offset | No | Rows to skip before the page starts, must be >= 0 (default 0 = first page). Raise it by 'limit' while 'truncated' is true. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, and the description adds substantial behavior beyond that: 'parses local baseline YAML only, no database, network, or compliance API' and exact pagination behavior via 'truncated tells you definitively whether to raise offset'. This gives an agent confidence about side effects, latency, and paging in one place.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the essential purpose, then returns format, then behavioral caveats, then sibling routing. Every sentence carries operational value with no filler, despite the length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description fully specifies the return envelope ({items, returned, limit, total, truncated, hint}) and item fields, including severity enum and advanced_setting example. Combined with parameters and annotations, nothing needed to invoke and interpret the tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds genuinely useful semantics: the entire catalog is loaded and paged locally, keeping total exact and making truncated a definitive paging signal. This explains why offset/limit behave as they do beyond the schema's field descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'List the built-in vSphere 9 / VCF 9 STIG-aligned host baseline's controls', including the exact baseline id. This clearly differentiates it from sibling tools like scan_target and list_violations, so an agent knows precisely what the tool returns.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly routes to alternatives: use scan_target with the same baseline to evaluate controls against a target, and describe_stig_content_sync to learn about catalog sync. It also characterizes the operation as read-only local parsing, making it clear when this listing tool is the right choice.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_violationsARead-onlyIdempotent
[READ] List compliance violations recorded by the most recent scan
snapshot in the local twin DB (~/.vmware-harden/twin.duckdb).
Returns an envelope {violations: [...], total, limit, offset,
has_more, coverage, note}; each violation is {id, rule_id, node_id,
severity, baseline_id, evidence}, sorted severity-descending then rule_id.
total is the full matching count (unbounded by limit) so nothing is
hidden — page by raising offset while has_more is true. AN EMPTY LIST IS
NOT A COMPLIANCE VERDICT: rules whose data no collector gathers are not
executed and count as undetermined, never as passing. Read coverage
{evaluated, undetermined, total, tracked, complete, undetermined_rules}
before summarising — when complete is false, say how many rules were
evaluated out of how many and do not call the estate compliant or clean;
when tracked is false the snapshot predates coverage tracking, so re-scan
rather than assume. note states the same in one sentence, or null when
coverage is complete. Empty envelope (total 0) when no scan exists — run
scan_target first. Read-only local DB query, no network calls. Pass a
row's 'id' to get_remediation for a fix plan.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum rows in this page, must be >= 1 (default 50). It bounds the rows serialized, not the 'total' count, so a small limit never hides how much there is. | |
| offset | No | Rows to skip before the page starts, must be >= 0 (default 0 = first page). Page by raising it by 'limit' while the envelope's has_more is true. | |
| severity | No | Return only violations of exactly this severity. One of 'critical', 'high', 'medium', 'low', 'info' — lowercase, matched exactly; anything else is refused with a ValueError naming the five. Omit to return every severity (the default). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With readOnlyHint=true and idempotentHint=true, annotations already establish the safe, non-destructive nature, but the description adds substantial context: no network calls, local DuckDB storage, envelope shape, pagination semantics, coverage semantics, and the critical warning that an empty list means undetermined, not compliant. This goes well beyond what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but dense with essential operational warnings, making it justifiably detailed for a tool with tricky semantics (coverage, empty-list meaning). It front-loads the purpose and read-only nature. Minor redundancy with schema-level pagination descriptions keeps it from a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description compensates by fully specifying the return envelope and violation fields, sorting, pagination, coverage semantics, and the no-scan case. It also covers the prerequisite action and the remediation handoff. The agent has everything needed to call this tool correctly and interpret its results safely.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the parameter descriptions already explain limit/offset behavior, severity matching, and defaults. The tool description adds little to parameter-level meaning beyond reinforcing pagination with has_more and noting that total is unbounded. Baseline 3 is appropriate since the schema carries the semantic burden.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb-resource pair: '[READ] List compliance violations recorded by the most recent scan snapshot'. This clearly identifies what is returned and the data source (local twin DB). It distinguishes itself from related tools by referencing get_remediation for follow-up on a row ID.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when to use this tool (to list violations from the latest scan), when not to trust an empty result as a compliance verdict, and what to do first if no scan exists ('run scan_target first'). It also tells the agent to route to get_remediation for a fix plan, providing clear alternative guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
scan_targetARead-onlyIdempotent
[READ] Run a compliance scan of a vCenter target against a baseline and
persist results locally. Makes read-only vCenter API calls (inventory collection only — never modifies
VMware infrastructure) and writes a new snapshot, violations, and drift
events (vs the prior scan of the same target) to the local twin DB
(~/.vmware-harden/twin.duckdb). Returns summary counts {snapshot_id,
target, baseline, hosts, violations, coverage, note}; inspect details via
list_violations and list_drift_events. violations is meaningful only
together with coverage: rules whose data no collector gathers are not
executed and count as undetermined, never as passing, so violations=0 is
not by itself evidence of compliance. When coverage.complete is false,
report how many rules were evaluated out of how many instead of calling
the estate compliant. May take minutes on large inventories.
| Name | Required | Description | Default |
|---|---|---|---|
| target | Yes | A vCenter target name as configured in vmware-aiops (~/.vmware-aiops/config.yaml) — this skill has no target config of its own and borrows aiops' connection manager. Use the config's target key, not a hostname or IP. | |
| baseline | No | A baseline id from list_baselines (default 'cis-vmware-esxi-8.0-subset'). Which baseline you pick decides which rules can reach a verdict at all: a baseline whose rules need data no collector gathers reports them as undetermined, which is why coverage must be read alongside the violation count. | cis-vmware-esxi-8.0-subset |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description is extremely transparent about side effects: it writes a new snapshot, violations, and drift events to twin.duckdb, makes only read-only vCenter calls, and warns about coverage interpretation. However, it contradicts the annotations: readOnlyHint=true and idempotentHint=true despite 'writes a new snapshot' and persistent local writes, so the required contradiction penalty applies.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but dense and front-loaded: the main purpose and '[READ]' safety cue come first, followed by side-effect details, return shape, interpretation caveat, and timing warning. Every sentence adds operational value; none is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description still specifies the exact summary fields, names follow-up tools, discloses local persistence and duration, and explains how to interpret violations/coverage. This is complete for an agent to decide to call it and to interpret its result correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the description adds interpretive meaning beyond the schema, especially for baseline: the choice of baseline determines which rules can reach a verdict, and coverage must be read alongside violations. The target parameter's 'config key, not hostname' rule is already in the schema, so the description doesn't need to repeat it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific action ('Run a compliance scan of a vCenter target against a baseline and persist results locally') and a clear resource (vCenter target). It also distinguishes itself from sibling list/get tools by stating that follow-up details are inspected via list_violations and list_drift_events.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit context: target must be a configured vmware-aiops key, baseline should come from list_baselines, and results are inspected with the list_violations/list_drift_events siblings. It does not explicitly state 'use X instead of this' because no sibling performs scans, but the when-to-use context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
8 tool updates
v1.10.4- Changed
describe_stig_content_sync1 field changed- added
Input schema / additionalPropertiesAdded value: +false
- Changed
get_baseline_rules2 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / baseline_id / descriptionAdded value: +"A baseline id exactly as returned by list_baselines — e.g. 'cis-vmware-esxi-8.0-subset', 'vsphere-stig-v9-subset' — not the baseline's display name. Unknown ids raise a not-found error; re-run list_baselines for the valid set, which includes any YAML you dropped in ~/.vmware-harden/baselines/."
- Changed
get_remediation2 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / violation_id / descriptionAdded value: +"The 'id' field of a row returned by list_violations (the violation's own id, not its rule_id or node_id). An id with no stored suggestion returns None rather than an error, so None means \"not generated yet\", not \"not found\"."
- Changed
list_baselines1 field changed- added
Input schema / additionalPropertiesAdded value: +false
- Changed
list_drift_events2 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / limit / descriptionAdded value: +"Maximum rows returned, ordered by node_id then field (default 50). There is no offset or cursor here — this tool cannot page, so when the envelope's 'truncated' is true the only way to see the rest is to re-call with a larger limit."
- Changed
list_stig_controls3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / limit / descriptionAdded value: +"Maximum rows in this page, must be >= 1 (default 50). The whole catalog is loaded and paged locally, so 'total' stays exact whatever you pass." - added
Input schema / properties / offset / descriptionAdded value: +"Rows to skip before the page starts, must be >= 0 (default 0 = first page). Raise it by 'limit' while 'truncated' is true."
- Changed
list_violations4 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / limit / descriptionAdded value: +"Maximum rows in this page, must be >= 1 (default 50). It bounds the rows serialized, not the 'total' count, so a small limit never hides how much there is." - added
Input schema / properties / offset / descriptionAdded value: +"Rows to skip before the page starts, must be >= 0 (default 0 = first page). Page by raising it by 'limit' while the envelope's has_more is true." - added
Input schema / properties / severity / descriptionAdded value: +"Return only violations of exactly this severity. One of 'critical', 'high', 'medium', 'low', 'info' — lowercase, matched exactly; anything else is refused with a ValueError naming the five. Omit to return every severity (the default)."
- Changed
scan_target3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / baseline / descriptionAdded value: +"A baseline id from list_baselines (default 'cis-vmware-esxi-8.0-subset'). Which baseline you pick decides which rules can reach a verdict at all: a baseline whose rules need data no collector gathers reports them as undetermined, which is why coverage must be read alongside the violation count." - added
Input schema / properties / target / descriptionAdded value: +"A vCenter target name as configured in vmware-aiops (~/.vmware-aiops/config.yaml) — this skill has no target config of its own and borrows aiops' connection manager. Use the config's target key, not a hostname or IP."
2 tool updates
v1.9.0- Added
describe_stig_content_sync - Added
list_stig_controls
3 tool updates
v1.8.8- Changed
get_baseline_rules1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "items": { - "additionalProperties": true, - "type": "object" - }, - "title": "Result", - "type": "array" - } - }, - "required": [ - "result" - ], - "title": "_get_baseline_rules_implOutput", - "type": "object" -}New value: +null
- Changed
list_baselines1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "items": { - "additionalProperties": true, - "type": "object" - }, - "title": "Result", - "type": "array" - } - }, - "required": [ - "result" - ], - "title": "_list_baselines_implOutput", - "type": "object" -}New value: +null
- Changed
list_drift_events1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "items": { - "additionalProperties": true, - "type": "object" - }, - "title": "Result", - "type": "array" - } - }, - "required": [ - "result" - ], - "title": "_list_drift_events_implOutput", - "type": "object" -}New value: +null
1 tool update
v1.6.2- Changed
list_violations3 fields changed- added
Input schema / properties / limitAdded value: +{ + "default": 50, + "title": "Limit", + "type": "integer" +} - added
Input schema / properties / offsetAdded value: +{ + "default": 0, + "title": "Offset", + "type": "integer" +} - changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "items": { - "additionalProperties": true, - "type": "object" - }, - "title": "Result", - "type": "array" - } - }, - "required": [ - "result" - ], - "title": "_list_violations_implOutput", - "type": "object" -}New value: +null
6 tool updates
v1.5.29- Added
get_baseline_rules - Added
get_remediation - Added
list_baselines - Added
list_drift_events - Added
list_violations - Added
scan_target
6 tool updates
v1.5.28- Removed
get_baseline_rules - Removed
get_remediation - Removed
list_baselines - Removed
list_drift_events - Removed
list_violations - Removed
scan_target
6 tool updates
v1.5.22- First observed
get_baseline_rules - First observed
get_remediation - First observed
list_baselines - First observed
list_drift_events - First observed
list_violations - First observed
scan_target
TDQS
Scored across 8 tools
Most tools have clearly distinct purposes: baselines, rules, scans, violations, drift, remediation, and STIG sync are separate concerns. The main ambiguity is between get_baseline_rules and list_stig_controls, since both can return rule/control lists for baselines, though the STIG-specific tool adds advanced_setting detail.
The naming pattern is mostly verb_noun and readable, with list_* for collections and get_* for specific lookups. Minor inconsistency exists between list_baselines and get_baseline_rules, plus scan_target and describe_stig_content_sync break the simple list/get prefix pattern, but the style is consistent enough to predict behavior.
Eight tools is well-scoped for a compliance scanning and remediation advisory server. Each tool covers a distinct part of the workflow from baseline discovery, rule preview, scanning, violation review, drift tracking, and remediation lookup without feeling padded or redundant.
The core lifecycle is covered: discover baselines, inspect rules, scan a target, list violations, inspect drift, and fetch remediation. Minor gaps exist—there is no tool to manage scan history, list targets, or generate remediation suggestions directly—but agents can work around these via the CLI or by treating this as a read-only reporting surface.
Maintenance
Related MCP Connectors
Compliance frameworks (SOC 2, ISO 27001, CMMC, NIST, more) delivered to AI agents as MCP tools.
CTEM for your Trusteed tenant: security summary, findings, compliance gaps, and scans via OAuth.
Threat modeling, code/cloud/pipeline scanning, shadow-AI discovery, compliance checks and fixes.
HIPAA compliance AI agent — scan, grade, SRA, and generate compliance docs.
Related MCP Servers
- FlicenseBqualityDmaintenanceEnables security auditing, penetration testing, and compliance validation with tools like Semgrep, Trivy, Gitleaks, and OWASP ZAP. Features strict project boundary enforcement and supports OWASP, CIS, and NIST compliance frameworks.7-
- AlicenseNot gradedqualityDmaintenanceEnables secure management of VMware vCenter 8.0+ environments through controlled operations including VM lifecycle management, snapshots, and resource discovery with built-in RBAC authorization, audit logging, and rate limiting.6MIT
- AlicenseAqualityAmaintenanceRead-only VMware vCenter/ESXi monitoring. 8 MCP tools for VM inventory, host status, datastore capacity, cluster info, alarms, events, and VM details. Code-level enforced safety — no destructive operations exist in the codebase. Supports vSphere 6.5–8.0. Works with local models via Ollama/LM Studio.3212MIT
- AlicenseNot gradedqualityBmaintenanceIntegrates authoritative security compliance frameworks (ISO 27001, NIST 800-53, OWASP ASVS, NIST SSDF) into AI-assisted development, offering control lookups, cross-framework mappings, build-time guardrails, and automated audit evidence generation.174 npm3MIT