Skip to main content
Glama
d4ngkh04w

NVD/NIST MCP server

by d4ngkh04w

NIST NVD MCP server

MCP server exposing the NVD APIs - CVE search, CVE history, the Official CPE Dictionary and CPE Match Criteria - over stdio, with a local SQLite + JSON disk cache so repeated lookups do not hit the (heavily rate-limited) upstream API.

Requirements

  • Node.js >= 22.5 (uses the built-in node:sqlite module - no native compilation)

  • Optional but recommended: a free NVD API key

Related MCP server: vuln-nist-mcp-server

Register with an MCP client

npm install && npm run build
{
  "mcpServers": {
    "nist-nvd": {
      "command": "node",
      "args": ["/absolute/path/to/nist-nvd-mcp-server/dist/main.js"],
      "env": { "NVD_API_KEY": "your-key" }
    }
  }
}

The server speaks JSON-RPC on stdin/stdout: stdout carries protocol frames only, every log line goes to stderr. It is not an HTTP server and opens no ports.

The API key is sent only in the apiKey request header - never in a URL, never logged, never written to SQLite or the disk cache. Without it the public API allows roughly 5 requests / 30 s, so one full sweep of the 10 tools takes 60-90 s.

Tools

Tool

Purpose

nvd_get_cve

Full record for one CVE: description, all CVSS metrics, CWEs, configurations, references, CISA KEV status

nvd_get_cve_summary

Compact view of one CVE: timestamps, status, English summary, primary CVSS, CWEs, affected products, KEV

nvd_get_cves

Summaries for up to 100 CVE IDs in one batch (only missing/stale IDs are fetched)

nvd_search_cves

Filter CVEs by keyword, IDs, CPE, CWE, CVSS, vulnStatuses, KEV date window, published/modified window

nvd_get_recent_cves

CVEs ordered by publication date, newest first

nvd_get_modified_cves

CVEs ordered by last-modified date, newest first

nvd_get_cve_history

Change history of one CVE (paged; eventName is documented on the tool itself)

nvd_search_cpes

Search the CPE Dictionary by keyword, CPE match string, match-criteria UUID, or last-modified window

nvd_get_cpe

One CPE Dictionary entry, by cpeNameId or by exact cpeName

nvd_search_cpe_matches

Search CPE Match Criteria (the CVE ↔ CPE version-range links)

Response shape

{
  "data": { /* tool-specific */ },
  "meta": {
    "source": "cache",           // "cache" | "nvd"
    "cacheStatus": "hit",        // "hit" | "miss" | "refresh" | "stale_fallback"
    "fetchedAt": "...", "expiresAt": "...", "ageSeconds": 3, "stale": false,
    "warnings": [],              // stale fallback, local filtering, truncation, ...
    "window": { "start": "...", "end": "..." }, // the window actually queried, when time bounded
    "fieldsApplied": ["id"]      // only when the caller passed `fields`
  },
  "pagination": {                // list tools only
    "page": 1, "pageCount": 16, "pageSize": 20, "returned": 20, "totalResults": 312, "hasMore": true,
    "nextCursor": "eyJ2ZXJzaW9uIjoxLC..."
  }
}

Pagination

Read pagination.nextCursor (top level, not inside meta) and pass it back as cursor with identical filters and pageSize until hasMore is false. pagination.page is the 1-based ordinal of the current page in that walk and pagination.pageCount is the number of pages the current upstream total divides into. page is carried inside the signed cursor rather than derived from the offset, because the descending feeds read their first page from the end of the window; pageCount is an estimate, since NVD recomputes the total on every call.

The cursor is an opaque HMAC-signed token that stands in for NVD's internal startIndex. It cannot be forged or edited - a tampered token, a cursor reused with different filters, or one older than CURSOR_TTL_SECONDS (default 30 min) returns INVALID_CURSOR, which carries details.reason so the cases are distinguishable: signature means the ~350-character token was altered in transit (the message also reports the received length when it is short, which points at truncation), filter_mismatch means the token is intact but the filters or pageSize changed, and expired means it is older than the TTL. The server keeps no cursor state, so a valid token is always accepted. Relative date windows (days: 7) are frozen into the cursor so every page sees the same range.

pageSize defaults to 20 everywhere; the maxima differ per resource:

Resource

Tools

Default

Maximum

cves

nvd_search_cves, nvd_get_recent_cves, nvd_get_modified_cves

20

50

cve-history

nvd_get_cve_history

20

50

cpes

nvd_search_cpes

20

100

cpe-matches

nvd_search_cpe_matches

20

100

pagination.totalResults is the upstream NVD count before local filtering, so it can exceed the number of returned items. It stays the same on every page of a walk - it is a total, not a remaining count - and reordering a feed window server side does not change it. Because pagination walks NVD's startIndex offsets, a walk is a snapshot of one ordering at request time rather than a stable view: if NVD inserts or removes a record between two page requests, an item can appear twice or be skipped.

