Model or dataset
mukul975/cve-mcp-server avatar
mukul975/cve-mcp-server

mukul975/cve-mcp-server: CVE Triage Inside Claude, Wired to 24 Data Sources

Production-grade MCP server giving Claude 27 security intelligence tools across 21 APIs — CVE lookup, EPSS scoring, CISA KEV, MITRE ATT&CK, Shodan, VirusTotal, and more.

1,594 stars261 forksPythonApache-2.0

At a glance

What is it?
An MCP server that exposes vulnerability and threat-intelligence lookups as Claude tools, fronted by a single triage_cve call that fans out to NVD, EPSS and CISA KEV. Here is what it actually does, how to install it, and where it stops being the right tool.
Who is it for?
Adopt cve-mcp-server if your triage work already happens in Claude Desktop or Claude Code and you want NVD, EPSS and CISA KEV evidence pulled into one answer instead of five tabs. Do not adopt it if you need a scanner of your own assets, a scheduled pipeline, or a stable 1.0 API surface; the package metadata still marks Development Status 4 - Beta.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 11 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The tab-switching problem triage_cve is built to remove

Triaging one CVE by hand means opening NVD for CVSS and CWE data, EPSS for exploitation probability, CISA KEV to see whether it is being exploited in the wild, GitHub for patch references, and VirusTotal or a similar source for malware associations. The README states the cost plainly: for 50 CVEs, that is an entire day lost. The work is not hard, it is serial. Each source answers one question, and the correlation happens in the analyst's head.

The project targets that specific bottleneck rather than vulnerability scanning. It does not discover CVEs in your code or your images. It answers questions about CVE identifiers you already have, and it answers them where the question is asked: inside Claude. The intended reader is a security engineer, a DevSecOps person, or an incident responder who already runs Claude Desktop or Claude Code and wants the correlation step to happen in the same conversation as the decision.

That framing matters when you evaluate it. If your problem is "which of my dependencies are vulnerable," this is the wrong category of tool. If your problem is "I have a list of CVE IDs and I need to know which ones matter this week," the design is aimed directly at you.

How the MCP server actually reaches 24 sources

The architecture is a single Python process speaking the Model Context Protocol to the client over stdio by default. The README's diagram splits the internals into three parts: a tool layer, a composite risk engine, and a SQLite cache with an audit log. Below those sits an async HTTP client built on httpx, with a rate limiter and a response cache in front of it.

Outbound traffic is HTTPS only. The README states that no inbound ports are opened, that API keys are loaded from environment variables and never logged, and that private and internal IP addresses are blocked from all lookup tools. That last constraint is a deliberate narrowing: the network-intelligence tools (AbuseIPDB, GreyNoise, Shodan, CIRCL PDNS) will not be pointed at your own internal ranges.

The orchestration layer is where the design gets interesting. triage_cve is described as fanning out to NVD, EPSS and CISA KEV concurrently, computing a composite risk score, and applying a CISA KEV hard override. At depth="deep" it also emits an SSVC v2 gated decision. When NIST NVD is throttled or unreachable, the README says triage_cve falls back transparently to VulnCheck NVD++ if a token is configured. The tool also exposes MCP resources such as kev://catalog and epss://scores/{cve_id}, plus a manifest://tool-hash resource described as a SHA-256 hash over the registered tool surface for tamper detection. Prompts named patch_decision, compare_and_prioritize and dependency_triage ship alongside the tools.

One inconsistency worth flagging: the README headline says 28 tools and 24 data sources, while the architecture diagram labels the tool layer as 27 MCP tools and the package description in pyproject.toml says "20+ APIs." Treat the exact counts as drifting documentation rather than a specification.

Installing cve-mcp-server and running a first triage

