@cyanheads/cpsc-recalls-mcp-server 0.1.1

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 (34) hide show
  1. package/AGENTS.md +372 -0
  2. package/CLAUDE.md +372 -0
  3. package/Dockerfile +99 -0
  4. package/LICENSE +201 -0
  5. package/README.md +266 -0
  6. package/changelog/0.1.x/0.1.0.md +11 -0
  7. package/changelog/0.1.x/0.1.1.md +26 -0
  8. package/changelog/template.md +127 -0
  9. package/dist/index.d.ts +7 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +25 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/mcp-server/tools/definitions/cpsc-get-recall.tool.d.ts +51 -0
  14. package/dist/mcp-server/tools/definitions/cpsc-get-recall.tool.d.ts.map +1 -0
  15. package/dist/mcp-server/tools/definitions/cpsc-get-recall.tool.js +239 -0
  16. package/dist/mcp-server/tools/definitions/cpsc-get-recall.tool.js.map +1 -0
  17. package/dist/mcp-server/tools/definitions/cpsc-get-recent.tool.d.ts +36 -0
  18. package/dist/mcp-server/tools/definitions/cpsc-get-recent.tool.d.ts.map +1 -0
  19. package/dist/mcp-server/tools/definitions/cpsc-get-recent.tool.js +147 -0
  20. package/dist/mcp-server/tools/definitions/cpsc-get-recent.tool.js.map +1 -0
  21. package/dist/mcp-server/tools/definitions/cpsc-search-recalls.tool.d.ts +54 -0
  22. package/dist/mcp-server/tools/definitions/cpsc-search-recalls.tool.d.ts.map +1 -0
  23. package/dist/mcp-server/tools/definitions/cpsc-search-recalls.tool.js +245 -0
  24. package/dist/mcp-server/tools/definitions/cpsc-search-recalls.tool.js.map +1 -0
  25. package/dist/services/cpsc-recall/cpsc-recall-service.d.ts +29 -0
  26. package/dist/services/cpsc-recall/cpsc-recall-service.d.ts.map +1 -0
  27. package/dist/services/cpsc-recall/cpsc-recall-service.js +97 -0
  28. package/dist/services/cpsc-recall/cpsc-recall-service.js.map +1 -0
  29. package/dist/services/cpsc-recall/types.d.ts +86 -0
  30. package/dist/services/cpsc-recall/types.d.ts.map +1 -0
  31. package/dist/services/cpsc-recall/types.js +6 -0
  32. package/dist/services/cpsc-recall/types.js.map +1 -0
  33. package/package.json +101 -0
  34. package/server.json +99 -0
