Skip to main content
Glama
cyanheads

nist-nvd-mcp-server

by cyanheads

Version License Docker MCP SDK npm TypeScript Bun

Install in Claude Desktop Install in Cursor Install in VS Code

Framework

Public Hosted Server: https://nist-nvd.caseyjhand.com/mcp


Tools

Five tools for vulnerability research, CPE auditing, and change tracking against the NIST NVD API 2.0:

Tool

Description

nvd_search_cves

Search CVEs by keyword, severity, CWE, date range, or CISA KEV status.

nvd_get_cve

Fetch one or more CVEs by ID — full CVSS scores, CWE, CPE configs, KEV fields, and references.

nvd_search_cpes

Search the NVD CPE dictionary by product keyword or partial match string.

nvd_audit_cpe

Find all CVEs affecting a specific product version by CPE name or virtual match string.

nvd_get_cve_history

Retrieve the change history for a CVE — score revisions, status transitions, and reference additions.

nvd_search_cves

The primary discovery tool for vulnerability surveillance and triage workflows.

  • Full-text keyword search across CVE descriptions (AND-semantics across words), or exactPhrase: true to match the keyword as a phrase

  • Severity filter by CVSS v2/v3/v4 label (LOW, MEDIUM, HIGH, CRITICAL)

  • CWE weakness filter (e.g., CWE-79, NVD-CWE-Other)

  • CISA KEV filter — limit results to known-exploited vulnerabilities

  • Convenience date shorthands: pubDays and lastModDays for "last N days" queries

  • Explicit ISO 8601 date range parameters (pubStartDate/pubEndDate, etc.) with 120-day max span

  • Auto-clamps convenience date params that exceed 120 days and reports clamped values in the response enrichment

  • Pagination via limit (up to 2000) and offset

  • Every row carries a truncated description alongside the ID, so results are distinguishable without a follow-up fetch

  • Results are always brief; call nvd_get_cve for full detail


nvd_get_cve

Fetch one or more CVEs by ID with full detail or brief summaries.

  • Batch up to 100 CVE IDs per call

  • Full mode: all CVSS scores across v2.0, v3.0, v3.1, and v4.0; CWE weaknesses; CPE configurations; CISA KEV fields; references

  • Brief mode (brief: true): ID, status, top severity, KEV name, truncated description — recommended for batches larger than 10

  • includeReferences: false to strip the references array and reduce response size

  • Per-ID parity check: the missingIds enrichment field lists any requested IDs NVD didn't return

  • Rendered text carries the affected-product criteria and references the record holds, capped with a … N more trailer; allLanguages: true renders every localized description, not just English


nvd_search_cpes

Look up product identifiers before auditing.

  • Keyword search (e.g., "apache http server", "openssl") or partial CPEv2.3 pattern

  • Returns full CPE name, human-readable title, deprecation status, and superseding CPEs

  • Pagination via limit (up to 10,000 per page) and offset — a vendor-level keyword can match tens of thousands of entries, so page with offset rather than trying to narrow further

  • Use this before nvd_audit_cpe — CPE names are arcane strings; guessing audits the wrong product


nvd_audit_cpe

Full CVE audit for a specific product version.

  • Two modes: exact cpeName (NVD auto-applies isVulnerable) or virtualMatchString with optional version range bounds

  • Version range via versionStart/versionEnd with inclusive/exclusive type control

  • Client-side severity filter (severityMin) to strip low-signal entries

  • Returns full CVE records (ID, CVSS scores, CWE, CPE configurations, KEV fields, references)

  • Pagination via limit (up to 2000) and offset — page at a modest limit instead of raising it, since each result is a full record

  • Echoes the CPE identifier used in the response enrichment so callers can verify the correct product was queried


nvd_get_cve_history

Track a CVE's lifecycle over time.

  • Returns change events: CVSS revisions, status transitions, reference additions, CPE configuration updates

  • order picks which end to read from — newest (default) returns the most recent events first, oldest returns NVD's native oldest-first order

  • Paginated via limit and offset, where offset counts from the end order anchors to

  • Note: the NVD history endpoint is significantly slower without an API key — set NVD_API_KEY and raise NVD_REQUEST_TIMEOUT_MS for reliable operation

Resource

Type

Name

Description

Resource

nvd://cve/{cveId}

Full CVE record by ID — same data as nvd_get_cve for a single ID, as a stable URI for injectable context.

All resource data is also reachable via tools.

Features

Built on @cyanheads/mcp-ts-core:

  • Declarative tool, resource, and prompt definitions — single file per primitive, framework handles registration and validation

  • Unified error handling — handlers throw, framework catches, classifies, and formats

  • Pluggable auth: none, jwt, oauth

  • Swappable storage backends: in-memory, filesystem, Supabase, Cloudflare KV/R2/D1

  • Structured logging with optional OpenTelemetry tracing

  • STDIO and Streamable HTTP transports

NVD-specific:

  • Request pacer enforces NVD's 5 req/30s (no key) and 50 req/30s (with key) limits with automatic queuing, at a minimum inter-request gap derived from the window and limit

  • Retry wraps the pacer rather than sitting inside it — every attempt takes its own turn in the queue, so retries count against the rate budget instead of bursting past it

  • A 403's Retry-After holds the whole queue until NVD's window resets. Keyless, a 403 fails fast and names NVD_API_KEY rather than spending a 5-request budget on retries that cannot outlast a 30-second window

  • Deterministic rejections fail fast instead of consuming retries. NVD answers both a bad parameter and a refused API key with HTTP 404, separated only by a message header — a refused key surfaces as a config fault naming NVD_API_KEY rather than as a malformed CVE ID

  • HTML-response guard catches NVD rate-limit pages served as HTML instead of 403

