tenable-vpr-mcp
MCP server for Tenable.io/One Vulnerability Management that provides read-only tools for querying scans, assets, plugins, and vulnerabilities, plus specialized reporting tools for VPR re-prioritization, CISA KEV/EPSS exposure, and scan delta comparisons.
README
Tenable VPR MCP
MCP server for Tenable.io / Tenable One (Vulnerability Management API), built for pentest and exposure-management reporting workflows.
Most Tenable MCP servers (including Tenable's own hosted Hexa AI MCP) expose the API 1:1 as tools. This one does that too, but adds three tools that aren't available anywhere else on the Exchange today:
Why this one exists: compare_vpr_reprioritization
Tenable reports two ratings for the same finding:
- CVSS-based severity (
severity): the static, plugin-assigned bucket - VPR (
vpr.score): threat-intel and exploitability-weighted score
When you re-scope a client's exposure using VPR instead of raw CVSS, some findings get escalated (low CVSS, actively exploited) and some get downgraded (high CVSS, no real-world exploitation activity). That before/after delta is exactly what you need to show in a CTEM / Tenable One POC deliverable, and building it by hand from raw exports is tedious.
compare_vpr_reprioritization pulls live findings from the vulnerability
workbench and returns a sorted table (escalations first) plus a summary
rollup, ready to drop into a report or slide.
{
"summary": {"escalated": 4, "downgraded": 11, "unchanged": 52, "unrated": 2, "total_findings": 69},
"findings": [
{
"plugin_id": 12345,
"plugin_name": "Example Actively-Exploited RCE",
"cvss_severity": "medium",
"vpr_score": 9.4,
"vpr_severity": "critical",
"rerating": "escalated",
"affected_assets": 5
}
]
}
check_kev_epss_exposure
VPR is a Tenable proprietary score. This tool backs a re-prioritization
argument with two independent, public data sources instead: the CISA
KEV catalog (confirmed real-world exploitation) and FIRST.org EPSS
(30-day exploitation probability). Each finding gets a signal:
confirmed_exploited > high_probability > low_signal > no_cve_data,
sorted most urgent first, plus a ransomware-association flag from KEV.
Note: this does one extra Tenable API call per distinct plugin (to resolve
CVEs via workbenches.vuln_info), so keep limit modest for interactive
use.
scan_delta
Compares a baseline scan against a re-test scan by plugin ID and buckets
findings into fixed, still_open, and new_since_baseline, with a
remediation-rate percentage. Built for the re-test report every pentest
engagement ends with.
All tools
| Tool | Description |
|---|---|
list_scans |
List scans, optionally by folder |
get_scan_details |
Latest results for one scan (hosts, findings, severity counts) |
list_assets |
List known assets (capped) |
get_asset_details |
Full detail for one asset by UUID |
search_vulnerabilities |
Workbench findings, filterable by severity / plugin family |
get_plugin_details |
Plugin description, solution, CVEs, VPR drivers |
list_tags |
Asset tag categories and values |
list_agents |
Nessus Agent inventory and status |
compare_vpr_reprioritization |
CVSS vs. VPR before/after comparison table |
check_kev_epss_exposure |
CVSS/VPR findings cross-referenced against CISA KEV + EPSS |
scan_delta |
Baseline vs. re-test comparison for remediation validation |
This server is read-only by design: no scan launch, edit, or delete tools are exposed, so it's safe to point at a production tenant.
Filter arguments
search_vulnerabilities, compare_vpr_reprioritization, and
check_kev_epss_exposure share two optional filters:
severity— a list ofinfo/low/medium/high/critical. Case-insensitive; the server capitalizes them to the form the workbench API requires.plugin_family— a list of family names (["Windows", "Web Servers"]) or numeric family IDs. Names are resolved to IDs on first use, since the workbench only filters onplugin.family_id. An unknown name raises before any API call is made.
Output
Every tool returns the same envelope, so credential, authentication, and API errors reach the client as readable text instead of a crash:
{"ok": true, "data": ...}
{"ok": false, "error": "UnexpectedValueError: ..."}
compare_vpr_reprioritization and check_kev_epss_exposure return a
summary rollup plus a findings list sorted most-urgent-first, in the
shape shown in the compare_vpr_reprioritization example above.
scan_delta returns fixed / still_open / new_since_baseline lists
plus a summary with counts and remediation_rate_pct. The remaining
tools return the Tenable API payload as-is under data.
Prerequisites
- Python 3.10 or newer
- A Tenable.io / Tenable One account that can generate API keys
Setup
See USAGE.md for full setup, client configuration, and example prompts. Quick version:
git clone https://github.com/Sabastiaz/tenable-vpr-mcp
cd tenable-vpr-mcp
python -m venv .venv && source .venv/bin/activate
pip install -e .
export TIO_ACCESS_KEY=your_access_key
export TIO_SECRET_KEY=your_secret_key
# optional, defaults to https://cloud.tenable.com
export TIO_URL=https://cloud.tenable.com
tenable-vpr-mcp
Generate API keys in Tenable.io / Tenable One under Settings > My Account > API Keys. Never pass keys as CLI arguments; use environment variables only.
Claude Code
claude mcp add tenable-vpr -- tenable-vpr-mcp
(with TIO_ACCESS_KEY / TIO_SECRET_KEY set in your shell environment
before running the command above).
Claude Desktop (claude_desktop_config.json)
{
"mcpServers": {
"tenable-vpr": {
"command": "tenable-vpr-mcp",
"env": {
"TIO_ACCESS_KEY": "your_access_key",
"TIO_SECRET_KEY": "your_secret_key"
}
}
}
}
Limitations
- The vulnerability workbench caps every query at 5,000 findings. This
is a Tenable API limit, not a limit of this server — raising
limitpast 5,000 returns no more records. On a large tenant, filter byseverityorplugin_familyto keep each query under the cap, or the results are silently truncated. (pyTenable also marks the workbench module deprecated in favour of the exports API; moving to exports is the fix for full-tenant extraction and is not implemented yet.) check_kev_epss_exposureissues one extra Tenable API call per distinct plugin to resolve CVEs viaworkbenches.vuln_info. Keeplimitmodest (20–30) for interactive use. Plugin CVE lookups are not cached between calls; the CISA KEV catalog is cached in-process for six hours.- Findings are aggregated per plugin, not per host.
affected_assetsis a host count; useget_scan_detailsorscan_deltawhen you need scan-scoped, per-host detail. search_vulnerabilitiesandcompare_vpr_reprioritizationread tenant-wide state, not the results of one scan.- A VPR score of
Noneis reported asunrated, not as low risk. Tenable does not score every plugin — end-of-life and configuration findings frequently have no VPR at all, so they need to be reviewed separately rather than sorted to the bottom. - No write operations (scan launch/configure, tag assignment, asset deletion) are implemented, by design.
Development
pip install -e ".[dev]"
pytest tests/ -v
(Quote the extras — unquoted .[dev] is a glob pattern in zsh.)
The suite runs with no live Tenable / CISA / FIRST.org calls:
| File | Covers |
|---|---|
tests/test_findings.py |
Normalizing the workbench's flat records and integer severities |
tests/test_vpr.py |
CVSS vs. VPR comparison and bucket boundaries |
tests/test_kev.py |
KEV/EPSS signal classification and CVE extraction |
tests/test_scan_diff.py |
Baseline vs. re-test bucketing |
tests/test_server_filters.py |
Severity capitalization and family-name resolution |
tests/fixtures.py |
Payloads captured verbatim from a live tenant |
Keep tests/fixtures.py faithful to what the API actually returns. The
workbench sends plugin_id / plugin_name / vpr_score at the top level
and severity as an integer 0–4, not the nested, label-severity shape
most Tenable API examples use — fixtures written in the nested shape pass
while every live call fails.
demo.py exercises all 11 tools through their real code path with the
Tenable client and KEV/EPSS lookups faked, so it needs no credentials:
python demo.py
License
MIT
Recommended Servers
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.
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.
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.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
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.
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.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
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.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.