@cyanheads/nist-nvd-mcp-server 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/AGENTS.md +410 -0
  2. package/CLAUDE.md +410 -0
  3. package/Dockerfile +99 -0
  4. package/LICENSE +201 -0
  5. package/README.md +306 -0
  6. package/changelog/0.1.x/0.1.0.md +19 -0
  7. package/changelog/0.1.x/0.1.1.md +29 -0
  8. package/changelog/0.1.x/0.1.2.md +12 -0
  9. package/changelog/0.1.x/0.1.3.md +22 -0
  10. package/changelog/template.md +119 -0
  11. package/dist/config/server-config.d.ts +15 -0
  12. package/dist/config/server-config.d.ts.map +1 -0
  13. package/dist/config/server-config.js +27 -0
  14. package/dist/config/server-config.js.map +1 -0
  15. package/dist/index.d.ts +8 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +32 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/mcp-server/resources/definitions/index.d.ts +6 -0
  20. package/dist/mcp-server/resources/definitions/index.d.ts.map +1 -0
  21. package/dist/mcp-server/resources/definitions/index.js +6 -0
  22. package/dist/mcp-server/resources/definitions/index.js.map +1 -0
  23. package/dist/mcp-server/resources/definitions/nvd-cve.resource.d.ts +9 -0
  24. package/dist/mcp-server/resources/definitions/nvd-cve.resource.d.ts.map +1 -0
  25. package/dist/mcp-server/resources/definitions/nvd-cve.resource.js +36 -0
  26. package/dist/mcp-server/resources/definitions/nvd-cve.resource.js.map +1 -0
  27. package/dist/mcp-server/tools/definitions/index.d.ts +10 -0
  28. package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -0
  29. package/dist/mcp-server/tools/definitions/index.js +10 -0
  30. package/dist/mcp-server/tools/definitions/index.js.map +1 -0
  31. package/dist/mcp-server/tools/definitions/nvd-audit-cpe.tool.d.ts +116 -0
  32. package/dist/mcp-server/tools/definitions/nvd-audit-cpe.tool.d.ts.map +1 -0
  33. package/dist/mcp-server/tools/definitions/nvd-audit-cpe.tool.js +329 -0
  34. package/dist/mcp-server/tools/definitions/nvd-audit-cpe.tool.js.map +1 -0
  35. package/dist/mcp-server/tools/definitions/nvd-get-cve-history.tool.d.ts +45 -0
  36. package/dist/mcp-server/tools/definitions/nvd-get-cve-history.tool.d.ts.map +1 -0
  37. package/dist/mcp-server/tools/definitions/nvd-get-cve-history.tool.js +132 -0
  38. package/dist/mcp-server/tools/definitions/nvd-get-cve-history.tool.js.map +1 -0
  39. package/dist/mcp-server/tools/definitions/nvd-get-cve.tool.d.ts +36 -0
  40. package/dist/mcp-server/tools/definitions/nvd-get-cve.tool.d.ts.map +1 -0
  41. package/dist/mcp-server/tools/definitions/nvd-get-cve.tool.js +183 -0
  42. package/dist/mcp-server/tools/definitions/nvd-get-cve.tool.js.map +1 -0
  43. package/dist/mcp-server/tools/definitions/nvd-search-cpes.tool.d.ts +40 -0
  44. package/dist/mcp-server/tools/definitions/nvd-search-cpes.tool.d.ts.map +1 -0
  45. package/dist/mcp-server/tools/definitions/nvd-search-cpes.tool.js +140 -0
  46. package/dist/mcp-server/tools/definitions/nvd-search-cpes.tool.js.map +1 -0
  47. package/dist/mcp-server/tools/definitions/nvd-search-cves.tool.d.ts +90 -0
  48. package/dist/mcp-server/tools/definitions/nvd-search-cves.tool.d.ts.map +1 -0
  49. package/dist/mcp-server/tools/definitions/nvd-search-cves.tool.js +342 -0
  50. package/dist/mcp-server/tools/definitions/nvd-search-cves.tool.js.map +1 -0
  51. package/dist/services/nvd-cpe/nvd-cpe-service.d.ts +27 -0
  52. package/dist/services/nvd-cpe/nvd-cpe-service.d.ts.map +1 -0
  53. package/dist/services/nvd-cpe/nvd-cpe-service.js +58 -0
  54. package/dist/services/nvd-cpe/nvd-cpe-service.js.map +1 -0
  55. package/dist/services/nvd-cpe/types.d.ts +41 -0
  56. package/dist/services/nvd-cpe/types.d.ts.map +1 -0
  57. package/dist/services/nvd-cpe/types.js +6 -0
  58. package/dist/services/nvd-cpe/types.js.map +1 -0
  59. package/dist/services/nvd-cve/nvd-cve-service.d.ts +79 -0
  60. package/dist/services/nvd-cve/nvd-cve-service.d.ts.map +1 -0
  61. package/dist/services/nvd-cve/nvd-cve-service.js +345 -0
  62. package/dist/services/nvd-cve/nvd-cve-service.js.map +1 -0
  63. package/dist/services/nvd-cve/types.d.ts +185 -0
  64. package/dist/services/nvd-cve/types.d.ts.map +1 -0
  65. package/dist/services/nvd-cve/types.js +6 -0
  66. package/dist/services/nvd-cve/types.js.map +1 -0
  67. package/dist/services/nvd-http/nvd-http-client.d.ts +26 -0
  68. package/dist/services/nvd-http/nvd-http-client.d.ts.map +1 -0
  69. package/dist/services/nvd-http/nvd-http-client.js +175 -0
  70. package/dist/services/nvd-http/nvd-http-client.js.map +1 -0
  71. package/package.json +91 -0
  72. package/server.json +125 -0
