@cyanheads/federal-regulations-mcp-server 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/AGENTS.md +34 -31
  2. package/CLAUDE.md +34 -31
  3. package/Dockerfile +11 -7
  4. package/LICENSE +1 -1
  5. package/README.md +9 -5
  6. package/changelog/0.1.x/0.1.3.md +40 -0
  7. package/changelog/template.md +5 -3
  8. package/dist/mcp-server/tools/definitions/browse-cfr.tool.d.ts +10 -7
  9. package/dist/mcp-server/tools/definitions/browse-cfr.tool.d.ts.map +1 -1
  10. package/dist/mcp-server/tools/definitions/browse-cfr.tool.js +71 -31
  11. package/dist/mcp-server/tools/definitions/browse-cfr.tool.js.map +1 -1
  12. package/dist/mcp-server/tools/definitions/find-comments.tool.d.ts +1 -1
  13. package/dist/mcp-server/tools/definitions/get-cfr-section.tool.d.ts +1 -1
  14. package/dist/mcp-server/tools/definitions/get-docket.tool.d.ts +2 -2
  15. package/dist/mcp-server/tools/definitions/index.d.ts +182 -191
  16. package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -1
  17. package/dist/mcp-server/tools/definitions/list-open-comments.tool.d.ts +0 -5
  18. package/dist/mcp-server/tools/definitions/list-open-comments.tool.d.ts.map +1 -1
  19. package/dist/mcp-server/tools/definitions/list-open-comments.tool.js +0 -6
  20. package/dist/mcp-server/tools/definitions/list-open-comments.tool.js.map +1 -1
  21. package/dist/mcp-server/tools/definitions/search-rules.tool.d.ts +2 -7
  22. package/dist/mcp-server/tools/definitions/search-rules.tool.d.ts.map +1 -1
  23. package/dist/mcp-server/tools/definitions/search-rules.tool.js +0 -6
  24. package/dist/mcp-server/tools/definitions/search-rules.tool.js.map +1 -1
  25. package/dist/services/ecfr/ecfr-service.d.ts +18 -2
  26. package/dist/services/ecfr/ecfr-service.d.ts.map +1 -1
  27. package/dist/services/ecfr/ecfr-service.js +126 -19
  28. package/dist/services/ecfr/ecfr-service.js.map +1 -1
  29. package/dist/services/ecfr/types.d.ts +30 -19
  30. package/dist/services/ecfr/types.d.ts.map +1 -1
  31. package/dist/services/ecfr-mirror/ecfr-mirror.d.ts +32 -6
  32. package/dist/services/ecfr-mirror/ecfr-mirror.d.ts.map +1 -1
  33. package/dist/services/ecfr-mirror/ecfr-mirror.js +75 -7
  34. package/dist/services/ecfr-mirror/ecfr-mirror.js.map +1 -1
  35. package/dist/services/federal-register/federal-register-service.d.ts.map +1 -1
  36. package/dist/services/federal-register/federal-register-service.js +6 -3
  37. package/dist/services/federal-register/federal-register-service.js.map +1 -1
  38. package/dist/services/regulations-gov/regulations-gov-service.d.ts.map +1 -1
  39. package/package.json +20 -9
  40. package/scripts/_mirror-context.ts +16 -14
  41. package/scripts/ecfr-mirror-verify.ts +13 -3
  42. package/server.json +3 -3
package/AGENTS.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Developer Protocol
2
2
 
3
3
  **Server:** federal-regulations-mcp-server
4
- **Version:** 0.1.2
5
- **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.10.9`
4
+ **Version:** 0.1.3
5
+ **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.11.1`
6
6
  **Engines:** Bun ≥1.3.0, Node ≥24.0.0
7
- **MCP SDK:** `@modelcontextprotocol/sdk` ^1.29.0
7
+ **MCP SDK:** `@modelcontextprotocol/sdk` ^1.30.0
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.
@@ -150,12 +150,14 @@ Handlers receive a unified `ctx` object. Key properties:
150
150
  | Property | Description |
151
151
  |:---------|:------------|
152
152
  | `ctx.log` | Request-scoped logger — `.debug()`, `.info()`, `.notice()`, `.warning()`, `.error()`. Auto-correlates requestId, traceId, tenantId. |
153
- | `ctx.state` | Tenant-scoped KV — `.get(key)`, `.set(key, value, { ttl? })`, `.delete(key)`, `.list(prefix, { cursor, limit })`. Accepts any serializable value. |
153
+ | `ctx.state` | Tenant-scoped KV — `.get(key)`, `.set(key, value, { ttl? })`, `.delete(key)`, `.getMany(keys)`, `.list(prefix, { cursor, limit })`. Accepts any serializable value. |
154
154
  | `ctx.elicit` | Ask user for structured input — form call `(message, schema)` or `.url(message, url)` for an external link. **Check for presence first:** `if (ctx.elicit) { ... }` |