meta.ordering is always one of published_desc, last_modified_desc, change_created_asc or nvd_default (NVD ordering kept as-is), and each tool emits exactly one marker on every page: nvd_get_recent_cves always published_desc, nvd_get_modified_cves always last_modified_desc, nvd_get_cve_history always change_created_asc, and the three search/CPE tools nvd_default because NVD returns their results unsorted.

meta.window echoes the absolute bounds that were queried, which is the only way to confirm that a relative days: 7 resolved to the range you meant. It is absent when the query was not time bounded and when both date filters are combined, since the field holds a single range.

Metadata-only responses

Every list tool accepts metaOnly: true, which returns an empty items array and pagination.returned: 0 while keeping the rest of the pagination block and meta intact. It is a presentational switch: the upstream request and the cache read still happen, so it saves response bytes, not a call. Use it to confirm meta.ordering/meta.window or to count pages (pagination.totalResults, pagination.pageCount) without pulling items, and keep passing the returned nextCursor to walk on. Note the cursor still points past the suppressed page, so a pure metadata check can ignore it, while following it continues the walk without the skipped page's items.

Response shaping with fields

CVE configuration trees, change-history details, the expanded matches list of CPE Match Criteria and the titles/refs of a CPE dictionary entry dominate the payload, so fields returns only the item keys you need:

// ~5.7 kB  ->  ~570 B for the same record
{ "cveId": "CVE-2021-44228", "fields": ["id", "primaryCvss", "isKnownExploited", "kevDateAdded"] }
  • Omitting fields returns every field. Because a projection can omit any key, the published output schema does not mark item keys as required; the fields description lists what the default returns.

  • An unknown name is rejected with INVALID_INPUT and the supported set, instead of being dropped.

  • Fields the record does not carry are omitted rather than returned as null, and the applied list is echoed in meta.fieldsApplied (absent when no projection was requested).

  • It is purely presentational: the upstream query, the cache key, the TTL and the cursor are unchanged, so a page fetched with one projection can be continued with another. It prunes top-level keys only, so it cannot reach inside a configurations tree - to inspect one product of a CVE with hundreds of criteria, set includeConfigurations: false and use nvd_search_cpe_matches with matchStringSearch instead.

nvd_get_cve also has includeConfigurations / includeReferences (both default true, so they only matter when set to false), and nvd_get_cve_summary / nvd_get_cves / nvd_search_cves cap affectedProducts at 50 entries and report the truncation in meta.warnings.

Caching and rate limiting

  • Two tiers: a JSON disk cache with per-resource TTLs, backed by SQLite for entity lookups (nvd_get_cve, nvd_get_cve_summary, nvd_get_cve_history, nvd_get_cpe).

  • A cache hit never calls NVD. Expired entries are refreshed; if NVD is unreachable the stale copy is served with cacheStatus: "stale_fallback" and a meta.warnings entry.

  • Concurrent identical requests are collapsed (single-flight), so a burst of 25 identical calls produces exactly one upstream request.

  • Upstream calls are serialized with a minimum interval (NVD_MIN_INTERVAL_MS, default 6000) and retried with exponential backoff on 429/5xx/timeouts.

  • Default files live under ./data (nvd.sqlite + cache/). Schema migrations are applied at startup from migrations/.

Configuration

Every variable is optional - copy .env.example to .env and set what you need. Real environment variables take precedence over .env.

Variable

Default

Purpose

NVD_API_KEY

-

API key, sent as the apiKey header only

NVD_BASE_URL

https://services.nvd.nist.gov/rest/json

Upstream base URL (HTTPS, or HTTP for localhost)

NVD_MIN_INTERVAL_MS

6000

Minimum gap between upstream requests

NVD_REQUEST_TIMEOUT_MS

15000

Per-request timeout

NVD_MAX_RETRIES

4

Retries on 429/5xx/network errors

SQLITE_PATH

./data/nvd.sqlite

Database file

CACHE_DIRECTORY

./data/cache

JSON disk cache directory

*_CACHE_TTL_SECONDS

300-604800

Freshness window per resource

CURSOR_SECRET

random per process

HMAC key for cursors; set it (>= 16 chars) to keep cursors valid across restarts

CURSOR_TTL_SECONDS

1800

Cursor lifetime

LOG_LEVEL

info

debug | info | warn | error | silent

See .env.example for the full list with defaults and explanations.

Docker

docker build -t nist-nvd-mcp-server .
docker run -i --rm -e NVD_API_KEY=your-key -v nvd-data:/data nist-nvd-mcp-server

Use -i (not -t) so stdin stays open. The container runs as a non-root user with /data writable; docker stop shuts it down cleanly in a few milliseconds.

Development

npm run typecheck   # tsc --noEmit
npm run lint        # eslint (no-console is an error: stdout must stay protocol-only)
npm test            # vitest run (unit + integration + MCP contract); runs build first
npm run build       # emit dist/
npm run dev         # tsx src/main.ts, no build step

Tests never touch the real NVD API - they run against an in-process mock server, a temp SQLite database and a temp cache directory.

Evaluation

scripts/evaluation.py scores the ten tools the way a real client uses them: it hands each question from evaluations/nist-nvd-mcp-server.xml to an LLM together with this server's tool list, lets the model pick the tools itself, then compares the final answer with the expected value.

