The server defines 2 tools with explicit schemas and descriptions. Tool naming follows verb_noun convention (get_cve, search_cve), which is correct. Descriptions are present and contextually adequate (ranging from ~70-120 chars), meeting the 10-1024 character baseline. Both tools have complete input schemas with types and parameter descriptions. The major gaps are: (1) no documented output schema, callers cannot predict the return structure; (2) no error handling guidance, LLMs cannot determine recovery steps on API failures; (3) no pagination support despite search_cve potentially returning many results; (4) tool annotations (readOnlyHint, idempotentHint) are absent despite being safe, read-only operations. The format_cve() helper function produces detailed text output suitable for display, but the output format is not formally declared. The server is well-structured and reasonably complete for a domain-specific NVD lookup tool, but lacks the refinement expected of production-grade tools (e.g., structured JSON response schema, explicit error categorization, pagination).
Get a CVE based on the ID and return a formatted string with detailed attributes.
Search CVEs by keyword and return formatted results matching the get_cve format.
No documented output schema. Tools return formatted strings from format_cve() helper, but LLMs cannot predict the structure, field names, or data types in advance. This breaks downstream tool composition and forces agents to parse unstructured text.
No error handling guidance. When NVD API calls fail (HTTP error, timeout, invalid CVE ID), the tools return None or generic error text. Descriptions do not explain recovery steps, leaving LLMs unable to determine if the error is retryable, user-fixable, or fatal.
No pagination on search_cve despite variable result size. The 'results' parameter defaults to 10 and accepts integer input, but there is no 'offset' or 'next_cursor' parameter, no total_count return, and no guidance on how to fetch additional results. This violates the paginated-result pattern and risks context explosion if an LLM tries to retrieve all CVEs matching a broad keyword.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | A | 80 | <=2025-11-25 | v2 |
| 2026-03-09 | D | 56 | - | v1 |
Missing tool annotations. Both tools are read-only (Risk: READ_ONLY declared), but the tool definitions do not include readOnlyHint or idempotentHint annotations in the MCP protocol. Agents cannot infer safety from the schema alone and may treat these as mutable operations.
search_cve description does not clarify the distinction between 'exact_match=true' and 'exact_match=false'. What fields are searched? Is it a substring match on CVE ID, description, or keyword? What does 'exact' mean, full word only, whole CVE ID, or case-sensitive? Ambiguity forces LLMs to guess.
No guidance on CVE ID format validation. The 'cve_id' parameter has a simple string type with description 'The CVE identifier (e.g., CVE-2024-1234)', but does not specify: required format (CVE-YYYY-NNNNN?), case sensitivity, or acceptable variations. Invalid IDs will fail silently.
No result limits documented for get_cve or search_cve outputs. The search_cve tool accepts a 'results' parameter but the description does not state minimum (e.g., 1) or maximum (e.g., 100) constraints. An LLM could request 10000 results, causing a slow API call or memory issue.