155
+ | `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). |
156
+ | `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`. |
155
157
  | `ctx.signal` | `AbortSignal` for cancellation. |
156
158
  | `ctx.progress` | Task progress (present when `task: true`) — `.setTotal(n)`, `.increment()`, `.update(message)`. |
157
159
  | `ctx.requestId` | Unique request ID. |
158
- | `ctx.tenantId` | Tenant ID from JWT or `'default'` for stdio. |
160
+ | `ctx.tenantId` | Tenant ID from JWT; `'default'` for stdio or HTTP with auth off. |
159
161
 
160
162
  ---
161
163
 
@@ -163,7 +165,7 @@ Handlers receive a unified `ctx` object. Key properties:
163
165
 
164
166
  Handlers throw — the framework catches, classifies, and formats.
165
167
 
166
- **Recommended: typed error contract.** Declare `errors: [{ reason, code, when, recovery, retryable? }]` on `tool()` / `resource()` to receive `ctx.fail(reason, …)` typed against the reason union. TypeScript catches typos at compile time, `data.reason` is auto-populated for observability, linter enforces conformance against the handler body. `recovery` is required descriptive metadata for the agent's next move (≥ 5 words, lint-validated); for the wire `data.recovery.hint` (mirrored into `content[]` text), pass explicitly at the throw site when dynamic context matters: `ctx.fail('reason', msg, { recovery: { hint: '...' } })`. Baseline codes (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`) bubble freely and don't need declaring.
168
+ **Recommended: typed error contract.** Declare `errors: [{ reason, code, when, recovery, retryable? }]` on `tool()` / `resource()` to receive `ctx.fail(reason, …)` typed against the reason union. TypeScript catches typos at compile time, `data.reason` is auto-populated for observability, linter enforces conformance against the handler body. `recovery` is required (≥ 5 words, lint-validated) — the single source of truth for the agent's next move. Pass `ctx.recoveryFor('reason')` as the throw's data to put it on the wire (`data.recovery.hint`, mirrored into `content[]` text); override with an explicit `{ recovery: { hint: '...' } }` when dynamic runtime context matters. Baseline codes (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`) bubble freely and don't need declaring.
167
169
 
168
170
  ```ts
169
171
  import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
@@ -175,7 +177,7 @@ errors: [
175
177
  ],
176
178
  async handler(input, ctx) {
177
179
  const item = await db.find(input.id);
178
- if (!item) throw ctx.fail('no_match', `No item ${input.id}`);
180
+ if (!item) throw ctx.fail('no_match', `No item ${input.id}`, ctx.recoveryFor('no_match'));
179
181
  return item;
180
182
  }
181
183
  ```
@@ -243,7 +245,7 @@ No prompts in v1 — `createApp({ prompts: [] })`.
243
245
 
244
246
  ## Skills
245
247
 
246
- Skills are modular instructions in `skills/` at the project root. Read them directly when a task matches — e.g., `skills/add-tool/SKILL.md` when adding a tool.
248
+ Skills are modular instructions in `skills/` at the project root. Read them directly when a task matches — e.g., `skills/add-tool/SKILL.md` when adding a tool. `bun run list-skills` prints the full registry.
247
249
 
248
250
  **Agent skill directory:** Copy skills into the directory your agent discovers (Claude Code: `.claude/skills/`, others: equivalent). Skills then load as context without referencing `skills/` paths. After framework updates, run the `maintenance` skill — Phase B re-syncs the agent directory.
249
251
 
@@ -263,7 +265,6 @@ Available skills:
263
265
  | `tool-defs-analysis` | Read-only audit of MCP definition language across the surface — voice, leaks, defaults, recovery hints, output descriptions |
264
266
  | `security-pass` | Audit server for MCP-flavored security gaps: output injection, scope blast radius, input sinks, tenant isolation |
265
267
  | `code-simplifier` | Post-session cleanup against `git diff` — modernize syntax, consolidate duplication, align with the codebase |
266
- | `devcheck` | Lint, format, typecheck, audit |
267
268
  | `polish-docs-meta` | Finalize docs, README, metadata, and agent protocol for shipping |
268
269
  | `git-wrapup` | Land working-tree changes as a versioned commit + annotated tag — version bump, changelog, verify, tag. Local only. |
269
270
  | `release-and-publish` | Push + npm + MCP Registry + GH Release + Docker. Picks up from `git-wrapup` |
@@ -271,12 +272,14 @@ Available skills:
271
272
  | `orchestrations` | Chain task skills into a gated multi-phase pipeline — build-out, QA-fix, update-ship — when you can spawn sub-agents |
272
273
  | `report-issue-framework` | File a bug or feature request against `@cyanheads/mcp-ts-core` via `gh` CLI |
273
274
  | `report-issue-local` | File a bug or feature request against this server's own repo via `gh` CLI |
275
+ | `techniques` | Catalog of response/data-shaping techniques — overflow handling, payload shaping, retrieval patterns |
274
276
  | `api-auth` | Auth modes, scopes, JWT/OAuth |
275
277
  | `api-canvas` | DataCanvas: register tabular data, run SQL, export, plus the `spillover()` helper for big result sets — Tier 3 opt-in |
276
278
  | `api-config` | AppConfig, parseConfig, env vars |
277
279
  | `api-context` | Context interface, logger, state, progress |
278
280
  | `api-errors` | McpError, JsonRpcErrorCode, error patterns |
279
281
  | `api-linter` | Definition linter rule catalog — invoked by `bun run lint:mcp` and `devcheck` |
282
+ | `api-mirror` | MirrorService: persistent self-refreshing local mirror (embedded SQLite + FTS5) of a bulk upstream dataset — Tier 3 opt-in |
280
283
  | `api-services` | LLM, Speech, Graph services |
281
284
  | `api-testing` | createMockContext, test patterns |
282
285
  | `api-utils` | Formatting, parsing, security, pagination, scheduling, telemetry helpers |
@@ -295,32 +298,32 @@ When you complete a skill's checklist, check the boxes and add a completion time
295
298
 
296
299
  | Command | Purpose |
297
300
  |:--------|:--------|
298
- | `npm run build` | Compile TypeScript |
299
- | `npm run rebuild` | Clean + build |
300
- | `npm run clean` | Remove build artifacts |
301
- | `npm run devcheck` | Lint + format + typecheck + security + changelog sync |
301
+ | `bun run build` | Compile TypeScript |
302
+ | `bun run rebuild` | Clean + build |
303
+ | `bun run clean` | Remove build artifacts |
304
+ | `bun run devcheck` | Lint + format + typecheck + security + changelog sync |
302
305
  | `bun run audit:refresh` | Delete `bun.lock`, reinstall, and re-run `bun audit`. Use when `devcheck` flags a transitive advisory — Bun's `update` is sticky on transitive resolutions, so the advisory may be a stale-lockfile false positive. If it survives the refresh, it's real. |
303
- | `npm run tree` | Generate directory structure doc |
304
- | `npm run format` | Auto-fix formatting (safe fixes only) |
305
- | `npm run format:unsafe` | Also apply Biome's unsafe autofixes — review the diff; they can change behavior |
306
- | `npm test` | Run tests |
307
- | `npm run start:stdio` | Production mode (stdio) |
308
- | `npm run start:http` | Production mode (HTTP) |
309
- | `npm run changelog:build` | Regenerate `CHANGELOG.md` from `changelog/*.md` |
310
- | `npm run changelog:check` | Verify `CHANGELOG.md` is in sync (used by devcheck) |
311
- | `npm run bundle` | Build, pack, and clean a `.mcpb` for one-click Claude Desktop install |
312
- | `npm run lint:mcp` | Validate MCP tool/resource definitions against the linter rule catalog |
313
- | `npm run lint:packaging` | Verify `server.json` ↔ `manifest.json` env var names match (used by devcheck) |
314
- | `npm run mirror:init` | Build the eCFR codified-text mirror (out-of-band, idempotent, resumable). Scope with `ECFR_MIRROR_TITLES`. |
315
- | `npm run mirror:refresh` | Incremental refresh of the eCFR mirror against the latest eCFR issues |
316
- | `npm run mirror:verify` | Report mirror row counts and the last-synced issue date |
317
- | `npm run list-skills` | List the project skills and their paths |
306
+ | `bun run lint:mcp` | Run the MCP definition linter standalone (rule catalog: `api-linter` skill) |
307
+ | `bun run lint:packaging` | Packaging surface checks — `server.json`/`manifest.json` env-var parity (run by devcheck) |
308
+ | `bun run list-skills` | Print the skill registry |
309
+ | `bun run tree` | Generate directory structure doc |
310
+ | `bun run format` | Auto-fix formatting (safe fixes only) |
311
+ | `bun run format:unsafe` | Also apply Biome's unsafe autofixes — review the diff; they can change behavior |
312
+ | `bun run test` | Run tests (Vitest — use `bun run test`, not `bun test`) |
313
+ | `bun run start:stdio` | Production mode (stdio) |
314
+ | `bun run start:http` | Production mode (HTTP) |
315
+ | `bun run changelog:build` | Regenerate `CHANGELOG.md` from `changelog/*.md` |
316
+ | `bun run changelog:check` | Verify `CHANGELOG.md` is in sync (used by devcheck) |
317
+ | `bun run bundle` | Build, pack, and clean a `.mcpb` for one-click Claude Desktop install |
318
+ | `bun run mirror:init` | Build the eCFR codified-text mirror (out-of-band, idempotent, resumable). Scope with `ECFR_MIRROR_TITLES`. |
319
+ | `bun run mirror:refresh` | Incremental refresh of the eCFR mirror against the latest eCFR issues |
320
+ | `bun run mirror:verify` | Report mirror row counts and the last-synced issue date |
318
321
 
319
322
  ---
320
323
 
321
324
  ## Bundling
322
325
 
323
- `npm run bundle` produces a `.mcpb` extension bundle for one-click install in Claude Desktop. The pack step is followed by `scripts/clean-mcpb.ts`, which prunes dev dependencies (`mcpb clean`) and strips dependency-shipped agent docs (`node_modules/**` `skills/`, `.claude/`, `.agents/`, `SKILL.md`) that root-anchored `.mcpbignore` patterns cannot reach. MCPB is stdio-only — HTTP and Cloudflare Workers deployments are unaffected. Consumers who don't need it can delete `manifest.json` and `.mcpbignore`; `lint:packaging` skips cleanly.
326
+ `npm run bundle` produces a `.mcpb` extension bundle for one-click install in Claude Desktop. The pack step is followed by `scripts/clean-mcpb.ts`, which prunes dev dependencies (`mcpb clean`) and strips two classes of `node_modules/**` content that root-anchored `.mcpbignore` patterns cannot reach: dependency-shipped agent docs (`skills/`, `.claude/`, `.agents/`, `SKILL.md`) and platform-specific native bindings, which would otherwise lock the bundle to the platform it was packed on. A server using DataCanvas therefore ships a portable bundle without the DuckDB native — `@duckdb/node-api` is an optional peer loaded lazily, so canvas tools report an actionable install hint and every other tool works normally. MCPB is stdio-only — HTTP and Cloudflare Workers deployments are unaffected. Consumers who don't need it can delete `manifest.json` and `.mcpbignore`; `lint:packaging` skips cleanly.
324
327
 
325
328
  **Adding an env var requires both files:** `server.json` (registry discovery, `environmentVariables[]`) and `manifest.json` (bundle install UX, `mcp_config.env` + `user_config`). `lint:packaging` (run by `devcheck`) verifies the env var names match.
326
329
 
@@ -338,14 +341,14 @@ Each per-version file opens with YAML frontmatter:
338
341
  ---
339
342
  summary: "One-line headline, ≤350 chars" # required — powers the rollup index
340
343
  breaking: false # optional — true flags breaking changes
341
- security: false # optional — true flags security fixes
344
+ security: false # optional — true ONLY for a source-code security fix, never a dependency CVE bump
342
345
  ---
343
346
 
344
347
  # 0.1.0 — YYYY-MM-DD
345
348
  ...
346
349
  ```
347
350
 
348
- `breaking: true` renders a `· ⚠️ Breaking` badge — use it when consumers must update code on upgrade (signature changes, removed APIs, config renames). `security: true` renders a `· 🛡️ Security` badge and pairs with a `## Security` body section. When both are set, badges render `· ⚠️ Breaking · 🛡️ Security`.
351
+ `breaking: true` renders a `· ⚠️ Breaking` badge — use it when consumers must update code on upgrade (signature changes, removed APIs, config renames). `security: true` renders a `· 🛡️ Security` badge and pairs with a `## Security` body section — set it only for a security fix in this server's *own source code*, never for a routine dependency or transitive CVE bump (record those under `## Dependencies`). When both are set, badges render `· ⚠️ Breaking · 🛡️ Security`.
349
352
 
350
353
  `agent-notes` is an optional free-form field for maintenance agents processing the release downstream. Content here won't appear in the rendered CHANGELOG — it's consumed by agents running the `maintenance` skill. Use it for adoption instructions that don't fit the human-facing sections: new files to create, fields to populate, one-time migration steps. Omit entirely when there's nothing to say.
351
354
 
package/CLAUDE.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Developer Protocol
2
2
 
3
3
  **Server:** federal-regulations-mcp-server
4
- **Version:** 0.1.2
5
- **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.10.9`
4
+ **Version:** 0.1.3
5
+ **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.11.1`
6
6
  **Engines:** Bun ≥1.3.0, Node ≥24.0.0
7
- **MCP SDK:** `@modelcontextprotocol/sdk` ^1.29.0
7
+ **MCP SDK:** `@modelcontextprotocol/sdk` ^1.30.0
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.
@@ -150,12 +150,14 @@ Handlers receive a unified `ctx` object. Key properties:
150
150
  | Property | Description |
151
151
  |:---------|:------------|
152
152
  | `ctx.log` | Request-scoped logger — `.debug()`, `.info()`, `.notice()`, `.warning()`, `.error()`. Auto-correlates requestId, traceId, tenantId. |
153
- | `ctx.state` | Tenant-scoped KV — `.get(key)`, `.set(key, value, { ttl? })`, `.delete(key)`, `.list(prefix, { cursor, limit })`. Accepts any serializable value. |
153
+ | `ctx.state` | Tenant-scoped KV — `.get(key)`, `.set(key, value, { ttl? })`, `.delete(key)`, `.getMany(keys)`, `.list(prefix, { cursor, limit })`. Accepts any serializable value. |
154
154
  | `ctx.elicit` | Ask user for structured input — form call `(message, schema)` or `.url(message, url)` for an external link. **Check for presence first:** `if (ctx.elicit) { ... }` |
155
+ | `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). |
156
+ | `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`. |
155
157
  | `ctx.signal` | `AbortSignal` for cancellation. |
156
158
  | `ctx.progress` | Task progress (present when `task: true`) — `.setTotal(n)`, `.increment()`, `.update(message)`. |
157
159
  | `ctx.requestId` | Unique request ID. |
158
- | `ctx.tenantId` | Tenant ID from JWT or `'default'` for stdio. |
160
+ | `ctx.tenantId` | Tenant ID from JWT; `'default'` for stdio or HTTP with auth off. |
159
161
 
160
162
  ---
161
163
 
@@ -163,7 +165,7 @@ Handlers receive a unified `ctx` object. Key properties:
163
165
 
164
166
  Handlers throw — the framework catches, classifies, and formats.
165
167
 
166
- **Recommended: typed error contract.** Declare `errors: [{ reason, code, when, recovery, retryable? }]` on `tool()` / `resource()` to receive `ctx.fail(reason, …)` typed against the reason union. TypeScript catches typos at compile time, `data.reason` is auto-populated for observability, linter enforces conformance against the handler body. `recovery` is required descriptive metadata for the agent's next move (≥ 5 words, lint-validated); for the wire `data.recovery.hint` (mirrored into `content[]` text), pass explicitly at the throw site when dynamic context matters: `ctx.fail('reason', msg, { recovery: { hint: '...' } })`. Baseline codes (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`) bubble freely and don't need declaring.
168
+ **Recommended: typed error contract.** Declare `errors: [{ reason, code, when, recovery, retryable? }]` on `tool()` / `resource()` to receive `ctx.fail(reason, …)` typed against the reason union. TypeScript catches typos at compile time, `data.reason` is auto-populated for observability, linter enforces conformance against the handler body. `recovery` is required (≥ 5 words, lint-validated) — the single source of truth for the agent's next move. Pass `ctx.recoveryFor('reason')` as the throw's data to put it on the wire (`data.recovery.hint`, mirrored into `content[]` text); override with an explicit `{ recovery: { hint: '...' } }` when dynamic runtime context matters. Baseline codes (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`) bubble freely and don't need declaring.
167
169
 
168
170
  ```ts
169
171
  import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
@@ -175,7 +177,7 @@ errors: [
175
177
  ],
176
178
  async handler(input, ctx) {
177
179
  const item = await db.find(input.id);
178
- if (!item) throw ctx.fail('no_match', `No item ${input.id}`);
180
+ if (!item) throw ctx.fail('no_match', `No item ${input.id}`, ctx.recoveryFor('no_match'));
179
181
  return item;
180
182
  }
181
183
  ```
@@ -243,7 +245,7 @@ No prompts in v1 — `createApp({ prompts: [] })`.
243
245
 
244
246
  ## Skills
245
247
 
246
- Skills are modular instructions in `skills/` at the project root. Read them directly when a task matches — e.g., `skills/add-tool/SKILL.md` when adding a tool.
248
+ Skills are modular instructions in `skills/` at the project root. Read them directly when a task matches — e.g., `skills/add-tool/SKILL.md` when adding a tool. `bun run list-skills` prints the full registry.
247
249
 
248
250
  **Agent skill directory:** Copy skills into the directory your agent discovers (Claude Code: `.claude/skills/`, others: equivalent). Skills then load as context without referencing `skills/` paths. After framework updates, run the `maintenance` skill — Phase B re-syncs the agent directory.
249
251
 
@@ -263,7 +265,6 @@ Available skills:
263
265
  | `tool-defs-analysis` | Read-only audit of MCP definition language across the surface — voice, leaks, defaults, recovery hints, output descriptions |
264
266
  | `security-pass` | Audit server for MCP-flavored security gaps: output injection, scope blast radius, input sinks, tenant isolation |
265
267
  | `code-simplifier` | Post-session cleanup against `git diff` — modernize syntax, consolidate duplication, align with the codebase |
266
- | `devcheck` | Lint, format, typecheck, audit |
267
268
  | `polish-docs-meta` | Finalize docs, README, metadata, and agent protocol for shipping |
268
269
  | `git-wrapup` | Land working-tree changes as a versioned commit + annotated tag — version bump, changelog, verify, tag. Local only. |
269
270
  | `release-and-publish` | Push + npm + MCP Registry + GH Release + Docker. Picks up from `git-wrapup` |
@@ -271,12 +272,14 @@ Available skills:
271
272
  | `orchestrations` | Chain task skills into a gated multi-phase pipeline — build-out, QA-fix, update-ship — when you can spawn sub-agents |
272
273
  | `report-issue-framework` | File a bug or feature request against `@cyanheads/mcp-ts-core` via `gh` CLI |
273
274
  | `report-issue-local` | File a bug or feature request against this server's own repo via `gh` CLI |
275
+ | `techniques` | Catalog of response/data-shaping techniques — overflow handling, payload shaping, retrieval patterns |
274
276
  | `api-auth` | Auth modes, scopes, JWT/OAuth |
275
277
  | `api-canvas` | DataCanvas: register tabular data, run SQL, export, plus the `spillover()` helper for big result sets — Tier 3 opt-in |
276
278
  | `api-config` | AppConfig, parseConfig, env vars |
277
279
  | `api-context` | Context interface, logger, state, progress |
278
280
  | `api-errors` | McpError, JsonRpcErrorCode, error patterns |
279
281
  | `api-linter` | Definition linter rule catalog — invoked by `bun run lint:mcp` and `devcheck` |
282
+ | `api-mirror` | MirrorService: persistent self-refreshing local mirror (embedded SQLite + FTS5) of a bulk upstream dataset — Tier 3 opt-in |
280
283
  | `api-services` | LLM, Speech, Graph services |
281
284
  | `api-testing` | createMockContext, test patterns |
282
285
  | `api-utils` | Formatting, parsing, security, pagination, scheduling, telemetry helpers |
@@ -295,32 +298,32 @@ When you complete a skill's checklist, check the boxes and add a completion time
295
298
 
296
299
  | Command | Purpose |
297
300
  |:--------|:--------|
298
- | `npm run build` | Compile TypeScript |
299
- | `npm run rebuild` | Clean + build |
300
- | `npm run clean` | Remove build artifacts |
301
- | `npm run devcheck` | Lint + format + typecheck + security + changelog sync |
301
+ | `bun run build` | Compile TypeScript |
302
+ | `bun run rebuild` | Clean + build |
303
+ | `bun run clean` | Remove build artifacts |
304
+ | `bun run devcheck` | Lint + format + typecheck + security + changelog sync |
302
305
  | `bun run audit:refresh` | Delete `bun.lock`, reinstall, and re-run `bun audit`. Use when `devcheck` flags a transitive advisory — Bun's `update` is sticky on transitive resolutions, so the advisory may be a stale-lockfile false positive. If it survives the refresh, it's real. |
303
- | `npm run tree` | Generate directory structure doc |
304
- | `npm run format` | Auto-fix formatting (safe fixes only) |
305
- | `npm run format:unsafe` | Also apply Biome's unsafe autofixes — review the diff; they can change behavior |
306
- | `npm test` | Run tests |
307
- | `npm run start:stdio` | Production mode (stdio) |
308
- | `npm run start:http` | Production mode (HTTP) |
309
- | `npm run changelog:build` | Regenerate `CHANGELOG.md` from `changelog/*.md` |
310
- | `npm run changelog:check` | Verify `CHANGELOG.md` is in sync (used by devcheck) |
311
- | `npm run bundle` | Build, pack, and clean a `.mcpb` for one-click Claude Desktop install |
312
- | `npm run lint:mcp` | Validate MCP tool/resource definitions against the linter rule catalog |
313
- | `npm run lint:packaging` | Verify `server.json` ↔ `manifest.json` env var names match (used by devcheck) |
314
- | `npm run mirror:init` | Build the eCFR codified-text mirror (out-of-band, idempotent, resumable). Scope with `ECFR_MIRROR_TITLES`. |
315
- | `npm run mirror:refresh` | Incremental refresh of the eCFR mirror against the latest eCFR issues |
316
- | `npm run mirror:verify` | Report mirror row counts and the last-synced issue date |
317
- | `npm run list-skills` | List the project skills and their paths |
306
+ | `bun run lint:mcp` | Run the MCP definition linter standalone (rule catalog: `api-linter` skill) |
307
+ | `bun run lint:packaging` | Packaging surface checks — `server.json`/`manifest.json` env-var parity (run by devcheck) |
308
+ | `bun run list-skills` | Print the skill registry |
309
+ | `bun run tree` | Generate directory structure doc |
310
+ | `bun run format` | Auto-fix formatting (safe fixes only) |
311
+ | `bun run format:unsafe` | Also apply Biome's unsafe autofixes — review the diff; they can change behavior |
312
+ | `bun run test` | Run tests (Vitest — use `bun run test`, not `bun test`) |
313
+ | `bun run start:stdio` | Production mode (stdio) |
314
+ | `bun run start:http` | Production mode (HTTP) |
315
+ | `bun run changelog:build` | Regenerate `CHANGELOG.md` from `changelog/*.md` |
316
+ | `bun run changelog:check` | Verify `CHANGELOG.md` is in sync (used by devcheck) |
317
+ | `bun run bundle` | Build, pack, and clean a `.mcpb` for one-click Claude Desktop install |
318
+ | `bun run mirror:init` | Build the eCFR codified-text mirror (out-of-band, idempotent, resumable). Scope with `ECFR_MIRROR_TITLES`. |
319
+ | `bun run mirror:refresh` | Incremental refresh of the eCFR mirror against the latest eCFR issues |
320
+ | `bun run mirror:verify` | Report mirror row counts and the last-synced issue date |
318
321
 
319
322
  ---
320
323
 
321
324
  ## Bundling
322
325
 
323
- `npm run bundle` produces a `.mcpb` extension bundle for one-click install in Claude Desktop. The pack step is followed by `scripts/clean-mcpb.ts`, which prunes dev dependencies (`mcpb clean`) and strips dependency-shipped agent docs (`node_modules/**` `skills/`, `.claude/`, `.agents/`, `SKILL.md`) that root-anchored `.mcpbignore` patterns cannot reach. MCPB is stdio-only — HTTP and Cloudflare Workers deployments are unaffected. Consumers who don't need it can delete `manifest.json` and `.mcpbignore`; `lint:packaging` skips cleanly.
326
+ `npm run bundle` produces a `.mcpb` extension bundle for one-click install in Claude Desktop. The pack step is followed by `scripts/clean-mcpb.ts`, which prunes dev dependencies (`mcpb clean`) and strips two classes of `node_modules/**` content that root-anchored `.mcpbignore` patterns cannot reach: dependency-shipped agent docs (`skills/`, `.claude/`, `.agents/`, `SKILL.md`) and platform-specific native bindings, which would otherwise lock the bundle to the platform it was packed on. A server using DataCanvas therefore ships a portable bundle without the DuckDB native — `@duckdb/node-api` is an optional peer loaded lazily, so canvas tools report an actionable install hint and every other tool works normally. MCPB is stdio-only — HTTP and Cloudflare Workers deployments are unaffected. Consumers who don't need it can delete `manifest.json` and `.mcpbignore`; `lint:packaging` skips cleanly.
324
327
 
325
328
  **Adding an env var requires both files:** `server.json` (registry discovery, `environmentVariables[]`) and `manifest.json` (bundle install UX, `mcp_config.env` + `user_config`). `lint:packaging` (run by `devcheck`) verifies the env var names match.
326
329
 
@@ -338,14 +341,14 @@ Each per-version file opens with YAML frontmatter:
338
341
  ---
339
342
  summary: "One-line headline, ≤350 chars" # required — powers the rollup index
340
343
  breaking: false # optional — true flags breaking changes
341
- security: false # optional — true flags security fixes
344
+ security: false # optional — true ONLY for a source-code security fix, never a dependency CVE bump
342
345
  ---
343
346
 
344
347
  # 0.1.0 — YYYY-MM-DD
345
348
  ...
346
349
  ```
347
350
 
348
- `breaking: true` renders a `· ⚠️ Breaking` badge — use it when consumers must update code on upgrade (signature changes, removed APIs, config renames). `security: true` renders a `· 🛡️ Security` badge and pairs with a `## Security` body section. When both are set, badges render `· ⚠️ Breaking · 🛡️ Security`.
351
+ `breaking: true` renders a `· ⚠️ Breaking` badge — use it when consumers must update code on upgrade (signature changes, removed APIs, config renames). `security: true` renders a `· 🛡️ Security` badge and pairs with a `## Security` body section — set it only for a security fix in this server's *own source code*, never for a routine dependency or transitive CVE bump (record those under `## Dependencies`). When both are set, badges render `· ⚠️ Breaking · 🛡️ Security`.
349
352
 
350
353
  `agent-notes` is an optional free-form field for maintenance agents processing the release downstream. Content here won't appear in the rendered CHANGELOG — it's consumed by agents running the `maintenance` skill. Use it for adoption instructions that don't fit the human-facing sections: new files to create, fields to populate, one-time migration steps. Omit entirely when there's nothing to say.
351
354
 
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.3 AS build
7
+ FROM oven/bun:1.3.14 AS build
8
8
 
9
9
  WORKDIR /usr/src/app
10
10
 
@@ -15,8 +15,10 @@ COPY package.json bun.lock ./
15
15
  # lifecycle scripts: better-sqlite3's native gyp compile breaks under the bun
16
16
  # base image, and it is never loaded at runtime (Bun's built-in bun:sqlite
17
17
  # drives the mirror reads; the build-time ingest path resolves it on a real
18
- # Node host, not in this image).
19
- RUN bun install --frozen-lockfile --ignore-scripts
18
+ # Node host, not in this image). The BuildKit cache mount persists Bun's global
19
+ # package cache across builds.
20
+ RUN --mount=type=cache,target=/root/.bun/install/cache \
21
+ bun install --frozen-lockfile --ignore-scripts
20
22
 
21
23
  # Copy the rest of the source code
22
24
  COPY . .
@@ -32,7 +34,7 @@ RUN bun run build
32
34
  # application. It uses a slim base image and only includes production
33
35
  # dependencies and build artifacts.
34
36
  # ==============================================================================
35
- FROM oven/bun:1.3-slim AS production
37
+ FROM oven/bun:1.3.14-slim AS production
36
38
 
37
39
  WORKDIR /usr/src/app
38
40
 
@@ -53,14 +55,16 @@ COPY package.json bun.lock ./
53
55
 
54
56
  # Install only production dependencies, ignoring any lifecycle scripts (like 'prepare')
55
57
  # that are not needed in the final production image.
56
- RUN bun install --production --frozen-lockfile --ignore-scripts
58
+ RUN --mount=type=cache,target=/root/.bun/install/cache \
59
+ bun install --production --frozen-lockfile --ignore-scripts
57
60
 
58
61
  # Conditionally install OpenTelemetry optional peer dependencies (Tier 3).
59
62
  # These are not bundled by default to keep the base image lean. Enable at build time
60
63
  # with: docker build --build-arg OTEL_ENABLED=true
61
64
  ARG OTEL_ENABLED=true
62
- RUN if [ "$OTEL_ENABLED" = "true" ]; then \
63
- bun add @hono/otel \
65
+ RUN --mount=type=cache,target=/root/.bun/install/cache \
66
+ if [ "$OTEL_ENABLED" = "true" ]; then \
67
+ bun add --omit=dev --ignore-scripts @hono/otel \
64
68
  @opentelemetry/instrumentation-http \
65
69
  @opentelemetry/exporter-metrics-otlp-http \
66
70
  @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 2025 Casey Hand @cyanheads
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
- [![Version](https://img.shields.io/badge/Version-0.1.2-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![Docker](https://img.shields.io/badge/Docker-ghcr.io-2496ED?style=flat-square&logo=docker&logoColor=white)](https://github.com/users/cyanheads/packages/container/package/federal-regulations-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^1.29.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![npm](https://img.shields.io/npm/v/@cyanheads/federal-regulations-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/federal-regulations-mcp-server) [![TypeScript](https://img.shields.io/badge/TypeScript-^6.0.3-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.3-blueviolet.svg?style=flat-square)](https://bun.sh/)
10
+ [![Version](https://img.shields.io/badge/Version-0.1.3-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![Docker](https://img.shields.io/badge/Docker-ghcr.io-2496ED?style=flat-square&logo=docker&logoColor=white)](https://github.com/users/cyanheads/packages/container/package/federal-regulations-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^1.30.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![npm](https://img.shields.io/npm/v/@cyanheads/federal-regulations-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/federal-regulations-mcp-server) [![TypeScript](https://img.shields.io/badge/TypeScript-^7.0.2-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.3-blueviolet.svg?style=flat-square)](https://bun.sh/)
11
11
 
12
12
  </div>
13
13
 
@@ -74,7 +74,9 @@ Explore the codified Code of Federal Regulations via eCFR in two modes. Keyless.
74
74
 
75
75
  - `structure` mode walks the CFR tree (all 50 titles, or one title's chapters → parts → sections) to discover a cite when the exact citation is unknown
76
76
  - `search` mode runs a full-text query across the codified CFR and returns matching sections with their hierarchy path and a snippet
77
- - Search is served from a synced local mirror (FTS5) when available and falls back to the live eCFR search API on a cold deploy; the `source` (`mirror` or `live`) is reported on each result
77
+ - Search is served from the synced local mirror (FTS5) only when the mirror's title coverage can answer the request — a title it does not hold, an all-titles query against a scoped mirror, a `date`, or a cold deploy all go to the live eCFR search API instead
78
+ - Every search result reports `source` (`mirror` or `live`) and `sourceScope` — which corpus answered and what it covers, so an empty result is never mistaken for "no such regulation"
79
+ - `date` searches the section text in effect that day; eCFR indexes 2017-01-03 onward, and an undated search is pinned to eCFR's current index date rather than spanning every historical version
78
80
  - Both modes assemble a `cfrCite` that feeds `regulations_get_cfr_section`
79
81
 
80
82
  ---
@@ -145,12 +147,12 @@ Federal-regulations-specific:
145
147
  - One workflow over three official sources — the agent sees regulatory verbs, not three API clients; which source is hit is a service-layer detail
146
148
  - Cross-source stitching — every Federal Register document surfaces its docket ID and CFR-part handles next to the tools that consume them, priming the proposal → comments → final → codified-text trace
147
149
  - Keyless core — Federal Register + eCFR (5 of 7 tools) is a complete deployment with no API key; the Regulations.gov leg layers on top
148
- - Locally mirrored codified CFR — the eCFR is synced once into embedded SQLite + FTS5 and queried by exact cite or full text, with a live-API fallback before the mirror is ready
150
+ - Locally mirrored codified CFR — the eCFR is synced once into embedded SQLite + FTS5 and queried by exact cite or full text, with a live-API fallback whenever the mirror's title coverage cannot answer the request
149
151
  - Three independent service clients, each with its own base URL, retry/backoff, and rate-limit handling (Regulations.gov honors `Retry-After` on 429)
150
152
 
151
153
  Agent-friendly output:
152
154
 
153
- - Provenance on every CFR read — `source: "mirror" | "live"` so agents know whether text came from the synced index or the live API
155
+ - Provenance on every CFR read — `source: "mirror" | "live"` so agents know whether text came from the synced index or the live API, and on search a `sourceScope` line naming what that corpus covers
154
156
  - Honest truncation — Federal Register (50-page / 5,000-record) and Regulations.gov (20-page / 5,000-record) ceilings are surfaced with guidance to narrow, never silently dropped
155
157
  - Attachment-aware comments — `attachmentOnly` flags when a comment's substance is a file rather than inline text, with the download URLs, on both the structured and text surfaces
156
158
  - Actionable `auth_required` errors — the two keyed tools name the env var and the free signup URL rather than passing through a raw 401/403
@@ -284,7 +286,7 @@ All configuration is validated at startup via Zod schemas in `src/config/server-
284
286
  | `REGULATIONS_GOV_BASE_URL` | Regulations.gov API v4 base URL. | `https://api.regulations.gov/v4` |
285
287
  | `ECFR_MIRROR_PATH` | Filesystem path for the eCFR SQLite mirror database. | `./data/ecfr-mirror.sqlite` |
286
288
  | `ECFR_MIRROR_REFRESH_CRON` | Cron expression for the weekly mirror refresh (HTTP transport only). | `0 4 * * 0` |
287
- | `ECFR_MIRROR_TITLES` | Comma-separated CFR title numbers to scope the mirror to (e.g. `21,40`). Omit to mirror all 50 titles. Cites outside the set fall through to the live eCFR API. | — (all titles) |
289
+ | `ECFR_MIRROR_TITLES` | Comma-separated CFR title numbers to scope the mirror to (e.g. `21,40`). Omit to mirror all 50 titles. Cites and searches outside the set fall through to the live eCFR API, as does any all-titles search while this is set. | — (all titles) |
288
290
  | `MCP_TRANSPORT_TYPE` | Transport: `stdio` or `http`. | `stdio` |
289
291
  | `MCP_HTTP_PORT` | Port for the HTTP server. | `3010` |
290
292
  | `MCP_AUTH_MODE` | Auth mode: `none`, `jwt`, or `oauth`. | `none` |
@@ -298,6 +300,8 @@ See [`.env.example`](./.env.example) for the full list of optional overrides.
298
300
 
299
301
  The codified CFR is large (~50 titles, hundreds of MB of XML — Title 40 alone is ~150 MB) but changes far less often than it is queried. This server mirrors it once into an embedded SQLite + FTS5 index and serves `regulations_get_cfr_section` (current single sections) and `regulations_browse_cfr` (full-text search) from it, falling back to the live eCFR API when the mirror has not yet completed an init or a historical/whole-part read is requested.
300
302
 
303
+ **The mirror answers only what it holds.** A scoped mirror (`ECFR_MIRROR_TITLES`) is consulted for a search only when the requested title is in the set, and never for an all-titles search — a three-title index reporting zero matches for the whole CFR is worse than no index at all. Those requests go to live eCFR instead, and every search result names the corpus that answered it in `sourceScope`.
304
+
301
305
  **The mirror is populated out-of-band, never on startup** — a full title sweep takes a while and must not block the server. Build it with:
302
306
 
303
307
  ```sh
@@ -0,0 +1,40 @@
1
+ ---
2
+ summary: "regulations_browse_cfr search fixes (title filter, date, partial-mirror scoping) plus mcp-ts-core ^0.10.9 → ^0.11.1 and dependency-hygiene overrides that clear 20 audit advisories."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.1.3 — 2026-08-09
8
+
9
+ ## Changed
10
+
11
+ - **`regulations_browse_cfr` search-mode `date`** — now forwarded to eCFR's `date` parameter; an undated query pins to eCFR's current index date instead of matching every historical version of a section alongside its current text. Out-of-range dates raise `date_out_of_range` (`InvalidParams`) naming the indexed window (`2017-01-03` through the current index date). ([#1](https://github.com/cyanheads/federal-regulations-mcp-server/issues/1))
12
+ - **`regulations_browse_cfr` title-scoped search** — sends `hierarchy[title]` instead of the upstream-rejected `conditions[title]`. ([#1](https://github.com/cyanheads/federal-regulations-mcp-server/issues/1))
13
+ - **Search result `heading`** — now taken from eCFR's `headings` map (the node's name) rather than `hierarchy_headings` (its structural label); appendix hits, which carry no `hierarchy.section`, are identified via `hierarchy.appendix` and no longer fall through to `(untitled)`. ([#1](https://github.com/cyanheads/federal-regulations-mcp-server/issues/1))
14
+ - **eCFR mirror search routing** — a scoped mirror (`ECFR_MIRROR_TITLES`) now answers a search only when the requested title is in its indexed set, and never answers an all-titles query unless the index is complete; everything else falls through to live eCFR instead of returning a false empty result from a corpus that never held the answer. Coverage is read from a new `cfr_mirror_meta` table written at sync time, not from the environment the server happens to boot with. ([#2](https://github.com/cyanheads/federal-regulations-mcp-server/issues/2))
15
+ - **`regulations_browse_cfr` output** — every search result now carries `sourceScope`, naming which corpus answered (mirror titles, or the live index and its date); the empty-result `notice` names it too, so a zero-match search is never mistaken for "no such regulation." `mirror:verify` prints the same coverage.
16
+ - **`no_results` error contracts removed** — `regulations_search_rules`, `regulations_list_open_comments`, and `regulations_browse_cfr` no longer declare a `no_results` reason; a zero-match query is a successful empty result with a `notice`, not a domain error, on all three. ([#4](https://github.com/cyanheads/federal-regulations-mcp-server/issues/4))
17
+
18
+ ### Dependency bumps
19
+
20
+ - `@cyanheads/mcp-ts-core` ^0.10.9 → ^0.11.1
21
+ - `typescript` ^6.0.3 → ^7.0.2
22
+ - `better-sqlite3` ^12.11.1 → ^13.0.1
23
+ - `@biomejs/biome` 2.5.0 → 2.5.6
24
+ - `@types/node` 26.0.0 → 26.1.2
25
+ - `tsc-alias` ^1.8.17 → ^1.9.1
26
+ - `vitest` ^4.1.9 → ^4.1.10
27
+ - `ignore` ^7.0.5 → ^7.0.6
28
+ - new `overrides` block (`body-parser`, `fast-uri`, `ip-address`, `js-yaml`, `nanoid`, `postcss`) takes `bun audit` from 20 advisories to 0
29
+
30
+ ## Added
31
+
32
+ - **Socket install scanner** — `@socketsecurity/bun-security-scanner` wired through `bunfig.toml`; scans every package before install for malware, typosquats, and CVEs.
33
+ - **`minimumReleaseAge` supply-chain guard** — `bunfig.toml` blocks package versions published less than 3 days ago, with `@cyanheads/mcp-ts-core` excluded for same-day framework adoption.
34
+ - **MCPB native-binding strip** — `scripts/clean-mcpb.ts` and `scripts/lint-packaging.ts` now also strip/reject platform-specific native bindings (`@duckdb/node-bindings-*`) from packed bundles, alongside the existing agent-doc strip, so a DataCanvas-enabled server's `.mcpb` stays portable and under the registry size cap.
35
+ - **`.github/SECURITY.md`, `.github/FUNDING.yml`, `.gitattributes`** — template files the project was missing.
36
+
37
+ ## Fixed
38
+
39
+ - **Dockerfile** — pinned the `oven/bun` base image to `1.3.14` (was floating `1.3`), added BuildKit cache mounts on every `bun install`/`bun add` layer, and switched the OTel peer-dependency install to `--omit=dev --ignore-scripts`.
40
+
@@ -15,9 +15,11 @@ summary: ""
15
15
  # usage. Flagged as `Breaking` in the rollup.
16
16
  breaking: false
17
17
 
18
- # Set `true` if this release contains any security fix. Pairs with the
19
- # `## Security` section below. Flagged as `Security` in the rollup so
20
- # users can triage upgrade urgency at a glance.
18
+ # Set `true` ONLY for a security fix in THIS project's own source code — a
19
+ # vulnerability or hardening in code you ship. A dependency or transitive CVE
20
+ # bump is routine maintenance, NOT a security release: record it under
21
+ # `## Dependencies` (with the advisory ID) and leave this `false`. When true,
22
+ # pairs with the `## Security` section below and flags `Security` in the rollup.
21
23
  security: false
22
24
 
23
25
  # Optional free-form notes for maintenance agents processing this release.
@@ -1,8 +1,10 @@
1
1
  /**
2
2
  * @fileoverview regulations_browse_cfr — navigate the CFR hierarchy (structure
3
3
  * mode) or full-text-search the codified CFR (search mode) via eCFR. Search runs
4
- * against the local mirror's FTS5 index when ready, falling back to the live eCFR
5
- * search API on a cold deploy. Keyless. Feeds regulations_get_cfr_section.
4
+ * against the local mirror's FTS5 index only when the mirror's title coverage can
5
+ * answer the request; a scoped mirror, an unscoped (all-titles) query it cannot
6
+ * answer completely, a historical date, or a cold deploy all route to the live
7
+ * eCFR search API. Keyless. Feeds regulations_get_cfr_section.
6
8
  * @module mcp-server/tools/definitions/browse-cfr.tool
7
9
  */
8
10
  import { z } from '@cyanheads/mcp-ts-core';
@@ -32,9 +34,10 @@ export declare const browseCfrTool: import("@cyanheads/mcp-ts-core").ToolDefinit
32
34
  cfrCite: z.ZodNullable<z.ZodString>;
33
35
  }, z.core.$strip>>>;