python -m venv .venv && . .venv/bin/activate     # Windows: .venv\Scripts\activate
pip install -r scripts/requirements.txt

OPENAI_API_KEY=... python scripts/evaluation.py \
  -t stdio -c node -a "$PWD/dist/main.js" \
  -e PATH="$PATH" NVD_MIN_INTERVAL_MS=6500 \
  --base-url http://127.0.0.1:20128/v1 -m <model-id> \
  -o evaluations/report-<model>.md evaluations/nist-nvd-mcp-server.xml

The LLM is reached through the OpenAI-compatible chat-completions API, so any gateway serving /v1/chat/completions with tool calling works. Set NVD_MIN_INTERVAL_MS above 6000 to stay inside the anonymous rate limit, and point SQLITE_PATH/CACHE_DIRECTORY at a scratch directory if another instance already has the defaults open.

The question set asks for capabilities, never tool names, and every expected answer is a stable fact (KEV dates, CVSS scores, immutable cpeNameId / matchCriteriaId, counts over wide windows) verified against the live API. Reports are git-ignored; the question set is committed. When reading a report, judge the server by the per-task **Feedback** blocks and the recorded nvd_* call arguments rather than by the score: grading is an exact string comparison, so a model that states the right value and then adds a sentence is marked wrong, and a gateway model's scoring is not deterministic at temperature=0.

Troubleshooting

Symptom

Cause

Fix

startup_failed: Failed to configure the SQLite database

Another process holds the database file (two instances sharing ./data, or the same file opened from Windows and WSL)

Give each instance its own SQLITE_PATH and CACHE_DIRECTORY

startup_failed: Invalid environment configuration

A variable failed validation (e.g. CURSOR_SECRET shorter than 16 characters)

Fix the value named in the stderr JSON, or unset it - every variable is optional

UPSTREAM_RATE_LIMITED / UPSTREAM_UNAVAILABLE

NVD throttled or unreachable

Set NVD_API_KEY; cached entries are still served, with stale_fallback and a warning

UPSTREAM_BAD_RESPONSE with details.status: 404 on every tool

NVD_API_KEY is invalid or expired - NVD answers 404 on every endpoint, exactly as it does for an unsupported parameter

Drop NVD_API_KEY to run anonymously (slower), or issue a new key

UPSTREAM_BAD_RESPONSE otherwise

NVD returned a payload that failed schema validation

Raise LOG_LEVEL=debug and read the stderr log; the failing path is logged, not the body

No output when running by hand

The server is waiting for JSON-RPC on stdin

It is a stdio server; drive it from an MCP client, or pipe a initialize request

License

MIT - this project is not affiliated with or endorsed by NIST/NVD. It is a client for the public NVD API, whose data is provided by NIST in the public domain.

Available Tools

10 tools
nvd_get_cpeGet a CPE nameA
Read-onlyIdempotent

Return one entry of the NVD Official CPE Dictionary. Provide exactly one of cpeNameId (preferred, exact) or cpeName. cpeName is resolved by upstream pattern search over at most 3 pages; if the exact name is not in that window the tool returns CPE_NOT_FOUND with the scanned/total counts and suggests nvd_search_cpes. That search ignores the deprecation filter, so deprecated entries resolve too. Entries are cached for 7 days.

ParametersJSON Schema
NameRequiredDescriptionDefault
cpeNameNoExact CPE name to resolve
cpeNameIdNoCPE name UUID (preferred lookup key)

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataYes
metaYesCache/freshness metadata; warnings carries stale-fallback and truncation notices

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnly, idempotent, non-destructive, openWorld), yet the description adds substantial behavior that structured fields do not: a 3-page pattern-search bound, a CPE_NOT_FOUND error shape with scanned/total counts, the fact that the upstream search ignores the deprecation filter, and a 7-day cache. These are exactly the operational traits an agent needs to reason about failure and staleness.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four compact sentences, front-loaded with what is returned, then the key-selection rule, then failure behavior, then caching. Every sentence carries distinct operational information with no repetition of the schema or annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return structure need not be explained, and the description instead covers the one output case that matters (CPE_NOT_FOUND). For a two-parameter, read-only lookup with a documented fallback path, nothing needed to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and both properties carry descriptions, so the baseline is 3. The description adds real value beyond the schema by declaring cpeNameId 'preferred, exact' versus cpeName, which is only 'resolved by upstream pattern search' — a semantic distinction the schema does not convey.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence states a specific verb and resource ('Return one entry of the NVD Official CPE Dictionary'), immediately scoping it to a single-entry lookup. The mention of nvd_search_cpes on failure distinguishes it from the sibling search tools without the agent needing to open either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states the selection rule explicitly: 'Provide exactly one of cpeNameId (preferred, exact) or cpeName', and names the alternative (nvd_search_cpes) for the failure case. It also explains what happens when the exact name is outside the scanned window, so the agent knows the escape hatch.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

nvd_get_cveGet CVE detailsA
Read-onlyIdempotent

