@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.
- package/AGENTS.md +410 -0
- package/CLAUDE.md +410 -0
- package/Dockerfile +99 -0
- package/LICENSE +201 -0
- package/README.md +306 -0
- package/changelog/0.1.x/0.1.0.md +19 -0
- package/changelog/0.1.x/0.1.1.md +29 -0
- package/changelog/0.1.x/0.1.2.md +12 -0
- package/changelog/0.1.x/0.1.3.md +22 -0
- package/changelog/template.md +119 -0
- package/dist/config/server-config.d.ts +15 -0
- package/dist/config/server-config.d.ts.map +1 -0
- package/dist/config/server-config.js +27 -0
- package/dist/config/server-config.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server/resources/definitions/index.d.ts +6 -0
- package/dist/mcp-server/resources/definitions/index.d.ts.map +1 -0
- package/dist/mcp-server/resources/definitions/index.js +6 -0
- package/dist/mcp-server/resources/definitions/index.js.map +1 -0
- package/dist/mcp-server/resources/definitions/nvd-cve.resource.d.ts +9 -0
- package/dist/mcp-server/resources/definitions/nvd-cve.resource.d.ts.map +1 -0
- package/dist/mcp-server/resources/definitions/nvd-cve.resource.js +36 -0
- package/dist/mcp-server/resources/definitions/nvd-cve.resource.js.map +1 -0
- package/dist/mcp-server/tools/definitions/index.d.ts +10 -0
- package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/index.js +10 -0
- package/dist/mcp-server/tools/definitions/index.js.map +1 -0
- package/dist/mcp-server/tools/definitions/nvd-audit-cpe.tool.d.ts +116 -0
- package/dist/mcp-server/tools/definitions/nvd-audit-cpe.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/nvd-audit-cpe.tool.js +329 -0
- package/dist/mcp-server/tools/definitions/nvd-audit-cpe.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/nvd-get-cve-history.tool.d.ts +45 -0
- package/dist/mcp-server/tools/definitions/nvd-get-cve-history.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/nvd-get-cve-history.tool.js +132 -0
- package/dist/mcp-server/tools/definitions/nvd-get-cve-history.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/nvd-get-cve.tool.d.ts +36 -0
- package/dist/mcp-server/tools/definitions/nvd-get-cve.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/nvd-get-cve.tool.js +183 -0
- package/dist/mcp-server/tools/definitions/nvd-get-cve.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/nvd-search-cpes.tool.d.ts +40 -0
- package/dist/mcp-server/tools/definitions/nvd-search-cpes.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/nvd-search-cpes.tool.js +140 -0
- package/dist/mcp-server/tools/definitions/nvd-search-cpes.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/nvd-search-cves.tool.d.ts +90 -0
- package/dist/mcp-server/tools/definitions/nvd-search-cves.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/nvd-search-cves.tool.js +342 -0
- package/dist/mcp-server/tools/definitions/nvd-search-cves.tool.js.map +1 -0
- package/dist/services/nvd-cpe/nvd-cpe-service.d.ts +27 -0
- package/dist/services/nvd-cpe/nvd-cpe-service.d.ts.map +1 -0
- package/dist/services/nvd-cpe/nvd-cpe-service.js +58 -0
- package/dist/services/nvd-cpe/nvd-cpe-service.js.map +1 -0
- package/dist/services/nvd-cpe/types.d.ts +41 -0
- package/dist/services/nvd-cpe/types.d.ts.map +1 -0
- package/dist/services/nvd-cpe/types.js +6 -0
- package/dist/services/nvd-cpe/types.js.map +1 -0
- package/dist/services/nvd-cve/nvd-cve-service.d.ts +79 -0
- package/dist/services/nvd-cve/nvd-cve-service.d.ts.map +1 -0
- package/dist/services/nvd-cve/nvd-cve-service.js +345 -0
- package/dist/services/nvd-cve/nvd-cve-service.js.map +1 -0
- package/dist/services/nvd-cve/types.d.ts +185 -0
- package/dist/services/nvd-cve/types.d.ts.map +1 -0
- package/dist/services/nvd-cve/types.js +6 -0
- package/dist/services/nvd-cve/types.js.map +1 -0
- package/dist/services/nvd-http/nvd-http-client.d.ts +26 -0
- package/dist/services/nvd-http/nvd-http-client.d.ts.map +1 -0
- package/dist/services/nvd-http/nvd-http-client.js +175 -0
- package/dist/services/nvd-http/nvd-http-client.js.map +1 -0
- package/package.json +91 -0
- package/server.json +125 -0
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Tool for searching CVEs by keyword, severity, CWE, date range, or KEV status.
|
|
3
|
+
* @module src/mcp-server/tools/definitions/nvd-search-cves
|
|
4
|
+
*/
|
|
5
|
+
import { tool, z } from '@cyanheads/mcp-ts-core';
|
|
6
|
+
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
7
|
+
import { getNvdCveService } from '../../../services/nvd-cve/nvd-cve-service.js';
|
|
8
|
+
const MAX_DATE_RANGE_DAYS = 120;
|
|
9
|
+
/** Returns the date N days ago from now as ISO 8601 string (milliseconds zeroed, UTC). */
|
|
10
|
+
function daysAgo(days) {
|
|
11
|
+
const d = new Date();
|
|
12
|
+
d.setDate(d.getDate() - days);
|
|
13
|
+
return d.toISOString().replace(/\.\d{3}Z$/, '.000Z');
|
|
14
|
+
}
|
|
15
|
+
/** Returns the current datetime as ISO 8601 string (milliseconds zeroed, UTC). */
|
|
16
|
+
function nowIso() {
|
|
17
|
+
return new Date().toISOString().replace(/\.\d{3}Z$/, '.000Z');
|
|
18
|
+
}
|
|
19
|
+
const BriefCveRecordSchema = z.object({
|
|
20
|
+
cveId: z.string().describe('CVE identifier (e.g., "CVE-2021-44228").'),
|
|
21
|
+
vulnStatus: z.string().describe('NVD analysis status.'),
|
|
22
|
+
published: z.string().describe('ISO 8601 publication datetime.'),
|
|
23
|
+
severity: z
|
|
24
|
+
.object({
|
|
25
|
+
label: z.string().describe('Highest severity label across all CVSS versions.'),
|
|
26
|
+
score: z.number().describe('Highest base score (0.0–10.0).'),
|
|
27
|
+
fromVersion: z.string().describe('CVSS version this score came from.'),
|
|
28
|
+
})
|
|
29
|
+
.optional()
|
|
30
|
+
.describe('Top severity. Absent if no CVSS scores are present.'),
|
|
31
|
+
cisaVulnerabilityName: z
|
|
32
|
+
.string()
|
|
33
|
+
.optional()
|
|
34
|
+
.describe('CISA KEV vulnerability name. Present only when in the KEV catalog.'),
|
|
35
|
+
});
|
|
36
|
+
export const nvdSearchCves = tool('nvd_search_cves', {
|
|
37
|
+
title: 'Search CVEs',
|
|
38
|
+
description: 'Search CVEs by keyword, severity, CWE, date range, or CISA KEV status. ' +
|
|
39
|
+
'The primary discovery tool for vulnerability surveillance and triage workflows. ' +
|
|
40
|
+
'pubDays and lastModDays are convenience shorthands that expand to date pairs; values over 120 days are clamped to the NVD maximum and reported in queryMeta. ' +
|
|
41
|
+
'Returns brief summaries — call nvd_get_cve for full detail on specific IDs. ' +
|
|
42
|
+
'At least one filter is recommended; omitting all filters returns CVEs in default NVD index order (oldest first by CVE ID).',
|
|
43
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
44
|
+
input: z.object({
|
|
45
|
+
keyword: z
|
|
46
|
+
.string()
|
|
47
|
+
.optional()
|
|
48
|
+
.describe('Full-text search across CVE descriptions (AND-semantics across words).'),
|
|
49
|
+
severity: z
|
|
50
|
+
.enum(['LOW', 'MEDIUM', 'HIGH', 'CRITICAL'])
|
|
51
|
+
.optional()
|
|
52
|
+
.describe('Filter to CVEs at this CVSS severity level or above.'),
|
|
53
|
+
severityVersion: z
|
|
54
|
+
.enum(['v2', 'v3', 'v4'])
|
|
55
|
+
.default('v3')
|
|
56
|
+
.describe('CVSS version to use for the severity filter. Default: v3 (maps to cvssV3Severity).'),
|
|
57
|
+
cweId: z
|
|
58
|
+
.string()
|
|
59
|
+
.optional()
|
|
60
|
+
.describe('Filter by CWE weakness ID (e.g., "CWE-79", "NVD-CWE-Other").'),
|
|
61
|
+
pubDays: z
|
|
62
|
+
.number()
|
|
63
|
+
.int()
|
|
64
|
+
.positive()
|
|
65
|
+
.optional()
|
|
66
|
+
.describe('CVEs published in the last N days (max 120; values over 120 are clamped). ' +
|
|
67
|
+
'Mutually exclusive with pubStartDate/pubEndDate.'),
|
|
68
|
+
lastModDays: z
|
|
69
|
+
.number()
|
|
70
|
+
.int()
|
|
71
|
+
.positive()
|
|
72
|
+
.optional()
|
|
73
|
+
.describe('CVEs last modified in the last N days (max 120; values over 120 are clamped). ' +
|
|
74
|
+
'Mutually exclusive with lastModStartDate/lastModEndDate.'),
|
|
75
|
+
pubStartDate: z
|
|
76
|
+
.string()
|
|
77
|
+
.optional()
|
|
78
|
+
.describe('ISO 8601 datetime for publication range start. Both pubStartDate and pubEndDate required together. ' +
|
|
79
|
+
'Mutually exclusive with pubDays.'),
|
|
80
|
+
pubEndDate: z
|
|
81
|
+
.string()
|
|
82
|
+
.optional()
|
|
83
|
+
.describe('ISO 8601 datetime for publication range end. Both pubStartDate and pubEndDate required together.'),
|
|
84
|
+
lastModStartDate: z
|
|
85
|
+
.string()
|
|
86
|
+
.optional()
|
|
87
|
+
.describe('ISO 8601 datetime for last-modified range start. Both required together. Mutually exclusive with lastModDays.'),
|
|
88
|
+
lastModEndDate: z
|
|
89
|
+
.string()
|
|
90
|
+
.optional()
|
|
91
|
+
.describe('ISO 8601 datetime for last-modified range end. Both required together.'),
|
|
92
|
+
kevOnly: z
|
|
93
|
+
.boolean()
|
|
94
|
+
.default(false)
|
|
95
|
+
.describe('When true, filters results to CVEs in the CISA Known Exploited Vulnerabilities catalog.'),
|
|
96
|
+
noRejected: z
|
|
97
|
+
.boolean()
|
|
98
|
+
.default(true)
|
|
99
|
+
.describe('When true (default), excludes CVEs with REJECT/Rejected status.'),
|
|
100
|
+
limit: z
|
|
101
|
+
.number()
|
|
102
|
+
.int()
|
|
103
|
+
.min(1)
|
|
104
|
+
.max(2000)
|
|
105
|
+
.default(20)
|
|
106
|
+
.describe('Maximum number of results to return (default 20, max 2000).'),
|
|
107
|
+
offset: z.number().int().min(0).default(0).describe('Zero-based page offset for pagination.'),
|
|
108
|
+
}),
|
|
109
|
+
output: z.object({
|
|
110
|
+
cves: z
|
|
111
|
+
.array(BriefCveRecordSchema.describe('Brief summary for one matching CVE.'))
|
|
112
|
+
.describe('Matching CVE summaries. Call nvd_get_cve for full detail on specific IDs.'),
|
|
113
|
+
queryMeta: z
|
|
114
|
+
.object({
|
|
115
|
+
totalResults: z.number().describe('Total matching CVEs in NVD before pagination.'),
|
|
116
|
+
returned: z.number().describe('Number of CVEs returned in this response.'),
|
|
117
|
+
offset: z.number().describe('Page offset used in this query.'),
|
|
118
|
+
datesClamped: z
|
|
119
|
+
.array(z
|
|
120
|
+
.object({
|
|
121
|
+
param: z
|
|
122
|
+
.string()
|
|
123
|
+
.describe('The parameter that was clamped (pubDays or lastModDays).'),
|
|
124
|
+
original: z.number().describe('The original value supplied.'),
|
|
125
|
+
clamped: z.number().describe('The clamped value used (max 120).'),
|
|
126
|
+
})
|
|
127
|
+
.describe('A single clamping event for one convenience date parameter.'))
|
|
128
|
+
.optional()
|
|
129
|
+
.describe('Entries for any pubDays/lastModDays values that exceeded 120 and were auto-clamped. ' +
|
|
130
|
+
'Absent when no clamping occurred.'),
|
|
131
|
+
})
|
|
132
|
+
.describe('Query execution metadata including total count and any date clamping applied.'),
|
|
133
|
+
}),
|
|
134
|
+
errors: [
|
|
135
|
+
{
|
|
136
|
+
reason: 'mutually_exclusive_params',
|
|
137
|
+
code: JsonRpcErrorCode.InvalidParams,
|
|
138
|
+
when: 'Both pubDays and pubStartDate/pubEndDate provided, or both lastModDays and lastModStartDate/lastModEndDate.',
|
|
139
|
+
recovery: 'Use either the convenience shorthand (pubDays) or the explicit date range (pubStartDate + pubEndDate), not both.',
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
reason: 'missing_date_pair',
|
|
143
|
+
code: JsonRpcErrorCode.InvalidParams,
|
|
144
|
+
when: 'Only one of pubStartDate/pubEndDate (or lastModStartDate/lastModEndDate) was provided — NVD requires both.',
|
|
145
|
+
recovery: 'Provide both the start and end date, or use pubDays/lastModDays instead of an explicit date range.',
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
reason: 'date_range_inverted',
|
|
149
|
+
code: JsonRpcErrorCode.InvalidParams,
|
|
150
|
+
when: 'The end date is before the start date.',
|
|
151
|
+
recovery: 'Ensure the end date is after the start date.',
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
reason: 'date_range_exceeds_max',
|
|
155
|
+
code: JsonRpcErrorCode.InvalidParams,
|
|
156
|
+
when: 'Explicit pubStartDate/pubEndDate or lastModStartDate/lastModEndDate span more than 120 days.',
|
|
157
|
+
recovery: 'Narrow the date range to 120 days or fewer, or use multiple paginated queries.',
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
reason: 'invalid_date_format',
|
|
161
|
+
code: JsonRpcErrorCode.InvalidParams,
|
|
162
|
+
when: 'A date string provided for pubStartDate, pubEndDate, lastModStartDate, or lastModEndDate is not a valid ISO 8601 datetime.',
|
|
163
|
+
recovery: 'Use ISO 8601 format, e.g. 2024-01-01T00:00:00.000Z.',
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
reason: 'invalid_severity_for_version',
|
|
167
|
+
code: JsonRpcErrorCode.InvalidParams,
|
|
168
|
+
when: 'severity="CRITICAL" was specified with severityVersion="v2" — CVSS v2 has no CRITICAL tier.',
|
|
169
|
+
recovery: 'Use LOW, MEDIUM, or HIGH when severityVersion is "v2". Use v3 or v4 for CRITICAL.',
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
reason: 'rate_limited',
|
|
173
|
+
code: JsonRpcErrorCode.ServiceUnavailable,
|
|
174
|
+
when: 'NVD returned HTTP 403 indicating the rate limit was exceeded.',
|
|
175
|
+
retryable: true,
|
|
176
|
+
recovery: 'Wait for the NVD rate window to reset or set the NVD_API_KEY environment variable for higher limits.',
|
|
177
|
+
},
|
|
178
|
+
],
|
|
179
|
+
async handler(input, ctx) {
|
|
180
|
+
ctx.log.info('Searching CVEs', {
|
|
181
|
+
keyword: input.keyword,
|
|
182
|
+
severity: input.severity,
|
|
183
|
+
kevOnly: input.kevOnly,
|
|
184
|
+
limit: input.limit,
|
|
185
|
+
});
|
|
186
|
+
// Validate mutual exclusivity
|
|
187
|
+
if (input.pubDays !== undefined && (input.pubStartDate || input.pubEndDate)) {
|
|
188
|
+
throw ctx.fail('mutually_exclusive_params', 'pubDays and pubStartDate/pubEndDate are mutually exclusive.', ctx.recoveryFor('mutually_exclusive_params'));
|
|
189
|
+
}
|
|
190
|
+
if (input.lastModDays !== undefined && (input.lastModStartDate || input.lastModEndDate)) {
|
|
191
|
+
throw ctx.fail('mutually_exclusive_params', 'lastModDays and lastModStartDate/lastModEndDate are mutually exclusive.', {
|
|
192
|
+
recovery: {
|
|
193
|
+
hint: 'Use either the convenience shorthand (lastModDays) or the explicit date range (lastModStartDate + lastModEndDate), not both.',
|
|
194
|
+
},
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
// Validate co-requirement: start and end must be provided together.
|
|
198
|
+
if (input.pubStartDate && !input.pubEndDate) {
|
|
199
|
+
throw ctx.fail('missing_date_pair', 'pubStartDate requires pubEndDate.', ctx.recoveryFor('missing_date_pair'));
|
|
200
|
+
}
|
|
201
|
+
if (input.pubEndDate && !input.pubStartDate) {
|
|
202
|
+
throw ctx.fail('missing_date_pair', 'pubEndDate requires pubStartDate.', ctx.recoveryFor('missing_date_pair'));
|
|
203
|
+
}
|
|
204
|
+
if (input.lastModStartDate && !input.lastModEndDate) {
|
|
205
|
+
throw ctx.fail('missing_date_pair', 'lastModStartDate requires lastModEndDate.', ctx.recoveryFor('missing_date_pair'));
|
|
206
|
+
}
|
|
207
|
+
if (input.lastModEndDate && !input.lastModStartDate) {
|
|
208
|
+
throw ctx.fail('missing_date_pair', 'lastModEndDate requires lastModStartDate.', ctx.recoveryFor('missing_date_pair'));
|
|
209
|
+
}
|
|
210
|
+
const datesClamped = [];
|
|
211
|
+
let pubStartDate = input.pubStartDate;
|
|
212
|
+
let pubEndDate = input.pubEndDate;
|
|
213
|
+
let lastModStartDate = input.lastModStartDate;
|
|
214
|
+
let lastModEndDate = input.lastModEndDate;
|
|
215
|
+
// Track whether dates came from convenience params — those are always within range.
|
|
216
|
+
let pubDatesFromConvenience = false;
|
|
217
|
+
let lastModDatesFromConvenience = false;
|
|
218
|
+
// Expand pubDays convenience param
|
|
219
|
+
if (input.pubDays !== undefined) {
|
|
220
|
+
let days = input.pubDays;
|
|
221
|
+
if (days > MAX_DATE_RANGE_DAYS) {
|
|
222
|
+
datesClamped.push({ param: 'pubDays', original: days, clamped: MAX_DATE_RANGE_DAYS });
|
|
223
|
+
days = MAX_DATE_RANGE_DAYS;
|
|
224
|
+
}
|
|
225
|
+
pubStartDate = daysAgo(days);
|
|
226
|
+
pubEndDate = nowIso();
|
|
227
|
+
pubDatesFromConvenience = true;
|
|
228
|
+
}
|
|
229
|
+
// Expand lastModDays convenience param
|
|
230
|
+
if (input.lastModDays !== undefined) {
|
|
231
|
+
let days = input.lastModDays;
|
|
232
|
+
if (days > MAX_DATE_RANGE_DAYS) {
|
|
233
|
+
datesClamped.push({ param: 'lastModDays', original: days, clamped: MAX_DATE_RANGE_DAYS });
|
|
234
|
+
days = MAX_DATE_RANGE_DAYS;
|
|
235
|
+
}
|
|
236
|
+
lastModStartDate = daysAgo(days);
|
|
237
|
+
lastModEndDate = nowIso();
|
|
238
|
+
lastModDatesFromConvenience = true;
|
|
239
|
+
}
|
|
240
|
+
// Validate severity cross-field constraint: CVSS v2 has no CRITICAL tier.
|
|
241
|
+
if (input.severity === 'CRITICAL' && input.severityVersion === 'v2') {
|
|
242
|
+
throw ctx.fail('invalid_severity_for_version', 'CVSS v2 has no CRITICAL severity tier. Valid values for severityVersion="v2" are LOW, MEDIUM, HIGH.', ctx.recoveryFor('invalid_severity_for_version'));
|
|
243
|
+
}
|
|
244
|
+
// Validate explicit date range spans — skip when dates came from convenience params
|
|
245
|
+
// (those are always within the max range after clamping).
|
|
246
|
+
if (!pubDatesFromConvenience && pubStartDate && pubEndDate) {
|
|
247
|
+
const start = new Date(pubStartDate);
|
|
248
|
+
const end = new Date(pubEndDate);
|
|
249
|
+
if (Number.isNaN(start.getTime())) {
|
|
250
|
+
throw ctx.fail('invalid_date_format', `Invalid date for pubStartDate: "${pubStartDate}". Expected ISO 8601 format.`, ctx.recoveryFor('invalid_date_format'));
|
|
251
|
+
}
|
|
252
|
+
if (Number.isNaN(end.getTime())) {
|
|
253
|
+
throw ctx.fail('invalid_date_format', `Invalid date for pubEndDate: "${pubEndDate}". Expected ISO 8601 format.`, ctx.recoveryFor('invalid_date_format'));
|
|
254
|
+
}
|
|
255
|
+
const days = (end.getTime() - start.getTime()) / (1000 * 60 * 60 * 24);
|
|
256
|
+
if (days < 0) {
|
|
257
|
+
throw ctx.fail('date_range_inverted', 'pubEndDate is before pubStartDate — the date range is inverted.', ctx.recoveryFor('date_range_inverted'));
|
|
258
|
+
}
|
|
259
|
+
if (days > MAX_DATE_RANGE_DAYS) {
|
|
260
|
+
throw ctx.fail('date_range_exceeds_max', `Publication date range spans ${Math.ceil(days)} days; maximum is 120.`, ctx.recoveryFor('date_range_exceeds_max'));
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (!lastModDatesFromConvenience && lastModStartDate && lastModEndDate) {
|
|
264
|
+
const start = new Date(lastModStartDate);
|
|
265
|
+
const end = new Date(lastModEndDate);
|
|
266
|
+
if (Number.isNaN(start.getTime())) {
|
|
267
|
+
throw ctx.fail('invalid_date_format', `Invalid date for lastModStartDate: "${lastModStartDate}". Expected ISO 8601 format.`, ctx.recoveryFor('invalid_date_format'));
|
|
268
|
+
}
|
|
269
|
+
if (Number.isNaN(end.getTime())) {
|
|
270
|
+
throw ctx.fail('invalid_date_format', `Invalid date for lastModEndDate: "${lastModEndDate}". Expected ISO 8601 format.`, ctx.recoveryFor('invalid_date_format'));
|
|
271
|
+
}
|
|
272
|
+
const days = (end.getTime() - start.getTime()) / (1000 * 60 * 60 * 24);
|
|
273
|
+
if (days < 0) {
|
|
274
|
+
throw ctx.fail('date_range_inverted', 'lastModEndDate is before lastModStartDate — the date range is inverted.', ctx.recoveryFor('date_range_inverted'));
|
|
275
|
+
}
|
|
276
|
+
if (days > MAX_DATE_RANGE_DAYS) {
|
|
277
|
+
throw ctx.fail('date_range_exceeds_max', `Last-modified date range spans ${Math.ceil(days)} days; maximum is 120.`, ctx.recoveryFor('date_range_exceeds_max'));
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
const service = getNvdCveService();
|
|
281
|
+
const result = await service.searchCves({
|
|
282
|
+
...(input.keyword && { keyword: input.keyword }),
|
|
283
|
+
...(input.severity && { severityParam: input.severity }),
|
|
284
|
+
severityVersion: input.severityVersion,
|
|
285
|
+
...(input.cweId && { cweId: input.cweId }),
|
|
286
|
+
...(pubStartDate && { pubStartDate }),
|
|
287
|
+
...(pubEndDate && { pubEndDate }),
|
|
288
|
+
...(lastModStartDate && { lastModStartDate }),
|
|
289
|
+
...(lastModEndDate && { lastModEndDate }),
|
|
290
|
+
kevOnly: input.kevOnly,
|
|
291
|
+
noRejected: input.noRejected,
|
|
292
|
+
limit: input.limit,
|
|
293
|
+
offset: input.offset,
|
|
294
|
+
}, ctx);
|
|
295
|
+
return {
|
|
296
|
+
cves: result.cves,
|
|
297
|
+
queryMeta: {
|
|
298
|
+
totalResults: result.totalResults,
|
|
299
|
+
returned: result.returned,
|
|
300
|
+
offset: result.offset,
|
|
301
|
+
...(datesClamped.length > 0 && { datesClamped }),
|
|
302
|
+
},
|
|
303
|
+
};
|
|
304
|
+
},
|
|
305
|
+
format: (result) => {
|
|
306
|
+
const lines = [];
|
|
307
|
+
lines.push(`**Total:** ${result.queryMeta.totalResults} matching CVEs | ` +
|
|
308
|
+
`**Showing:** ${result.queryMeta.returned} (offset ${result.queryMeta.offset})`);
|
|
309
|
+
if (result.queryMeta.datesClamped && result.queryMeta.datesClamped.length > 0) {
|
|
310
|
+
for (const c of result.queryMeta.datesClamped) {
|
|
311
|
+
lines.push(`> **Note:** ${c.param} value ${c.original} exceeded the 120-day maximum and was clamped to ${c.clamped}.`);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
if (result.cves.length === 0) {
|
|
315
|
+
if (result.queryMeta.totalResults > 0) {
|
|
316
|
+
lines.push(`\nOffset ${result.queryMeta.offset} is past the end of the result set ` +
|
|
317
|
+
`(${result.queryMeta.totalResults} total). Use a lower offset to page through results.`);
|
|
318
|
+
}
|
|
319
|
+
else {
|
|
320
|
+
lines.push('\nNo CVEs matched the search criteria. Try broadening the keyword or date range.');
|
|
321
|
+
}
|
|
322
|
+
return [{ type: 'text', text: lines.join('\n') }];
|
|
323
|
+
}
|
|
324
|
+
lines.push('');
|
|
325
|
+
for (const cve of result.cves) {
|
|
326
|
+
lines.push(`### ${cve.cveId}`);
|
|
327
|
+
lines.push(`**Status:** ${cve.vulnStatus} | **Published:** ${cve.published}`);
|
|
328
|
+
if (cve.severity) {
|
|
329
|
+
lines.push(`**Severity:** ${cve.severity.label} (${cve.severity.score}) from CVSS ${cve.severity.fromVersion}`);
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
lines.push('**Severity:** Not available');
|
|
333
|
+
}
|
|
334
|
+
if (cve.cisaVulnerabilityName) {
|
|
335
|
+
lines.push(`**CISA KEV:** ${cve.cisaVulnerabilityName}`);
|
|
336
|
+
}
|
|
337
|
+
lines.push('');
|
|
338
|
+
}
|
|
339
|
+
return [{ type: 'text', text: lines.join('\n') }];
|
|
340
|
+
},
|
|
341
|
+
});
|
|
342
|
+
//# sourceMappingURL=nvd-search-cves.tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nvd-search-cves.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/nvd-search-cves.tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Service for the NIST NVD CPE API 2.0.
|
|
3
|
+
* Provides CPE dictionary search by keyword and match string.
|
|
4
|
+
* @module services/nvd-cpe/nvd-cpe-service
|
|
5
|
+
*/
|
|
6
|
+
import type { Context } from '@cyanheads/mcp-ts-core';
|
|
7
|
+
import type { AppConfig } from '@cyanheads/mcp-ts-core/config';
|
|
8
|
+
import type { StorageService } from '@cyanheads/mcp-ts-core/storage';
|
|
9
|
+
import type { CpeRecord } from './types.js';
|
|
10
|
+
export declare class NvdCpeService {
|
|
11
|
+
constructor(_config: AppConfig, _storage: StorageService);
|
|
12
|
+
/**
|
|
13
|
+
* Search CPEs by keyword or partial match string.
|
|
14
|
+
*/
|
|
15
|
+
searchCpes(params: {
|
|
16
|
+
keyword?: string;
|
|
17
|
+
cpeMatchString?: string;
|
|
18
|
+
limit?: number;
|
|
19
|
+
}, ctx: Context): Promise<{
|
|
20
|
+
cpes: CpeRecord[];
|
|
21
|
+
totalResults: number;
|
|
22
|
+
returned: number;
|
|
23
|
+
}>;
|
|
24
|
+
}
|
|
25
|
+
export declare function initNvdCpeService(config: AppConfig, storage: StorageService): void;
|
|
26
|
+
export declare function getNvdCpeService(): NvdCpeService;
|
|
27
|
+
//# sourceMappingURL=nvd-cpe-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nvd-cpe-service.d.ts","sourceRoot":"","sources":["../../../src/services/nvd-cpe/nvd-cpe-service.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAErE,OAAO,KAAK,EAAE,SAAS,EAA8B,MAAM,YAAY,CAAC;AAqBxE,qBAAa,aAAa;gBAEZ,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc;IAExD;;OAEG;IACG,UAAU,CACd,MAAM,EAAE;QACN,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,EACD,GAAG,EAAE,OAAO,GACX,OAAO,CAAC;QAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CAsB1E;AAMD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAElF;AAED,wBAAgB,gBAAgB,IAAI,aAAa,CAKhD"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Service for the NIST NVD CPE API 2.0.
|
|
3
|
+
* Provides CPE dictionary search by keyword and match string.
|
|
4
|
+
* @module services/nvd-cpe/nvd-cpe-service
|
|
5
|
+
*/
|
|
6
|
+
import { getNvdHttpClient } from '../nvd-http/nvd-http-client.js';
|
|
7
|
+
/** Normalize a raw CPE item to a CpeRecord. */
|
|
8
|
+
function normalizeCpe(raw) {
|
|
9
|
+
const titles = (raw.titles ?? [])
|
|
10
|
+
.filter((t) => t.lang === 'en' && t.title)
|
|
11
|
+
.map((t) => t.title);
|
|
12
|
+
const deprecatedBy = (raw.deprecatedBy ?? [])
|
|
13
|
+
.filter((d) => d.cpeName)
|
|
14
|
+
.map((d) => d.cpeName);
|
|
15
|
+
return {
|
|
16
|
+
cpeName: raw.cpeName ?? '',
|
|
17
|
+
...(titles.length > 0 && { title: titles[0] }),
|
|
18
|
+
deprecated: raw.deprecated ?? false,
|
|
19
|
+
...(deprecatedBy.length > 0 && { deprecatedBy }),
|
|
20
|
+
...(raw.lastModified && { lastModified: raw.lastModified }),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export class NvdCpeService {
|
|
24
|
+
// biome-ignore lint/complexity/noUselessConstructor: preserves framework init-pattern signature
|
|
25
|
+
constructor(_config, _storage) { }
|
|
26
|
+
/**
|
|
27
|
+
* Search CPEs by keyword or partial match string.
|
|
28
|
+
*/
|
|
29
|
+
async searchCpes(params, ctx) {
|
|
30
|
+
const client = getNvdHttpClient();
|
|
31
|
+
const apiParams = {
|
|
32
|
+
resultsPerPage: Math.min(params.limit ?? 20, 10_000),
|
|
33
|
+
startIndex: 0,
|
|
34
|
+
};
|
|
35
|
+
if (params.keyword)
|
|
36
|
+
apiParams.keywordSearch = params.keyword;
|
|
37
|
+
if (params.cpeMatchString)
|
|
38
|
+
apiParams.cpeMatchString = params.cpeMatchString;
|
|
39
|
+
const response = await client.get('cpes/2.0', apiParams, ctx);
|
|
40
|
+
const items = (response.products ?? []).map((p) => p.cpe).filter((c) => !!c);
|
|
41
|
+
const cpes = items.map(normalizeCpe);
|
|
42
|
+
const totalResults = response.totalResults ?? 0;
|
|
43
|
+
ctx.log.info('CPE search completed', { totalResults, returned: cpes.length });
|
|
44
|
+
return { cpes, totalResults, returned: cpes.length };
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// --- Init/accessor pattern ---
|
|
48
|
+
let _service;
|
|
49
|
+
export function initNvdCpeService(config, storage) {
|
|
50
|
+
_service = new NvdCpeService(config, storage);
|
|
51
|
+
}
|
|
52
|
+
export function getNvdCpeService() {
|
|
53
|
+
if (!_service) {
|
|
54
|
+
throw new Error('NvdCpeService not initialized — call initNvdCpeService() in setup()');
|
|
55
|
+
}
|
|
56
|
+
return _service;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=nvd-cpe-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nvd-cpe-service.js","sourceRoot":"","sources":["../../../src/services/nvd-cpe/nvd-cpe-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Domain types for the NVD CPE API 2.0 response shapes and normalized domain objects.
|
|
3
|
+
* @module services/nvd-cpe/types
|
|
4
|
+
*/
|
|
5
|
+
/** Raw CPE item from the NVD API response. */
|
|
6
|
+
export interface RawCpeItem {
|
|
7
|
+
cpeName?: string;
|
|
8
|
+
cpeNameId?: string;
|
|
9
|
+
created?: string;
|
|
10
|
+
deprecated?: boolean;
|
|
11
|
+
deprecatedBy?: Array<{
|
|
12
|
+
cpeName?: string;
|
|
13
|
+
cpeNameId?: string;
|
|
14
|
+
}>;
|
|
15
|
+
lastModified?: string;
|
|
16
|
+
titles?: Array<{
|
|
17
|
+
title?: string;
|
|
18
|
+
lang?: string;
|
|
19
|
+
}>;
|
|
20
|
+
}
|
|
21
|
+
/** Raw NVD CPE search response. */
|
|
22
|
+
export interface RawCpeResponse {
|
|
23
|
+
format?: string;
|
|
24
|
+
products?: Array<{
|
|
25
|
+
cpe?: RawCpeItem;
|
|
26
|
+
}>;
|
|
27
|
+
resultsPerPage?: number;
|
|
28
|
+
startIndex?: number;
|
|
29
|
+
timestamp?: string;
|
|
30
|
+
totalResults?: number;
|
|
31
|
+
version?: string;
|
|
32
|
+
}
|
|
33
|
+
/** Normalized CPE record. */
|
|
34
|
+
export interface CpeRecord {
|
|
35
|
+
cpeName: string;
|
|
36
|
+
deprecated: boolean;
|
|
37
|
+
deprecatedBy?: string[];
|
|
38
|
+
lastModified?: string;
|
|
39
|
+
title?: string;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/nvd-cpe/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,8CAA8C;AAC9C,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,KAAK,CAAC;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACnD;AAED,mCAAmC;AACnC,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,GAAG,CAAC,EAAE,UAAU,CAAA;KAAE,CAAC,CAAC;IACvC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,6BAA6B;AAC7B,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/services/nvd-cpe/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Service for the NIST NVD CVE API 2.0 and CVE History API.
|
|
3
|
+
* Provides normalized CVE records, search, audit-by-CPE, and change history.
|
|
4
|
+
* @module services/nvd-cve/nvd-cve-service
|
|
5
|
+
*/
|
|
6
|
+
import type { Context } from '@cyanheads/mcp-ts-core';
|
|
7
|
+
import type { AppConfig } from '@cyanheads/mcp-ts-core/config';
|
|
8
|
+
import type { StorageService } from '@cyanheads/mcp-ts-core/storage';
|
|
9
|
+
import type { BriefCveRecord, CveChangeEvent, CveRecord } from './types.js';
|
|
10
|
+
export interface SearchCvesParams {
|
|
11
|
+
cweId?: string;
|
|
12
|
+
kevOnly?: boolean;
|
|
13
|
+
keyword?: string;
|
|
14
|
+
lastModEndDate?: string;
|
|
15
|
+
lastModStartDate?: string;
|
|
16
|
+
limit?: number;
|
|
17
|
+
noRejected?: boolean;
|
|
18
|
+
offset?: number;
|
|
19
|
+
pubEndDate?: string;
|
|
20
|
+
pubStartDate?: string;
|
|
21
|
+
severityParam?: string;
|
|
22
|
+
severityVersion?: 'v2' | 'v3' | 'v4';
|
|
23
|
+
}
|
|
24
|
+
export interface AuditCpeParams {
|
|
25
|
+
cpeName?: string;
|
|
26
|
+
limit?: number;
|
|
27
|
+
severityMin?: string;
|
|
28
|
+
versionEnd?: string;
|
|
29
|
+
versionEndType?: 'including' | 'excluding';
|
|
30
|
+
versionStart?: string;
|
|
31
|
+
versionStartType?: 'including' | 'excluding';
|
|
32
|
+
virtualMatchString?: string;
|
|
33
|
+
}
|
|
34
|
+
export declare class NvdCveService {
|
|
35
|
+
constructor(_config: AppConfig, _storage: StorageService);
|
|
36
|
+
/**
|
|
37
|
+
* Fetch one or more CVEs by ID (up to 100).
|
|
38
|
+
* Returns full records. Throws `invalid_cve_id_format` for malformed IDs (HTTP 404 from NVD)
|
|
39
|
+
* and `cve_not_found` when NVD returns empty results for a valid-format ID.
|
|
40
|
+
*/
|
|
41
|
+
fetchById(rawIds: string[], includeReferences: boolean, ctx: Context): Promise<{
|
|
42
|
+
cves: CveRecord[];
|
|
43
|
+
returned: number;
|
|
44
|
+
requested: number;
|
|
45
|
+
missingIds: string[];
|
|
46
|
+
}>;
|
|
47
|
+
/**
|
|
48
|
+
* Search CVEs using various filters. Always returns brief records.
|
|
49
|
+
*/
|
|
50
|
+
searchCves(params: SearchCvesParams, ctx: Context): Promise<{
|
|
51
|
+
cves: BriefCveRecord[];
|
|
52
|
+
totalResults: number;
|
|
53
|
+
returned: number;
|
|
54
|
+
offset: number;
|
|
55
|
+
}>;
|
|
56
|
+
/**
|
|
57
|
+
* Find CVEs affecting a specific CPE (by name or virtual match string with version range).
|
|
58
|
+
*/
|
|
59
|
+
auditCpe(params: AuditCpeParams, ctx: Context): Promise<{
|
|
60
|
+
cves: CveRecord[];
|
|
61
|
+
totalResults: number;
|
|
62
|
+
returned: number;
|
|
63
|
+
cpeName?: string;
|
|
64
|
+
virtualMatchString?: string;
|
|
65
|
+
}>;
|
|
66
|
+
/**
|
|
67
|
+
* Retrieve the change history for a CVE.
|
|
68
|
+
*/
|
|
69
|
+
getCveHistory(rawId: string, limit: number, offset: number, ctx: Context): Promise<{
|
|
70
|
+
cveId: string;
|
|
71
|
+
changes: CveChangeEvent[];
|
|
72
|
+
totalResults: number;
|
|
73
|
+
returned: number;
|
|
74
|
+
offset: number;
|
|
75
|
+
}>;
|
|
76
|
+
}
|
|
77
|
+
export declare function initNvdCveService(config: AppConfig, storage: StorageService): void;
|
|
78
|
+
export declare function getNvdCveService(): NvdCveService;
|
|
79
|
+
//# sourceMappingURL=nvd-cve-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nvd-cve-service.d.ts","sourceRoot":"","sources":["../../../src/services/nvd-cve/nvd-cve-service.ts"],"names":[],"mappings":"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"}
|