34
36
  source: z.ZodOptional<z.ZodEnum<{
35
- mirror: "mirror";
36
37
  live: "live";
38
+ mirror: "mirror";
37
39
  }>>;
40
+ sourceScope: z.ZodOptional<z.ZodString>;
38
41
  results: z.ZodOptional<z.ZodArray<z.ZodObject<{
39
42
  title: z.ZodNumber;
40
43
  part: z.ZodString;
@@ -55,10 +58,10 @@ export declare const browseCfrTool: import("@cyanheads/mcp-ts-core").ToolDefinit
55
58
  readonly when: "Structure mode with a title outside 1–50, or a part not found in the title.";
56
59
  readonly recovery: "Omit title to list all titles, or pick a number in 1–50 and a part that exists.";
57
60
  }, {
58
- readonly reason: "no_results";
59
- readonly code: JsonRpcErrorCode.NotFound;
60
- readonly when: "Search mode returned zero matches.";
61
- readonly recovery: "Broaden the phrase or drop the title filter and retry.";
61
+ readonly reason: "date_out_of_range";
62
+ readonly code: JsonRpcErrorCode.InvalidParams;
63
+ readonly when: "Search mode with a date outside eCFR's indexed window (before 2017-01-03, or past its current index date).";
64
+ readonly recovery: "Pick a date inside the window the error names, or omit date to search the current text.";
62
65
  }, {
63
66
  readonly reason: "upstream_unavailable";
64
67
  readonly code: JsonRpcErrorCode.ServiceUnavailable;
@@ -1 +1 @@
1
- {"version":3,"file":"browse-cfr.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/browse-cfr.tool.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAkCjE,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqMxB,CAAC"}
1
+ {"version":3,"file":"browse-cfr.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/browse-cfr.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAmEjE,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8NxB,CAAC"}