Agent-friendly output:

  • An enrichment block on every response, carried on both structuredContent and the rendered text — total results, returned count, page offset, the filters actually applied, and any date-clamping events, so agents can reason about what was really queried

  • missingIds in batch CVE lookups — per-ID parity check instead of a silent partial result

  • CPE echo in audit responses — cpeName or virtualMatchString reflected back so callers can verify the correct product was audited

  • Empty-result notices that name the cause — an unmatched query, a severity threshold that emptied the page, and an offset past the end of the result set are told apart rather than all reading as "nothing found"

  • An audit that finds nothing is a result, not an error — a product with no CVEs in NVD returns an empty page with totalCount: 0 on either input arm, so "no known vulnerabilities" reads as the answer it is

Getting started

Add the following to your MCP client configuration file.

{
  "mcpServers": {
    "nist-nvd-mcp-server": {
      "type": "stdio",
      "command": "bunx",
      "args": ["@cyanheads/nist-nvd-mcp-server@latest"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info",
        "NVD_API_KEY": "your-api-key"
      }
    }
  }
}

Or with npx (no Bun required):

{
  "mcpServers": {
    "nist-nvd-mcp-server": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@cyanheads/nist-nvd-mcp-server@latest"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info",
        "NVD_API_KEY": "your-api-key"
      }
    }
  }
}

Or with Docker:

{
  "mcpServers": {
    "nist-nvd-mcp-server": {
      "type": "stdio",
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "MCP_TRANSPORT_TYPE=stdio",
        "-e", "NVD_API_KEY=your-api-key",
        "ghcr.io/cyanheads/nist-nvd-mcp-server:latest"
      ]
    }
  }
}

For Streamable HTTP, set the transport and start the server:

MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 NVD_API_KEY=... bun run start:http
# Server listens at http://localhost:3010/mcp

Prerequisites

  • Bun v1.3.0 or higher (or Node.js v24+).

  • Optional: NVD API key — free, raises rate limit from 5 req/30s to 50 req/30s.

Installation

  1. Clone the repository:

git clone https://github.com/cyanheads/nist-nvd-mcp-server.git
  1. Navigate into the directory:

cd nist-nvd-mcp-server
  1. Install dependencies:

bun install
  1. Configure environment:

cp .env.example .env
# edit .env and set NVD_API_KEY if you have one

Configuration

Variable

Description

Default

NVD_API_KEY

NVD API key. Without it, rate limit is 5 req/30s; with it, 50 req/30s. Get one free at nvd.nist.gov/developers/request-an-api-key.

NVD_REQUEST_TIMEOUT_MS

Per-request timeout in milliseconds. The history endpoint is slow without an API key — raise to 60000 if using nvd_get_cve_history without a key.

10000

MCP_TRANSPORT_TYPE

Transport: stdio or http.

stdio

MCP_HTTP_PORT

Port for HTTP server.

3010

MCP_AUTH_MODE

Auth mode: none, jwt, or oauth.

none

MCP_LOG_LEVEL

Log level (RFC 5424).

info

LOGS_DIR

Directory for log files (Node.js only).

<project-root>/logs

OTEL_ENABLED

Enable OpenTelemetry instrumentation.

false

See .env.example for the full list of optional overrides.

Running the server

Local development

  • Build and run:

    # One-time build
    bun run rebuild
    
    # Run the built server
    bun run start:stdio
    # or
    bun run start:http
  • Run checks and tests:

    bun run devcheck   # Lint, format, typecheck, security
    bun run test       # Vitest test suite
    bun run lint:mcp   # Validate MCP definitions against spec

Docker

docker build -t nist-nvd-mcp-server .
docker run --rm -e NVD_API_KEY=your-key -p 3010:3010 nist-nvd-mcp-server

The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/nist-nvd-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.

Project structure

Directory

Purpose

src/index.ts

createApp() entry point — registers tools/resources and inits services.

src/config

Server-specific environment variable parsing and validation with Zod.

src/mcp-server/tools

Tool definitions (*.tool.ts).

src/mcp-server/resources

Resource definitions (*.resource.ts).

src/services/nvd-http

NVD HTTP client with rate-limit pacing and retry.

src/services/nvd-cve

CVE service — search, fetch-by-ID, CPE audit, change history, normalization.

src/services/nvd-cpe

CPE service — dictionary search and normalization.

src/services/nvd-source

Source service — resolves NVD contributor identifiers to their published names.

tests/

Unit and integration tests mirroring src/.

Development guide

See CLAUDE.md for development guidelines and architectural rules. The short version:

  • Handlers throw, framework catches — no try/catch in tool logic

  • Use ctx.log for request-scoped logging, ctx.state for tenant-scoped storage

  • Register new tools and resources via the barrels in src/mcp-server/*/definitions/index.ts

  • Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields

Contributing

Issues and pull requests are welcome. Run checks and tests before submitting:

bun run devcheck
bun run test

License

Apache-2.0 — see LICENSE for details.