@@ -0,0 +1,239 @@
1
+ /**
2
+ * @fileoverview Full detail for a single CPSC recall by recall number.
3
+ * @module mcp-server/tools/definitions/cpsc-get-recall
4
+ */
5
+ import { tool, z } from '@cyanheads/mcp-ts-core';
6
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
+ import { getCpscRecallService } from '../../../services/cpsc-recall/cpsc-recall-service.js';
8
+ /** Static jurisdiction note included in every response. */
9
+ const JURISDICTION = 'CPSC covers consumer products — toys, electronics, furniture, appliances, tools, clothing. ' +
10
+ 'Does NOT cover: food/drugs (FDA), motor vehicles/tires (NHTSA), boats (USCG), pesticides (EPA), firearms (ATF).';
11
+ export const cpscGetRecall = tool('cpsc_get_recall', {
12
+ title: 'Get CPSC Recall Detail',
13
+ description: 'Full detail for a single CPSC recall by recall number. ' +
14
+ 'Returns the complete record: hazard description, remedy instructions, all product variants, ' +
15
+ 'incident/injury reports, images, and the official CPSC recall page URL. ' +
16
+ 'Use after cpsc_search_recalls or cpsc_get_recent to get the full picture on a specific recall. ' +
17
+ 'CPSC jurisdiction: consumer products only — food, vehicles, drugs, and pesticides are covered by other agencies.',
18
+ annotations: { readOnlyHint: true, idempotentHint: true },
19
+ input: z.object({
20
+ recall_number: z
21
+ .string()
22
+ .regex(/^\d{5}([a-d])?$/)
23
+ .describe('CPSC recall number. Modern records (2002–present) are 5-digit numeric, e.g. "25043". ' +
24
+ 'Historical records from 1998–2001 may have a letter suffix a–d, e.g. "99003a". ' +
25
+ 'Obtain from cpsc_search_recalls results.'),
26
+ }),
27
+ output: z.object({
28
+ recall_number: z.string().describe('Recall identifier.'),
29
+ recall_date: z.string().describe('Date issued, ISO 8601.'),
30
+ last_updated: z.string().describe('Date last published, ISO 8601.'),
31
+ title: z.string().describe('Official recall title.'),
32
+ description: z
33
+ .string()
34
+ .describe('Full recall description including product identification details. ' +
35
+ 'Model numbers are typically embedded here, not in a structured field.'),
36
+ cpsc_url: z
37
+ .string()
38
+ .describe('Official CPSC recall page — authoritative source for consumers.'),
39
+ consumer_contact: z
40
+ .string()
41
+ .nullable()
42
+ .describe('Contact information for claiming the remedy. Null when not provided.'),
43
+ hazards: z
44
+ .array(z
45
+ .object({ description: z.string().describe('What is dangerous about this product.') })
46
+ .describe('A hazard associated with this recall.'))
47
+ .describe('Hazards — read this first.'),
48
+ remedy_options: z
49
+ .array(z.string().describe('Remedy type.'))
50
+ .describe('Remedy types available: Refund, Repair, Replace, Dispose, Label, New Instructions.'),
51
+ remedy_instructions: z
52
+ .string()
53
+ .describe('Full remedy instructions — exactly what a consumer should do and how to claim.'),
54
+ products: z
55
+ .array(z
56
+ .object({
57
+ name: z.string().describe('Product name.'),
58
+ units_recalled: z
59
+ .string()
60
+ .describe('Estimated number of units recalled, e.g. "About 2,500".'),
61
+ })
62
+ .describe('A product covered by this recall.'))
63
+ .describe('Products covered. A recall may include multiple products. ' +
64
+ 'Note: model numbers are often in the description text, not a structured field.'),
65
+ upcs: z
66
+ .array(z.string().describe('UPC code.'))
67
+ .describe('UPC codes for this recall (sparse — ~4% of records have UPCs). ' +
68
+ 'UPCs are stored at the recall level in the API, not per-product; ' +
69
+ 'when the recall covers multiple products, UPC-to-product attribution is ambiguous.'),
70
+ injuries: z
71
+ .string()
72
+ .describe('Injury and incident report narrative, e.g. "None reported" or incident count.'),
73
+ manufacturers: z
74
+ .array(z.string().describe('Manufacturer name.'))
75
+ .describe('Manufacturer names (often empty — see importers).'),
76
+ importers: z.array(z.string().describe('Importer name.')).describe('Importer company names.'),
77
+ retailers: z
78
+ .array(z.string().describe('Retailer name with sale date range and price.'))
79
+ .describe('Retailer names with sale date ranges and price.'),
80
+ distributors: z
81
+ .array(z.string().describe('Distributor name.'))
82
+ .describe('Distributor company names.'),
83
+ manufacturer_countries: z
84
+ .array(z.string().describe('Country of manufacture.'))
85
+ .describe('Countries of manufacture.'),
86
+ images: z
87
+ .array(z
88
+ .object({
89
+ url: z.string().describe('Image URL.'),
90
+ caption: z.string().describe('Caption describing what the image shows.'),
91
+ })
92
+ .describe('An image from the recall notice.'))
93
+ .describe('Product and identification images from the recall notice.'),
94
+ coordinated_recalls: z
95
+ .array(z.string().describe('URL of coordinated recall by another agency.'))
96
+ .describe('URLs of coordinated recalls by other agencies (e.g., Canada Health).'),
97
+ cpsc_jurisdiction: z
98
+ .string()
99
+ .describe('CPSC covers consumer products — toys, electronics, furniture, appliances, tools, clothing. ' +
100
+ 'Does NOT cover: food/drugs (FDA), motor vehicles/tires (NHTSA), boats (USCG), pesticides (EPA), firearms (ATF).'),
101
+ }),
102
+ errors: [
103
+ {
104
+ reason: 'not_found',
105
+ code: JsonRpcErrorCode.NotFound,
106
+ when: 'No recall exists with the given recall number',
107
+ recovery: 'Verify the recall number (e.g. "25043" for modern records, "99003a" for 1998–2001 historical records). Use cpsc_search_recalls or cpsc_get_recent to find the correct number.',
108
+ },
109
+ {
110
+ reason: 'upstream_error',
111
+ code: JsonRpcErrorCode.ServiceUnavailable,
112
+ when: 'The saferproducts.gov API returned an error or timed out',
113
+ recovery: 'The CPSC API is occasionally unavailable. Retry in a few seconds.',
114
+ retryable: true,
115
+ },
116
+ ],
117
+ async handler(input, ctx) {
118
+ ctx.log.info('Fetching CPSC recall detail', { recall_number: input.recall_number });
119
+ const svc = getCpscRecallService();
120
+ let raw;
121
+ try {
122
+ raw = await svc.getByNumber(input.recall_number, ctx);
123
+ }
124
+ catch (err) {
125
+ throw ctx.fail('upstream_error', 'CPSC API request failed.', { ...ctx.recoveryFor('upstream_error') }, { cause: err });
126
+ }
127
+ if (!raw) {
128
+ throw ctx.fail('not_found', `No CPSC recall found with number "${input.recall_number}".`, {
129
+ ...ctx.recoveryFor('not_found'),
130
+ });
131
+ }
132
+ return {
133
+ recall_number: raw.RecallNumber,
134
+ recall_date: raw.RecallDate.slice(0, 10),
135
+ last_updated: raw.LastPublishDate.slice(0, 10),
136
+ title: raw.Title,
137
+ description: raw.Description,
138
+ cpsc_url: raw.URL,
139
+ consumer_contact: raw.ConsumerContact,
140
+ hazards: raw.Hazards.filter((h) => h.Name).map((h) => ({ description: h.Name })),
141
+ remedy_options: raw.RemedyOptions.map((o) => o.Option).filter(Boolean),
142
+ remedy_instructions: raw.Remedies.map((r) => r.Name)
143
+ .filter(Boolean)
144
+ .join(' '),
145
+ products: raw.Products.map((p) => ({
146
+ name: p.Name,
147
+ units_recalled: p.NumberOfUnits ?? '',
148
+ })),
149
+ upcs: raw.ProductUPCs.map((u) => u.UPC).filter(Boolean),
150
+ injuries: raw.Injuries.map((i) => i.Name)
151
+ .filter(Boolean)
152
+ .join(' '),
153
+ manufacturers: raw.Manufacturers.map((m) => m.Name).filter(Boolean),
154
+ importers: raw.Importers.map((i) => i.Name).filter(Boolean),
155
+ retailers: raw.Retailers.map((r) => r.Name).filter(Boolean),
156
+ distributors: raw.Distributors.map((d) => d.Name).filter(Boolean),
157
+ manufacturer_countries: raw.ManufacturerCountries.map((c) => c.Country).filter(Boolean),
158
+ images: raw.Images.map((img) => ({ url: img.URL, caption: img.Caption })),
159
+ coordinated_recalls: raw.Inconjunctions.map((inj) => inj.URL).filter(Boolean),
160
+ cpsc_jurisdiction: JURISDICTION,
161
+ };
162
+ },
163
+ format(result) {
164
+ const lines = [];
165
+ lines.push(`# [${result.recall_number}] — ${result.title}`);
166
+ lines.push(`Issued: ${result.recall_date} | Last updated: ${result.last_updated}`);
167
+ lines.push('');
168
+ const hazardText = result.hazards.length > 0
169
+ ? result.hazards.map((h) => h.description).join('; ')
170
+ : 'Not specified';
171
+ lines.push(`**⚠️ Hazard:** ${hazardText}`);
172
+ const remedyTypes = result.remedy_options.length > 0 ? result.remedy_options.join(', ') : 'Not specified';
173
+ const remedyText = result.remedy_instructions || 'See CPSC recall page.';
174
+ lines.push(`**✅ Remedy:** ${remedyTypes} — ${remedyText}`);
175
+ const contact = result.consumer_contact ?? 'See CPSC recall page.';
176
+ lines.push(`**Contact:** ${contact}`);
177
+ lines.push('');
178
+ lines.push('## Products Affected');
179
+ for (const p of result.products) {
180
+ lines.push(`- ${p.name} — ${p.units_recalled || 'units not specified'}`);
181
+ }
182
+ lines.push('**Note:** Model numbers are in the description text below if not listed here.');
183
+ if (result.upcs.length > 0) {
184
+ lines.push(`**UPCs (recall-level):** ${result.upcs.join(', ')} — applies to this recall as a whole`);
185
+ }
186
+ lines.push('');
187
+ lines.push('## Description');
188
+ lines.push(result.description);
189
+ lines.push('');
190
+ lines.push('## Incidents / Injuries');
191
+ lines.push(result.injuries || 'None reported');
192
+ lines.push('');
193
+ if (result.retailers.length > 0) {
194
+ lines.push('## Sold By');
195
+ for (const r of result.retailers) {
196
+ lines.push(`- ${r}`);
197
+ }
198
+ lines.push('');
199
+ }
200
+ const orgs = [...result.manufacturers, ...result.importers];
201
+ if (orgs.length > 0) {
202
+ lines.push('## Manufactured By / Imported By');
203
+ for (const org of orgs) {
204
+ lines.push(`- ${org}`);
205
+ }
206
+ }
207
+ if (result.manufacturer_countries.length > 0) {
208
+ lines.push(`Country of origin: ${result.manufacturer_countries.join(', ')}`);
209
+ }
210
+ if (orgs.length > 0 || result.manufacturer_countries.length > 0) {
211
+ lines.push('');
212
+ }
213
+ if (result.distributors.length > 0) {
214
+ lines.push('## Distributors');
215
+ for (const d of result.distributors) {
216
+ lines.push(`- ${d}`);
217
+ }
218
+ lines.push('');
219
+ }
220
+ if (result.images.length > 0) {
221
+ lines.push(`## Images (${result.images.length})`);
222
+ for (const img of result.images) {
223
+ lines.push(`- ${img.caption} — ${img.url}`);
224
+ }
225
+ lines.push('');
226
+ }
227
+ if (result.coordinated_recalls.length > 0) {
228
+ lines.push('## Coordinated Recalls');
229
+ for (const url of result.coordinated_recalls) {
230
+ lines.push(`- ${url}`);
231
+ }
232
+ lines.push('');
233
+ }
234
+ lines.push(`[View official CPSC recall page](${result.cpsc_url})`);
235
+ lines.push(`CPSC jurisdiction: ${result.cpsc_jurisdiction}`);
236
+ return [{ type: 'text', text: lines.join('\n') }];
237
+ },
238
+ });
239
+ //# sourceMappingURL=cpsc-get-recall.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cpsc-get-recall.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/cpsc-get-recall.tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @fileoverview Fetch the most recent CPSC recalls ordered newest-first, scoped to a
3
+ * configurable date window.
4
+ * @module mcp-server/tools/definitions/cpsc-get-recent
5
+ */
6
+ import { z } from '@cyanheads/mcp-ts-core';
7
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
8
+ export declare const cpscGetRecent: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
9
+ days: z.ZodDefault<z.ZodNumber>;
10
+ limit: z.ZodDefault<z.ZodNumber>;
11
+ }, z.core.$strip>, z.ZodObject<{
12
+ recalls: z.ZodArray<z.ZodObject<{
13
+ recall_number: z.ZodString;
14
+ recall_date: z.ZodString;
15
+ title: z.ZodString;
16
+ hazards: z.ZodArray<z.ZodString>;
17
+ remedy_options: z.ZodArray<z.ZodString>;
18
+ products: z.ZodArray<z.ZodString>;
19
+ cpsc_url: z.ZodString;
20
+ }, z.core.$strip>>;
21
+ period: z.ZodObject<{
22
+ start: z.ZodString;
23
+ end: z.ZodString;
24
+ days: z.ZodNumber;
25
+ }, z.core.$strip>;
26
+ total_found: z.ZodNumber;
27
+ truncated: z.ZodBoolean;
28
+ cpsc_jurisdiction: z.ZodString;
29
+ }, z.core.$strip>, readonly [{
30
+ readonly reason: "upstream_error";
31
+ readonly code: JsonRpcErrorCode.ServiceUnavailable;
32
+ readonly when: "The saferproducts.gov API returned an error or timed out";
33
+ readonly recovery: "The CPSC API is occasionally unavailable. Retry in a few seconds.";
34
+ readonly retryable: true;
35
+ }], undefined>;
36
+ //# sourceMappingURL=cpsc-get-recent.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cpsc-get-recent.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/cpsc-get-recent.tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAajE,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;cAmKxB,CAAC"}
@@ -0,0 +1,147 @@
1
+ /**
2
+ * @fileoverview Fetch the most recent CPSC recalls ordered newest-first, scoped to a
3
+ * configurable date window.
4
+ * @module mcp-server/tools/definitions/cpsc-get-recent
5
+ */
6
+ import { tool, z } from '@cyanheads/mcp-ts-core';
7
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
8
+ import { getCpscRecallService } from '../../../services/cpsc-recall/cpsc-recall-service.js';
9
+ /** Static jurisdiction note included in every response. */
10
+ const JURISDICTION = 'CPSC covers consumer products — toys, electronics, furniture, appliances, tools, clothing. ' +
11
+ 'Does NOT cover: food/drugs (FDA), motor vehicles/tires (NHTSA), boats (USCG), pesticides (EPA), firearms (ATF).';
12
+ /** Format a Date as "YYYY-MM-DD". */
13
+ function toIsoDate(d) {
14
+ return d.toISOString().slice(0, 10);
15
+ }
16
+ export const cpscGetRecent = tool('cpsc_get_recent', {
17
+ title: 'Get Recent CPSC Recalls',
18
+ description: 'Fetch the most recent CPSC consumer product recalls, ordered newest-first. ' +
19
+ 'Use for "what\'s been recalled lately?" or a product safety feed. ' +
20
+ 'Always applies a date window (default: last 30 days) — without a date filter the API returns all 9,800+ records. ' +
21
+ 'CPSC jurisdiction: consumer products only — food, vehicles, drugs, and pesticides are covered by other agencies.',
22
+ annotations: { readOnlyHint: true },
23
+ input: z.object({
24
+ days: z
25
+ .number()
26
+ .int()
27
+ .min(1)
28
+ .max(365)
29
+ .default(30)
30
+ .describe('Look back this many days from today. Defaults to 30. Use 7 for a weekly digest, 90 for a quarterly review.'),
31
+ limit: z
32
+ .number()
33
+ .int()
34
+ .min(1)
35
+ .max(100)
36
+ .default(20)
37
+ .describe('Maximum number of recalls to return. Defaults to 20.'),
38
+ }),
39
+ output: z.object({
40
+ recalls: z
41
+ .array(z
42
+ .object({
43
+ recall_number: z
44
+ .string()
45
+ .describe('Recall identifier. Pass to cpsc_get_recall for full detail.'),
46
+ recall_date: z.string().describe('Date issued, ISO 8601.'),
47
+ title: z.string().describe('Recall title.'),
48
+ hazards: z
49
+ .array(z.string().describe('Hazard description.'))
50
+ .describe('What is dangerous.'),
51
+ remedy_options: z.array(z.string().describe('Remedy type.')).describe('Remedy types.'),
52
+ products: z
53
+ .array(z.string().describe('Product name.'))
54
+ .describe('Product names recalled.'),
55
+ cpsc_url: z.string().describe('Official CPSC recall page URL.'),
56
+ })
57
+ .describe('A recent CPSC recall.'))
58
+ .describe('Recent recalls, newest-first.'),
59
+ period: z
60
+ .object({
61
+ start: z.string().describe('Start date of the query window, ISO 8601.'),
62
+ end: z.string().describe('End date (today), ISO 8601.'),
63
+ days: z.number().describe('Window length in days.'),
64
+ })
65
+ .describe('Date range queried.'),
66
+ total_found: z.number().describe('Total recalls in this period before the limit was applied.'),
67
+ truncated: z.boolean().describe('True when total_found exceeds the limit.'),
68
+ cpsc_jurisdiction: z
69
+ .string()
70
+ .describe('CPSC covers consumer products — toys, electronics, furniture, appliances, tools, clothing. ' +
71
+ 'Does NOT cover: food/drugs (FDA), motor vehicles/tires (NHTSA), boats (USCG), pesticides (EPA), firearms (ATF).'),
72
+ }),
73
+ errors: [
74
+ {
75
+ reason: 'upstream_error',
76
+ code: JsonRpcErrorCode.ServiceUnavailable,
77
+ when: 'The saferproducts.gov API returned an error or timed out',
78
+ recovery: 'The CPSC API is occasionally unavailable. Retry in a few seconds.',
79
+ retryable: true,
80
+ },
81
+ ],
82
+ async handler(input, ctx) {
83
+ const endDate = new Date();
84
+ const startDate = new Date(endDate);
85
+ startDate.setDate(endDate.getDate() - input.days);
86
+ const dateStart = toIsoDate(startDate);
87
+ const dateEnd = toIsoDate(endDate);
88
+ ctx.log.info('Fetching recent CPSC recalls', {
89
+ days: input.days,
90
+ date_start: dateStart,
91
+ date_end: dateEnd,
92
+ limit: input.limit,
93
+ });
94
+ const svc = getCpscRecallService();
95
+ let raw;
96
+ try {
97
+ raw = await svc.getRecent(dateStart, dateEnd, ctx);
98
+ }
99
+ catch (err) {
100
+ throw ctx.fail('upstream_error', 'CPSC API request failed.', { ...ctx.recoveryFor('upstream_error') }, { cause: err });
101
+ }
102
+ const total_found = raw.length;
103
+ const slice = raw.slice(0, input.limit);
104
+ const truncated = total_found > input.limit;
105
+ const recalls = slice.map((r) => ({
106
+ recall_number: r.RecallNumber,
107
+ recall_date: r.RecallDate.slice(0, 10),
108
+ title: r.Title,
109
+ hazards: r.Hazards.map((h) => h.Name).filter(Boolean),
110
+ remedy_options: r.RemedyOptions.map((o) => o.Option).filter(Boolean),
111
+ products: r.Products.map((p) => p.Name).filter(Boolean),
112
+ cpsc_url: r.URL,
113
+ }));
114
+ ctx.log.info('Recent recalls fetched', { total_found, returned: recalls.length, truncated });
115
+ return {
116
+ recalls,
117
+ period: { start: dateStart, end: dateEnd, days: input.days },
118
+ total_found,
119
+ truncated,
120
+ cpsc_jurisdiction: JURISDICTION,
121
+ };
122
+ },
123
+ format(result) {
124
+ const lines = [];
125
+ lines.push(`# Recent CPSC Recalls — ${result.period.start} to ${result.period.end} (${result.period.days} days)`);
126
+ lines.push('');
127
+ const truncNote = result.truncated
128
+ ? `, showing first ${result.recalls.length} (truncated)`
129
+ : '';
130
+ lines.push(`Found ${result.total_found} recall${result.total_found !== 1 ? 's' : ''}${truncNote}.`);
131
+ lines.push('');
132
+ lines.push('---');
133
+ for (const r of result.recalls) {
134
+ const hazardText = r.hazards.length > 0 ? r.hazards.join('; ') : 'Not specified';
135
+ const remedyText = r.remedy_options.length > 0 ? r.remedy_options.join(', ') : 'Not specified';
136
+ const productText = r.products.length > 0 ? r.products.join(', ') : 'Not specified';
137
+ lines.push(`**${r.recall_date}** — [${r.recall_number}] ${r.title}`);
138
+ lines.push(`Hazard: ${hazardText} | Remedy: ${remedyText}`);
139
+ lines.push(`Products: ${productText}`);
140
+ lines.push(`[CPSC page](${r.cpsc_url})`);
141
+ lines.push('---');
142
+ }
143
+ lines.push(`CPSC jurisdiction: ${result.cpsc_jurisdiction}`);
144
+ return [{ type: 'text', text: lines.join('\n') }];
145
+ },
146
+ });
147
+ //# sourceMappingURL=cpsc-get-recent.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cpsc-get-recent.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/cpsc-get-recent.tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,+CAA+C,CAAC;AAErF,2DAA2D;AAC3D,MAAM,YAAY,GAChB,6FAA6F;IAC7F,iHAAiH,CAAC;AAEpH,qCAAqC;AACrC,SAAS,SAAS,CAAC,CAAO;IACxB,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC,iBAAiB,EAAE;IACnD,KAAK,EAAE,yBAAyB;IAChC,WAAW,EACT,6EAA6E;QAC7E,oEAAoE;QACpE,mHAAmH;QACnH,kHAAkH;IACpH,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE;IAEnC,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,IAAI,EAAE,CAAC;aACJ,MAAM,EAAE;aACR,GAAG,EAAE;aACL,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,GAAG,CAAC;aACR,OAAO,CAAC,EAAE,CAAC;aACX,QAAQ,CACP,4GAA4G,CAC7G;QACH,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,GAAG,EAAE;aACL,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,GAAG,CAAC;aACR,OAAO,CAAC,EAAE,CAAC;aACX,QAAQ,CAAC,sDAAsD,CAAC;KACpE,CAAC;IAEF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,OAAO,EAAE,CAAC;aACP,KAAK,CACJ,CAAC;aACE,MAAM,CAAC;YACN,aAAa,EAAE,CAAC;iBACb,MAAM,EAAE;iBACR,QAAQ,CAAC,6DAA6D,CAAC;YAC1E,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC;YAC1D,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC;YAC3C,OAAO,EAAE,CAAC;iBACP,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAC;iBACjD,QAAQ,CAAC,oBAAoB,CAAC;YACjC,cAAc,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,eAAe,CAAC;YACtF,QAAQ,EAAE,CAAC;iBACR,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;iBAC3C,QAAQ,CAAC,yBAAyB,CAAC;YACtC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gCAAgC,CAAC;SAChE,CAAC;aACD,QAAQ,CAAC,uBAAuB,CAAC,CACrC;aACA,QAAQ,CAAC,+BAA+B,CAAC;QAC5C,MAAM,EAAE,CAAC;aACN,MAAM,CAAC;YACN,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2CAA2C,CAAC;YACvE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;YACvD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC;SACpD,CAAC;aACD,QAAQ,CAAC,qBAAqB,CAAC;QAClC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,4DAA4D,CAAC;QAC9F,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC;QAC3E,iBAAiB,EAAE,CAAC;aACjB,MAAM,EAAE;aACR,QAAQ,CACP,6FAA6F;YAC3F,iHAAiH,CACpH;KACJ,CAAC;IAEF,MAAM,EAAE;QACN;YACE,MAAM,EAAE,gBAAgB;YACxB,IAAI,EAAE,gBAAgB,CAAC,kBAAkB;YACzC,IAAI,EAAE,0DAA0D;YAChE,QAAQ,EAAE,mEAAmE;YAC7E,SAAS,EAAE,IAAI;SAChB;KACF;IAED,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG;QACtB,MAAM,OAAO,GAAG,IAAI,IAAI,EAAE,CAAC;QAC3B,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC;QACpC,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;QAElD,MAAM,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;QACvC,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;QAEnC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,8BAA8B,EAAE;YAC3C,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,UAAU,EAAE,SAAS;YACrB,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,KAAK,CAAC,KAAK;SACnB,CAAC,CAAC;QAEH,MAAM,GAAG,GAAG,oBAAoB,EAAE,CAAC;QACnC,IAAI,GAA8C,CAAC;QACnD,IAAI,CAAC;YACH,GAAG,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;QACrD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,CAAC,IAAI,CACZ,gBAAgB,EAChB,0BAA0B,EAC1B,EAAE,GAAG,GAAG,CAAC,WAAW,CAAC,gBAAgB,CAAC,EAAE,EACxC,EAAE,KAAK,EAAE,GAAG,EAAE,CACf,CAAC;QACJ,CAAC;QAED,MAAM,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC;QAC/B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QACxC,MAAM,SAAS,GAAG,WAAW,GAAG,KAAK,CAAC,KAAK,CAAC;QAE5C,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAChC,aAAa,EAAE,CAAC,CAAC,YAAY;YAC7B,WAAW,EAAE,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;YACtC,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;YACrD,cAAc,EAAE,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;YACpE,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;YACvD,QAAQ,EAAE,CAAC,CAAC,GAAG;SAChB,CAAC,CAAC,CAAC;QAEJ,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,wBAAwB,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;QAE7F,OAAO;YACL,OAAO;YACP,MAAM,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE;YAC5D,WAAW;YACX,SAAS;YACT,iBAAiB,EAAE,YAAY;SAChC,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,MAAM;QACX,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,KAAK,CAAC,IAAI,CACR,2BAA2B,MAAM,CAAC,MAAM,CAAC,KAAK,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,QAAQ,CACtG,CAAC;QACF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS;YAChC,CAAC,CAAC,mBAAmB,MAAM,CAAC,OAAO,CAAC,MAAM,cAAc;YACxD,CAAC,CAAC,EAAE,CAAC;QACP,KAAK,CAAC,IAAI,CACR,SAAS,MAAM,CAAC,WAAW,UAAU,MAAM,CAAC,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,SAAS,GAAG,CACxF,CAAC;QACF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAElB,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YAC/B,MAAM,UAAU,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC;YACjF,MAAM,UAAU,GACd,CAAC,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC;YAC9E,MAAM,WAAW,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC;YAEpF,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,SAAS,CAAC,CAAC,aAAa,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;YACrE,KAAK,CAAC,IAAI,CAAC,WAAW,UAAU,gBAAgB,UAAU,EAAE,CAAC,CAAC;YAC9D,KAAK,CAAC,IAAI,CAAC,aAAa,WAAW,EAAE,CAAC,CAAC;YACvC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC;YACzC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,sBAAsB,MAAM,CAAC,iBAAiB,EAAE,CAAC,CAAC;QAE7D,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpD,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * @fileoverview Search CPSC consumer product recalls by product name, brand, retailer,
3
+ * hazard keyword, or date range.
4
+ * @module mcp-server/tools/definitions/cpsc-search-recalls
5
+ */
6
+ import { z } from '@cyanheads/mcp-ts-core';
7
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
8
+ export declare const cpscSearchRecalls: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
9
+ product_name: z.ZodOptional<z.ZodString>;
10
+ manufacturer: z.ZodOptional<z.ZodString>;
11
+ retailer: z.ZodOptional<z.ZodString>;
12
+ importer: z.ZodOptional<z.ZodString>;
13
+ description_search: z.ZodOptional<z.ZodString>;
14
+ date_start: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"">, z.ZodString]>>;
15
+ date_end: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"">, z.ZodString]>>;
16
+ limit: z.ZodDefault<z.ZodNumber>;
17
+ }, z.core.$strip>, z.ZodObject<{
18
+ recalls: z.ZodArray<z.ZodObject<{
19
+ recall_number: z.ZodString;
20
+ recall_date: z.ZodString;
21
+ title: z.ZodString;
22
+ hazards: z.ZodArray<z.ZodString>;
23
+ remedy_options: z.ZodArray<z.ZodString>;
24
+ remedy_summary: z.ZodString;
25
+ products: z.ZodArray<z.ZodObject<{
26
+ name: z.ZodString;
27
+ units_recalled: z.ZodString;
28
+ }, z.core.$strip>>;
29
+ upcs: z.ZodArray<z.ZodString>;
30
+ manufacturers: z.ZodArray<z.ZodString>;
31
+ importers: z.ZodArray<z.ZodString>;
32
+ retailers: z.ZodArray<z.ZodString>;
33
+ cpsc_url: z.ZodString;
34
+ images: z.ZodArray<z.ZodObject<{
35
+ url: z.ZodString;
36
+ caption: z.ZodString;
37
+ }, z.core.$strip>>;
38
+ }, z.core.$strip>>;
39
+ total_found: z.ZodNumber;
40
+ truncated: z.ZodBoolean;
41
+ cpsc_jurisdiction: z.ZodString;
42
+ }, z.core.$strip>, readonly [{
43
+ readonly reason: "no_results";
44
+ readonly code: JsonRpcErrorCode.NotFound;
45
+ readonly when: "No recalls matched the search filters";
46
+ readonly recovery: "Broaden the search — try a shorter product name, fewer filters, or remove the date range. Check CPSC jurisdiction: food, vehicle, and drug recalls are not in this database.";
47
+ }, {
48
+ readonly reason: "upstream_error";
49
+ readonly code: JsonRpcErrorCode.ServiceUnavailable;
50
+ readonly when: "The saferproducts.gov API returned an error or timed out";
51
+ readonly recovery: "The CPSC API is occasionally unavailable. Retry in a few seconds.";
52
+ readonly retryable: true;
53
+ }], undefined>;
54
+ //# sourceMappingURL=cpsc-search-recalls.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cpsc-search-recalls.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/cpsc-search-recalls.tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AASjE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAqS5B,CAAC"}