@cyanheads/cpsc-recalls-mcp-server 0.1.7 → 0.2.0
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 +55 -26
- package/CLAUDE.md +55 -26
- package/README.md +40 -59
- package/changelog/0.1.x/0.1.8.md +32 -0
- package/changelog/0.2.x/0.2.0.md +31 -0
- package/changelog/template.md +9 -26
- package/dist/index.js +7 -5
- package/dist/index.js.map +1 -1
- package/dist/mcp-server/tools/definitions/cpsc-get-recall.tool.d.ts +4 -4
- package/dist/mcp-server/tools/definitions/cpsc-get-recall.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/cpsc-get-recall.tool.js +16 -34
- package/dist/mcp-server/tools/definitions/cpsc-get-recall.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/cpsc-get-recent.tool.d.ts +6 -4
- package/dist/mcp-server/tools/definitions/cpsc-get-recent.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/cpsc-get-recent.tool.js +142 -115
- package/dist/mcp-server/tools/definitions/cpsc-get-recent.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/cpsc-search-recalls.tool.d.ts +12 -9
- package/dist/mcp-server/tools/definitions/cpsc-search-recalls.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/cpsc-search-recalls.tool.js +372 -244
- package/dist/mcp-server/tools/definitions/cpsc-search-recalls.tool.js.map +1 -1
- package/dist/mcp-server/tools/response-budget.d.ts +34 -0
- package/dist/mcp-server/tools/response-budget.d.ts.map +1 -0
- package/dist/mcp-server/tools/response-budget.js +53 -0
- package/dist/mcp-server/tools/response-budget.js.map +1 -0
- package/dist/services/cpsc-recall/cpsc-recall-service.d.ts +1 -1
- package/dist/services/cpsc-recall/cpsc-recall-service.d.ts.map +1 -1
- package/dist/services/cpsc-recall/cpsc-recall-service.js +4 -5
- package/dist/services/cpsc-recall/cpsc-recall-service.js.map +1 -1
- package/package.json +10 -9
- package/server.json +3 -3
|
@@ -5,32 +5,111 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { tool, z } from '@cyanheads/mcp-ts-core';
|
|
7
7
|
import { JsonRpcErrorCode, McpError } from '@cyanheads/mcp-ts-core/errors';
|
|
8
|
+
import { budgetCutNotice, countWithinBudget, pageOverheadBytes, } from '../response-budget.js';
|
|
8
9
|
import { getCpscRecallService } from '../../../services/cpsc-recall/cpsc-recall-service.js';
|
|
9
10
|
/** 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).';
|
|
11
|
+
const JURISDICTION = 'CPSC covers consumer products — toys, electronics, furniture, appliances, tools, clothing. Does NOT cover: food/drugs (FDA), motor vehicles/tires (NHTSA), boats (USCG), pesticides (EPA), firearms (ATF).';
|
|
12
12
|
/** Static provenance caveat included in every response. */
|
|
13
|
-
const SOURCE_NOTE = 'Recall fields are relayed verbatim from the CPSC record and are neither edited nor verified by this server. '
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
const SOURCE_NOTE = 'Recall fields are relayed verbatim from the CPSC record and are neither edited nor verified by this server. CPSC records occasionally carry missing or inconsistent text. Check cpsc_url before acting on a recall for a consumer-facing decision.';
|
|
14
|
+
/** The longest window `days` accepts. */
|
|
15
|
+
const MAX_DAYS = 365;
|
|
16
16
|
/** Format a Date as "YYYY-MM-DD". */
|
|
17
17
|
function toIsoDate(d) {
|
|
18
18
|
return d.toISOString().slice(0, 10);
|
|
19
19
|
}
|
|
20
|
+
const recentRecallSchema = z
|
|
21
|
+
.object({
|
|
22
|
+
recall_number: z
|
|
23
|
+
.string()
|
|
24
|
+
.describe('Recall identifier. Pass to cpsc_get_recall for full detail.'),
|
|
25
|
+
recall_date: z.string().describe('Date issued, ISO 8601.'),
|
|
26
|
+
title: z.string().describe('Recall title.'),
|
|
27
|
+
hazards: z.array(z.string().describe('Hazard description.')).describe('What is dangerous.'),
|
|
28
|
+
remedy_options: z
|
|
29
|
+
.array(z.string().describe('Remedy type.'))
|
|
30
|
+
.describe('Remedy types: Refund, Repair, Replace, New Instructions, Dispose, Label, No Remedy Available, Inspect. Multiple may apply. Often empty — CPSC classified the remedy on fewer than half its records; call cpsc_get_recall for the remedy instructions when this is empty.'),
|
|
31
|
+
products: z.array(z.string().describe('Product name.')).describe('Product names recalled.'),
|
|
32
|
+
cpsc_url: z.string().describe('Official CPSC recall page URL.'),
|
|
33
|
+
data_quality_notes: z
|
|
34
|
+
.array(z.string().describe('One gap found in the CPSC record.'))
|
|
35
|
+
.describe('Gaps this server observed in the CPSC record — absent hazard text, absent product entries. Derived from which fields CPSC left empty, not from any judgement about the recall itself. Empty when nothing is missing.'),
|
|
36
|
+
})
|
|
37
|
+
.describe('A recent CPSC recall.');
|
|
38
|
+
/** Shapes one upstream record for the response. */
|
|
39
|
+
function toRecentRecall(r) {
|
|
40
|
+
const hazards = r.Hazards.map((h) => h.Name).filter(Boolean);
|
|
41
|
+
const products = r.Products.map((p) => p.Name).filter(Boolean);
|
|
42
|
+
const data_quality_notes = [];
|
|
43
|
+
if (hazards.length === 0) {
|
|
44
|
+
data_quality_notes.push('CPSC listed no hazard description for this recall.');
|
|
45
|
+
}
|
|
46
|
+
if (products.length === 0) {
|
|
47
|
+
data_quality_notes.push('CPSC listed no product entries for this recall.');
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
recall_number: r.RecallNumber,
|
|
51
|
+
recall_date: r.RecallDate.slice(0, 10),
|
|
52
|
+
title: r.Title,
|
|
53
|
+
hazards,
|
|
54
|
+
remedy_options: r.RemedyOptions.map((o) => o.Option).filter(Boolean),
|
|
55
|
+
products,
|
|
56
|
+
cpsc_url: r.URL,
|
|
57
|
+
data_quality_notes,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* One recall's `content[]` block. `format()` and the response budget both call it, so the
|
|
62
|
+
* bytes charged for a record are the bytes rendered for it.
|
|
63
|
+
*/
|
|
64
|
+
function renderRecallBlock(r) {
|
|
65
|
+
const hazardText = r.hazards.length > 0 ? r.hazards.join('; ') : 'Not specified';
|
|
66
|
+
const remedyText = r.remedy_options.length > 0 ? r.remedy_options.join(', ') : 'Not specified';
|
|
67
|
+
const productText = r.products.length > 0 ? r.products.join(', ') : 'Not specified';
|
|
68
|
+
const lines = [
|
|
69
|
+
`**${r.recall_date}** — [${r.recall_number}] ${r.title}`,
|
|
70
|
+
'CPSC source fields:',
|
|
71
|
+
`Hazard: ${hazardText} | Remedy: ${remedyText}`,
|
|
72
|
+
`Products: ${productText}`,
|
|
73
|
+
`[CPSC page](${r.cpsc_url})`,
|
|
74
|
+
];
|
|
75
|
+
if (r.data_quality_notes.length > 0) {
|
|
76
|
+
lines.push(`**Data quality (server-assessed):** ${r.data_quality_notes.join(' ')}`);
|
|
77
|
+
}
|
|
78
|
+
lines.push('---');
|
|
79
|
+
return lines.join('\n');
|
|
80
|
+
}
|
|
81
|
+
/** The text before the record blocks, for a page that returned `returned` records. */
|
|
82
|
+
function renderHeader(page, returned) {
|
|
83
|
+
const { start, end, days } = page.period;
|
|
84
|
+
const truncNote = page.truncated ? ' (truncated)' : '';
|
|
85
|
+
const windowNote = page.truncated || page.offset > 0
|
|
86
|
+
? `, showing ${returned} from offset ${page.offset}${truncNote}`
|
|
87
|
+
: '';
|
|
88
|
+
const lines = [
|
|
89
|
+
`# Recent CPSC Recalls — ${start} to ${end} (${days} day${days === 1 ? '' : 's'})`,
|
|
90
|
+
'',
|
|
91
|
+
`Found ${page.total_found} recall${page.total_found !== 1 ? 's' : ''}${windowNote}.`,
|
|
92
|
+
];
|
|
93
|
+
if (page.has_more) {
|
|
94
|
+
lines.push(`More available — repeat with offset ${page.offset + returned}.`);
|
|
95
|
+
}
|
|
96
|
+
lines.push('', '---');
|
|
97
|
+
return lines.join('\n');
|
|
98
|
+
}
|
|
99
|
+
/** The text after the record blocks. */
|
|
100
|
+
function renderFooter(page) {
|
|
101
|
+
return `Source: ${page.source_note}\nCPSC jurisdiction: ${page.cpsc_jurisdiction}`;
|
|
102
|
+
}
|
|
20
103
|
export const cpscGetRecent = tool('cpsc_get_recent', {
|
|
21
104
|
title: 'Get Recent CPSC Recalls',
|
|
22
|
-
description: 'Fetch the most recent CPSC consumer product recalls,
|
|
23
|
-
'Use for "what\'s been recalled lately?" or a product safety feed. ' +
|
|
24
|
-
'Always applies a date window (default: last 30 days) — without a date filter the API returns all 9,800+ records. ' +
|
|
25
|
-
'Page past limit with offset: narrowing days cannot page, because the window is anchored to today and shrinking it drops the oldest records rather than advancing past the newest. ' +
|
|
26
|
-
'CPSC jurisdiction: consumer products only — food, vehicles, drugs, and pesticides are covered by other agencies.',
|
|
105
|
+
description: 'Fetch the most recent CPSC consumer product recalls, newest-first, from a window of the last N days (default 30, up to 365). Use for "what\'s been recalled lately?" or a product safety feed; to find recalls by product, brand, hazard, or an older date range, use cpsc_search_recalls. Page past limit with offset: narrowing days cannot page, because the window is anchored to today and shrinking it drops the oldest recalls rather than advancing past the newest. A page returns fewer than limit recalls when it reaches the 64,000-byte response size budget; has_more and the notice give the offset to continue from. Pass a recall_number to cpsc_get_recall for the full record. CPSC jurisdiction: consumer products only — food/drugs (FDA), motor vehicles/tires (NHTSA), boats (USCG), pesticides (EPA), and firearms (ATF) are covered by other agencies.',
|
|
27
106
|
annotations: { readOnlyHint: true },
|
|
28
107
|
input: z.object({
|
|
29
108
|
days: z
|
|
30
109
|
.number()
|
|
31
110
|
.int()
|
|
32
111
|
.min(1)
|
|
33
|
-
.max(
|
|
112
|
+
.max(MAX_DAYS)
|
|
34
113
|
.default(30)
|
|
35
114
|
.describe('Look back this many days from today. Defaults to 30. Use 7 for a weekly digest, 90 for a quarterly review.'),
|
|
36
115
|
limit: z
|
|
@@ -39,43 +118,16 @@ export const cpscGetRecent = tool('cpsc_get_recent', {
|
|
|
39
118
|
.min(1)
|
|
40
119
|
.max(100)
|
|
41
120
|
.default(20)
|
|
42
|
-
.describe('Maximum number of recalls to return. Defaults to 20.'),
|
|
121
|
+
.describe('Maximum number of recalls to return. Defaults to 20. A page returns fewer when it reaches the 64,000-byte response size budget.'),
|
|
43
122
|
offset: z
|
|
44
123
|
.number()
|
|
45
124
|
.int()
|
|
46
125
|
.min(0)
|
|
47
126
|
.default(0)
|
|
48
|
-
.describe('Skip this many recalls in the window before returning results.
|
|
49
|
-
'An offset at or past total_found returns an empty result set rather than an error.'),
|
|
127
|
+
.describe('Skip this many recalls in the window before returning results. To page through total_found, raise offset by the number of recalls the previous page returned — limit, unless that page reached the response size budget. An offset at or past total_found returns an empty result set rather than an error.'),
|
|
50
128
|
}),
|
|
51
129
|
output: z.object({
|
|
52
|
-
recalls: z
|
|
53
|
-
.array(z
|
|
54
|
-
.object({
|
|
55
|
-
recall_number: z
|
|
56
|
-
.string()
|
|
57
|
-
.describe('Recall identifier. Pass to cpsc_get_recall for full detail.'),
|
|
58
|
-
recall_date: z.string().describe('Date issued, ISO 8601.'),
|
|
59
|
-
title: z.string().describe('Recall title.'),
|
|
60
|
-
hazards: z
|
|
61
|
-
.array(z.string().describe('Hazard description.'))
|
|
62
|
-
.describe('What is dangerous.'),
|
|
63
|
-
remedy_options: z
|
|
64
|
-
.array(z.string().describe('Remedy type.'))
|
|
65
|
-
.describe('Remedy types: Refund, Repair, Replace, New Instructions, Dispose, Label, No Remedy Available, Inspect. ' +
|
|
66
|
-
'Multiple may apply. Often empty — CPSC classified the remedy on fewer than half its records; ' +
|
|
67
|
-
'call cpsc_get_recall for the remedy narrative when this is empty.'),
|
|
68
|
-
products: z
|
|
69
|
-
.array(z.string().describe('Product name.'))
|
|
70
|
-
.describe('Product names recalled.'),
|
|
71
|
-
cpsc_url: z.string().describe('Official CPSC recall page URL.'),
|
|
72
|
-
data_quality_notes: z
|
|
73
|
-
.array(z.string().describe('One gap found in the upstream record.'))
|
|
74
|
-
.describe('Gaps this server observed in the upstream CPSC record — absent hazard text, absent product entries. ' +
|
|
75
|
-
'Derived from which fields CPSC left empty, not from any judgement about the recall itself. Empty when nothing is missing.'),
|
|
76
|
-
})
|
|
77
|
-
.describe('A recent CPSC recall.'))
|
|
78
|
-
.describe('Recent recalls, newest-first.'),
|
|
130
|
+
recalls: z.array(recentRecallSchema).describe('Recent recalls, newest-first.'),
|
|
79
131
|
period: z
|
|
80
132
|
.object({
|
|
81
133
|
start: z.string().describe('Start date of the query window, ISO 8601.'),
|
|
@@ -85,34 +137,39 @@ export const cpscGetRecent = tool('cpsc_get_recent', {
|
|
|
85
137
|
.describe('Date range queried.'),
|
|
86
138
|
total_found: z
|
|
87
139
|
.number()
|
|
88
|
-
.describe('Total recalls in this period, counted before offset and
|
|
140
|
+
.describe('Total recalls in this period, counted before offset, limit, and the response size budget narrow the window.'),
|
|
89
141
|
truncated: z
|
|
90
142
|
.boolean()
|
|
91
|
-
.describe('True when
|
|
143
|
+
.describe('True when recalls in the window remain past this page — always equal to has_more.'),
|
|
92
144
|
offset: z.number().describe('Number of recalls skipped before this window.'),
|
|
93
145
|
has_more: z
|
|
94
146
|
.boolean()
|
|
95
147
|
.describe('True when recalls remain past this window — call again with offset raised by the number of recalls returned.'),
|
|
96
148
|
cpsc_jurisdiction: z
|
|
97
149
|
.string()
|
|
98
|
-
.describe('CPSC covers
|
|
99
|
-
'Does NOT cover: food/drugs (FDA), motor vehicles/tires (NHTSA), boats (USCG), pesticides (EPA), firearms (ATF).'),
|
|
150
|
+
.describe('Which products CPSC covers and which agencies cover the rest — food/drugs (FDA), motor vehicles/tires (NHTSA), boats (USCG), pesticides (EPA), firearms (ATF).'),
|
|
100
151
|
source_note: z
|
|
101
152
|
.string()
|
|
102
153
|
.describe('Provenance caveat: recall fields are relayed from CPSC unedited and unverified; check cpsc_url before a consumer-facing decision.'),
|
|
103
154
|
}),
|
|
155
|
+
enrichment: {
|
|
156
|
+
notice: z
|
|
157
|
+
.string()
|
|
158
|
+
.optional()
|
|
159
|
+
.describe('Present when the page needs explaining: a window with no recalls (with a larger days to try), an offset past the last recall, or a page cut short by the response size budget (with the offset to continue from).'),
|
|
160
|
+
},
|
|
104
161
|
errors: [
|
|
105
162
|
{
|
|
106
163
|
reason: 'upstream_error',
|
|
107
164
|
code: JsonRpcErrorCode.ServiceUnavailable,
|
|
108
|
-
when: 'The saferproducts.gov
|
|
109
|
-
recovery: 'The CPSC
|
|
165
|
+
when: 'The CPSC recall service (saferproducts.gov) was unavailable, timed out, or sent an unreadable response',
|
|
166
|
+
recovery: 'The CPSC recall service is occasionally unavailable. Retry in a few seconds.',
|
|
110
167
|
retryable: true,
|
|
111
168
|
},
|
|
112
169
|
{
|
|
113
170
|
reason: 'upstream_rejected',
|
|
114
171
|
code: JsonRpcErrorCode.ServiceUnavailable,
|
|
115
|
-
when: '
|
|
172
|
+
when: 'CPSC rejected the request instead of returning recalls, and it rejects the same request every time',
|
|
116
173
|
recovery: 'Do not retry this request unchanged — it fails deterministically. Read the message for what CPSC rejected, then try a different days window.',
|
|
117
174
|
retryable: false,
|
|
118
175
|
},
|
|
@@ -123,6 +180,7 @@ export const cpscGetRecent = tool('cpsc_get_recent', {
|
|
|
123
180
|
startDate.setDate(endDate.getDate() - input.days);
|
|
124
181
|
const dateStart = toIsoDate(startDate);
|
|
125
182
|
const dateEnd = toIsoDate(endDate);
|
|
183
|
+
const period = { start: dateStart, end: dateEnd, days: input.days };
|
|
126
184
|
ctx.log.info('Fetching recent CPSC recalls', {
|
|
127
185
|
days: input.days,
|
|
128
186
|
date_start: dateStart,
|
|
@@ -143,80 +201,49 @@ export const cpscGetRecent = tool('cpsc_get_recent', {
|
|
|
143
201
|
throw ctx.fail('upstream_error', `CPSC API request failed: ${detail}`, { ...ctx.recoveryFor('upstream_error') }, { cause: err });
|
|
144
202
|
}
|
|
145
203
|
const total_found = raw.length;
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
const has_more = input.offset + slice.length < total_found;
|
|
150
|
-
const recalls = slice.map((r) => {
|
|
151
|
-
const hazards = r.Hazards.map((h) => h.Name).filter(Boolean);
|
|
152
|
-
const products = r.Products.map((p) => p.Name).filter(Boolean);
|
|
153
|
-
const data_quality_notes = [];
|
|
154
|
-
if (hazards.length === 0) {
|
|
155
|
-
data_quality_notes.push('CPSC listed no hazard description for this recall.');
|
|
156
|
-
}
|
|
157
|
-
if (products.length === 0) {
|
|
158
|
-
data_quality_notes.push('CPSC listed no product entries for this recall.');
|
|
159
|
-
}
|
|
160
|
-
return {
|
|
161
|
-
recall_number: r.RecallNumber,
|
|
162
|
-
recall_date: r.RecallDate.slice(0, 10),
|
|
163
|
-
title: r.Title,
|
|
164
|
-
hazards,
|
|
165
|
-
remedy_options: r.RemedyOptions.map((o) => o.Option).filter(Boolean),
|
|
166
|
-
products,
|
|
167
|
-
cpsc_url: r.URL,
|
|
168
|
-
data_quality_notes,
|
|
169
|
-
};
|
|
170
|
-
});
|
|
171
|
-
ctx.log.info('Recent recalls fetched', {
|
|
204
|
+
const window = raw.slice(input.offset, input.offset + input.limit).map(toRecentRecall);
|
|
205
|
+
const page = {
|
|
206
|
+
period,
|
|
172
207
|
total_found,
|
|
173
|
-
returned: recalls.length,
|
|
174
208
|
offset: input.offset,
|
|
175
|
-
truncated,
|
|
176
|
-
has_more,
|
|
177
|
-
});
|
|
178
|
-
return {
|
|
179
|
-
recalls,
|
|
180
|
-
period: { start: dateStart, end: dateEnd, days: input.days },
|
|
181
|
-
total_found,
|
|
182
|
-
truncated,
|
|
183
|
-
offset: input.offset,
|
|
184
|
-
has_more,
|
|
185
209
|
cpsc_jurisdiction: JURISDICTION,
|
|
186
210
|
source_note: SOURCE_NOTE,
|
|
187
211
|
};
|
|
212
|
+
/**
|
|
213
|
+
* The overhead reserves the page's worst case: the longest header (truncated, with a
|
|
214
|
+
* next-page offset for a full limit of records) and a budget notice at the same counts.
|
|
215
|
+
*/
|
|
216
|
+
const overhead = pageOverheadBytes({ ...page, recalls: [], truncated: false, has_more: false }, `${renderHeader({ ...page, truncated: true, has_more: true }, input.limit)}\n${renderFooter(page)}`, { notice: budgetCutNotice(input.limit, input.limit, input.offset + input.limit) });
|
|
217
|
+
const returned = countWithinBudget(window, renderRecallBlock, overhead);
|
|
218
|
+
const recalls = window.slice(0, returned);
|
|
219
|
+
const has_more = input.offset + returned < total_found;
|
|
220
|
+
/** One notice slot, last-wins: the three page states are mutually exclusive. */
|
|
221
|
+
const notice = total_found === 0
|
|
222
|
+
? `No CPSC recalls were issued between ${dateStart} and ${dateEnd}.${input.days < MAX_DAYS
|
|
223
|
+
? ` Raise days (up to ${MAX_DAYS}) for a longer window.`
|
|
224
|
+
: ` ${MAX_DAYS} days is the longest window this tool covers — use cpsc_search_recalls with date_start and date_end to reach older recalls.`}`
|
|
225
|
+
: input.offset >= total_found
|
|
226
|
+
? `Offset ${input.offset} is past the last of the ${total_found} recall${total_found === 1 ? '' : 's'} in this window, so this page is empty. Use an offset below ${total_found}.`
|
|
227
|
+
: returned < window.length
|
|
228
|
+
? budgetCutNotice(returned, input.limit, input.offset + returned)
|
|
229
|
+
: undefined;
|
|
230
|
+
if (notice)
|
|
231
|
+
ctx.enrich.notice(notice);
|
|
232
|
+
ctx.log.info('Recent recalls fetched', {
|
|
233
|
+
total_found,
|
|
234
|
+
returned,
|
|
235
|
+
offset: input.offset,
|
|
236
|
+
has_more,
|
|
237
|
+
});
|
|
238
|
+
return { ...page, recalls, truncated: has_more, has_more };
|
|
188
239
|
},
|
|
189
240
|
format(result) {
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
: '';
|
|
197
|
-
lines.push(`Found ${result.total_found} recall${result.total_found !== 1 ? 's' : ''}${windowNote}.`);
|
|
198
|
-
if (result.has_more) {
|
|
199
|
-
lines.push(`More available — repeat with offset ${result.offset + result.recalls.length}.`);
|
|
200
|
-
}
|
|
201
|
-
lines.push('');
|
|
202
|
-
lines.push('---');
|
|
203
|
-
for (const r of result.recalls) {
|
|
204
|
-
const hazardText = r.hazards.length > 0 ? r.hazards.join('; ') : 'Not specified';
|
|
205
|
-
const remedyText = r.remedy_options.length > 0 ? r.remedy_options.join(', ') : 'Not specified';
|
|
206
|
-
const productText = r.products.length > 0 ? r.products.join(', ') : 'Not specified';
|
|
207
|
-
lines.push(`**${r.recall_date}** — [${r.recall_number}] ${r.title}`);
|
|
208
|
-
lines.push('CPSC source fields:');
|
|
209
|
-
lines.push(`Hazard: ${hazardText} | Remedy: ${remedyText}`);
|
|
210
|
-
lines.push(`Products: ${productText}`);
|
|
211
|
-
lines.push(`[CPSC page](${r.cpsc_url})`);
|
|
212
|
-
if (r.data_quality_notes.length > 0) {
|
|
213
|
-
lines.push(`**Data quality (server-assessed):** ${r.data_quality_notes.join(' ')}`);
|
|
214
|
-
}
|
|
215
|
-
lines.push('---');
|
|
216
|
-
}
|
|
217
|
-
lines.push(`Source: ${result.source_note}`);
|
|
218
|
-
lines.push(`CPSC jurisdiction: ${result.cpsc_jurisdiction}`);
|
|
219
|
-
return [{ type: 'text', text: lines.join('\n') }];
|
|
241
|
+
const text = [
|
|
242
|
+
renderHeader(result, result.recalls.length),
|
|
243
|
+
...result.recalls.map(renderRecallBlock),
|
|
244
|
+
renderFooter(result),
|
|
245
|
+
].join('\n');
|
|
246
|
+
return [{ type: 'text', text }];
|
|
220
247
|
},
|
|
221
248
|
});
|
|
222
249
|
//# sourceMappingURL=cpsc-get-recent.tool.js.map
|
|
@@ -1 +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,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,+CAA+C,CAAC;
|
|
1
|
+
{"version":3,"file":"cpsc-get-recent.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/cpsc-get-recent.tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -51,26 +51,29 @@ export declare const cpscSearchRecalls: import("@cyanheads/mcp-ts-core").ToolDef
|
|
|
51
51
|
cpsc_jurisdiction: z.ZodString;
|
|
52
52
|
source_note: z.ZodString;
|
|
53
53
|
}, z.core.$strip>, readonly [{
|
|
54
|
+
readonly reason: "missing_criteria";
|
|
55
|
+
readonly code: JsonRpcErrorCode.ValidationError;
|
|
56
|
+
readonly when: "No search criterion was given: every text filter was omitted or blank and no date bound was set";
|
|
57
|
+
readonly recovery: "Set at least one criterion — title_search, product_name, manufacturer, importer, retailer, distributor, description_search, remedy, hazard_search, or a date bound (date_start, date_end, updated_start, updated_end). To browse the latest recalls without a filter, call cpsc_get_recent instead.";
|
|
58
|
+
}, {
|
|
54
59
|
readonly reason: "invalid_date_range";
|
|
55
60
|
readonly code: JsonRpcErrorCode.ValidationError;
|
|
56
61
|
readonly when: "date_start is later than date_end, or updated_start is later than updated_end, so the range can never match";
|
|
57
62
|
readonly recovery: "Swap the two dates, or drop one of them. date_start and date_end bound the recall issue date; updated_start and updated_end bound the date CPSC last published the record.";
|
|
58
|
-
}, {
|
|
59
|
-
readonly reason: "no_results";
|
|
60
|
-
readonly code: JsonRpcErrorCode.NotFound;
|
|
61
|
-
readonly when: "No recalls matched the search filters, including hazard_search";
|
|
62
|
-
readonly recovery: "Broaden the search — try a shorter product name, fewer filters, or remove the date range. If hazard_search was set, drop it: it narrows the upstream results further, client-side. Check CPSC jurisdiction: food, vehicle, and drug recalls are not in this database.";
|
|
63
63
|
}, {
|
|
64
64
|
readonly reason: "upstream_error";
|
|
65
65
|
readonly code: JsonRpcErrorCode.ServiceUnavailable;
|
|
66
|
-
readonly when: "The saferproducts.gov
|
|
67
|
-
readonly recovery: "The CPSC
|
|
66
|
+
readonly when: "The CPSC recall service (saferproducts.gov) was unavailable, timed out, or sent an unreadable response";
|
|
67
|
+
readonly recovery: "The CPSC recall service is occasionally unavailable. Retry in a few seconds.";
|
|
68
68
|
readonly retryable: true;
|
|
69
69
|
}, {
|
|
70
70
|
readonly reason: "upstream_rejected";
|
|
71
71
|
readonly code: JsonRpcErrorCode.ServiceUnavailable;
|
|
72
|
-
readonly when: "
|
|
72
|
+
readonly when: "CPSC rejected the request instead of returning recalls, and it rejects the same request every time";
|
|
73
73
|
readonly recovery: "Do not retry this request unchanged — it fails deterministically. Read the message for what CPSC rejected, then change a filter value and call again.";
|
|
74
74
|
readonly retryable: false;
|
|
75
|
-
}],
|
|
75
|
+
}], {
|
|
76
|
+
readonly effectiveQuery: z.ZodString;
|
|
77
|
+
readonly notice: z.ZodOptional<z.ZodString>;
|
|
78
|
+
}>;
|
|
76
79
|
//# sourceMappingURL=cpsc-search-recalls.tool.d.ts.map
|
|
@@ -1 +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,EAAY,MAAM,+BAA+B,CAAC;
|
|
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,EAAY,MAAM,+BAA+B,CAAC;AAiV3E,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoW5B,CAAC"}
|