Return the full NVD record for one CVE: description, all CVSS metrics, CWEs, configurations, references and CISA KEV status. Use nvd_get_cve_summary for the essentials, nvd_get_cves for a batch. Cached for 24 hours; on an NVD outage the stale copy is returned with a warning in meta.warnings.

ParametersJSON Schema
NameRequiredDescriptionDefault
cveIdYesCVE identifier such as CVE-2024-3094 (case insensitive)
includeRawNoInclude the raw NVD payload when it is available in the local cache (default false)
includeReferencesNoInclude the reference list (default true)
includeConfigurationsNoInclude the CPE configuration tree (default true)

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataYes
metaYesCache/freshness metadata; warnings carries stale-fallback and truncation notices

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations establish read-only, idempotent, non-destructive and open-world, but the description adds behavior they cannot express: a 24-hour cache and a documented degradation path where a stale copy is returned during an NVD outage with a warning surfaced in meta.warnings. That is real operational context about freshness and failure modes.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences with no waste: the payload comes first, the sibling routing second, the caching/outage caveat last. Nothing is repeated and every clause carries new information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need not be described, and the description still covers the caching horizon and outage fallback. For a single-record fetch tool with 100% schema coverage and annotations, nothing an agent needs is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the three optional toggles (includeRaw, includeReferences, includeConfigurations) and the cveId pattern are already fully documented in the schema. The description implies the default shape of the record but adds no syntax or default-override guidance beyond it, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Return) and resource (the full NVD record for one CVE) and enumerates the payload contents: description, CVSS metrics, CWEs, configurations, references and CISA KEV status. It also explicitly distinguishes itself from nvd_get_cve_summary and nvd_get_cves, so an agent can pick it without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names two concrete alternatives with the condition that selects each: nvd_get_cve_summary for the essentials and nvd_get_cves for a batch. The full/summary/batch trichotomy is exactly the routing decision an agent needs.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

nvd_get_cve_historyGet CVE change historyA
Read-onlyIdempotent

Return the change history of one CVE: "New CVE Received", "Initial Analysis", "CVE Modified", "Rejected" and similar events, with their field-level changes and timestamps. Filter by eventName or changeBetween (maximum 120 days). Cached for 1 hour; paginate with the opaque cursor.

ParametersJSON Schema
NameRequiredDescriptionDefault
cveIdYesCVE identifier such as CVE-2024-3094 (case insensitive)
cursorNoOpaque signed cursor from the previous page: pass the response's pagination.nextCursor. Never build it by hand; it expires after 30 minutes and is bound to the filters, pageSize and date window.
pageSizeNoPage size (default 20, maximum 50)
eventNameNoExact event name, for example "CVE Modified" or "Initial Analysis"
changeBetweenNoFilter on the change creation date (max 120 days)

Output Schema

ParametersJSON Schema
NameRequiredDescription
metaYesCache/freshness metadata; warnings carries stale-fallback and truncation notices
itemsYes
paginationYesPagination block; nextCursor is null on the last page

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint and openWorldHint, so the safety profile is covered. The description adds non-structured behavior: a 1-hour cache and the 120-day maximum window, plus the opaque-cursor pagination model. It does not mention rate limits or auth, so it stops short of a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two dense sentences, front-loaded with what is returned, followed by filtering, caching, and pagination constraints. No filler and every clause carries operational information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be described. For a single-CVE read with nested filter objects, the description covers scope, filters, cache TTL, window limit, and pagination, leaving nothing an agent needs before calling it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so cveId, cursor, pageSize, eventName and changeBetween are already fully documented at the schema level. The description restates eventName and changeBetween and the 120-day cap but adds no syntax, default, or format detail beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Return the change history of one CVE') and enumerates the concrete event types returned, so an agent can distinguish it from nvd_get_cve, nvd_get_cve_summary, and nvd_get_modified_cves (which is multi-CVE) without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied through the description of filters ('Filter by eventName or changeBetween') and pagination, but there is no explicit when-to-use guidance, no prerequisites, and no named alternative such as nvd_get_modified_cves for bulk change tracking. Adequate but leaves routing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

nvd_get_cvesGet multiple CVE summariesA
Read-onlyIdempotent

Return summaries for up to 100 CVE identifiers in one call. Identifiers are uppercased and de-duplicated; only missing or stale ones are fetched, in one batch. Reports foundIds, missingIds and meta.requested/found/missing; use nvd_get_cve for a full record.

ParametersJSON Schema
NameRequiredDescriptionDefault
cveIdsYes1-100 CVE identifiers; duplicates are removed and identifiers normalized to uppercase

Output Schema

