Context for a CVE: CVSS, KEV, EPSS, SSVC and internet exposure from the EchelonGraph CVE Pulse public API. Runs as a CLI tool and a local MCP server (stdio).
Strong tool definitions with comprehensive descriptions (avg 180 chars) and well-structured JSON schemas. All 10 tools have clear verb-noun naming (get_*, search_*, match_*) and detailed parameter documentation. Schemas include proper types, enums, and constraints. However, output schemas are not explicitly documented in the source code provided, and error handling guidance is minimal. Tool descriptions are LLM-optimized but could better explain when to use each tool vs. alternatives (e.g., search_cves vs. match_product distinction).
The result-cache state: how many entries it holds, the TTL for each kind of result, and which config file was read (the path, or that there was none and where it looked).
Feed freshness and counts by severity: when the upstream index was last polled, how many CVEs it holds by severity band, and the rate limit budget left on this IP address.
One vendor advisory: title, severity, linked CVE IDs, affected products, remediation, references, and whether it was withdrawn. Compact by default, with counts of what was left out; pass `section` to page the description or the remediation (by characters) or a list (by items) in full.
Context for one CVE: CVSS (by version, with who rated it), CISA KEV, EPSS, SSVC, exploitation evidence, patch availability and EchelonGraph's fused score. The default answer is compact: the top affected products and references, with counts of what was left out. Pass `section` to page one large part in full. A block named in `absent` means upstream holds no data for it — not a negative.
Internet-exposure footprint of one CVE from upstream's passive radar: exposed host count with the top countries and products. tracked:false means the radar does not follow this CVE — it is not a count of zero, and it says nothing about KEV status.
Output schemas not documented in source. While input schemas are comprehensive, return types for each tool are not explicitly defined in the code provided, forcing LLMs to infer structure from descriptions alone.
Error handling lacks recovery guidance. Error codes (invalid_argument, unknown_tool, response_too_large, internal_error) are defined but descriptions do not explain what the LLM should do next (retry, ask user, call alternative tool).
Tool selection ambiguity: search_cves and match_product both find CVEs but serve different purposes (text search vs. CPE matching). Descriptions explain the difference but could be more explicit about when to use each.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 66 | 2026-07-28+ | v2 |
CVEs upstream relates to one CVE — same product, same vendor advisory, same CWE — up to ten per relation, ranked by EchelonGraph's score, each with what ties it (join_key). Use it to widen a triage from one CVE to its neighbours. incomplete:true means the empty lists could not be verified and are not an answer. An empty same_product is not evidence that the product has no other CVEs; match_product answers that.
The full reference: every tool, its arguments, result schemas, error codes and recovery paths. Returned as Markdown, not JSON.
CVEs that apply to a product, matched at the CPE layer by vendor and product tokens (lower case, underscores: nginx, linux_kernel, http_server). product_known:false means upstream does not know the token — an unknown product, not a product with no CVEs. The vendor does not filter: rows whose vendor upstream could not confirm stay in the list, marked, and vendor_unverified counts them — when it equals the row count, the vendor given matched nothing. No version is accepted: a product plus a version would tell a third party what you run.
Vendor security advisories, newest first: Microsoft, Red Hat, GitHub, Cisco, AWS, Google Cloud, GitLab. Many appear before NVD assigns a CVE ID — has_cve:false lists exactly those. There is no text search over advisories; filter by vendor and page. Each row's advisory_id is what get_advisory takes.
Search the free text of CVE descriptions, newest first by default, with filters. This is not a product lookup: zero hits is not evidence that a product is unaffected — match_product answers that. Rows are compact and descriptions are clipped; get_cve returns the whole record.
Pagination guidance incomplete. search_cves, match_product, and search_advisories accept limit/offset but descriptions do not state the default limit or explain how to detect end-of-results (e.g., 'if returned rows < limit, you've reached the end').
Utility tools (feed_status, cache_status, get_usage) have minimal descriptions (65-70 chars). feed_status and cache_status lack context on when an LLM should call them or how to interpret results.