MCP server for CVE and vulnerability searching, optimized for PR reviews
The CVE Search MCP server has generally well-structured tools with consistent naming conventions, clear descriptions, and properly defined input schemas. Most tools follow verb_noun patterns (search_*, get_*, check_*). Descriptions are adequately detailed (100-300 chars typical) and include context about when to use each tool. Input parameters have types and descriptions. However, there are significant gaps: output schemas are not documented in the code, no error handling guidance is visible, and several tools lack actionable error recovery hints. The server does not implement tool annotations (readOnlyHint despite all tools being READ_ONLY) or structured error responses that guide LLM recovery. Parameter constraints are present but could be more explicit (e.g., 'CVE-YYYY-NNNN' format is mentioned but not enforced in schema). Dependencies between tools (e.g., 'call search_by_keyword first') are hinted but incomplete.
Look up multiple CVEs by ID concurrently (max 20 IDs). Useful for scanning dependency lists extracted from pull requests. Returns a dict of {cve_id: result} with severity info for each entry.
Get high-severity CVEs (CVSS >= 7.0) from the last N days (1-365). Fast. Covers Critical (9.0-10.0) and High (7.0-8.9) severity. Example: check_high_severity_cves(7) — this week's critical threats.
Get a detailed CVSS v3/v4 breakdown for a CVE: base score, vector string, and individual metrics (Attack Vector, Complexity, Privileges Required, User Interaction, Scope, Confidentiality/Integrity/Availability Impact). Uses NVD which carries the richest CVSS data.
Get CVEs published in the last N days (1-365). Fast. Returns a list with severity analysis and alert level. Example: get_recent_cves(7, 30) — last week's top 30 CVEs.
Get CVE database statistics: total count, last updated timestamp, and source info. Fast. Useful for health checks and confirming database freshness before analysis.
No documented output schemas for any tool. Tool descriptions mention what is returned ('complete CVE details with CVSS score', 'dict of {cve_id: result}') but the actual JSON structure is not specified. LLMs cannot plan downstream operations without knowing response structure.
No error handling guidance or recovery paths defined. Tools like search_vulnerabilities_by_product warn 'can be slow (10-15 seconds)' but provide no timeout handling, retry strategy, or fallback. If a lookup fails (CVE not found, API timeout), there is no guidance for LLM recovery.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 55 | <=2025-11-25 | v2 |
| 2026-03-09 | F | 36 | - | v1 |
Smart CVE search by technology/library keyword. Fast. Normalizes common variations ("Node.js", "Spring Boot", "log4j2"). Searches NVD, GitHub Advisory, and OSV concurrently and deduplicates results. Example: search_by_keyword("nodejs"), search_by_keyword("spring boot").
Search for a specific CVE by exact ID (e.g., CVE-2021-44228). Use when you have a CVE ID from code, docs, or security reports. Returns complete CVE details with CVSS score and severity analysis.
Search vulnerabilities by vendor and product name (e.g., vendor="apache", product="struts"). WARNING: This can be slow (10-15 seconds). Use search_by_keyword for faster results. Returns matched vulnerabilities with severity summary.
Missing tool annotations. All 8 tools are READ_ONLY (stateless queries to public CVE databases), but none have 'readOnlyHint' annotations in the schema. This forces LLMs to reason about side effects when there are none, wasting reasoning cycles.
Parameter format constraints are mentioned in descriptions but not enforced in schema. 'CVE-YYYY-NNNN' format is mentioned verbally but the input schema uses bare 'string' type with no regex pattern or validation. This invites hallucinated invalid CVE IDs (e.g., 'CVE-20-1234' or 'cve-2021-44228').
bulk_cve_lookup accepts 'max 20 IDs' but this constraint is stated in the description, not enforced in the schema. No minItems/maxItems declaration. If an LLM passes 100 CVE IDs, the tool will fail ungracefully.
Parameter 'limit' defaults are mentioned inconsistently. search_by_keyword defaults to 30, get_recent_cves to 100, search_vulnerabilities_by_product to 50. No clear reasoning for different limits, and no explanation why limit is unbounded in schema (could cause result explosion).
Tool composition could be improved. search_by_keyword, search_cve_by_id, and search_vulnerabilities_by_product all search for CVEs but with different semantics. The descriptions hint at when to use each ('Use when you have a CVE ID' vs 'Smart search by keyword' vs 'can be slow') but LLMs may conflate them or choose the wrong one.