ParametersJSON Schema
NameRequiredDescription
metaYes
itemsYes
foundIdsYes
missingIdsYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/openWorld, so safety is covered; the description adds non-obvious behavior: identifiers are uppercased, de-duplicated, and only missing/stale entries are fetched (a cache-aware batch read). That is real value beyond the annotations, though it overlaps the output schema by naming the response fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense, front-loaded sentences with no filler; the batch limit and routing to nvd_get_cve come early. Minor redundancy in enumerating response fields (foundIds, missingIds, meta.*) that the output schema already exposes.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With a complete input schema, an output schema, and rich read-only annotations, the description supplies the remaining essentials: batch cap, normalization/dedup semantics, cache behavior, and sibling routing. Nothing needed to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single param already documents the 1-100 range, case-insensitivity, and de-duplication. The description restates the same normalization/limit facts rather than adding format or syntax detail beyond the schema, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource with scope ('summaries for up to 100 CVE identifiers in one call') and explicitly routes the single-record case to nvd_get_cve, which lets an agent separate it from siblings without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names the alternative (nvd_get_cve for a full record) with the condition that selects it, giving clear batch-vs-single guidance. It stops short of addressing the other siblings (nvd_get_cve_summary, nvd_search_cves, nvd_search_cves), so no explicit exclusions beyond the one alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

nvd_get_cve_summaryGet CVE summaryA
Read-onlyIdempotent

Return a compact view of one CVE: id, timestamps, status, English summary, primary CVSS score, CWEs, affected products, KEV flag and reference count. Configurations, references and the raw payload are omitted - use nvd_get_cve for those. Derived from the cached record, so it shares the same 24 hour freshness window.

ParametersJSON Schema
NameRequiredDescriptionDefault
cveIdYesCVE identifier such as CVE-2024-3094 (case insensitive)

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataYes
metaYesCache/freshness metadata; warnings carries stale-fallback and truncation notices

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, openWorld and non-destructive, so the safety profile is covered. The description adds genuinely new behavioral context: the result is derived from a cached record sharing a 24 hour freshness window, which tells the agent results may be stale. It does not mention rate limits or auth, but the caching disclosure is the meaningful extra.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences: field inventory first, exclusions and the alternative second, freshness caveat last. Every sentence carries information and nothing is repeated from the schema or annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need no prose, yet the field list usefully frames the compactness tradeoff. Combined with the named alternative and the cache-freshness disclosure, an agent has everything needed to select and call this correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and there is only one parameter (cveId) with a regex pattern and example already in the schema. The description adds no format or case-handling detail beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (return) and resource (compact view of one CVE) and enumerates exactly what the view contains (id, timestamps, status, summary, CVSS, CWEs, products, KEV flag, reference count). It also names the sibling it differs from (nvd_get_cve), so an agent can separate the two without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It routes the agent explicitly: configurations, references and raw payload are omitted, so 'use nvd_get_cve for those'. That gives a clear condition for choosing this tool versus its sibling. It stops short of stating broader when-not-to-use conditions (e.g., bulk retrieval, history), but the core routing decision is unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

nvd_get_modified_cvesGet recently modified CVEsA
Read-onlyIdempotent

Return CVEs ordered by last-modified date, newest first (ordering "last_modified_desc"). Defaults to the last 7 days: use days or an explicit start+end window (mutually exclusive, maximum 120 days). All filters are sent to NVD, so totalResults is the exact upstream total. Cached for 5 minutes; paginate by passing pagination.nextCursor back as cursor with the same filters and pageSize - the resolved window travels inside the cursor, so a relative days window stays stable across pages.

ParametersJSON Schema
NameRequiredDescriptionDefault
endNoISO-8601 window end (use with `start`)
cvssNoCVSS metric filter; requires at least one of severity or metrics
daysNoRelative window in days counted back from now (default 7)
startNoISO-8601 window start (use with `end`)
cursorNoOpaque signed cursor from the previous page: pass the response's pagination.nextCursor. Never build it by hand; it expires after 30 minutes and is bound to the filters, pageSize and date window.
cpeNameNoOptional CPE name filter
kevOnlyNoOnly CISA KEV entries
keywordNoOptional keyword filter
pageSizeNoPage size (default 20, maximum 50)
noRejectedNoExclude rejected CVEs
vulnStatusesNoVulnerability statuses (Received, Awaiting Analysis, Undergoing Analysis, Analyzed, Modified, Deferred, Rejected). Spaced and camel-case spellings are both canonicalized, and the filter is applied by NVD.

Output Schema

ParametersJSON Schema
NameRequiredDescription
metaYesCache/freshness metadata; warnings carries stale-fallback and truncation notices
itemsYes
paginationYesPagination block; nextCursor is null on the last page

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond annotations: notes the 5-minute cache, that filters are pushed upstream so totalResults is exact, that the resolved window is embedded in the cursor so a relative `days` window stays stable across pages, and the 30-minute cursor TTL. This is exactly the kind of pagination/caching contract an agent needs for a read tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with return semantics and ordering, then window rules, then caching and pagination. Four dense sentences, no filler, every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, it needn't describe return values, and it covers the operational hazards (caching, cursor lifetime/binding, window exclusivity, upstream filtering) that an agent would otherwise guess wrong. Complete for an 11-param read tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema already documents most params with enums and constraints. The description still adds non-obvious semantics: cursor binding to filters/pageSize/window and cursor stability with relative days, which the schema only partly conveys.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states precisely what the tool returns (CVEs ordered by last-modified date, newest first) and separates it from siblings like nvd_search_cves or nvd_get_cve by its ordering and windowing behavior. An agent can immediately tell this is the 'recently modified' feed.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explains the default window (last 7 days), the exclusive `days` vs `start`+`end` choice, and the 120-day cap. It doesn't explicitly say when to prefer a sibling (e.g. search_cves for keyword-driven queries), so it's clear but not fully routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

nvd_get_recent_cvesGet recently published CVEsA
Read-onlyIdempotent

Return CVEs ordered by publication date, newest first (ordering "published_desc"). Defaults to the last 7 days: use days or an explicit start+end window (mutually exclusive, maximum 120 days). Cached for 5 minutes; paginate by passing pagination.nextCursor back as cursor with the same filters and pageSize - the resolved window travels inside the cursor, so a relative days window stays stable across pages.

ParametersJSON Schema
NameRequiredDescriptionDefault
endNoISO-8601 window end (use with `start`)
cvssNoCVSS metric filter; requires at least one of severity or metrics
daysNoRelative window in days counted back from now (default 7)
startNoISO-8601 window start (use with `end`)
cursorNoOpaque signed cursor from the previous page: pass the response's pagination.nextCursor. Never build it by hand; it expires after 30 minutes and is bound to the filters, pageSize and date window.
cpeNameNoOptional CPE name filter
kevOnlyNoOnly CISA KEV entries
keywordNoOptional keyword filter
pageSizeNoPage size (default 20, maximum 50)
noRejectedNoExclude rejected CVEs

Output Schema

ParametersJSON Schema
NameRequiredDescription
metaYesCache/freshness metadata; warnings carries stale-fallback and truncation notices
itemsYes
paginationYesPagination block; nextCursor is null on the last page

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnly/idempotent annotations, it discloses two non-obvious behaviors: results are cached for 5 minutes (a freshness caveat), and the resolved date window is embedded in the cursor so a relative `days` window stays stable across pages while filters and pageSize are bound. Neither fact is derivable from the annotations or top-level schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two dense sentences, front-loaded with the ordering and default window before pagination mechanics. The parenthetical `("published_desc")` and nested asides add some visual noise but every clause carries operational information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 10 optional parameters, a nested CVSS object, and an output schema present, the description covers the things structured fields cannot: default window, window-size cap, mutual exclusivity, cache TTL, and the exact cursor round-trip protocol. An agent has everything needed to call and paginate correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the parameter baseline is 3. The description exceeds that by stating the cross-parameter constraint (days vs start/end mutual exclusivity, 120-day max) and the default lookback, none of which appear in the per-parameter schema text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource ("Return CVEs") plus the ordering dimension ("ordered by publication date, newest first"), which separates it from date-based siblings like nvd_get_modified_cves. It does not explicitly name or contrast any sibling tool (nvd_get_cves, nvd_search_cves), so differentiation is implied by scope rather than stated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives concrete usage rules: default 7-day lookback, and that `days` and `start`+`end` are mutually exclusive alternatives capped at 120 days. What it lacks is guidance on when to prefer this over nvd_get_cves or nvd_search_cves — no tool-level alternatives are named.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

nvd_search_cpe_matchesSearch CPE Match CriteriaA
Read-onlyIdempotent

Search CPE Match Criteria, which link CVEs to CPE names and version ranges. At least one filter is required: cveId, matchCriteriaId, matchStringSearch or lastModified (maximum 120 days). matchStringSearch must be a complete CPE match string such as cpe:2.3:a:vendor:product::::::::; upstream rejects partial keywords and version ranges. Cached for 24 hours; paginate with the opaque cursor.

ParametersJSON Schema
NameRequiredDescriptionDefault
cveIdNoReturn the match criteria referenced by this CVE
cursorNoOpaque signed cursor from the previous page: pass the response's pagination.nextCursor. Never build it by hand; it expires after 30 minutes and is bound to the filters, pageSize and date window.
pageSizeNoPage size (default 20, maximum 100)
lastModifiedNoFilter on the match criteria last-modified date (max 120 days)
matchCriteriaIdNoMatch criteria UUID
matchStringSearchNoComplete CPE match string (wildcards allowed, no version ranges)

Output Schema

ParametersJSON Schema
NameRequiredDescription
metaYesCache/freshness metadata; warnings carries stale-fallback and truncation notices
itemsYes
paginationYesPagination block; nextCursor is null on the last page

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnly, idempotent, non-destructive, openWorld), so the description's job is to add operational context — and it does: 24-hour caching, cursor-based pagination, and the upstream rejection of partial keywords and version ranges in matchStringSearch. These are non-obvious behaviors an agent cannot infer from the 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three densely packed sentences with the resource definition front-loaded, then the filter requirement, then the two gotchas (matchString syntax, caching/pagination). No filler, nothing repeated from the schema verbatim.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a six-parameter, nested-object search with an output schema present, the description covers what the tool returns conceptually, the filter precondition, the pagination mechanics, the cache window, and the input-format trap. An agent can call it correctly without opening anything else.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3, but the description adds real meaning on top: matchStringSearch must be a complete CPE match string with the cpe:2.3:a:vendor:product:*... form, and the lastModified window is capped at 120 days. It does not add anything further about cursor freshness or pageSize, which the schema already handles.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Search) and resource (CPE Match Criteria) and explains what the resource is: the join that links CVEs to CPE names and version ranges. That implicitly separates it from nvd_search_cpes / nvd_get_cpe, but no sibling is named explicitly and no exclusion is stated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a hard precondition ('At least one filter is required') and enumerates the four admissible filters plus the 120-day ceiling on lastModified, so an agent knows how to form a valid call. It does not, however, say when to reach for this tool over nvd_search_cpes or how it complements nvd_get_cve.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

