Tenable PCI ASV Scan Readiness

Tenable PCI ASV Scan Readiness

Connects AI assistants to the Tenable VM API to evaluate PCI quarterly external scan readiness with deterministic filtering, a readiness score, and dispute worksheets.

Category
Visit Server

README

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.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured