cvescout
Integrates the FIRST Exploit Prediction Scoring System (EPSS) to enrich CVE data with an estimate of the likelihood of a vulnerability being exploited in the next 30 days.
Provides access to the GitHub Advisory Database for tracking vulnerabilities in open-source packages, as well as sourcing public Proof-of-Concept (PoC) repositories.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@cvescoutshow me this week's critical CVEs ranked by patch priority"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
cvescout
English | Polski
Find the latest CVEs from live sources, rank them by patch priority, and get alerts for your products. Includes a Claude agent that is not allowed to answer from memory, and an MCP server so any agent can use the same live data.
Why: a language model only knows the CVEs that existed before its training cutoff, so when asked for the "latest" ones it
lists old ones. cvescout fetches the data at query time, in a time window counted from today:
Source | What it gives |
CVEs from the last N days or since a date, CVSS, CWE, exploit links | |
the official CVE list: last 30 days with no rate limit, about an hour ahead of NVD, vendor-supplied affected versions | |
advisories for open-source packages: package, vulnerable range, patched version | |
vulnerabilities exploited in the wild (filtered by | |
probability of exploitation in the next 30 days |
The agent (claude-opus-5-5) has tools for these sources, a prompt that forbids citing CVEs from memory, and a hard
post-check: any CVE in its answer that no tool returned is flagged with a warning. The same tools are exposed by the
MCP server, so Claude Code, Claude Desktop, Codex or your own agent can use them without a separate API key.
Installation
Works on Linux, macOS and Windows; requires Python 3.11 or newer (tested in CI on all three with Python 3.11 and 3.14).
macOS / Linux:
git clone https://github.com/zember/cvescout.git && cd cvescout
python3 -m venv .venv && .venv/bin/pip install -e '.[dev]'Windows (cmd):
git clone https://github.com/zember/cvescout.git && cd cvescout
python -m venv .venv
.venv\Scripts\pip install -e .[dev]The cvescout command lives in the virtual environment, so activate it in each new terminal
(source .venv/bin/activate, or .venv\Scripts\activate in cmd) or see Running without activate.
Note that ./cvescout in the project folder is the Python package directory, not an executable — running it gives
permission denied.
API keys are all optional except ANTHROPIC_API_KEY for ask. In cmd use set instead of export (or setx to keep it):
export NVD_API_KEY=... # 50 instead of 5 requests / 30 s: https://nvd.nist.gov/developers/request-an-api-key
export GITHUB_TOKEN=... # 5000 instead of 60 requests / h for GHSA, e.g. $(gh auth token)
export ANTHROPIC_API_KEY=... # only for `cvescout ask` (or `ant auth login`); the MCP server does not need itRelated MCP server: cve-lookup-mcp
Running without activate
Windows: the project folder contains
cvescout.cmd. RunC:\path\to\cvescout\cvescout.cmd feed --days 2, or add the project folder to PATH so thatcvescout feed --days 2works in any cmd window.macOS / Linux: run from the project folder:
mkdir -p ~/.local/bin && ln -s "$PWD/.venv/bin/cvescout" ~/.local/bin/cvescoutIf
~/.local/binis not on PATH yet, addexport PATH="$HOME/.local/bin:$PATH"to~/.zshrc(or~/.bashrc). Alternatively, an alias in the same file:alias cvescout="/path/to/cvescout/.venv/bin/cvescout". Don't put the whole.venv/binon PATH — it would shadowpythonandpipeverywhere.Any system:
pipx install -e .installscvescoutglobally in its own environment.
Usage
Every command has its own --help with all options and examples: cvescout feed --help, cvescout watch --help, ...
cvescout alone shows the commands and the most used feed options.
cvescout feed --days 2 # CVEs from the last 48 h, newest first
cvescout feed --days 7 --severity CRITICAL --enrich # this week's critical ones + EPSS/KEV/risk
cvescout feed --days 7 --sort risk # this week, most urgent to patch first
cvescout feed --days 30 --keyword fortinet
cvescout feed --days 30 --kev # added to CISA KEV in the last month
cvescout feed --days 1 --jsonOutput: for people or for agents
Mode | For | Contents |
| people | table with column headers: date, ID, CVSS, |
| scripts, other agents, pipelines | full data: whole description, CWE, CVSS vector, links, |
| people | the Claude agent's answer, in the language of the question |
| agents (Claude Code, Claude Desktop, Codex, other MCP clients) | tools returning JSON, as in |
The table may change and truncates data, so programs should read --json. Errors go to stderr with exit code 1, so a
script can detect failures. The agent behind ask does not read the table; its tools get JSON directly.
Filters
Option | Meaning |
| CVSS ≥ 8 |
| severity at least HIGH (≥ 7.0) |
| likely remote code execution (heuristic: code/command-injection CWE or wording, network vector |
| public PoC repository on GitHub or exploited in the wild; the repositories are listed under each CVE |
| one of the conditions above is enough (by default all must hold) |
| from a date instead of |
| word in the description; repeat for OR |
| exact product in NVD, e.g. |
cvescout feed --days 7 --rce --min-score 8 # RCE and CVSS >= 8
cvescout feed --days 7 --rce --min-score 8 --any # RCE or CVSS >= 8
cvescout feed --days 7 --min-score 8 --poc # CVSS >= 8 with a PoC on GitHub, links listed
cvescout feed --since 2020-01-01 --cpe nodejs:node.js --cpe haxx:curl --rce # RCE in Node.js or curl since 2020
cvescout feed --since 2020-01-01 --keyword node.js --keyword curl --rce --limit 100 # broader, by description wordsThe TAGS column shows RCE, PoC (PoC rating; GitHub repositories with --poc, --enrich or --sort risk) or EXPLOITED
(exploited in the wild: CISA KEV, SSVC or CVSS v4).
NVD accepts date ranges of up to 120 days. A longer range (
--since) needs--keywordor--cpe: the product's whole history is fetched and trimmed locally.--cpeis more precise than--keyword: it returns only CVEs where NVD marked the product as vulnerable (it skips e.g. applications that merely "run on" Linux). It only covers CVEs NVD has already analyzed, which takes days to weeks, so for the newest CVEs use--keyword, or--cvelistwith--url(below).PoC means a public PoC repository on GitHub, from nomi-sec/PoC-in-GitHub (updated daily; listed under each CVE, most starred first, and as
github_pocsin--json), or a CISA SSVCpoc/ CVSS v4E:Prating, e.g. for an exploit in a gist. The rating is ignored when the CVE links a bug bounty report (HackerOne, Bugcrowd, huntr, …): for curl it rests on the HackerOne report with reproduction steps, not on exploit code. A reference NVD tagged "Exploit" alone does not count.--pocalso passes CVEs exploited in the wild (EXPLOITED). Exploits published only in blog posts are missed, and some "PoC" repositories are only scanners.The list of CVEs with a PoC costs 2–3 GitHub API requests and is kept for 6 hours in
~/.cache/cvescout/(Windows:%LOCALAPPDATA%\cvescout\). WithoutGITHUB_TOKENGitHub allows 60 requests / h, shared with--cvelist; if the lookup fails,--enrichand--sort riskgo on without it,--pocstops with an error.PoC repositories are unverified third-party code, and fake "PoCs" carrying malware are common. Read them; don't run them outside an isolated lab.
--rceis a heuristic: treat results as "likely RCE" and read the description.Rejected CVEs (REJECTED: duplicates, IDs assigned by mistake, reports that turned out not to be vulnerabilities) are skipped.
get_cve_detailsfor a single CVE still shows the rejection.
Risk score: what to patch first
cvescout feed --days 7 --sort risk --limit 20 # this week, most urgent first
cvescout feed --cvelist --days 3 --sort risk --keyword php
cvescout feed --ghsa --days 30 --ecosystem npm --sort risk--sort risk adds EPSS and KEV, scores all matching CVEs (not just the newest --limit) and sorts them by priority.
--enrich adds the same score without reordering. In --json every CVE has
risk: {score, priority, factors}, and factors explains the rating (e.g. actively exploited (CISA KEV),
EPSS 34.00%, CVSS 9.8).
Priority | When |
| exploited in the wild (CISA KEV, SSVC "active", CVSS v4 |
| public exploit or EPSS ≥ 10% with CVSS ≥ 7 (or unknown), or likely RCE with CVSS ≥ 9 |
| public exploit or EPSS ≥ 10% (with lower CVSS), or CVSS ≥ 9, or CVSS ≥ 7 together with likely RCE or EPSS ≥ 1% |
| the rest, e.g. CVSS 7–8.9 without RCE, without an exploit and with EPSS < 1% |
For medium, likely RCE or EPSS ≥ 1% is enough. To see only RCE, add the filter: cvescout feed --days 7 --sort risk --rce.
score (0–100) orders CVEs within a priority: 50% threat (exploited 1.0, PoC 0.7, EPSS scaled so that 10% counts like a
PoC) + 40% CVSS + 10% likely RCE. Threat weighs most because most CVEs, even critical ones, are never exploited. This
is cvescout's heuristic, not an official rating. New CVEs have no EPSS yet (no EPSS yet), so their score rests on CVSS
and known exploits.
Vendor-supplied affected versions
The affected field (CVE List, get_cve_details) shows the versions the vendor (CNA) reported, and default_status
what the vendor says about all other versions (affected, unaffected, unknown or missing).
Vendors usually list only supported branches. Example: CVE-2026-109618 in PHP lists 8.2–8.5 with
default_status: unaffected, although older, unsupported versions (e.g. 7.x) may have the same bug: nobody checked
them and they will get no fix. A version missing from the list is not a safe version; the agent and the MCP server
have this in their instructions and get the warning in the affected_note field.
CPE names: cvescout cpe
A CPE name has the form vendor:product, and the vendor often differs from the common name (curl is haxx:curl, after
Haxx AB, the company of curl's author). cvescout cpe looks it up in the NVD CPE dictionary:
$ cvescout cpe nginx
CPE products for 'nginx':
f5:nginx 582 ver. F5 NGINX
nginx:nginx 543 ver. Nginx [deprecated -> f5:nginx]
igor_sysoev:nginx 383 ver. Nginx [deprecated -> nginx:nginx]
...
Use: cvescout feed --cpe f5:nginx --since 2020-01-01Products whose name matches come first. Deprecated names show what replaced them. Operating systems have the o:
prefix (e.g. o:linux:linux_kernel), hardware h:.
feed --cpe does this lookup itself when given a bare name: it takes the first result (following a deprecated name to
its replacement) and prints the choice and the runners-up to stderr:
$ cvescout feed --days 90 --sort risk --cpe curl
--cpe curl -> haxx:curl (Haxx Curl; also: curl_project:curl, lexiforest:curl_cffi; see: cvescout cpe curl)For ambiguous names (e.g. nginx: f5:nginx vs f5:nginx_open_source) check the list and pass the exact name.
CVE List (CVEProject/cvelistV5)
cvescout feed --cvelist --days 1 # everything from the last 24 h, no NVD rate limit
cvescout feed --cvelist --days 7 --rce --min-score 8 # the same filters as for NVD
cvescout feed --cvelist --days 3 --keyword nginx --json # word in the description, title, vendor or product name
cvescout feed --cvelist --days 7 --url nodejs.org/en/blog/vulnerability # CVEs linked from Node.js advisories--url matches part of a reference link. The vendor's security advisory page works best: it also finds CVEs filed
under a library bundled with the product. Example: CVE-2026-111497 was filed by Google for Brotli. Its description
never mentions Node.js, NVD has not assigned CPEs yet, and the only trace is a link to the Node.js security release.
--keyword node.js and --cpe nodejs:node.js miss it; --url nodejs.org/en/blog/vulnerability finds it.
--cvelist reads the official CVE list instead of NVD: the daily change files from
GitHub Releases (a few MB per day), completed with the deltaLog.json index.
Faster: a week of data downloads in seconds, without the 5 requests / 30 s limit; CVEs show up about an hour before NVD.
Last 30 days only. For longer ranges (
--since 2020-01-01) use NVD.Data from the CNA (the vendor or other CVE issuer) and CISA Vulnrichment (SSVC, KEV), without NVD analysis: the CVSS score sometimes differs, and
--cpeonly works where the issuer supplied CPEs, so prefer--keywordor--url.In
--jsonevery CVE has anaffectedfield: vendor, product and vulnerable versions (e.g.1.0 - <1.4).get_cve_details(agent and MCP) addsaffectedfrom the CVE List to the NVD data, and when NVD is down or does not have the CVE yet, returns the CVE List record.
GitHub Advisory Database
cvescout feed --ghsa --days 7 --ecosystem npm --severity HIGH # advisories for npm packages
cvescout feed --ghsa --days 30 --package django --rceGitHub "reviewed" advisories (the default) appear later than NVD because GitHub checks them by hand; --unreviewed
adds the unreviewed ones, usually NVD copies without package data. --ghsa returns at most the newest 100 advisories
per query, so long ranges (--since) are incomplete.
Agent
cvescout ask -v "Which critical CVEs were published in the last 3 days?"
cvescout ask "Show RCE in Node.js or curl since 2020 with a public exploit"The agent picks the filters itself (RCE, CVSS threshold, PoC, products, dates), looks up CPE names when needed and says which filters it applied.
Long ranges for large products (e.g. the Linux kernel since 2020) need many NVD requests: without NVD_API_KEY this
takes a few minutes.
Alerts about new CVEs: cvescout watch
cvescout watch checks for new CVEs in the products you choose, rates them with the
risk score and reports each CVE once, again only if its priority rises (e.g.
when CISA adds it to KEV). Nothing runs on its own: each watch run is a single check; you schedule it yourself.
cvescout watch init # creates an example config
cvescout watch run --dry-run # shows alerts without storing or sending them
cvescout watch run # checks, stores state, sends alerts
cvescout watch list # past alerts
cvescout watch schedule # prints a cron / Task Scheduler line (installs nothing)Config: ~/.config/cvescout/watch.toml (Windows: %APPDATA%\cvescout\watch.toml), or any file with --config.
State (SQLite) is kept next to it, in watch.db.
source = "cvelist" # "cvelist" (fresh, up to 30 days back) or "nvd"
min_priority = "high" # critical, high, medium or low
initial_days = 7 # how far back the first run looks
[[watch]]
name = "curl"
keywords = ["curl"]
[[watch]]
name = "Node.js"
cpes = ["nodejs:node.js"]
urls = ["nodejs.org/en/blog/vulnerability"] # always searched in the CVE List
source = "nvd" # per-product override (applies to keywords and cpes)
min_priority = "medium"
[notify]
webhook_url = "https://hooks.slack.com/services/..."
webhook_format = "slack" # slack, discord or jsonOne match is enough:
keywords,cpesorurls.keywordsare broad:node.jsmatches every "… is a Node.js CMS". For such products usecpes(find the name withcvescout cpe) andsource = "nvd", because the CVE List has CPEs from only some vendors. NVD assigns CPEs a few days late, but without false matches.urls(part of a reference link, always from the CVE List) catches CVEs right away, including those in libraries the product bundles: the Node.js advisory page links the Brotli CVE. In the week of 19–26 Oct 2026 onlyurlsfound the 10 Node.js CVEs, because NVD had not assigned them CPEs yet.Each run starts where the previous one ended (with an hour of overlap) and re-scores CVEs from the last 30 days (EPSS and KEV change after publication), so you also get an alert when an older CVE has just been added to KEV.
Alerts always go to stdout (
--jsonfor scripts), and withwebhook_urlalso to the webhook. If the webhook does not answer, the alerts are not marked as sent and come again on the next run.Some vendors (e.g. curl) publish no CVSS: until NVD scores the CVE, the risk score counts the missing CVSS as 5.0.
Turning on periodic checks
cvescout watch schedule prints the command with the right paths. macOS / Linux (cron, every hour):
crontab -e
# add:
0 * * * * "/path/to/cvescout/.venv/bin/cvescout" watch run >> "$HOME/.config/cvescout/watch.log" 2>&1Windows (cmd, Task Scheduler, every hour):
schtasks /Create /SC HOURLY /TN cvescout-watch /TR "\"C:\path\to\cvescout\.venv\Scripts\cvescout.exe\" watch run"
schtasks /Delete /TN cvescout-watchTo turn it off, remove the line from crontab -e or delete the cvescout-watch task.
MCP server
cvescout mcp runs an MCP server (stdio) with the same tools as the ask agent:
get_current_datetime, search_recent_cves (NVD or source="cvelist", sort_by="risk", reference_urls),
search_github_advisories, find_cpe_name, get_cve_details, get_recent_exploited. All tools are read-only. The
server never calls a model, so it needs no ANTHROPIC_API_KEY: the client answers the questions (e.g. Claude Code on
your subscription). The server's instructions forbid the client to cite CVEs from memory or to follow instructions
found inside CVE data; the hard post-check of ask is not available here, because the client writes the answer.
Claude Code (for all projects; a new session sees the mcp__cvescout__* tools):
claude mcp add --scope user cvescout -- "$PWD/.venv/bin/cvescout" mcpclaude mcp add --scope user cvescout -- C:\path\to\cvescout\.venv\Scripts\cvescout.exe mcpClaude Desktop, in claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/,
Windows: %APPDATA%\Claude\):
{
"mcpServers": {
"cvescout": {
"command": "/Users/you/dev/cvescout/.venv/bin/cvescout",
"args": ["mcp"]
}
}
}On Windows use "command": "C:\\path\\to\\cvescout\\.venv\\Scripts\\cvescout.exe". NVD_API_KEY and GITHUB_TOKEN
can be passed in an "env" field of the same section (or with claude mcp add -e NVD_API_KEY=...).
OpenAI Codex CLI:
codex mcp add cvescout -- "$PWD/.venv/bin/cvescout" mcpcodex mcp add cvescout -- C:\path\to\cvescout\.venv\Scripts\cvescout.exe mcpKeys go in with --env NVD_API_KEY=.... Long NVD queries (large products over several years, without NVD_API_KEY)
can take minutes, longer than Codex's default tool timeout, so raise it in ~/.codex/config.toml:
[mcp_servers.cvescout]
command = "/Users/you/dev/cvescout/.venv/bin/cvescout"
args = ["mcp"]
tool_timeout_sec = 300The server works with any MCP client that speaks stdio; it was checked with protocol versions 2025-03-26 through the current one. How strictly a client follows the server's instructions (no CVEs from memory) depends on the client.
Your own agent (Python):
from mcp import Client, StdioServerParameters
async with Client(StdioServerParameters(command=".venv/bin/cvescout", args=["mcp"])) as client:
result = await client.call_tool("search_recent_cves", {"days": 1, "source": "cvelist", "rce_only": True})
print(result.content[0].text) # JSONSecurity notes
CVE descriptions, titles and references are written by third parties. cvescout strips terminal control characters from them, and the agent and MCP instructions tell the model to treat them as data, never as instructions. If you feed
--jsonoutput into your own LLM pipeline, do the same.cvescout only reads public data; the only thing it sends anywhere is the optional
watchwebhook, to the URL you configure.To report a vulnerability in cvescout itself, see SECURITY.md.
Tests
.venv/bin/pytestLicense
Available Tools
6 toolsfind_cpe_nameARead-only
Look up the exact NVD CPE name ("vendor:product", or "o:vendor:product" for operating systems) for a product, to pass in search_recent_cves(cpes=...). Products whose name matches best come first; deprecated names show their replacement.
Args: product: Product name, e.g. "curl", "node.js", "apache http server", "linux kernel".
| Name | Required | Description | Default |
|---|---|---|---|
| product | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint and openWorldHint, and the description adds useful behavioral details beyond them: best matches are returned first, and deprecated names show their replacement. It does not discuss rate limits or auth, but those are not central for this lookup tool.
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 tightly written and front-loaded: purpose first, downstream usage second, result ordering and deprecation behavior third. The argument example is brief and useful, with no redundant sentences.
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 lookup tool with an output schema, the description gives enough context to invoke it correctly: the expected input shape, the returned CPE format, ordering behavior, and deprecation handling. No important invocation detail 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 description coverage is 0%, but the description compensates by explaining that the product parameter is a product name and providing representative examples such as "curl", "node.js", and "apache http server". That adds meaningful guidance beyond the bare string schema.
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 states a specific verb and resource: look up the exact NVD CPE name for a product. It also clarifies the exact format expected by a downstream tool, search_recent_cves(cpes=...), making its role distinct from the CVE-search siblings.
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 clearly explains the context of use: resolving a product name into a CPE string before passing it to search_recent_cves. It does not explicitly name when not to use it or list alternatives, but the intended workflow is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_current_datetimeARead-only
Return the current date and time in UTC. Call this first: "latest" and "recent" are relative to this date, not to your training data.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, so the safety profile is covered. The description adds genuinely useful context the annotations cannot — that this value supersedes the model's training cutoff when interpreting relative terms. It does not discuss precision or call cost, which is acceptable given the output schema exists.
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?
Two short sentences, zero waste, with the operational directive placed after the core purpose in a natural read order. Every clause earns its place.
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?
A trivial zero-param read tool with an output schema, so return values need no explanation. The one thing an agent could get wrong — assuming its own date is current — is addressed directly.
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?
Zero parameters, so the baseline is 4 by rule. The description correctly implies a no-argument call requiring no input context.
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 ('Return the current date and time in UTC') with the timezone scope made explicit. No sibling tool overlaps with this function, so ambiguity is effectively zero.
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 instructs 'Call this first' and explains exactly why: 'latest' and 'recent' in sibling tools are relative to this date, not the agent's training data. This is a clear when-to-use directive tied to real sibling behavior rather than generic advice.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_cve_detailsARead-only
Fetch full, current details of one CVE from the NVD, with the vendor's affected versions from the CVE List, EPSS, CISA KEV status and any GitHub advisories (affected packages and patched versions). Falls back to the CVE List when NVD is unavailable or does not have the CVE yet.
Args: cve_id: CVE identifier, e.g. "CVE-2026-12345".
| Name | Required | Description | Default |
|---|---|---|---|
| cve_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description goes beyond them by disclosing the source-fallback behavior when NVD is down or missing the CVE, which is genuinely useful operational context an agent couldn't infer from annotations. It stops short of stating latency, rate limits, or partial-failure semantics, keeping it at a 4.
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 core capability is front-loaded in one dense but readable sentence, followed by a minimal Args block. It is appropriately sized for the tool's scope, though the Args section largely repeats the parameter name and could be trimmed.
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?
An output schema exists, so return-value structure needn't be explained. Combined with annotations covering read-only/open-world behavior, the description supplies the missing pieces: what data categories come back and what happens on NVD failure. Only the undefined behavior on a nonexistent or malformed CVE ID is left unaddressed.
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 0%, so the description carries the burden for the single parameter. It compensates well by giving the exact accepted format with a concrete example ('CVE-2026-12345'), which the schema's bare 'Cve Id' title does not. The only remaining gap is whether the ID is case-sensitive or accepts variants.
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 ('Fetch full, current details of one CVE') and enumerates the exact data sources aggregated: NVD, CVE List vendor versions, EPSS, CISA KEV, and GitHub advisories. That level of detail clearly distinguishes it from siblings like search_recent_cves and search_github_advisories, which are lookup/list tools rather than single-CVE aggregators.
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 one useful conditional: falls back to the CVE List when NVD is unavailable or lacks the CVE. But it never explicitly says when to use this versus search_recent_cves or search_github_advisories, nor does it state prerequisites (e.g., that a CVE ID must be known first). Usage context is implied by the aggregation framing rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_recent_exploitedARead-only
List vulnerabilities CISA added to its Known Exploited Vulnerabilities (KEV) catalog in the last N days - CVEs confirmed exploited in the wild. Note: an old CVE can be newly added here; report its date_added.
Args: days: Look-back window in days. limit: Maximum number of entries to return.
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | ||
| limit | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so safety and scope are covered structurally. The description adds genuinely useful context that annotations cannot: catalog entries are keyed on date_added, so an old CVE can appear as a recent addition, and the agent must report date_added rather than assume a recent disclosure date.
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?
Two tight sentences with the core identification front-loaded, followed by the important date_added caveat and a minimal Arg block. Every sentence and every arg line earns its place with no restatement of the name.
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 an output schema present, the description need not explain return values, and the read-only/open-world profile is covered by annotations. It is nearly complete for a two-param list tool; only default values and any truncation behavior for 'limit' are left unstated.
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 0%, so the description carries the full burden and does compensate: 'days' is defined as the look-back window and 'limit' as the maximum number of entries returned. The gap is that neither the defaults (30 and 50) nor any upper bound or cap on 'limit' is mentioned.
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 gives a specific verb ('List') and a precisely scoped resource (vulnerabilities newly added to CISA's KEV catalog within a look-back window), plus a clarifying gloss that these are CVEs confirmed exploited in the wild. That scope implicitly separates it from the broader sibling search_recent_cves, but the description never names or contrasts a sibling explicitly.
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 'confirmed exploited in the wild' framing implies when this tool is appropriate versus a general CVE search, and the date_added caveat tells the agent how to report results. However, there is no explicit when-to-use/when-not or named alternative, so the routing decision is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_github_advisoriesARead-only
Search the GitHub Advisory Database for security advisories published in the last N days, newest first. Best source for open-source dependencies: each reviewed advisory names the package, vulnerable version range and first patched version. Some advisories have no CVE ID (only a GHSA ID).
Args: days: Look-back window in days. ecosystem: Optional package ecosystem filter (pip = Python, npm = JavaScript, maven = Java, rust = crates.io, ...). package: Optional package name, e.g. "lodash" or "django". min_severity: Optional minimum severity. include_unreviewed: Also include advisories not yet reviewed by GitHub (usually NVD mirrors without package data). limit: Maximum number of advisories to return (1-100). min_score: Optional minimum CVSS base score (0-10), e.g. 8. rce_only: Only remote code execution (code/command injection reachable over the network; heuristic on CWE, description and CVSS vector). match_any: If true, keep items meeting ANY of min_severity/min_score/rce_only/poc_only instead of ALL of them. poc_only: Only items with a public exploit: a PoC repository on GitHub (listed in github_pocs, from nomi-sec/PoC-in-GitHub), a CISA SSVC or CVSS v4 rating of a public PoC (ignored when the CVE links a bug bounty report such as HackerOne), or exploitation in the wild (CISA KEV). A reference NVD tagged "Exploit" alone does not count. sort_by: "published" (newest first) or "risk" (highest patch priority first, over the newest 100 advisories).
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | ||
| limit | No | ||
| package | No | ||
| sort_by | No | published | |
| poc_only | No | ||
| rce_only | No | ||
| ecosystem | No | ||
| match_any | No | ||
| min_score | No | ||
| min_severity | No | ||
| include_unreviewed | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint and openWorldHint annotations, the description discloses important behavior: newest-first default ordering, a special risk sort limited to the newest 100 advisories, inclusion/exclusion of unreviewed NVD mirrors, nuanced PoC detection rules, and the heuristic nature of rce_only. These details materially affect result interpretation and are not present in annotations or schema.
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 purpose and caveats are front-loaded before the Args section, and the parameter list is dense but necessary for an 11-parameter tool with several non-obvious filters. Every sentence contributes operational meaning, with no 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?
For a read-only search tool with an output schema and no required parameters, the description is complete enough to invoke correctly: it covers purpose, source scope, default ordering, filtering interactions, and all parameter semantics. The output schema handles return-value details.
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?
Although schema description coverage is 0%, the description documents all 11 parameters with meaning beyond names and types. It explains ecosystem aliases, package examples, limit bounds, severity and score thresholds, the match_any ALL-vs-ANY behavior, and the precise conditions for poc_only and rce_only.
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 states a specific verb and resource: searching the GitHub Advisory Database for security advisories, with scope (last N days, newest first) and output characteristics (package, vulnerable range, patched version, GHSA-only entries). It also implicitly differentiates from CVE-oriented siblings by calling itself the best source for open-source dependencies with package-level advisory data.
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 clear usage context by positioning itself as the best source for open-source dependency advisories, which helps distinguish it from get_cve_details and search_recent_cves. However, it does not explicitly state when not to use it or name the sibling tools it should replace in specific scenarios.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_recent_cvesARead-only
Search for CVEs published in the last N days (or since a date), enriched with EPSS exploit probability, CISA KEV membership and a risk score (patch priority).
Args:
sort_by: "published" (newest first) or "risk" (highest patch priority first, ranked over all matches). Use "risk" for "what should I patch first", "most dangerous", "top N".
reference_urls: Only with source="cvelist": match parts of reference links, OR-ed with keywords/cpes. A product's security advisory page finds CVEs filed under libraries it bundles, e.g. ["nodejs.org/en/blog/vulnerability"] finds a Brotli or OpenSSL CVE that Node.js lists. Use it together with keywords for a product.
source: "nvd" (default; NVD API, any date range, CPE filters cover NVD-analyzed CVEs) or "cvelist" (CVEProject CVE List: last 30 days only, no rate limit, CVEs appear about an hour before NVD, includes vendor-supplied affected versions; keywords also match vendor and product names; CPE filters only match where the vendor supplied CPEs). Use "cvelist" for the last hours or days, or when NVD is unavailable or slow.
days: Look-back window in days. Use small windows (1-7) for "latest". Ignored when since is set.
keywords: Optional free-text filters, OR-ed (one search each), e.g. ["openssl"] or ["node.js", "curl"]. Matches anywhere in the description, so it is broad.
since: Optional start date YYYY-MM-DD for historical questions ("since 2020"). Ranges over 120 days require keywords or cpes.
cpes: Optional exact products as CPE names, OR-ed: "vendor:product" for applications, "o:vendor:product" for operating systems, e.g. ["nodejs:node.js", "haxx:curl", "o:linux:linux_kernel"]. Use find_cpe_name if unsure. More precise than keywords but only covers CVEs NVD has already analyzed.
min_severity: Optional minimum CVSS severity.
limit: Maximum number of CVEs to return (1-100).
min_score: Optional minimum CVSS base score (0-10), e.g. 8.
rce_only: Only remote code execution (code/command injection reachable over the network; heuristic on CWE, description and CVSS vector).
match_any: If true, keep items meeting ANY of min_severity/min_score/rce_only/poc_only instead of ALL of them.
poc_only: Only items with a public exploit: a PoC repository on GitHub (listed in github_pocs, from nomi-sec/PoC-in-GitHub), a CISA SSVC or CVSS v4 rating of a public PoC (ignored when the CVE links a bug bounty report such as HackerOne), or exploitation in the wild (CISA KEV). A reference NVD tagged "Exploit" alone does not count.
| Name | Required | Description | Default |
|---|---|---|---|
| cpes | No | ||
| days | No | ||
| limit | No | ||
| since | No | ||
| source | No | nvd | |
| sort_by | No | published | |
| keywords | No | ||
| poc_only | No | ||
| rce_only | No | ||
| match_any | No | ||
| min_score | No | ||
| min_severity | No | ||
| reference_urls | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond readOnlyHint/openWorldHint: it discloses that cvelist has no rate limit and publishes about an hour ahead of NVD, that NVD CPE filters only cover analyzed CVEs, that ranges over 120 days require keywords or cpes, and that keywords match anywhere so they are broad. The poc_only caveats (what does and does not count as a public exploit, HackerOne exclusion) are exactly the kind of behavioral detail annotations cannot carry.
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 length is justified by 13 undocumented parameters and the prose is front-loaded with purpose before the parameter notes. It is dense docstring-style rather than scannable, with some long parenthetical clauses (the reference_urls Node.js example, the poc_only definition), but very little is genuinely wasteful.
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?
Complete on the hard parts: multi-source behavior, date-window constraints, filter interaction, and enrichment contents, with an output schema covering return values. Minor gaps remain: nothing about whether results are truncated or how to page past limit, and no guidance on the overlap with get_recent_exploited.
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 0% across 13 parameters, so the description carries the full burden and does so: nearly every parameter gets meaning, format examples, OR vs AND interaction (keywords/cpes are OR-ed, match_any flips filter combination) and precedence rules. Only limit (1-100) lacks added nuance beyond its bounds.
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 opening sentence gives a specific verb (search), a specific resource (CVEs), a scope (last N days or since a date) and the enrichment payload (EPSS, CISA KEV, risk score / patch priority). That is enough for an agent to tell it apart from get_cve_details (single-CVE lookup) and search_github_advisories (advisories, not CVEs) without opening a schema.
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?
Strong in-tool routing: sort_by="risk" is tied to concrete intents ("what should I patch first", "most dangerous", "top N"), days 1-7 is prescribed for "latest", source="cvelist" is prescribed for "last hours or days, or when NVD is unavailable or slow", and find_cpe_name is named for uncertain CPEs. It also states exclusions (reference_urls only with source="cvelist", days ignored when since is set). What is missing is routing against siblings such as get_recent_exploited, which overlaps with poc_only=true.
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.
6 tool updates
v0.1.1- First observed
find_cpe_name - First observed
get_current_datetime - First observed
get_cve_details - First observed
get_recent_exploited - First observed
search_github_advisories - First observed
search_recent_cves
TDQS
Scored across 6 tools
Each tool has a distinct role: a clock reference, two source-specific searches (NVD/CVE List vs GitHub Advisories), a CPE lookup helper, single-CVE detail, and a KEV feed. The only potential confusion is between search_recent_cves and search_github_advisories, but descriptions explicitly steer (NVD for broad CVE history, GHSA for open-source dependencies with package fix versions).
All tools use consistent verb_noun snake_case (get_current_datetime, search_recent_cves, search_github_advisories, find_cpe_name, get_cve_details, get_recent_exploited). Verbs get/search/find are used predictably for their intent.
Six tools is well-scoped for a CVE scouting server, and each earns its place: reference time, two complementary search sources, CPE resolution, detail lookup, and exploited-in-the-wild feed. No redundant or filler tools.
The surface covers discovery, enrichment (EPSS/KEV/risk), dependency advisories, CPE resolution, and single-CVE detail with fallbacks — a full scouting lifecycle. Minor gaps like batch detail fetching or saved watchlists exist but agents can work around them via the search tools.
Maintenance
Related MCP Connectors
Real-time CVE, exploit, and vulnerability intelligence for AI assistants (350K+ CVEs, 115K+ PoCs)
CVE patch-priority API + MCP: CISA KEV, EPSS, CVSS, SSVC. Keys $19/mo; 200 free calls/day.
CVE lookups (NVD) and dependency-manifest audits (OSV) for AI agents. No API keys.
CVE lookups (NVD) and dependency-manifest audits (OSV) for AI agents. No API keys.
Related MCP Servers
- AlicenseAqualityCmaintenanceUnifies NVD, EPSS, CISA KEV, GitHub Advisory, and OSV into a single MCP server, enabling AI agents to query vulnerability intelligence conversationally with 23 tools for incident response, prioritization, dependency audits, and threat monitoring.41292 npm30MIT
- AlicenseAqualityDmaintenanceProvides live CVE data from NVD and EPSS without API key, enabling AI assistants to look up CVSS scores, search vulnerabilities, and check product CVEs.3MIT
- FlicenseNot gradedqualityCmaintenanceProvides Claude with live access to multiple vulnerability databases (NVD, OSV, GitHub Advisories, Snyk) for querying CVEs, package vulnerabilities, and remediation guidance.-
- AlicenseNot gradedqualityDmaintenanceProvides CVE lookup, search, and exploit intelligence from public vulnerability sources (NVD, CISA KEV, EPSS) for AI agents to produce remediation guidance without consuming LLM tokens for data fetching.18 PyPI1MIT