nvd_search_cpesSearch CPE namesA
Read-onlyIdempotent

Search the NVD Official CPE Dictionary by keyword, match string, criteria UUID, or last-modified window. At least one filter is required; date windows are limited to 120 days. Deprecated CPEs are filtered locally unless includeDeprecated is true. totalResults is the upstream NVD count before local filtering, so it may be greater than returned items or even > 0 with an empty items array when matching entries are filtered out. Results are cached for 24 hours and use opaque cursor pagination; reuse nextCursor with the same filters and pageSize.

ParametersJSON Schema
NameRequiredDescriptionDefault
cursorNoOpaque signed cursor from the previous page: pass the response's pagination.nextCursor. Never build it by hand; it expires after 30 minutes and is bound to the filters, pageSize and date window.
keywordNoKeyword matched against CPE titles
pageSizeNoPage size (default 20, maximum 100)
lastModifiedNoFilter on the CPE last-modified date (max 120 days)
cpeMatchStringNoCPE match string to look up
matchCriteriaIdNoCPE Match Criteria UUID whose CPE names should be returned
includeDeprecatedNoInclude deprecated CPE names (default false). This filter runs locally; see meta.filteredOut.
keywordExactMatchNoRequire the exact keyword phrase (requires keyword)

Output Schema

ParametersJSON Schema
NameRequiredDescription
metaYesCache/freshness metadata; warnings carries stale-fallback and truncation notices
itemsYes
paginationYesPagination block; nextCursor is null on the last page

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With annotations already covering read-only/idempotent/non-destructive/open-world, the description still adds substantial non-obvious behavior: deprecated CPEs filtered locally unless includeDeprecated, totalResults being the upstream count that can exceed returned items or be positive with an empty items array, and 24-hour caching. This is exactly the operational context annotations cannot express.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four dense sentences, all load-bearing, with the core scope stated first and constraints/edge cases after. The totalResults explanation is the longest clause but justifies its length because it prevents a misinterpretation of an empty result set.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-parameter, nested-object tool with an output schema, the description covers the prerequisites, the local-vs-upstream filtering split, cache lifetime, and cursor lifetime/binding — everything an agent needs to call it correctly and interpret pagination. Return-value shape is rightly left to the output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds genuine cross-parameter semantics: cursors must be reused with the same filters and pageSize, the 120-day cap on the date window, and that includeDeprecated is a local filter reflected in meta.filteredOut. keywordExactMatch and cpeMatchString get no extra narrative, but the schema already documents them.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Search the NVD Official CPE Dictionary") and enumerates the four filter modes (keyword, match string, criteria UUID, last-modified window), so the agent knows exactly what the tool operates on. It is clear it deals with the CPE Dictionary rather than CPE matches, but it never names the nearest sibling (nvd_search_cpe_matches or nvd_get_cpe) to harden the boundary.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

"At least one filter is required; date windows are limited to 120 days" gives a firm precondition the agent must satisfy before calling. It stops short of routing guidance — no statement of when to prefer nvd_get_cpe or nvd_search_cpe_matches instead — so the alternative-selection layer is missing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

nvd_search_cvesSearch CVEsA
Read-onlyIdempotent

Search CVE records with the NVD 2.0 filters: keyword, CVE IDs, CPE name or match string, CWE, source identifier, vuln statuses, published/last-modified windows, KEV window, CVSS metrics and CERT flags. Rules: keywordExactMatch requires keyword; isVulnerable requires cpeName; cpeName and virtualMatchString are mutually exclusive; date windows are limited to 120 days. NVD evaluates every filter, so totalResults is the exact upstream total. Cached for 15 minutes; paginate by passing pagination.nextCursor back as cursor with the same filters and pageSize.

ParametersJSON Schema
NameRequiredDescriptionDefault
kevNo
cvssNoCVSS metric filter; requires at least one of severity or metrics
cweIdNoCWE identifier such as CWE-79
cursorNoOpaque signed cursor from the previous page: pass the response's pagination.nextCursor. Never build it by hand; it expires after 30 minutes and is bound to the filters, pageSize and date window.
cveIdsNoRestrict the search to these CVE identifiers
cpeNameNoCPE name filter; translates to the upstream cpeName parameter
hasOvalNoOnly CVEs with OVAL definitions
keywordNoKeyword matched against CVE descriptions
pageSizeNoPage size (default 20, maximum 50)
publishedNoFilter on the published date (max 120 days)
noRejectedNoExclude rejected CVEs (upstream noRejected)
hasCertNotesNoOnly CVEs with CERT notes
isVulnerableNoOnly CVEs where cpeName is marked vulnerable; requires cpeName, incompatible with virtualMatchString
lastModifiedNoFilter on the last-modified date (max 120 days)
vulnStatusesNoVulnerability statuses (Received, Awaiting Analysis, Undergoing Analysis, Analyzed, Modified, Deferred, Rejected). Spaced and camel-case spellings are both canonicalized, and the filter is applied by NVD.
hasCertAlertsNoOnly CVEs with CERT alerts
sourceIdentifierNoCNA or NVD source identifier, for example secalert@redhat.com
keywordExactMatchNoRequire the exact keyword phrase (requires keyword)
virtualMatchStringNoCPE match string (supports wildcards and version ranges); mutually exclusive with cpeName