The repository ships a pyproject.toml, a Dockerfile, a .env.example and a .mcp.json, so there are two plausible paths: a local Python install and a container. The Dockerfile is a multi-stage build that copies the uv binary from the official Astral image, installs dependencies into /app/.venv, then produces a python:3.12-slim runtime that runs as a non-root user and exposes a streamable-HTTP MCP endpoint on port 8000. The header comments give the build and run commands:

bash
docker build -t cve-mcp-server .
docker run --rm -p 8000:8000 --env-file .env cve-mcp-server

The container path is for HTTP transport. For Claude Desktop or Claude Code, the default stdio transport is what you want, and the .env.example shows the switch: MCP_TRANSPORT=http selects streamable-HTTP on HOST:PORT, while anything else or unset uses stdio. HOST defaults to 0.0.0.0 and PORT to 8000.

Keys are optional but change the experience. The .env.example documents the trade-offs directly: without an NVD_API_KEY you get 5 requests per 30 seconds, with one you get 50. A GITHUB_TOKEN raises the advisory API limit from 60 per hour to 5000. A VULNCHECK_TOKEN enables the NVD++ fallback inside triage_cve, and the file notes that community tokens expire after 30 days of inactivity. CIRCL hashlookup and the HIBP Pwned Passwords range API need no key at all.

bash
NVD_API_KEY=
GITHUB_TOKEN=
VULNCHECK_TOKEN=
MCP_TRANSPORT=stdio
REQUEST_TIMEOUT=30
MAX_RETRIES=3

Those last two are worth setting deliberately. REQUEST_TIMEOUT defaults to 30 seconds and MAX_RETRIES to 3, with backoff delays of 6s, 12s and 24s according to the .env.example. A deep triage that fans out across several slow sources can therefore sit for a while before it gives up.

The first real use is a single tool call. The README gives the example triage_cve("CVE-2021-44228", depth="deep"). You should expect a composite risk score with a KEV override applied if the CVE is in the CISA KEV catalog, supporting evidence from the sources that answered, and, at deep depth, an SSVC v2 decision. If you want the raw record instead of the verdict, lookup_cve("CVE-2024-3400") returns the NVD entry with CVSS scores, CWEs, affected products, references and timeline. Cache and audit paths default to ~/.cve-mcp/cache.db and ~/.cve-mcp/audit.log unless CACHE_DB_PATH and AUDIT_LOG_PATH override them; the audit log rotates at 50MB and keeps five backups.

Where cve-mcp-server is the wrong tool

The composite risk score is the part to scrutinize hardest. The README describes a KEV hard override, which means a CVE in the CISA KEV catalog will outrank a CVE with a higher CVSS that is not. That is a defensible editorial position, and it is also an opinion baked into a number. If your organization prioritizes by CVSS threshold or by an internal exploitability model, the score triage_cve returns will not match your policy, and you will be reconciling two rankings by hand.

Coverage is bounded by the sources listed. A CVE that no upstream source has enriched yet, or one that lives only in a vendor advisory outside the 24 APIs, will come back thin. The fallback to VulnCheck NVD++ only helps when a token is configured; without one, an NVD throttle degrades the result rather than routing around it.

The transport choice also constrains deployment. stdio means one client process, which suits a desktop assistant and does not suit a shared service. The HTTP mode is described as stateless and container-friendly, but the README does not document authentication in front of that endpoint. Anyone who can reach port 8000 can call the tools, and every call spends your API keys. If you expose it beyond localhost, that is a decision you have to make deliberately, because the project does not make it for you.

Finally, this is not a scanner and not an inventory. It will not tell you which of your services run CVE-2024-3400. It tells you what is known about that CVE once you name it.

How it compares with querying the sources directly

The obvious alternative is not another MCP server. It is a script or a notebook that calls the NVD API 2.0, the FIRST EPSS API and the CISA KEV feed, then joins the results on CVE ID. That approach gives you full control over the scoring formula, the caching layer and the output format, and it costs you the conversational interface. You write the correlation logic yourself, and you maintain it when a source changes shape.

