@cyanheads/cpsc-recalls-mcp-server 0.1.6 → 0.1.7
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 +11 -9
- package/CLAUDE.md +11 -9
- package/Dockerfile +9 -4
- package/LICENSE +1 -1
- package/README.md +2 -1
- package/changelog/0.1.x/0.1.7.md +37 -0
- package/changelog/template.md +55 -16
- package/dist/services/cpsc-recall/cpsc-recall-service.d.ts.map +1 -1
- package/dist/services/cpsc-recall/cpsc-recall-service.js +3 -7
- package/dist/services/cpsc-recall/cpsc-recall-service.js.map +1 -1
- package/package.json +7 -7
- package/server.json +3 -3
package/AGENTS.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Developer Protocol
|
|
2
2
|
|
|
3
3
|
**Server:** cpsc-recalls-mcp-server
|
|
4
|
-
**Version:** 0.1.
|
|
5
|
-
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.
|
|
4
|
+
**Version:** 0.1.7
|
|
5
|
+
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.12.3`
|
|
6
6
|
**Engines:** Bun ≥1.3.0, Node ≥24.0.0
|
|
7
|
-
**MCP SDK:** `@modelcontextprotocol/
|
|
7
|
+
**MCP SDK:** `@modelcontextprotocol/server` ^2.0.0 (protocol revisions 2026-07-28 and 2025-*)
|
|
8
8
|
**Zod:** ^4.4.3
|
|
9
9
|
|
|
10
10
|
> **Read the framework docs first:** `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md` contains the full API reference — builders, Context, error codes, exports, patterns. This file covers server-specific conventions only.
|
|
@@ -35,7 +35,7 @@ Tailor suggestions to what's actually missing or stale — don't recite the full
|
|
|
35
35
|
- **Logic throws, framework catches.** Tool/resource handlers are pure — throw on failure, no `try/catch`. Plain `Error` is fine; the framework catches, classifies, and formats. Use error factories (`notFound()`, `validationError()`, etc.) when the error code matters.
|
|
36
36
|
- **Use `ctx.log`** for request-scoped logging. No `console` calls.
|
|
37
37
|
- **Use `ctx.state`** for tenant-scoped storage. Never access persistence directly.
|
|
38
|
-
- **
|
|
38
|
+
- **Need input the caller didn't supply?** `return ctx.requestInput(...)` and read `ctx.inputs` when the handler is re-entered. Never `await` for user input mid-handler.
|
|
39
39
|
- **Secrets in env vars only** — never hardcoded.
|
|
40
40
|
- **Close the loop on issues.** When implementing work tracked by a GitHub issue, comment on the issue with what landed and close it. Do both — a comment without a close leaves stale issues open; a close without a comment leaves no record of what shipped. The comment is for future readers — state the concrete changes, not the conversation that produced them.
|
|
41
41
|
|
|
@@ -91,7 +91,7 @@ export const itemData = resource('inventory://{itemId}', {
|
|
|
91
91
|
params: z.object({ itemId: z.string().describe('Item identifier') }),
|
|
92
92
|
auth: ['inventory:read'],
|
|
93
93
|
async handler(params, ctx) {
|
|
94
|
-
const item = await ctx.state.get(`item
|
|
94
|
+
const item = await ctx.state.get(`item/${params.itemId}`);
|
|
95
95
|
if (!item) throw notFound(`Item ${params.itemId} not found`, { itemId: params.itemId });
|
|
96
96
|
return item;
|
|
97
97
|
},
|
|
@@ -125,6 +125,7 @@ import { parseEnvConfig } from '@cyanheads/mcp-ts-core/config';
|
|
|
125
125
|
const ServerConfigSchema = z.object({
|
|
126
126
|
apiKey: z.string().describe('External API key'),
|
|
127
127
|
maxResults: z.coerce.number().default(100),
|
|
128
|
+
verboseLogging: z.stringbool().default(false).describe('Enable verbose logging'),
|
|
128
129
|
});
|
|
129
130
|
|
|
130
131
|
let _config: z.infer<typeof ServerConfigSchema> | undefined;
|
|
@@ -132,6 +133,7 @@ export function getServerConfig() {
|
|
|
132
133
|
_config ??= parseEnvConfig(ServerConfigSchema, {
|
|
133
134
|
apiKey: 'MY_API_KEY',
|
|
134
135
|
maxResults: 'MY_MAX_RESULTS',
|
|
136
|
+
verboseLogging: 'MY_VERBOSE_LOGGING',
|
|
135
137
|
});
|
|
136
138
|
return _config;
|
|
137
139
|
}
|
|
@@ -166,13 +168,13 @@ Handlers receive a unified `ctx` object. Key properties:
|
|
|
166
168
|
|
|
167
169
|
| Property | Description |
|
|
168
170
|
|:---------|:------------|
|
|
169
|
-
| `ctx.log` | Request-scoped logger — `.debug()`, `.info()`, `.notice()`, `.warning()`, `.error()`. Auto-correlates requestId, traceId, tenantId. |
|
|
171
|
+
| `ctx.log` | Request-scoped logger — `.debug()`, `.info()`, `.notice()`, `.warning()`, `.error()`. Auto-correlates requestId, traceId, tenantId. Dual-sink: Pino **and** `notifications/message` to the client, so treat it as client-visible. |
|
|
170
172
|
| `ctx.state` | Tenant-scoped KV — `.get(key)`, `.set(key, value, { ttl? })`, `.delete(key)`, `.getMany(keys)`, `.list(prefix, { cursor, limit })`. Accepts any serializable value. |
|
|
171
|
-
| `ctx.
|
|
173
|
+
| `ctx.requestInput` | Suspend and ask the caller for more input — `return ctx.requestInput({ inputRequests: { key: inputRequired.elicit({ message, requestedSchema }) } })`. Never returns; the handler is re-entered with the answers. Always present. |
|
|
174
|
+
| `ctx.inputs` | Reader over a retried request's responses — `.accepted(key, schema)`, `.view(key)`, `.state()`, `.dropped`. Empty on the first round. |
|
|
172
175
|
| `ctx.enrich` | Success-path agent context (empty-result notices, query echo, pagination totals) — `ctx.enrich(...)` or `.notice()` / `.total()` / `.echo()` / `.truncated()`. Reaches `structuredContent` and `content[]`; lands only when the definition declares an `enrichment` block (no-op otherwise). |
|
|
173
176
|
| `ctx.content` | Non-text content blocks — `.image(data, mimeType)`, `.audio(data, mimeType)`, or `ctx.content(block)` for a raw block. Prepended to `content[]` after `format()`; never enters `structuredContent`. |
|
|
174
177
|
| `ctx.signal` | `AbortSignal` for cancellation. |
|
|
175
|
-
| `ctx.progress` | Task progress (present when `task: true`) — `.setTotal(n)`, `.increment()`, `.update(message)`. |
|
|
176
178
|
| `ctx.requestId` | Unique request ID. |
|
|
177
179
|
| `ctx.tenantId` | Tenant ID from JWT; `'default'` for stdio or HTTP with auth off. |
|
|
178
180
|
|
|
@@ -286,7 +288,7 @@ Available skills:
|
|
|
286
288
|
| `api-auth` | Auth modes, scopes, JWT/OAuth |
|
|
287
289
|
| `api-canvas` | DataCanvas: register tabular data, run SQL, export, plus the `spillover()` helper for big result sets — Tier 3 opt-in |
|
|
288
290
|
| `api-config` | AppConfig, parseConfig, env vars |
|
|
289
|
-
| `api-context` | Context interface, logger, state,
|
|
291
|
+
| `api-context` | Context interface, RequestContext, logger, state, multi-round-trip input |
|
|
290
292
|
| `api-errors` | McpError, JsonRpcErrorCode, error patterns |
|
|
291
293
|
| `api-linter` | Definition linter rule catalog — invoked by `bun run lint:mcp` and `devcheck` |
|
|
292
294
|
| `api-mirror` | MirrorService: persistent self-refreshing local mirror (embedded SQLite + FTS5) of a bulk upstream dataset — Tier 3 opt-in |
|
package/CLAUDE.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Developer Protocol
|
|
2
2
|
|
|
3
3
|
**Server:** cpsc-recalls-mcp-server
|
|
4
|
-
**Version:** 0.1.
|
|
5
|
-
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.
|
|
4
|
+
**Version:** 0.1.7
|
|
5
|
+
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.12.3`
|
|
6
6
|
**Engines:** Bun ≥1.3.0, Node ≥24.0.0
|
|
7
|
-
**MCP SDK:** `@modelcontextprotocol/
|
|
7
|
+
**MCP SDK:** `@modelcontextprotocol/server` ^2.0.0 (protocol revisions 2026-07-28 and 2025-*)
|
|
8
8
|
**Zod:** ^4.4.3
|
|
9
9
|
|
|
10
10
|
> **Read the framework docs first:** `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md` contains the full API reference — builders, Context, error codes, exports, patterns. This file covers server-specific conventions only.
|
|
@@ -35,7 +35,7 @@ Tailor suggestions to what's actually missing or stale — don't recite the full
|
|
|
35
35
|
- **Logic throws, framework catches.** Tool/resource handlers are pure — throw on failure, no `try/catch`. Plain `Error` is fine; the framework catches, classifies, and formats. Use error factories (`notFound()`, `validationError()`, etc.) when the error code matters.
|
|
36
36
|
- **Use `ctx.log`** for request-scoped logging. No `console` calls.
|
|
37
37
|
- **Use `ctx.state`** for tenant-scoped storage. Never access persistence directly.
|
|
38
|
-
- **
|
|
38
|
+
- **Need input the caller didn't supply?** `return ctx.requestInput(...)` and read `ctx.inputs` when the handler is re-entered. Never `await` for user input mid-handler.
|
|
39
39
|
- **Secrets in env vars only** — never hardcoded.
|
|
40
40
|
- **Close the loop on issues.** When implementing work tracked by a GitHub issue, comment on the issue with what landed and close it. Do both — a comment without a close leaves stale issues open; a close without a comment leaves no record of what shipped. The comment is for future readers — state the concrete changes, not the conversation that produced them.
|
|
41
41
|
|
|
@@ -91,7 +91,7 @@ export const itemData = resource('inventory://{itemId}', {
|
|
|
91
91
|
params: z.object({ itemId: z.string().describe('Item identifier') }),
|
|
92
92
|
auth: ['inventory:read'],
|
|
93
93
|
async handler(params, ctx) {
|
|
94
|
-
const item = await ctx.state.get(`item
|
|
94
|
+
const item = await ctx.state.get(`item/${params.itemId}`);
|
|
95
95
|
if (!item) throw notFound(`Item ${params.itemId} not found`, { itemId: params.itemId });
|
|
96
96
|
return item;
|
|
97
97
|
},
|
|
@@ -125,6 +125,7 @@ import { parseEnvConfig } from '@cyanheads/mcp-ts-core/config';
|
|
|
125
125
|
const ServerConfigSchema = z.object({
|
|
126
126
|
apiKey: z.string().describe('External API key'),
|
|
127
127
|
maxResults: z.coerce.number().default(100),
|
|
128
|
+
verboseLogging: z.stringbool().default(false).describe('Enable verbose logging'),
|
|
128
129
|
});
|
|
129
130
|
|
|
130
131
|
let _config: z.infer<typeof ServerConfigSchema> | undefined;
|
|
@@ -132,6 +133,7 @@ export function getServerConfig() {
|
|
|
132
133
|
_config ??= parseEnvConfig(ServerConfigSchema, {
|
|
133
134
|
apiKey: 'MY_API_KEY',
|
|
134
135
|
maxResults: 'MY_MAX_RESULTS',
|
|
136
|
+
verboseLogging: 'MY_VERBOSE_LOGGING',
|
|
135
137
|
});
|
|
136
138
|
return _config;
|
|
137
139
|
}
|
|
@@ -166,13 +168,13 @@ Handlers receive a unified `ctx` object. Key properties:
|
|
|
166
168
|
|
|
167
169
|
| Property | Description |
|
|
168
170
|
|:---------|:------------|
|
|
169
|
-
| `ctx.log` | Request-scoped logger — `.debug()`, `.info()`, `.notice()`, `.warning()`, `.error()`. Auto-correlates requestId, traceId, tenantId. |
|
|
171
|
+
| `ctx.log` | Request-scoped logger — `.debug()`, `.info()`, `.notice()`, `.warning()`, `.error()`. Auto-correlates requestId, traceId, tenantId. Dual-sink: Pino **and** `notifications/message` to the client, so treat it as client-visible. |
|
|
170
172
|
| `ctx.state` | Tenant-scoped KV — `.get(key)`, `.set(key, value, { ttl? })`, `.delete(key)`, `.getMany(keys)`, `.list(prefix, { cursor, limit })`. Accepts any serializable value. |
|
|
171
|
-
| `ctx.
|
|
173
|
+
| `ctx.requestInput` | Suspend and ask the caller for more input — `return ctx.requestInput({ inputRequests: { key: inputRequired.elicit({ message, requestedSchema }) } })`. Never returns; the handler is re-entered with the answers. Always present. |
|
|
174
|
+
| `ctx.inputs` | Reader over a retried request's responses — `.accepted(key, schema)`, `.view(key)`, `.state()`, `.dropped`. Empty on the first round. |
|
|
172
175
|
| `ctx.enrich` | Success-path agent context (empty-result notices, query echo, pagination totals) — `ctx.enrich(...)` or `.notice()` / `.total()` / `.echo()` / `.truncated()`. Reaches `structuredContent` and `content[]`; lands only when the definition declares an `enrichment` block (no-op otherwise). |
|
|
173
176
|
| `ctx.content` | Non-text content blocks — `.image(data, mimeType)`, `.audio(data, mimeType)`, or `ctx.content(block)` for a raw block. Prepended to `content[]` after `format()`; never enters `structuredContent`. |
|
|
174
177
|
| `ctx.signal` | `AbortSignal` for cancellation. |
|
|
175
|
-
| `ctx.progress` | Task progress (present when `task: true`) — `.setTotal(n)`, `.increment()`, `.update(message)`. |
|
|
176
178
|
| `ctx.requestId` | Unique request ID. |
|
|
177
179
|
| `ctx.tenantId` | Tenant ID from JWT; `'default'` for stdio or HTTP with auth off. |
|
|
178
180
|
|
|
@@ -286,7 +288,7 @@ Available skills:
|
|
|
286
288
|
| `api-auth` | Auth modes, scopes, JWT/OAuth |
|
|
287
289
|
| `api-canvas` | DataCanvas: register tabular data, run SQL, export, plus the `spillover()` helper for big result sets — Tier 3 opt-in |
|
|
288
290
|
| `api-config` | AppConfig, parseConfig, env vars |
|
|
289
|
-
| `api-context` | Context interface, logger, state,
|
|
291
|
+
| `api-context` | Context interface, RequestContext, logger, state, multi-round-trip input |
|
|
290
292
|
| `api-errors` | McpError, JsonRpcErrorCode, error patterns |
|
|
291
293
|
| `api-linter` | Definition linter rule catalog — invoked by `bun run lint:mcp` and `devcheck` |
|
|
292
294
|
| `api-mirror` | MirrorService: persistent self-refreshing local mirror (embedded SQLite + FTS5) of a bulk upstream dataset — Tier 3 opt-in |
|
package/Dockerfile
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This stage installs all dependencies (including dev), builds the TypeScript
|
|
5
5
|
# source code into JavaScript, and prepares the production assets.
|
|
6
6
|
# ==============================================================================
|
|
7
|
-
FROM oven/bun:1.
|
|
7
|
+
FROM --platform=$BUILDPLATFORM oven/bun:1.4.0 AS build
|
|
8
8
|
|
|
9
9
|
WORKDIR /usr/src/app
|
|
10
10
|
|
|
@@ -30,7 +30,7 @@ RUN bun run build
|
|
|
30
30
|
# application. It uses a slim base image and only includes production
|
|
31
31
|
# dependencies and build artifacts.
|
|
32
32
|
# ==============================================================================
|
|
33
|
-
FROM oven/bun:1.
|
|
33
|
+
FROM oven/bun:1.4.0-slim AS production
|
|
34
34
|
|
|
35
35
|
WORKDIR /usr/src/app
|
|
36
36
|
|
|
@@ -51,8 +51,13 @@ COPY package.json bun.lock ./
|
|
|
51
51
|
|
|
52
52
|
# Install only production dependencies, ignoring any lifecycle scripts (like 'prepare')
|
|
53
53
|
# that are not needed in the final production image.
|
|
54
|
+
# `--omit=peer` drops the framework's optional peer tiers (test runner, service
|
|
55
|
+
# SDKs, parsers) that Bun would otherwise auto-install. Anything this server
|
|
56
|
+
# actually imports belongs in its own `dependencies`, so nothing needed at
|
|
57
|
+
# runtime is lost. The OTEL step below carries the same flag — without it, that
|
|
58
|
+
# install re-resolves the graph and pulls every optional peer back in.
|
|
54
59
|
RUN --mount=type=cache,target=/root/.bun/install/cache \
|
|
55
|
-
bun install --production --frozen-lockfile --ignore-scripts
|
|
60
|
+
bun install --production --omit=peer --frozen-lockfile --ignore-scripts
|
|
56
61
|
|
|
57
62
|
# Conditionally install OpenTelemetry optional peer dependencies (Tier 3).
|
|
58
63
|
# These are not bundled by default to keep the base image lean. Enable at build time
|
|
@@ -60,7 +65,7 @@ RUN --mount=type=cache,target=/root/.bun/install/cache \
|
|
|
60
65
|
ARG OTEL_ENABLED=true
|
|
61
66
|
RUN --mount=type=cache,target=/root/.bun/install/cache \
|
|
62
67
|
if [ "$OTEL_ENABLED" = "true" ]; then \
|
|
63
|
-
bun add --omit=dev --ignore-scripts @hono/otel \
|
|
68
|
+
bun add --omit=dev --omit=peer --ignore-scripts @hono/otel \
|
|
64
69
|
@opentelemetry/instrumentation-http \
|
|
65
70
|
@opentelemetry/exporter-metrics-otlp-http \
|
|
66
71
|
@opentelemetry/exporter-trace-otlp-http \
|
package/LICENSE
CHANGED
|
@@ -186,7 +186,7 @@ Apache License
|
|
|
186
186
|
same "printed page" as the copyright notice for easier
|
|
187
187
|
identification within third-party archives.
|
|
188
188
|
|
|
189
|
-
Copyright
|
|
189
|
+
Copyright 2026 Casey Hand @cyanheads
|
|
190
190
|
|
|
191
191
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
192
|
you may not use this file except in compliance with the License.
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
<div align="center">
|
|
9
9
|
|
|
10
|
-
[](./CHANGELOG.md) [](./LICENSE) [](https://github.com/users/cyanheads/packages/container/package/cpsc-recalls-mcp-server) [](https://modelcontextprotocol.io/) [](https://www.npmjs.com/package/@cyanheads/cpsc-recalls-mcp-server) [](https://www.typescriptlang.org/) [](https://bun.sh/)
|
|
11
11
|
|
|
12
12
|
</div>
|
|
13
13
|
|
|
@@ -230,6 +230,7 @@ All configuration is validated at startup via Zod schemas. Key environment varia
|
|
|
230
230
|
| `MCP_HTTP_HOST` | HTTP server host | `127.0.0.1` |
|
|
231
231
|
| `MCP_HTTP_ENDPOINT_PATH` | HTTP endpoint path | `/mcp` |
|
|
232
232
|
| `MCP_PUBLIC_URL` | Public origin for TLS-terminating reverse-proxy deployments | — |
|
|
233
|
+
| `MCP_SESSION_MODE` | Session handling: `auto`, `stateful`, or `stateless`. The schema default `auto` resolves to stateful; this server sets `stateless` explicitly. | `stateless` |
|
|
233
234
|
| `MCP_AUTH_MODE` | Authentication: `none`, `jwt`, or `oauth` | `none` |
|
|
234
235
|
| `MCP_LOG_LEVEL` | Log level (`debug`, `info`, `warning`, `error`) | `info` |
|
|
235
236
|
| `LOGS_DIR` | Directory for log files (Node.js only) | `<project-root>/logs` |
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Adopts mcp-ts-core 0.12.3 and MCP SDK v2 — the HTTP endpoint serves protocol revision 2026-07-28 alongside the 2025 era, tool inputs are strict so an undeclared argument key is rejected instead of ignored, and HTTP session mode is now stateless explicitly."
|
|
3
|
+
breaking: false
|
|
4
|
+
security: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 0.1.7 — 2026-08-24
|
|
8
|
+
|
|
9
|
+
## Changed
|
|
10
|
+
|
|
11
|
+
- **Tool inputs are strict.** An argument key none of `cpsc_search_recalls`, `cpsc_get_recall`, or `cpsc_get_recent` declares is rejected by name with a validation error, where it was previously dropped and the call ran without it. A caller sending a misspelled or unsupported parameter now gets a clean error naming the key instead of a silent success.
|
|
12
|
+
- **The HTTP endpoint serves MCP protocol revision `2026-07-28`** alongside the 2025 revisions; a 2025-era client negotiates exactly as before.
|
|
13
|
+
- **HTTP session mode is `stateless` explicitly** — `MCP_SESSION_MODE` is set in `.env.example` and documented in the README config table. The schema default `auto` resolves to stateful, so a source run and the published container previously resolved to different modes; `/.well-known/mcp.json` also reports the resolved mode rather than `auto`.
|
|
14
|
+
- **Advertised schemas moved to JSON Schema 2020-12**, and `outputSchema` now declares the error envelope. A client that rejects draft-07 schemas outright, or that validates `structuredContent` without checking `isError`, no longer fails against these tools.
|
|
15
|
+
- **`ctx.log` output reaches the client** as `notifications/message` at its RFC 5424 level, gated by the client's `logging/setLevel`.
|
|
16
|
+
- **`CpscRecallService.fetchRecalls` passes the handler context straight to `fetchWithTimeout` and `withRetry`** instead of minting a synthetic one, so upstream fetch and retry telemetry carries the calling request's trace, span, and tenant IDs.
|
|
17
|
+
- **Docker: Bun pins move to `1.4.0`** on both stages, the production install drops the framework's optional peer tiers (`--omit=peer`), and the build stage runs on the native platform (`--platform=$BUILDPLATFORM`) rather than under emulation on the amd64 leg.
|
|
18
|
+
- **`tsconfig.json` splits typecheck from emit** — it covers `tests/` alongside `src/` under `noEmit`, while `tsconfig.build.json` carries `rootDir: "src"` for the build. The test suites reach `tsc` for the first time.
|
|
19
|
+
- **`.github/CONTRIBUTING.md` and `CODE_OF_CONDUCT.md`** added, and `SECURITY.md` routes vulnerability reports to `security@caseyjhand.com`.
|
|
20
|
+
- Framework skills, `scripts/`, and `changelog/template.md` re-synced to what mcp-ts-core 0.12.3 ships; the `outdated` allowlist in `devcheck.config.json` is empty again, so every dependency is gated.
|
|
21
|
+
|
|
22
|
+
## Fixed
|
|
23
|
+
|
|
24
|
+
- **The 30s upstream deadline bounds the whole saferproducts.gov exchange**, not just the response headers — a response that stalls mid-body aborts with the same `Timeout` error rather than holding the request open indefinitely.
|
|
25
|
+
- **An over-budget upstream error body is captured from both ends**, so a CPSC diagnostic sitting behind a boilerplate preamble survives into `error.data.body` instead of being truncated away.
|
|
26
|
+
- **Input-validation failures read as flat `path: message` sentences** instead of a serialized `ZodIssue[]` blob, and a call to an unknown tool rejects with `-32602` rather than resolving an error result.
|
|
27
|
+
- **A failure after the handler returns is recorded as a failed call** — output-schema validation, `format()`, and the enrichment merge run inside the measured region, so they produce an ERROR span and an error counter rather than a success.
|
|
28
|
+
- **Stdin EOF runs the full shutdown path before exiting**, so a stdio server whose client hangs up no longer stays resident.
|
|
29
|
+
|
|
30
|
+
## Dependencies
|
|
31
|
+
|
|
32
|
+
- `@cyanheads/mcp-ts-core` `^0.11.0` → `^0.12.3` (nine framework releases; `0.12.0` is the MCP SDK v2 adoption)
|
|
33
|
+
- `@biomejs/biome` `^2.5.5` → `^2.5.10`
|
|
34
|
+
- `@types/node` `^26.1.1` → `^26.2.0`
|
|
35
|
+
- `tsc-alias` `^1.9.1` → `^1.9.2`
|
|
36
|
+
- `vitest` `^4.1.10` → `^4.1.11`
|
|
37
|
+
- `packageManager` `bun@1.3.14` → `bun@1.4.0` (`engines.bun` stays `>=1.3.0`)
|
package/changelog/template.md
CHANGED
|
@@ -4,10 +4,11 @@
|
|
|
4
4
|
# to author a new release. Set that file's H1 to `# <version> — YYYY-MM-DD`
|
|
5
5
|
# with a concrete date.
|
|
6
6
|
|
|
7
|
-
# Required. One-line GitHub Release-style headline. 350 character cap
|
|
8
|
-
# Default short and scannable. Don't pad, don't stitch
|
|
9
|
-
#
|
|
10
|
-
#
|
|
7
|
+
# Required. One-line GitHub Release-style headline. 350 character cap — a
|
|
8
|
+
# ceiling, not a target. Default short and scannable. Don't pad, don't stitch
|
|
9
|
+
# unrelated changes with commas/semicolons into an inventory — pick the
|
|
10
|
+
# headline, like a tag's theme line. Quotes required: unquoted YAML treats
|
|
11
|
+
# `: ` inside the value as a key separator and fails GitHub's strict parser.
|
|
11
12
|
summary: ""
|
|
12
13
|
|
|
13
14
|
# Set `true` when consumers must change code to upgrade: API removals,
|
|
@@ -24,9 +25,10 @@ security: false
|
|
|
24
25
|
|
|
25
26
|
# Optional free-form notes for maintenance agents processing this release.
|
|
26
27
|
# Not rendered in CHANGELOG — consumed by agents running `maintenance` on
|
|
27
|
-
# downstream servers.
|
|
28
|
-
#
|
|
29
|
-
#
|
|
28
|
+
# downstream servers. ADOPTION STEPS ONLY — new files to create, fields to
|
|
29
|
+
# populate, one-time migration steps. Never a second rendering of the body:
|
|
30
|
+
# if a body bullet already says it, name the bullet's symbol instead of
|
|
31
|
+
# re-explaining. Omit the field entirely when there's nothing to say.
|
|
30
32
|
# agent-notes: |
|
|
31
33
|
# <instructions for downstream maintenance agents>
|
|
32
34
|
---
|
|
@@ -41,17 +43,54 @@ security: false
|
|
|
41
43
|
each bullet with the symbol or concept name in **bold** so they can skip
|
|
42
44
|
what's irrelevant and zoom in on what's not.
|
|
43
45
|
|
|
44
|
-
Tone: terse, fact-dense, not verbose.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
46
|
+
Tone: terse, fact-dense, not verbose. Bullet shape: **symbol** + what
|
|
47
|
+
changed + at most one consumer-facing caveat. One sentence by default, two
|
|
48
|
+
when the second carries weight — a bullet past ~40 words or three sentences
|
|
49
|
+
is wrong. The depth lives one hop away: the linked issue carries the why,
|
|
50
|
+
the commit diff carries the how. The changelog names what changed and what
|
|
51
|
+
a consumer does about it; a reader who wants mechanism opens the link.
|
|
52
|
+
|
|
53
|
+
Model length on THIS guide, never on the previous entry — entries modeled
|
|
54
|
+
on entries compound.
|
|
55
|
+
|
|
56
|
+
Cut (each has shipped as a wall of text; these are the cruft):
|
|
57
|
+
- History/justification narration — how the bug worked, why the old
|
|
58
|
+
behavior was wrong. One short clause at most; the issue carries the story.
|
|
59
|
+
- Design-rationale defense — "chosen over Y because…", "guarding the
|
|
60
|
+
getter is not enough…". That is the author arguing with a reviewer;
|
|
61
|
+
reviewers read the PR, not the changelog.
|
|
62
|
+
- Defensive unchanged-clauses — "X is unchanged", "byte-identical to
|
|
63
|
+
<prev>". Keep one only where its absence would cause a real misread,
|
|
64
|
+
as a short parenthetical.
|
|
65
|
+
- Edge-case inventories — marker lists, not-flagged lists, escape tables.
|
|
66
|
+
Tests and the issue carry those.
|
|
67
|
+
- Mechanism walkthroughs (JSDoc, CLAUDE.md/AGENTS.md, or the relevant
|
|
68
|
+
skill own those), ceremonial framings ("This release introduces…"),
|
|
69
|
+
backwards-compat paragraphs, file-by-file test enumerations. Prefer
|
|
70
|
+
code/symbol names over English re-explanations.
|
|
71
|
+
|
|
72
|
+
Verified ≠ included: the every-claim-verified-from-the-diff rule bounds
|
|
73
|
+
the TRUTH of what you write, never the AMOUNT.
|
|
74
|
+
|
|
75
|
+
Example — same fact, right size:
|
|
76
|
+
|
|
77
|
+
TOO LONG: **`fetchWithTimeout`'s `timeoutMs` bounds the whole exchange**
|
|
78
|
+
(#341). `fetch` resolves once headers arrive and the deadline was
|
|
79
|
+
cleared as the helper returned, so a peer that answered promptly and
|
|
80
|
+
then stalled the stream held the request open indefinitely. A 2xx
|
|
81
|
+
carrying a body now comes back as a passthrough wrapper that disarms
|
|
82
|
+
the deadline when the body closes, errors, or is cancelled; …
|
|
83
|
+
[+90 more words of mechanism and edge cases]
|
|
84
|
+
|
|
85
|
+
RIGHT: **`fetchWithTimeout`'s `timeoutMs` now bounds the whole
|
|
86
|
+
exchange, not just the headers** (#341). A stalled body aborts with
|
|
87
|
+
the same `Timeout` error; the returned `Response` is a wrapper, so
|
|
88
|
+
identity assertions (`toBe(response)`) no longer hold.
|
|
52
89
|
|
|
53
90
|
Narrative intro: skip by default. Add one short sentence only when the
|
|
54
|
-
release theme genuinely needs framing the bullets can't carry.
|
|
91
|
+
release theme genuinely needs framing the bullets can't carry. When many
|
|
92
|
+
bullets share one upgrade consequence, state it ONCE — intro line or
|
|
93
|
+
agent-notes — never per bullet.
|
|
55
94
|
|
|
56
95
|
Sections: Keep a Changelog order — Added, Changed, Deprecated, Removed,
|
|
57
96
|
Fixed, Security. Include only sections with entries; delete the rest
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cpsc-recall-service.d.ts","sourceRoot":"","sources":["../../../src/services/cpsc-recall/cpsc-recall-service.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAGtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAsB9D,qBAAa,iBAAiB;IAC5B;;;OAGG;IACH,MAAM,CAAC,MAAM,EAAE,gBAAgB,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAgBnE;IAED;;;OAGG;IACG,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAI/E;IAED;;;OAGG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAGhF;IAED,OAAO,CAAC,QAAQ;IAQhB,OAAO,CAAC,YAAY;
|
|
1
|
+
{"version":3,"file":"cpsc-recall-service.d.ts","sourceRoot":"","sources":["../../../src/services/cpsc-recall/cpsc-recall-service.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAGtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAsB9D,qBAAa,iBAAiB;IAC5B;;;OAGG;IACH,MAAM,CAAC,MAAM,EAAE,gBAAgB,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAgBnE;IAED;;;OAGG;IACG,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAI/E;IAED;;;OAGG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAGhF;IAED,OAAO,CAAC,QAAQ;IAQhB,OAAO,CAAC,YAAY;CA4CrB;AAMD,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED,wBAAgB,oBAAoB,IAAI,iBAAiB,CAKxD"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @module services/cpsc-recall/cpsc-recall-service
|
|
5
5
|
*/
|
|
6
6
|
import { serviceUnavailable } from '@cyanheads/mcp-ts-core/errors';
|
|
7
|
-
import { fetchWithTimeout,
|
|
7
|
+
import { fetchWithTimeout, withRetry } from '@cyanheads/mcp-ts-core/utils';
|
|
8
8
|
const BASE_URL = 'https://www.saferproducts.gov/RestWebServices/Recall';
|
|
9
9
|
/** Request timeout: 30 s. The API returns full datasets; allow enough time. */
|
|
10
10
|
const TIMEOUT_MS = 30_000;
|
|
@@ -72,12 +72,8 @@ export class CpscRecallService {
|
|
|
72
72
|
return `${BASE_URL}?${qs.toString()}`;
|
|
73
73
|
}
|
|
74
74
|
fetchRecalls(url, ctx) {
|
|
75
|
-
const reqCtx = requestContextService.createRequestContext({
|
|
76
|
-
operation: 'CpscRecallService.fetchRecalls',
|
|
77
|
-
requestId: ctx.requestId,
|
|
78
|
-
});
|
|
79
75
|
return withRetry(async () => {
|
|
80
|
-
const response = await fetchWithTimeout(url, TIMEOUT_MS,
|
|
76
|
+
const response = await fetchWithTimeout(url, TIMEOUT_MS, ctx, {
|
|
81
77
|
signal: ctx.signal,
|
|
82
78
|
});
|
|
83
79
|
const text = await response.text();
|
|
@@ -108,7 +104,7 @@ export class CpscRecallService {
|
|
|
108
104
|
return data;
|
|
109
105
|
}, {
|
|
110
106
|
operation: 'CpscRecallService.fetchRecalls',
|
|
111
|
-
context:
|
|
107
|
+
context: ctx,
|
|
112
108
|
baseDelayMs: 500,
|
|
113
109
|
signal: ctx.signal,
|
|
114
110
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cpsc-recall-service.js","sourceRoot":"","sources":["../../../src/services/cpsc-recall/cpsc-recall-service.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,
|
|
1
|
+
{"version":3,"file":"cpsc-recall-service.js","sourceRoot":"","sources":["../../../src/services/cpsc-recall/cpsc-recall-service.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyanheads/cpsc-recalls-mcp-server",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"mcpName": "io.github.cyanheads/cpsc-recalls-mcp-server",
|
|
5
5
|
"description": "Search and retrieve US consumer product recalls from the CPSC (Consumer Product Safety Commission) via MCP. STDIO or Streamable HTTP.",
|
|
6
6
|
"type": "module",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
}
|
|
77
77
|
],
|
|
78
78
|
"license": "Apache-2.0",
|
|
79
|
-
"packageManager": "bun@1.
|
|
79
|
+
"packageManager": "bun@1.4.0",
|
|
80
80
|
"engines": {
|
|
81
81
|
"bun": ">=1.3.0",
|
|
82
82
|
"node": ">=24.0.0"
|
|
@@ -85,18 +85,18 @@
|
|
|
85
85
|
"access": "public"
|
|
86
86
|
},
|
|
87
87
|
"dependencies": {
|
|
88
|
-
"@cyanheads/mcp-ts-core": "^0.
|
|
88
|
+
"@cyanheads/mcp-ts-core": "^0.12.3",
|
|
89
89
|
"pino-pretty": "^13.1.3",
|
|
90
90
|
"zod": "^4.4.3"
|
|
91
91
|
},
|
|
92
92
|
"devDependencies": {
|
|
93
|
-
"@biomejs/biome": "^2.5.
|
|
93
|
+
"@biomejs/biome": "^2.5.10",
|
|
94
94
|
"@socketsecurity/bun-security-scanner": "^1.1.2",
|
|
95
|
-
"@types/node": "^26.
|
|
95
|
+
"@types/node": "^26.2.0",
|
|
96
96
|
"depcheck": "^1.4.7",
|
|
97
97
|
"ignore": "^7.0.6",
|
|
98
|
-
"tsc-alias": "^1.9.
|
|
98
|
+
"tsc-alias": "^1.9.2",
|
|
99
99
|
"typescript": "^7.0.2",
|
|
100
|
-
"vitest": "^4.1.
|
|
100
|
+
"vitest": "^4.1.11"
|
|
101
101
|
}
|
|
102
102
|
}
|
package/server.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"url": "https://github.com/cyanheads/cpsc-recalls-mcp-server",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "0.1.
|
|
9
|
+
"version": "0.1.7",
|
|
10
10
|
"remotes": [
|
|
11
11
|
{
|
|
12
12
|
"type": "streamable-http",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"registryBaseUrl": "https://registry.npmjs.org",
|
|
20
20
|
"identifier": "@cyanheads/cpsc-recalls-mcp-server",
|
|
21
21
|
"runtimeHint": "bun",
|
|
22
|
-
"version": "0.1.
|
|
22
|
+
"version": "0.1.7",
|
|
23
23
|
"packageArguments": [
|
|
24
24
|
{
|
|
25
25
|
"type": "positional",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"registryBaseUrl": "https://registry.npmjs.org",
|
|
49
49
|
"identifier": "@cyanheads/cpsc-recalls-mcp-server",
|
|
50
50
|
"runtimeHint": "bun",
|
|
51
|
-
"version": "0.1.
|
|
51
|
+
"version": "0.1.7",
|
|
52
52
|
"packageArguments": [
|
|
53
53
|
{
|
|
54
54
|
"type": "positional",
|