Output Schema

ParametersJSON Schema
NameRequiredDescription
metaYesCache/freshness metadata; warnings carries stale-fallback and truncation notices
itemsYes
paginationYesPagination block; nextCursor is null on the last page

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only, idempotent, open-world behavior, so the description need not restate safety. It adds genuinely non-obvious traits: results are cached for 15 minutes, and NVD evaluates every filter so totalResults is the exact upstream total, plus how to paginate via nextCursor. Missing details like rate limits or cache-staleness implications keep it below 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with purpose then rules then caching/pagination, with no filler. The opening filter enumeration slightly overlaps with what the schema already lists, so it is not maximally economical, but every clause carries usable information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 19-parameter, nested-object tool with an output schema present, the description covers the essential non-schema gaps: constraint interactions, window caps, caching, exactness of totals, and pagination mechanics. An agent can call it correctly without opening the schema, though sibling routing is the one untouched area.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 95%, so the baseline is 3, but the description adds cross-parameter semantics the schema only partially encodes: the keyword/keywordExactMatch and cpeName/isVulnerable dependencies, the exclusivity pair, and the shared 120-day window limit. It also clarifies that statuses and filters are applied upstream by NVD, which is meaning beyond the field-level text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Search CVE records') and enumerates the exact NVD 2.0 filter dimensions the tool accepts, so the agent knows precisely what surface it covers. It is clearly distinct from get-style siblings in name and behavior, but never explicitly names those siblings or contrasts itself with them, keeping it short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The 'Rules' sentence gives real operational constraints (keywordExactMatch requires keyword; isVulnerable requires cpeName; cpeName/virtualMatchString mutually exclusive; 120-day windows) and explains pagination. However, there is no guidance on when to choose this over sibling tools like nvd_get_cves or nvd_get_recent_cves, which is the main 'when-to-use' question for a search tool.

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.

  1. 10 tool updatesv0.1.0
    • First observednvd_get_cpe
    • First observednvd_get_cve
    • First observednvd_get_cve_history
    • First observednvd_get_cve_summary
    • First observednvd_get_cves
    • First observednvd_get_modified_cves
    • First observednvd_get_recent_cves
    • First observednvd_search_cpe_matches
    • First observednvd_search_cpes
    • First observednvd_search_cves

TDQS

A4.3/5.0

Scored across 10 tools

Disambiguation4/5

Tool names and descriptions clearly delineate resource+action, but nvd_get_recent_cves and nvd_get_modified_cves are nearly identical except for ordering, and nvd_get_cve, nvd_get_cve_summary, and nvd_get_cves all target CVE records with overlapping semantics. The descriptions do distinguish scope and detail level, but an agent could easily misselect between the full, summary, and batch variants without careful reading.

Naming Consistency5/5

Every tool follows a consistent nvd_ verb_noun pattern (get, search, and entity names like cve, cves, cpe). Variants like nvd_get_cve_summary and nvd_get_cve_history extend the base name predictably. No mixed conventions or inconsistent casing.

Tool Count5/5

Ten tools is well within the sweet spot for a domain-specific API wrapper. Each tool maps to a distinct NVD endpoint or use case (single record, batch, search, history, CPE dictionary, CPE matches), so the surface feels scoped rather than padded.

Completeness4/5

The surface covers CVE retrieval (single, batch, summary, search, history, recent, modified) and CPE lookup (search, get, matches), which is core NVD functionality. Missing operations like CVE creation or modification don't apply since NVD is read-only, but there is no tool for bulk CPE dictionary listing or NVD API status, which could be minor gaps for some workflows.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    A Model Context Protocol (MCP) server for querying the CVE-Search API. This server provides comprehensive access to CVE-Search, browse vendor and product、get CVE per CVE-ID、get the last updated CVEs.
    6
    107
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    A Model Context Protocol (MCP) server for querying the NIST National Vulnerability Database (NVD) API, enabling search and retrieval of CVE details, temporal context, and KEV catalog entries.
    14
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    MCP server that provides tools to search, filter, and retrieve CVE data from the NVD API, including by ID, keyword, severity, and recency.
    4
    MIT
  • F
    license
    A
    quality
    B
    maintenance
    Enables querying and analyzing a legacy, file-based vulnerability registry via MCP tools for CVE lookup, search, vendor navigation, and aggregate statistics.
    5
    -