@@ -0,0 +1,175 @@
1
+ /**
2
+ * @fileoverview HTTP client for the NIST NVD API 2.0 with token-bucket rate limiting.
3
+ * Manages API key injection, queue-based rate limiting, retry with backoff, and Retry-After header parsing.
4
+ * @module services/nvd-http/nvd-http-client
5
+ */
6
+ import { rateLimited, serviceUnavailable, timeout } from '@cyanheads/mcp-ts-core/errors';
7
+ import { withRetry } from '@cyanheads/mcp-ts-core/utils';
8
+ const NVD_BASE_URL = 'https://services.nvd.nist.gov/rest/json';
9
+ /**
10
+ * Sliding-window rate-limit config per NVD documentation:
11
+ * - Without API key: 5 requests per 30-second window
12
+ * - With API key: 50 requests per 30-second window
13
+ */
14
+ const RATE_LIMIT_WINDOW_MS = 30_000;
15
+ const RATE_LIMIT_WITHOUT_KEY = 5;
16
+ const RATE_LIMIT_WITH_KEY = 50;
17
+ /** Minimum gap between requests in milliseconds derived from window/limit. */
18
+ function minGapMs(hasKey) {
19
+ const limit = hasKey ? RATE_LIMIT_WITH_KEY : RATE_LIMIT_WITHOUT_KEY;
20
+ return Math.ceil(RATE_LIMIT_WINDOW_MS / limit);
21
+ }
22
+ export class NvdHttpClient {
23
+ apiKey;
24
+ timeoutMs;
25
+ lastRequestAt = 0;
26
+ queue = [];
27
+ draining = false;
28
+ constructor(apiKey, timeoutMs) {
29
+ this.apiKey = apiKey;
30
+ this.timeoutMs = timeoutMs;
31
+ }
32
+ /**
33
+ * Enqueue and execute a request to the NVD API.
34
+ * Enforces minimum inter-request gap to stay within NVD rate limits.
35
+ */
36
+ // biome-ignore lint/suspicious/useAwait: returns Promise via new Promise() constructor — async typing is correct
37
+ async get(endpoint, params, ctx) {
38
+ return new Promise((resolve, reject) => {
39
+ const task = () => {
40
+ this.executeRequest(endpoint, params, ctx)
41
+ .then(resolve)
42
+ .catch(reject)
43
+ .finally(() => this.drainNext());
44
+ };
45
+ this.queue.push(task);
46
+ if (!this.draining)
47
+ this.drainNext();
48
+ });
49
+ }
50
+ drainNext() {
51
+ const task = this.queue.shift();
52
+ if (!task) {
53
+ this.draining = false;
54
+ return;
55
+ }
56
+ this.draining = true;
57
+ const gap = minGapMs(!!this.apiKey);
58
+ const now = Date.now();
59
+ const elapsed = now - this.lastRequestAt;
60
+ const delay = Math.max(0, gap - elapsed);
61
+ if (delay > 0) {
62
+ setTimeout(() => {
63
+ this.lastRequestAt = Date.now();
64
+ task();
65
+ }, delay);
66
+ }
67
+ else {
68
+ this.lastRequestAt = Date.now();
69
+ task();
70
+ }
71
+ }
72
+ // biome-ignore lint/suspicious/useAwait: delegates to withRetry() which returns a Promise — async typing is correct
73
+ async executeRequest(endpoint, params, ctx) {
74
+ return withRetry(async () => {
75
+ const url = this.buildUrl(endpoint, params);
76
+ ctx.log.debug('NVD API request', { endpoint, url: url.toString() });
77
+ const controller = new AbortController();
78
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
79
+ // Chain caller's signal
80
+ const onAbort = () => controller.abort();
81
+ ctx.signal.addEventListener('abort', onAbort, { once: true });
82
+ let response;
83
+ try {
84
+ response = await fetch(url.toString(), {
85
+ headers: this.buildHeaders(),
86
+ signal: controller.signal,
87
+ });
88
+ }
89
+ catch (err) {
90
+ if (err.name === 'AbortError') {
91
+ if (ctx.signal.aborted)
92
+ throw timeout('NVD request cancelled by caller.');
93
+ throw timeout(`NVD request timed out after ${this.timeoutMs}ms.`);
94
+ }
95
+ throw serviceUnavailable(`NVD API network error: ${err.message}`, { endpoint }, { cause: err });
96
+ }
97
+ finally {
98
+ clearTimeout(timer);
99
+ ctx.signal.removeEventListener('abort', onAbort);
100
+ }
101
+ if (response.status === 403) {
102
+ const retryAfter = response.headers.get('Retry-After');
103
+ throw rateLimited(`NVD rate limit exceeded. ${retryAfter ? `Retry after ${retryAfter}s.` : ''}`, {
104
+ reason: 'rate_limited',
105
+ retryAfter: retryAfter ? Number(retryAfter) : 30,
106
+ recovery: {
107
+ hint: 'The NVD rate limit was exceeded. Wait for the retry window to reset or add an API key via NVD_API_KEY.',
108
+ },
109
+ });
110
+ }
111
+ if (response.status === 404) {
112
+ // NVD returns 404 for malformed/invalid request parameters.
113
+ // Callers translate this to domain-appropriate errors via catch blocks.
114
+ throw new Error('NVD returned HTTP 404.');
115
+ }
116
+ if (!response.ok) {
117
+ throw serviceUnavailable(`NVD API returned HTTP ${response.status}.`, {
118
+ endpoint,
119
+ status: response.status,
120
+ });
121
+ }
122
+ const text = await response.text();
123
+ if (/^\s*<(!DOCTYPE\s+html|html[\s>])/i.test(text)) {
124
+ throw serviceUnavailable('NVD API returned HTML instead of JSON — likely rate-limited or a temporary outage.');
125
+ }
126
+ try {
127
+ return JSON.parse(text);
128
+ }
129
+ catch (err) {
130
+ throw serviceUnavailable('NVD API returned malformed JSON.', { endpoint }, { cause: err });
131
+ }
132
+ }, {
133
+ operation: `NvdHttpClient.get:${endpoint}`,
134
+ baseDelayMs: 2_000,
135
+ signal: ctx.signal,
136
+ });
137
+ }
138
+ buildUrl(endpoint, params) {
139
+ const url = new URL(`${NVD_BASE_URL}/${endpoint}`);
140
+ for (const [key, value] of Object.entries(params)) {
141
+ if (value === undefined || value === null)
142
+ continue;
143
+ if (typeof value === 'boolean') {
144
+ // Boolean flag params are sent without a value (e.g., &hasKev)
145
+ if (value)
146
+ url.searchParams.append(key, '');
147
+ }
148
+ else {
149
+ url.searchParams.set(key, String(value));
150
+ }
151
+ }
152
+ return url;
153
+ }
154
+ buildHeaders() {
155
+ const headers = {
156
+ Accept: 'application/json',
157
+ };
158
+ if (this.apiKey) {
159
+ headers.apiKey = this.apiKey;
160
+ }
161
+ return headers;
162
+ }
163
+ }
164
+ // --- Init/accessor pattern ---
165
+ let _client;
166
+ export function initNvdHttpClient(apiKey, timeoutMs) {
167
+ _client = new NvdHttpClient(apiKey, timeoutMs);
168
+ }
169
+ export function getNvdHttpClient() {
170
+ if (!_client) {
171
+ throw new Error('NvdHttpClient not initialized — call initNvdHttpClient() in setup()');
172
+ }
173
+ return _client;
174
+ }
175
+ //# sourceMappingURL=nvd-http-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nvd-http-client.js","sourceRoot":"","sources":["../../../src/services/nvd-http/nvd-http-client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AACzF,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAEzD,MAAM,YAAY,GAAG,yCAAyC,CAAC;AAE/D;;;;GAIG;AACH,MAAM,oBAAoB,GAAG,MAAM,CAAC;AACpC,MAAM,sBAAsB,GAAG,CAAC,CAAC;AACjC,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAE/B,8EAA8E;AAC9E,SAAS,QAAQ,CAAC,MAAe;IAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,sBAAsB,CAAC;IACpE,OAAO,IAAI,CAAC,IAAI,CAAC,oBAAoB,GAAG,KAAK,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,OAAO,aAAa;IACP,MAAM,CAAqB;IAC3B,SAAS,CAAS;IAC3B,aAAa,GAAG,CAAC,CAAC;IAClB,KAAK,GAAsB,EAAE,CAAC;IAC9B,QAAQ,GAAG,KAAK,CAAC;IAEzB,YAAY,MAA0B,EAAE,SAAiB;QACvD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAED;;;OAGG;IACH,iHAAiH;IACjH,KAAK,CAAC,GAAG,CACP,QAAgB,EAChB,MAA6D,EAC7D,GAAY;QAEZ,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACxC,MAAM,IAAI,GAAG,GAAG,EAAE;gBAChB,IAAI,CAAC,cAAc,CAAI,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC;qBAC1C,IAAI,CAAC,OAAO,CAAC;qBACb,KAAK,CAAC,MAAM,CAAC;qBACb,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;YACrC,CAAC,CAAC;YACF,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtB,IAAI,CAAC,IAAI,CAAC,QAAQ;gBAAE,IAAI,CAAC,SAAS,EAAE,CAAC;QACvC,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,SAAS;QACf,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QAChC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;YACtB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QAErB,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC;QACzC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC;QAEzC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,UAAU,CAAC,GAAG,EAAE;gBACd,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBAChC,IAAI,EAAE,CAAC;YACT,CAAC,EAAE,KAAK,CAAC,CAAC;QACZ,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAChC,IAAI,EAAE,CAAC;QACT,CAAC;IACH,CAAC;IAED,oHAAoH;IAC5G,KAAK,CAAC,cAAc,CAC1B,QAAgB,EAChB,MAA6D,EAC7D,GAAY;QAEZ,OAAO,SAAS,CACd,KAAK,IAAI,EAAE;YACT,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAC5C,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,iBAAiB,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAEpE,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;YACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;YACnE,wBAAwB;YACxB,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;YACzC,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAE9D,IAAI,QAAkB,CAAC;YACvB,IAAI,CAAC;gBACH,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE;oBACrC,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE;oBAC5B,MAAM,EAAE,UAAU,CAAC,MAAM;iBAC1B,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAK,GAAa,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;oBACzC,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO;wBAAE,MAAM,OAAO,CAAC,kCAAkC,CAAC,CAAC;oBAC1E,MAAM,OAAO,CAAC,+BAA+B,IAAI,CAAC,SAAS,KAAK,CAAC,CAAC;gBACpE,CAAC;gBACD,MAAM,kBAAkB,CACtB,0BAA2B,GAAa,CAAC,OAAO,EAAE,EAClD,EAAE,QAAQ,EAAE,EACZ,EAAE,KAAK,EAAE,GAAY,EAAE,CACxB,CAAC;YACJ,CAAC;oBAAS,CAAC;gBACT,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpB,GAAG,CAAC,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACnD,CAAC;YAED,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC5B,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;gBACvD,MAAM,WAAW,CACf,4BAA4B,UAAU,CAAC,CAAC,CAAC,eAAe,UAAU,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,EAC7E;oBACE,MAAM,EAAE,cAAc;oBACtB,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE;oBAChD,QAAQ,EAAE;wBACR,IAAI,EAAE,wGAAwG;qBAC/G;iBACF,CACF,CAAC;YACJ,CAAC;YAED,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC5B,4DAA4D;gBAC5D,wEAAwE;gBACxE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;YAC5C,CAAC;YAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,kBAAkB,CAAC,yBAAyB,QAAQ,CAAC,MAAM,GAAG,EAAE;oBACpE,QAAQ;oBACR,MAAM,EAAE,QAAQ,CAAC,MAAM;iBACxB,CAAC,CAAC;YACL,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,IAAI,mCAAmC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnD,MAAM,kBAAkB,CACtB,oFAAoF,CACrF,CAAC;YACJ,CAAC;YAED,IAAI,CAAC;gBACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAM,CAAC;YAC/B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,kBAAkB,CACtB,kCAAkC,EAClC,EAAE,QAAQ,EAAE,EACZ,EAAE,KAAK,EAAE,GAAY,EAAE,CACxB,CAAC;YACJ,CAAC;QACH,CAAC,EACD;YACE,SAAS,EAAE,qBAAqB,QAAQ,EAAE;YAC1C,WAAW,EAAE,KAAK;YAClB,MAAM,EAAE,GAAG,CAAC,MAAM;SACnB,CACF,CAAC;IACJ,CAAC;IAEO,QAAQ,CACd,QAAgB,EAChB,MAA6D;QAE7D,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,YAAY,IAAI,QAAQ,EAAE,CAAC,CAAC;QACnD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAClD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;gBAAE,SAAS;YACpD,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;gBAC/B,+DAA+D;gBAC/D,IAAI,KAAK;oBAAE,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YAC9C,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAEO,YAAY;QAClB,MAAM,OAAO,GAA2B;YACtC,MAAM,EAAE,kBAAkB;SAC3B,CAAC;QACF,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC/B,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;CACF;AAED,gCAAgC;AAEhC,IAAI,OAAkC,CAAC;AAEvC,MAAM,UAAU,iBAAiB,CAAC,MAA0B,EAAE,SAAiB;IAC7E,OAAO,GAAG,IAAI,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAC;IACzF,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,91 @@
1
+ {
2
+ "name": "@cyanheads/nist-nvd-mcp-server",
3
+ "mcpName": "io.github.cyanheads/nist-nvd-mcp-server",
4
+ "version": "0.1.3",
5
+ "description": "Search and audit CVEs by keyword, severity, CWE, CISA KEV status, and CPE via the NIST National Vulnerability Database. STDIO or Streamable HTTP.",
6
+ "type": "module",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "bin": {
10
+ "nist-nvd-mcp-server": "dist/index.js"
11
+ },
12
+ "files": [
13
+ "changelog/",
14
+ "dist/",
15
+ "README.md",
16
+ "LICENSE",
17
+ "CLAUDE.md",
18
+ "AGENTS.md",
19
+ "Dockerfile",
20
+ "server.json"
21
+ ],
22
+ "scripts": {
23
+ "build": "tsx scripts/build.ts",
24
+ "rebuild": "tsx scripts/clean.ts && tsx scripts/build.ts",
25
+ "clean": "tsx scripts/clean.ts",
26
+ "devcheck": "tsx scripts/devcheck.ts",
27
+ "audit:refresh": "rm -f bun.lock && bun install && bun audit",
28
+ "tree": "tsx scripts/tree.ts",
29
+ "list-skills": "tsx scripts/list-skills.ts",
30
+ "format": "biome check --write --unsafe .",
31
+ "lint:mcp": "tsx scripts/lint-mcp.ts",
32
+ "lint:packaging": "tsx scripts/lint-packaging.ts",
33
+ "bundle": "bun run build && npx -y @anthropic-ai/mcpb pack . dist/nist-nvd-mcp-server.mcpb",
34
+ "changelog:build": "tsx scripts/build-changelog.ts",
35
+ "changelog:check": "tsx scripts/build-changelog.ts --check",
36
+ "test": "vitest run",
37
+ "start": "node dist/index.js",
38
+ "start:stdio": "MCP_TRANSPORT_TYPE=stdio node dist/index.js",
39
+ "start:http": "MCP_TRANSPORT_TYPE=http node dist/index.js"
40
+ },
41
+ "keywords": [
42
+ "mcp",
43
+ "mcp-server",
44
+ "model-context-protocol",
45
+ "typescript",
46
+ "bun",
47
+ "stdio",
48
+ "streamable-http",
49
+ "nist",
50
+ "nvd",
51
+ "cve",
52
+ "cpe",
53
+ "vulnerability",
54
+ "security",
55
+ "cvss",
56
+ "cwe",
57
+ "cisa-kev"
58
+ ],
59
+ "repository": {
60
+ "type": "git",
61
+ "url": "git+https://github.com/cyanheads/nist-nvd-mcp-server.git"
62
+ },
63
+ "homepage": "https://github.com/cyanheads/nist-nvd-mcp-server#readme",
64
+ "bugs": {
65
+ "url": "https://github.com/cyanheads/nist-nvd-mcp-server/issues"
66
+ },
67
+ "author": "cyanheads <casey@caseyjhand.com> (https://github.com/cyanheads/nist-nvd-mcp-server#readme)",
68
+ "license": "Apache-2.0",
69
+ "engines": {
70
+ "bun": ">=1.3.0",
71
+ "node": ">=24.0.0"
72
+ },
73
+ "publishConfig": {
74
+ "access": "public"
75
+ },
76
+ "dependencies": {
77
+ "@cyanheads/mcp-ts-core": "^0.9.9",
78
+ "pino-pretty": "^13.1.3",
79
+ "zod": "^4.4.3"
80
+ },
81
+ "devDependencies": {
82
+ "@biomejs/biome": "^2.4.7",
83
+ "@types/node": "^25.6.0",
84
+ "depcheck": "^1.4.7",
85
+ "ignore": "^7.0.5",
86
+ "tsc-alias": "^1.8.16",
87
+ "tsx": "^4.19.0",
88
+ "typescript": "^5.9.3",
89
+ "vitest": "^4.1.0"
90
+ }
91
+ }
package/server.json ADDED
@@ -0,0 +1,125 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
+ "name": "io.github.cyanheads/nist-nvd-mcp-server",
4
+ "description": "Search and audit NIST NVD CVEs by keyword, severity, CWE, CISA KEV status, and CPE.",
5
+ "repository": {
6
+ "url": "https://github.com/cyanheads/nist-nvd-mcp-server",
7
+ "source": "github"
8
+ },
9
+ "version": "0.1.3",
10
+ "packages": [
11
+ {
12
+ "registryType": "npm",
13
+ "registryBaseUrl": "https://registry.npmjs.org",
14
+ "identifier": "@cyanheads/nist-nvd-mcp-server",
15
+ "runtimeHint": "bun",
16
+ "version": "0.1.3",
17
+ "packageArguments": [
18
+ {
19
+ "type": "positional",
20
+ "value": "run"
21
+ },
22
+ {
23
+ "type": "positional",
24
+ "value": "start:stdio"
25
+ }
26
+ ],
27
+ "environmentVariables": [
28
+ {
29
+ "name": "NVD_API_KEY",
30
+ "description": "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.",
31
+ "format": "string",
32
+ "isRequired": false
33
+ },
34
+ {
35
+ "name": "NVD_REQUEST_TIMEOUT_MS",
36
+ "description": "Per-request timeout in milliseconds. Raise to 60000 when using nvd_get_cve_history without an API key.",
37
+ "format": "string",
38
+ "isRequired": false,
39
+ "default": "10000"
40
+ },
41
+ {
42
+ "name": "MCP_LOG_LEVEL",
43
+ "description": "Sets the minimum log level for output (e.g., 'debug', 'info', 'warn').",
44
+ "format": "string",
45
+ "isRequired": false,
46
+ "default": "info"
47
+ }
48
+ ],
49
+ "transport": {
50
+ "type": "stdio"
51
+ }
52
+ },
53
+ {
54
+ "registryType": "npm",
55
+ "registryBaseUrl": "https://registry.npmjs.org",
56
+ "identifier": "@cyanheads/nist-nvd-mcp-server",
57
+ "runtimeHint": "bun",
58
+ "version": "0.1.3",
59
+ "packageArguments": [
60
+ {
61
+ "type": "positional",
62
+ "value": "run"
63
+ },
64
+ {
65
+ "type": "positional",
66
+ "value": "start:http"
67
+ }
68
+ ],
69
+ "environmentVariables": [
70
+ {
71
+ "name": "NVD_API_KEY",
72
+ "description": "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.",
73
+ "format": "string",
74
+ "isRequired": false
75
+ },
76
+ {
77
+ "name": "NVD_REQUEST_TIMEOUT_MS",
78
+ "description": "Per-request timeout in milliseconds. Raise to 60000 when using nvd_get_cve_history without an API key.",
79
+ "format": "string",
80
+ "isRequired": false,
81
+ "default": "10000"
82
+ },
83
+ {
84
+ "name": "MCP_HTTP_HOST",
85
+ "description": "The hostname for the HTTP server.",
86
+ "format": "string",
87
+ "isRequired": false,
88
+ "default": "127.0.0.1"
89
+ },
90
+ {
91
+ "name": "MCP_HTTP_PORT",
92
+ "description": "The port to run the HTTP server on.",
93
+ "format": "string",
94
+ "isRequired": false,
95
+ "default": "3010"
96
+ },
97
+ {
98
+ "name": "MCP_HTTP_ENDPOINT_PATH",
99
+ "description": "The endpoint path for the MCP server.",
100
+ "format": "string",
101
+ "isRequired": false,
102
+ "default": "/mcp"
103
+ },
104
+ {
105
+ "name": "MCP_AUTH_MODE",
106
+ "description": "Authentication mode to use: 'none', 'jwt', or 'oauth'.",
107
+ "format": "string",
108
+ "isRequired": false,
109
+ "default": "none"
110
+ },
111
+ {
112
+ "name": "MCP_LOG_LEVEL",
113
+ "description": "Sets the minimum log level for output (e.g., 'debug', 'info', 'warn').",
114
+ "format": "string",
115
+ "isRequired": false,
116
+ "default": "info"
117
+ }
118
+ ],
119
+ "transport": {
120
+ "type": "streamable-http",
121
+ "url": "http://localhost:3010/mcp"
122
+ }
123
+ }
124
+ ]
125
+ }