A second alternative is using Claude or another assistant with web search and no MCP server at all. That works for a single CVE and falls apart for a list: the model reads pages rather than structured records, the answers are not reproducible, and nothing is cached or audited. The distinction is that cve-mcp-server returns typed fields from named APIs, writes to a SQLite cache, and logs calls to an audit file. Those are the properties you want when the triage output feeds a decision someone will be asked to justify later.

There is also the question of where the intelligence lives. A script keeps it in your repository, versioned with your code. This project keeps it in a tool surface registered with the MCP client, which is why the manifest://tool-hash resource exists: it lets you detect when that surface changes. If tool-surface integrity matters to your threat model, that resource is the feature to evaluate first.

Licence, maintenance and the cost of upgrading

The repository's LICENSE file and the pyproject.toml classifier both point to MIT, and the README badge says MIT. The repository metadata supplied alongside the project says Apache-2.0. Those two disagree, and the LICENSE file in the repository is the one that governs what you actually receive. Check it before you rely on either label, particularly if your legal team treats patent grants differently between the two.

Maintenance looks current. The last push was on 2026-08-05, and the repository is not archived. Two releases exist: v0.1.0 on 2026-04-14 and v0.2.0 on 2026-06-22, the latter adding the triage_cve orchestrator and what the release title calls security hardening. The package metadata still declares Development Status 4 - Beta, so the tool surface is not frozen.

Upgrade cost is concentrated in two places. First, the env file: v0.2.0 introduced MCP_TRANSPORT, HOST and PORT, so a configuration written against v0.1.0 will not know about the transport switch. Second, the tool surface itself, which is exactly what manifest://tool-hash is designed to make visible. If you build prompts or automation on top of specific tool names, pin the version and re-check the hash after each upgrade rather than assuming the surface is stable.

Editorial conclusion

Adopt cve-mcp-server if your triage work already happens in Claude Desktop or Claude Code and you want NVD, EPSS and CISA KEV evidence pulled into one answer instead of five tabs. Do not adopt it if you need a scanner of your own assets, a scheduled pipeline, or a stable 1.0 API surface; the package metadata still marks Development Status 4 - Beta. Before wiring it into anything, run triage_cve against two CVEs you already understand, confirm the composite score matches your own reading, and check whether the KEV hard override fires on a CVE that is not in the KEV catalog.

Frequently asked questions

What is mukul975/cve-mcp-server?

It is a Model Context Protocol server written in Python that gives Claude security intelligence tools across roughly two dozen APIs, covering CVE lookup, EPSS scoring, CISA KEV, MITRE ATT&CK, Shodan and VirusTotal among others. A one-call triage_cve orchestrator fans out to NVD, EPSS and CISA KEV concurrently and returns a composite risk score.

How do I install cve-mcp-server?

The repository ships a pyproject.toml for a Python 3.10+ install and a multi-stage Dockerfile that builds the server into /app/.venv and runs it as a non-root user on port 8000. For Claude Desktop or Claude Code, the default stdio transport is used; setting MCP_TRANSPORT=http switches it to streamable-HTTP on HOST:PORT.

Does cve-mcp-server need API keys?

It runs without keys, but the .env.example documents the cost: NVD allows 5 requests per 30 seconds without a key and 50 with one, and a GitHub token raises the advisory limit from 60 per hour to 5000. A VulnCheck token enables the NVD++ fallback inside triage_cve when NIST NVD is throttled, and the CIRCL hashlookup and HIBP Pwned Passwords range sources require no key at all.

What licence does cve-mcp-server use?

The README badge, the LICENSE file reference in pyproject.toml and the package classifier all say MIT, while the repository metadata says Apache-2.0. The two disagree, so read the LICENSE file in the repository before relying on either label.

Official sources

  1. License: Apache-2.0
  2. mukul975/cve-mcp-server on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/mukul975-cve-mcp-server.svg)](https://hysenlabs.com/projects/mukul975-cve-mcp-server)