Skip to main content
Glama
amcdonnell-dot

Tenable PCI ASV Scan Readiness

Tenable PCI ASV Scan Readiness — MCP Server

tests License: MIT Python 3.10+

An MCP server that sits between an AI assistant and Tenable's Vulnerability Management API and tells you whether a PCI Quarterly External scan is actually ready for ASV attestation — before you submit it and find out the hard way.

Why this exists

Tenable's ASV Workbench doesn't forgive an undisputed failure: every finding at Medium severity or above needs a disposition — remediate it or dispute it — and a few conditions (malware/backdoor indicators, unsupported software) fail the scan outright no matter what their CVSS score says. Working that out by hand means trawling the raw scan output, cross-referencing the ASV Program Guide, and guessing at which findings are actually worth disputing versus just patching.

This server does that work for you. It pulls a scan, filters it down to what actually matters for PCI (Info/Low noise gets dropped, but automatic-fail conditions are kept regardless of their scored severity), computes a 0–100 readiness score, and builds a dispute-prep worksheet keyed to the three reasons Tenable's Workbench will actually accept: False Positive, Compensating Controls, Exception.

Everything the score and worksheet are based on lives in plain, unit-tested Python functions (no LLM calls, no guessing) — the AI assistant is there to drive the tools and explain the output, not to invent the analysis.

Quick start

You'll need a Tenable VM account with a PCI ASV license and API keys, and Python 3.10+.

git clone https://github.com/amcdonnell-dot/pci-asv-readiness-mcp.git
cd pci-asv-readiness-mcp

Recommended — run it with uv, no manual install step:

{
  "mcpServers": {
    "tenable-pci-asv-readiness": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/pci-asv-readiness-mcp", "pci-asv-readiness-mcp"],
      "env": {
        "TENABLE_ACCESS_KEY": "your-access-key",
        "TENABLE_SECRET_KEY": "your-secret-key"
      }
    }
  }
}

Drop that into Claude Desktop's or Claude Code's MCP config, swap in your real path and keys, and restart the client. The first launch builds a virtual environment and installs dependencies automatically — there's nothing to activate and nothing to remember.

Or with pip, if you'd rather manage the venv yourself:

pip install -e .
{
  "mcpServers": {
    "tenable-pci-asv-readiness": {
      "command": "pci-asv-readiness-mcp",
      "env": {
        "TENABLE_ACCESS_KEY": "your-access-key",
        "TENABLE_SECRET_KEY": "your-secret-key"
      }
    }
  }
}

(pci-asv-readiness-mcp is the console script installed by the package — no need to point at a file path.)

Sanity-check it without an MCP client:

export TENABLE_ACCESS_KEY=your-access-key
export TENABLE_SECRET_KEY=your-secret-key
python smoke_test.py            # resolves the template, lists your PCI scans
python smoke_test.py <scan_id>  # full analysis of one scan

It only issues GET requests, so it's safe to point at a live account.

Run the tests (pure functions — no network, no credentials):

pip install -e ".[dev]"
pytest

Tools

Tool

What it returns

resolve_pci_template

The live UUID of the "PCI Quarterly External Scan" template for this account

list_pci_scans

Scans built on that template (id, name, status, last modified)

get_pci_failing_findings

PCI-impacting findings only, annotated with severity, auto-fail status, likely-false-positive pattern, and dispute category; Info/Low stripped with a count

asv_readiness_score

Advisory 0–100 composite with subscores: finding burden (40%), disputability (15%), automatic-fail exposure (20%), scan health (15%), timing (10%, only when a compliance_deadline is supplied). Unassessable dimensions are reported as not_assessed and excluded, with weights renormalized

prepare_dispute_worksheet

Per-finding evidence expectations, plausible Workbench dispute reasons, and customer questions. By default (analysis_depth="smart") also fetches per-host plugin output for the categories where it strengthens a dispute, parses what the scanner actually observed (banner, detected vs fixed version, negotiated weak ciphers), and generates finding-specific verification commands and dispute questions from it

get_finding_evidence

Deep-dive on one finding: raw plugin output across affected hosts, parsed evidence fields, and an evidence plan (verification commands + dispute questions) grounded in what the scanner actually saw

generate_html_report

Self-contained HTML readiness report — score with subscore bars, action plan, "what moves the score" table, findings, dispute worksheet. Opens offline, prints cleanly to PDF

research_finding

Research brief for an unfamiliar finding: Tenable's full plugin metadata plus scanner observations plus a deterministic first guess at the dispute angle, open research questions, and suggested web queries — built for handoff to the shipped research subagent

list_asv_workbench_scans

Scans via the dedicated GET /pci-asv/scans endpoint, with a clear message if Tenable support hasn't enabled it for your account

When a finding doesn't fit a known pattern

Every scan turns up something the deterministic layer hasn't seen before — a new plugin, an unusual asset, a finding outside the known dispute categories. When the worksheet flags one (research_recommended: true), call research_finding to pull everything Tenable knows about the plugin (GET /plugins/plugin/{id}) plus the parsed scanner output, then spawn the pci-finding-researcher subagent shipped in agents/pci-finding-researcher.md (copy it into your project's .claude/agents/ directory). It runs targeted web research against primary sources — vendor advisories, distro security notices, the ASV Program Guide — and comes back with a grounded call: what the finding actually is, whether to remediate or dispute it (and under which Workbench reason), what evidence to gather, and its confidence level with the gaps stated plainly. Note that the web research happens in your MCP client's agent runtime, not in this server — the server itself only ever talks to the Tenable API.

How the score works

Each dimension is framed as a question a security team is actually asking on the way to a passing attestation, and each subscore comes back with concrete next_actions derived from the scan data — the number is there to support the plan, not the other way around. The composite also returns an ordered action_plan from wherever the scan currently stands to a submittable attestation (incident response first if there are compromise indicators, then non-disputable critical/high remediation, dispute evidence gathering in parallel, medium cleanup, rescan, then submit with 30+ days of buffer).

Dimension (weight)

Question it answers

remediation_workload (40%)

How much remediation work stands between this scan and a passing attestation? Decays from 100 by severity-weighted penalties, sub-linear in instance count

dispute_leverage (15%)

How much of the failure burden could clear via evidence-backed disputes instead of patching? Names the candidate findings and the evidence to gather

attestation_blockers (20%)

Is anything present that fails the attestation regardless of CVSS? Malware/backdoor indicators zero it out (and route to IR); unsupported software caps it at 40

scan_reliability (15%)

Can this scan be trusted as the attestation basis? Scan status and host coverage

deadline_runway (10%)

Is there time left for the ASV review/dispute cycle? Only assessed when a deadline is provided, compared against the recommended 30-day buffer

All of it lives in pure functions in pci_asv_readiness/scoring.py — deterministic, unit-tested, and easy to read end to end if you want to check the math yourself.

The score is advisory. It's a readiness estimate built from the same data an ASV would see, not a compliance determination — only the actual ASV review of a submitted attestation decides that.

What data leaves your machine

This server makes outbound calls to exactly one place: the Tenable API base URL (https://cloud.tenable.com by default, overridable via TENABLE_BASE_URL). No telemetry, no other endpoints. API keys come from environment variables and are never logged or written to disk.

Rate limits

Tenable rate-limits per endpoint, and fetching per-host plugin output across a scan full of findings can trip it fast. Three things keep it under control: responses are cached in-process for the life of the server (so a score → worksheet → report sequence reuses one fetch instead of three), a per-scan host→plugin map means output is only fetched where a finding actually exists (roughly hosts + relevant-outputs calls, not hosts × findings), and 429s retry automatically with Retry-After/exponential backoff. The default analysis_depth="smart" also limits deep output analysis to categories where it actually strengthens a dispute (banner/version, SSL/TLS, automatic-fail, PCI policy); pass "full" for everything or "none" to skip it.

Known limitations

  • The score is advisory — see above. The grade bands describe readiness shape, not a compliance outcome.

  • Severity filtering uses the PCI template's own severity assignments from the scan results (which map the CVSS 4.0+ fail line to Medium+). It doesn't recompute CVSS from vectors, and recast rules don't apply to PCI template scans anyway.

  • Automatic-fail and false-positive-pattern detection are name/family heuristics (see pci_asv_readiness/filtering.py). They're intentionally conservative but can miss unusual plugin naming.

  • Plugin-output parsing (pci_asv_readiness/output_analysis.py) recognizes common Nessus evidence formats — installed/fixed version lines, banners, cipher tables. Unusual output formats fall back to category-level guidance, and output retrieval is capped per finding (max_hosts_per_finding) to bound API calls on large scans.

  • The dispute worksheet prepares evidence questions; it doesn't draft dispute text for you. Pair it with the pci-asv-dispute-assistant skill for drafting, and pci-asv-attestation-preflight for the pre-submission check.

  • GET /pci-asv/scans requires access granted by Tenable support, separate from just holding a valid ASV license.

License

MIT — see LICENSE.

-
license - not tested
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/amcdonnell-dot/pci-asv-readiness-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server