@cyanheads/hn-mcp-server 0.5.13 → 0.5.14

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 (39) hide show
  1. package/CLAUDE.md +17 -11
  2. package/Dockerfile +13 -7
  3. package/README.md +1 -1
  4. package/changelog/0.1.x/0.1.0.md +31 -0
  5. package/changelog/0.1.x/0.1.1.md +16 -0
  6. package/changelog/0.1.x/0.1.2.md +12 -0
  7. package/changelog/0.1.x/0.1.3.md +12 -0
  8. package/changelog/0.1.x/0.1.4.md +15 -0
  9. package/changelog/0.1.x/0.1.5.md +14 -0
  10. package/changelog/0.1.x/0.1.6.md +24 -0
  11. package/changelog/0.1.x/0.1.7.md +11 -0
  12. package/changelog/0.1.x/0.1.8.md +11 -0
  13. package/changelog/0.1.x/0.1.9.md +20 -0
  14. package/changelog/0.2.x/0.2.0.md +28 -0
  15. package/changelog/0.3.x/0.3.0.md +18 -0
  16. package/changelog/0.4.x/0.4.0.md +21 -0
  17. package/changelog/0.4.x/0.4.2.md +36 -0
  18. package/changelog/0.4.x/0.4.3.md +23 -0
  19. package/changelog/0.5.x/0.5.0.md +27 -0
  20. package/changelog/0.5.x/0.5.1.md +24 -0
  21. package/changelog/0.5.x/0.5.10.md +24 -0
  22. package/changelog/0.5.x/0.5.11.md +27 -0
  23. package/changelog/0.5.x/0.5.12.md +34 -0
  24. package/changelog/0.5.x/0.5.13.md +18 -0
  25. package/changelog/0.5.x/0.5.14.md +29 -0
  26. package/changelog/0.5.x/0.5.2.md +28 -0
  27. package/changelog/0.5.x/0.5.3.md +27 -0
  28. package/changelog/0.5.x/0.5.4.md +19 -0
  29. package/changelog/0.5.x/0.5.5.md +11 -0
  30. package/changelog/0.5.x/0.5.6.md +25 -0
  31. package/changelog/0.5.x/0.5.7.md +16 -0
  32. package/changelog/0.5.x/0.5.8.md +17 -0
  33. package/changelog/0.5.x/0.5.9.md +11 -0
  34. package/changelog/template.md +168 -0
  35. package/dist/services/hn/hn-service.d.ts.map +1 -1
  36. package/dist/services/hn/hn-service.js +28 -41
  37. package/dist/services/hn/hn-service.js.map +1 -1
  38. package/package.json +32 -22
  39. package/server.json +5 -5
package/CLAUDE.md CHANGED
@@ -1,8 +1,11 @@
1
- # Agent Protocol
1
+ # Developer Protocol
2
2
 
3
3
  **Server:** hn-mcp-server
4
- **Version:** 0.5.13
5
- **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core)
4
+ **Version:** 0.5.14
5
+ **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.12.3`
6
+ **Engines:** Bun ≥1.3.0, Node ≥24.0.0
7
+ **MCP SDK:** `@modelcontextprotocol/server` 2.0.0
8
+ **Zod:** ^4.4.3
6
9
 
7
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.
8
11
 
@@ -31,6 +34,8 @@ Tailor suggestions to what's actually missing or stale — don't recite the full
31
34
 
32
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.
33
36
  - **Use `ctx.log`** for request-scoped logging. No `console` calls.
37
+ - **Use `ctx.state`** for tenant-scoped storage. Never access persistence directly.
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.
34
39
  - **Secrets in env vars only** — never hardcoded.
35
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.
36
41
 
@@ -64,9 +69,9 @@ export const getStories = tool('hn_get_stories', {
64
69
 
65
70
  async handler(input, ctx) {
66
71
  const hn = getHnService();
67
- const feedIds = await hn.fetchFeed(input.feed);
72
+ const feedIds = await hn.fetchFeed(input.feed, ctx);
68
73
  const sliced = feedIds.slice(input.offset, input.offset + input.count);
69
- const items = filterLiveItems(await hn.fetchItems(sliced));
74
+ const items = filterLiveItems(await hn.fetchItems(sliced, ctx));
70
75
  ctx.log.info('Fetched stories', { feed: input.feed, count: items.length });
71
76
  return { stories: items.map(/* ... */), feed: input.feed, total: feedIds.length };
72
77
  },
@@ -124,13 +129,13 @@ Handlers receive a unified `ctx` object. Key properties:
124
129
 
125
130
  | Property | Description |
126
131
  |:---------|:------------|
127
- | `ctx.log` | Request-scoped logger — `.debug()`, `.info()`, `.notice()`, `.warning()`, `.error()`. Auto-correlates requestId, traceId, tenantId. |
132
+ | `ctx.log` | Request-scoped dual-sink logger — `.debug()`, `.info()`, `.notice()`, `.warning()`, `.error()`. Auto-correlates requestId, traceId, tenantId; eligible messages also reach the client through MCP logging notifications. |
128
133
  | `ctx.state` | Tenant-scoped KV — `.get(key)`, `.set(key, value, { ttl? })`, `.delete(key)`, `.getMany(keys)`, `.list(prefix, { cursor, limit })`. Accepts any serializable value. |
129
- | `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) { ... }` |
134
+ | `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. |
135
+ | `ctx.inputs` | Reader over a retried request's responses — `.accepted(key, schema)`, `.view(key)`, `.state()`, `.dropped`. Empty on the first round. |
130
136
  | `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). |
131
137
  | `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`. |
132
138
  | `ctx.signal` | `AbortSignal` for cancellation. |
133
- | `ctx.progress` | Task progress (present when `task: true`) — `.setTotal(n)`, `.increment()`, `.update(message)`. |
134
139
  | `ctx.requestId` | Unique request ID. |
135
140
  | `ctx.tenantId` | Tenant ID from JWT; `'default'` for stdio or HTTP with auth off. |
136
141
 
@@ -239,14 +244,14 @@ Available skills:
239
244
  | `code-simplifier` | Post-session cleanup against `git diff` — modernize syntax, consolidate duplication, align with the codebase |
240
245
  | `polish-docs-meta` | Finalize docs, README, metadata, and agent protocol for shipping |
241
246
  | `git-wrapup` | Land working-tree changes as a versioned commit + annotated tag — version bump, changelog, verify, tag. Local only. |
242
- | `release-and-publish` | Post-wrapup ship workflow: verification gate, push, publish to npm/MCP Registry/GHCR |
247
+ | `release-and-publish` | Push + npm + MCP Registry + GitHub Release + Docker. Picks up from `git-wrapup` |
243
248
  | `maintenance` | Investigate changelogs, adopt upstream changes, sync skills to agent dirs |
244
249
  | `orchestrations` | Chain task skills into a gated multi-phase pipeline — build-out, QA-fix, update-ship — when you can spawn sub-agents |
245
250
  | `techniques` | Catalog of reusable response/data-shaping patterns (outline-on-overflow, etc.) |
246
251
  | `api-auth` | Auth modes, scopes, JWT/OAuth |
247
252
  | `api-canvas` | DataCanvas: register tabular data, run SQL, export, plus the `spillover()` helper for big result sets — Tier 3 opt-in |
248
253
  | `api-config` | AppConfig, parseConfig, env vars |
249
- | `api-context` | Context interface, logger, state, progress |
254
+ | `api-context` | Context interface, RequestContext, logger, state, multi-round-trip input |
250
255
  | `api-errors` | McpError, JsonRpcErrorCode, error patterns |
251
256
  | `api-linter` | Definition linter rule catalog — invoked by `bun run lint:mcp` and `devcheck` |
252
257
  | `api-mirror` | MirrorService: persistent self-refreshing local index (SQLite+FTS5) for bulk/slow upstream datasets |
@@ -285,6 +290,7 @@ When you complete a skill's checklist, check the boxes and add a completion time
285
290
  | `bun run changelog:check` | Verify `CHANGELOG.md` is in sync (used by devcheck) |
286
291
  | `bun run audit:refresh` | Delete `bun.lock`, reinstall, re-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. |
287
292
  | `bun run test` | Run tests (Vitest — use `bun run test`, not `bun test`) |
293
+ | `bun run test:coverage` | Run the full Vitest suite with Istanbul coverage |
288
294
  | `bun run start:stdio` | Production mode (stdio) |
289
295
  | `bun run start:http` | Production mode (HTTP) |
290
296
 
@@ -317,7 +323,7 @@ security: false # optional — true ONLY for a source
317
323
  ...
318
324
  ```
319
325
 
320
- `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`).
326
+ `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 flags are set, the badges render `· ⚠️ Breaking · 🛡️ Security`.
321
327
 
322
328
  `agent-notes` is an optional free-form field for maintenance agents processing the release downstream. Content there 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.
323
329
 
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.14 AS build
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.3.14-slim AS production
33
+ FROM oven/bun:1.4.0-slim AS production
34
34
 
35
35
  WORKDIR /usr/src/app
36
36
 
@@ -51,8 +51,11 @@ 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; runtime imports must
55
+ # be declared by this server. The OTEL install below keeps the same flag so it
56
+ # does not pull those optional peers back into the image.
54
57
  RUN --mount=type=cache,target=/root/.bun/install/cache \
55
- bun install --production --frozen-lockfile --ignore-scripts
58
+ bun install --production --omit=peer --frozen-lockfile --ignore-scripts
56
59
 
57
60
  # Conditionally install OpenTelemetry optional peer dependencies (Tier 3).
58
61
  # These are not bundled by default to keep the base image lean. Enable at build time
@@ -60,7 +63,7 @@ RUN --mount=type=cache,target=/root/.bun/install/cache \
60
63
  ARG OTEL_ENABLED=true
61
64
  RUN --mount=type=cache,target=/root/.bun/install/cache \
62
65
  if [ "$OTEL_ENABLED" = "true" ]; then \
63
- bun add --omit=dev --ignore-scripts @hono/otel \
66
+ bun add --omit=dev --omit=peer --ignore-scripts @hono/otel \
64
67
  @opentelemetry/instrumentation-http \
65
68
  @opentelemetry/exporter-metrics-otlp-http \
66
69
  @opentelemetry/exporter-trace-otlp-http \
@@ -81,6 +84,10 @@ COPY --from=build /usr/src/app/dist ./dist
81
84
  # Create and set permissions for the log directory, assigning ownership to the 'bun' user.
82
85
  RUN mkdir -p /var/log/hn-mcp-server && chown -R bun:bun /var/log/hn-mcp-server
83
86
 
87
+ # Writable data directories for framework-backed caches and mirrors.
88
+ RUN mkdir -p /usr/src/app/.cache /usr/src/app/.mirror \
89
+ && chown -R bun:bun /usr/src/app/.cache /usr/src/app/.mirror
90
+
84
91
  # Switch to the non-root user
85
92
  USER bun
86
93
 
@@ -101,9 +108,8 @@ ENV MCP_FORCE_CONSOLE_LOGGING="true"
101
108
  # Expose the port the server listens on
102
109
  EXPOSE ${MCP_HTTP_PORT}
103
110
 
104
- # Health check against the /healthz endpoint
105
- HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
106
- CMD bun -e "fetch('http://localhost:' + (process.env.MCP_HTTP_PORT || '3010') + '/healthz').then(r => process.exit(r.ok ? 0 : 1)).catch(() => process.exit(1))"
111
+ # Health check using a bun-native fetch (slim image ships no curl/wget)
112
+ HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 CMD bun -e "fetch('http://localhost:'+(process.env.MCP_HTTP_PORT??'3010')+'/healthz').then((r)=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
107
113
 
108
114
  # The command to start the server
109
115
  CMD ["bun", "run", "dist/index.js"]
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.5.13-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/hn-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/hn-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/hn-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->=1.3.0-f9f1e1.svg?style=flat-square)](https://bun.sh/)
10
+ [![Version](https://img.shields.io/badge/Version-0.5.14-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/hn-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-2.0.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![npm](https://img.shields.io/npm/v/@cyanheads/hn-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/hn-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->=1.3.0-f9f1e1.svg?style=flat-square)](https://bun.sh/)
11
11
 
12
12
  </div>
13
13
 
@@ -0,0 +1,31 @@
1
+ ---
2
+ summary: "Initial release. Four read-only tools (`hn_get_stories`, `hn_get_thread`, `hn_get_user`, `hn_search_content`) over HN Firebase + Algolia. Concurrency-limited batch fetching, HTML stripping with code-block/link preservation, stdio + streamable-http transports."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.1.0 — 2026-03-21
8
+
9
+ Initial release.
10
+
11
+ ## Added
12
+
13
+ - **Tools:** `get_stories`, `get_thread`, `get_user`, `search_hn` — 4 read-only tools covering HN feeds, threaded discussions, user profiles, and full-text search
14
+ - **Service layer:** HN Firebase API client with concurrency-limited batch fetching, Algolia search client with filtering and pagination
15
+ - **HTML processing:** Entity decoding, tag stripping with code block and link preservation
16
+ - **Transports:** stdio and streamable-http via `@cyanheads/mcp-ts-core`
17
+ - **Configuration:** `HN_CONCURRENCY_LIMIT` env var for tuning batch fetch parallelism
18
+ - **Tests:** Comprehensive test suite covering all tools, service layer, and server config
19
+ - **Docs:** README with full tool documentation, design document, HN API reference, project structure tree
20
+ - **Infra:** Dockerfile, biome config, vitest config, devcheck config, server.json metadata, LICENSE (Apache-2.0), bunfig.toml
21
+
22
+ ## Fixed
23
+
24
+ - `search_hn` totalPages calculation now uses `Math.ceil(nbHits / count)` instead of Algolia's `nbPages` (which reflects Algolia's own page size, not the requested count)
25
+
26
+ ## Changed
27
+
28
+ - Updated `server.json` name to reverse-DNS format (`io.github.cyanheads/hn-mcp-server`), added `HN_CONCURRENCY_LIMIT` env var, set `runtimeHint` to `bun`
29
+ - Expanded `package.json` with `mcpName`, `homepage`, `bugs`, `author`, `packageManager`, and HN-specific keywords
30
+ - Added OCI image description and source labels to Dockerfile
31
+ - Customized `CLAUDE.md` agent protocol with HN-specific patterns, examples, and structure
@@ -0,0 +1,16 @@
1
+ ---
2
+ summary: "Renamed package to scoped `@cyanheads/hn-mcp-server`. Conditional OpenTelemetry install via `OTEL_ENABLED` Docker build arg. Framework `^0.1.22 → ^0.1.23`."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.1.1 — 2026-03-21
8
+
9
+ ## Changed
10
+
11
+ - Renamed package from `hn-mcp-server` to `@cyanheads/hn-mcp-server` (scoped npm package)
12
+ - Bumped `@cyanheads/mcp-ts-core` from `^0.1.22` to `^0.1.23`
13
+ - Added `@hono/otel` dependency for OpenTelemetry integration
14
+ - Dockerfile now conditionally installs OpenTelemetry peer dependencies via `OTEL_ENABLED` build arg (defaults to true)
15
+ - Updated `server.json` npm identifiers to scoped package name
16
+ - Updated README install commands to use scoped package name
@@ -0,0 +1,12 @@
1
+ ---
2
+ summary: "Framework patch `^0.1.23 → ^0.1.24`. Publishing instructions added to CLAUDE.md."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.1.2 — 2026-03-21
8
+
9
+ ## Changed
10
+
11
+ - Bumped `@cyanheads/mcp-ts-core` from `^0.1.23` to `^0.1.24`
12
+ - Added publishing instructions to `CLAUDE.md` agent protocol
@@ -0,0 +1,12 @@
1
+ ---
2
+ summary: "Framework patch `^0.1.23 → ^0.1.25`."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.1.3 — 2026-03-21
8
+
9
+ ## Changed
10
+
11
+ - Bumped `@cyanheads/mcp-ts-core` from `^0.1.23` to `^0.1.25`
12
+ - Added publishing instructions to `CLAUDE.md` agent protocol
@@ -0,0 +1,15 @@
1
+ ---
2
+ summary: "TypeScript major `^5.9.3 → ^6.0.2`. Framework `^0.1.25 → ^0.1.28`. Vitest patch. `remotes` entry on `server.json` with public streamable-http URL. `tsconfig.json` simplified (relative path alias)."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.1.4 — 2026-03-23
8
+
9
+ ## Changed
10
+
11
+ - Bumped `@cyanheads/mcp-ts-core` from `^0.1.25` to `^0.1.28`
12
+ - Bumped `typescript` from `^5.9.3` to `^6.0.2`
13
+ - Bumped `vitest` from `^4.1.0` to `^4.1.1`
14
+ - Added `remotes` entry to `server.json` with public streamable-http URL
15
+ - Simplified `tsconfig.json`: removed `baseUrl`, updated path alias to relative form
@@ -0,0 +1,14 @@
1
+ ---
2
+ summary: "Tool rename pass: all four tools gain `hn_` namespace prefix (`get_stories` → `hn_get_stories`, `get_thread` → `hn_get_thread`, `get_user` → `hn_get_user`, `search_hn` → `hn_search_content`). Breaking for any caller using the unprefixed names."
3
+ breaking: true
4
+ security: false
5
+ ---
6
+
7
+ # 0.1.5 — 2026-03-23
8
+
9
+ ## Changed
10
+
11
+ - Renamed all tools with `hn_` prefix for namespacing: `get_stories` → `hn_get_stories`, `get_thread` → `hn_get_thread`, `get_user` → `hn_get_user`, `search_hn` → `hn_search_content`
12
+ - Renamed `search-hn.tool.ts` → `search-content.tool.ts` (and corresponding test) to match new tool name
13
+ - Updated cross-reference descriptions in tool schemas to use new prefixed names
14
+ - Updated README, CLAUDE.md, and test suites with new tool names
@@ -0,0 +1,24 @@
1
+ ---
2
+ summary: "Framework `^0.1.28 → ^0.2.4`. `format()` output overhauled across all tools (markdown headers, IDs, dates, actionable hints). Security overrides for `path-to-regexp`, `picomatch`, `brace-expansion`. New `report-issue-framework` / `report-issue-local` skills."
3
+ breaking: false
4
+ security: true
5
+ ---
6
+
7
+ # 0.1.6 — 2026-03-28
8
+
9
+ ## Changed
10
+
11
+ - Bumped `@cyanheads/mcp-ts-core` from `^0.1.28` to `^0.2.4`
12
+ - Bumped `@biomejs/biome` from `^2.4.8` to `^2.4.9`
13
+ - Bumped `vitest` from `^4.1.1` to `^4.1.2`
14
+ - Added `overrides` for `path-to-regexp`, `picomatch`, and `brace-expansion` (security patches)
15
+ - Improved `format()` output across all 4 tools: markdown headers, item IDs, dates, full text rendering, and actionable hints
16
+ - Updated test assertions to match new format output
17
+
18
+ ## Added
19
+
20
+ - `report-issue-framework` skill for filing bugs against `@cyanheads/mcp-ts-core`
21
+ - `report-issue-local` skill for filing bugs against this server
22
+ - `LOGS_DIR` env var documented in README
23
+ - GitHub repo metadata sync step in `polish-docs-meta` skill
24
+ - Description propagation rule (package.json → README → server.json → Dockerfile)
@@ -0,0 +1,11 @@
1
+ ---
2
+ summary: "Framework patch `^0.2.4 → ^0.2.6`."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.1.7 — 2026-03-28
8
+
9
+ ## Changed
10
+
11
+ - Bumped `@cyanheads/mcp-ts-core` from `^0.2.4` to `^0.2.6`
@@ -0,0 +1,11 @@
1
+ ---
2
+ summary: "Framework patch `^0.2.6 → ^0.2.7`."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.1.8 — 2026-03-28
8
+
9
+ ## Changed
10
+
11
+ - Bumped `@cyanheads/mcp-ts-core` from `^0.2.6` to `^0.2.7`
@@ -0,0 +1,20 @@
1
+ ---
2
+ summary: "Framework `^0.2.7 → ^0.2.10`. Biome patch. Skill refreshes — `add-tool` v1.1 (tool response design), `add-resource` v1.1 (tool coverage guidance), `design-mcp-server` v2.1 (live API probing, batch input design, resilience planning)."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.1.9 — 2026-03-30
8
+
9
+ ## Changed
10
+
11
+ - Bumped `@cyanheads/mcp-ts-core` from `^0.2.7` to `^0.2.10`
12
+ - Bumped `@biomejs/biome` from `^2.4.9` to `^2.4.10`
13
+ - Updated author field and added funding metadata in `package.json`
14
+ - Updated `add-tool` skill (v1.1): expanded tool response design guidance — partial success, batch input, format function content-completeness, error classification
15
+ - Updated `add-resource` skill (v1.1): added tool coverage guidance for resource definitions
16
+ - Updated `design-mcp-server` skill (v2.1): live API probing, tool-first design philosophy, batch input design, error design patterns, resilience planning, naming conventions
17
+
18
+ ## Fixed
19
+
20
+ - Formatting fix in `get-thread.tool.test.ts` assertion
@@ -0,0 +1,28 @@
1
+ ---
2
+ summary: "Upstream resilience. `withRetry` + `fetchWithTimeout` wrap HN Firebase + Algolia fetches with 10s per-request timeout, HTML-error-body detection (for rate-limited 200 OK responses), and `ctx.signal` cancellation. `hn_get_stories` schema fields made optional to preserve upstream sparsity. Framework `^0.2.10 → ^0.4.1`."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.2.0 — 2026-04-19
8
+
9
+ ## Added
10
+
11
+ - Upstream resilience for HN Firebase and Algolia calls: `withRetry` + `fetchWithTimeout` wrap the full fetch-and-parse pipeline in `HnService`, with a 10-second per-request timeout, HTML-error-body detection (for rate-limited responses served as 200 OK), and `ctx.signal` wired through for cancellation.
12
+ - Sparse-upstream test fixtures for `hn_get_stories` covering omitted `score`/`by`/`time`/`title` fields and verifying `format()` does not fabricate meta.
13
+ - `add-app-tool` skill (v1.2) for scaffolding MCP App tool + UI resource pairs.
14
+
15
+ ## Changed
16
+
17
+ - Bumped `@cyanheads/mcp-ts-core` from `^0.2.10` to `^0.4.1`.
18
+ - Bumped `@biomejs/biome` (2.4.10 → 2.4.12), `@types/node` (25.5.0 → 25.6.0), `typescript` (6.0.2 → 6.0.3), `vitest` (4.1.2 → 4.1.4).
19
+ - Dropped the `overrides` block (`path-to-regexp`, `picomatch`, `brace-expansion`) — fresh resolution picks up clean transitive versions and `bun audit` now reports zero vulnerabilities.
20
+ - `HnService` methods (`fetchItem`, `fetchUser`, `fetchFeed`, `fetchItems`, `search`) now accept `ctx: Context` for correlated logs and cancellation; added a local `toRequestContext()` adapter to reconcile `exactOptionalPropertyTypes` differences between `Context` and `RequestContext`.
21
+ - `hn_get_stories` output schema: `title`, `score`, `by`, and `time` are now optional. The handler uses conditional spreads so upstream absence is preserved instead of being fabricated into `''`, `0`, or epoch zero. `format()` falls back to `[type]` when the title is unknown and omits meta segments that would otherwise render as blank.
22
+ - `hn_get_thread` and `hn_get_user` now throw `notFound()` for missing items/users instead of plain `Error`, giving the LLM a classified error code.
23
+ - Algolia HTTP error paths now surface as `ServiceUnavailable` via `fetchWithTimeout` + retry instead of raw `Error`.
24
+ - Synced project skills from `mcp-ts-core@0.4.1`: updated `add-prompt`, `add-resource`, `add-service`, `add-test`, `add-tool`, `api-testing`, `api-workers`, `design-mcp-server`, `devcheck`, `field-test`, `maintenance`, `migrate-mcp-ts-template`, `polish-docs-meta`, `setup`.
25
+
26
+ ## Fixed
27
+
28
+ - Per-item failures inside batch `fetchItems` calls are now tolerated (logged and nulled) rather than bubbling up and failing the whole feed after retries exhaust.
@@ -0,0 +1,18 @@
1
+ ---
2
+ summary: "Framework `^0.4.1 → ^0.5.3` adopts the `format-parity` lint rule. `format()` output expanded across all four tools: meta lines lead with `id:N`, dual ISO + Unix timestamps, comment depth/parent annotations, indent capped at 10 levels."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.3.0 — 2026-04-20
8
+
9
+ ## Changed
10
+
11
+ - Bumped `@cyanheads/mcp-ts-core` from `^0.4.1` to `^0.5.3`. The 0.5.x release adds a `format-parity` lint rule that verifies every field in a tool's `output` schema is rendered by its `format()` function — catching silent divergence between `structuredContent` (forwarded by clients like Claude Code) and `content[]` (forwarded by clients like Claude Desktop).
12
+ - `hn_get_stories` `format()`: meta line now leads with `id:N | type | …` and renders `time` as both ISO date and raw Unix timestamp (`2026-04-20 (t:1776717572)`); header includes raw `offset:N`.
13
+ - `hn_get_thread` `format()`: comment lines now include `depth:N | parent:N` annotations; visual indent is capped at 10 levels so a synthetic deep depth doesn't OOM `String.repeat`; root meta includes `type:N`; comment timestamps render with both formatted date and raw value; summary is always rendered (previously suppressed when fully loaded).
14
+ - `hn_get_user` `format()`: `created` and submission `time` now render with both formatted date and raw Unix timestamp.
15
+ - `hn_search_content` `format()`: header includes raw `p:N`; `createdAt` now renders the full ISO string (was truncated to date); comment results carry the parent story id in the heading; story results suppress the redundant self-referential parent ref.
16
+ - Dropped redundant `async` modifier on `HnService.fetchItem`/`fetchUser`/`fetchFeed` — they delegate directly to `withRetry()` and gain nothing from the wrapper.
17
+ - Synced project skills from `mcp-ts-core@0.5.3`: updated `add-tool` (1.4 → 1.6), `api-config` (1.1 → 1.2), `design-mcp-server` (2.3 → 2.4), `field-test` (1.1 → 1.2), `maintenance` (1.2 → 1.3), `polish-docs-meta` (1.3 → 1.4), `setup` (1.2 → 1.3).
18
+ - Bumped MCP SDK badge in `README.md` to `^1.29.0` and TypeScript badge to `^6.0.3`.
@@ -0,0 +1,21 @@
1
+ ---
2
+ summary: "Framework `^0.5.3 → ^0.7.0` (20 releases). `.describe()` now required recursively on array-element schemas — added to `stories[]`, `comments[]`, `submissions[]`, `hits[]`. New skills `api-linter`, `release-and-publish`, `security-pass`. `.github/ISSUE_TEMPLATE/` scaffolded."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.4.0 — 2026-04-24
8
+
9
+ ## Changed
10
+
11
+ - Bumped `@cyanheads/mcp-ts-core` from `^0.5.3` to `^0.7.0`. Spans 20 releases with substantial additions: landing page at `/` plus SEP-1649 Server Card at `/.well-known/mcp.json`, `MCP_PUBLIC_URL` override for TLS-terminating proxies, directory-based changelog convention, recursive `describe-on-fields` linter, new `security-pass` / `release-and-publish` / `api-linter` skills, a `Skills Sync` devcheck step, and flattened `ZodError` message shape. No runtime breaking changes for this server.
12
+ - `hn_get_stories`, `hn_get_thread`, `hn_get_user`, `hn_search_content`: added `.describe()` on each array-element object schema (`stories[]`, `comments[]`, `submissions[]`, `hits[]`) to satisfy the new recursive `describe-on-fields` rule introduced in `mcp-ts-core@0.6.16`.
13
+ - `hn_get_stories` handler: hoisted `normalizeUrl(item.url)` to a local `const` so it's called once per story instead of twice, and dropped the redundant `as string` cast. The conditional-spread "omit absent properties" contract is preserved.
14
+ - Bumped `@biomejs/biome` (2.4.12 → 2.4.13) and `vitest` (4.1.4 → 4.1.5).
15
+
16
+ ## Added
17
+
18
+ - `.github/ISSUE_TEMPLATE/` — bug report, feature request, and config templates scaffolded from the framework, aligned with `mcp-ts-core@0.7.0`'s secondary-label scheme.
19
+ - Framework scripts synced from `mcp-ts-core@0.7.0`: `scripts/build-changelog.ts`, `scripts/check-docs-sync.ts`, `scripts/check-skills-sync.ts`. `devcheck`, `lint-mcp`, and `tree` scripts also refreshed.
20
+ - Skills synced from `mcp-ts-core@0.7.0`: added `api-linter` (v1.1), `release-and-publish` (v2.1), `security-pass` (v1.1); updated `add-app-tool`, `add-prompt`, `add-resource`, `add-service`, `add-tool`, `api-context`, `api-services`, `api-utils`, `design-mcp-server`, `field-test`, `maintenance`, `polish-docs-meta`, `report-issue-framework`, `report-issue-local`, `setup`. Propagated to `.claude/skills/`.
21
+ - `CLAUDE.md`: added `security-pass` step to the "What's Next?" sequence (slot 8); added `security-pass`, `release-and-publish`, and `api-linter` rows to the skills table; pointed the Publishing section at the `release-and-publish` skill.
@@ -0,0 +1,36 @@
1
+ ---
2
+ summary: "Bundles two releases. (1) `hn_search_content` `dateRange` rejects unparseable dates via Zod `.refine()`. (2) Framework `^0.7.0 → ^0.8.17` brings the typed-error-contract API; adopted contracts on `hn_get_thread` (`item_not_found`) and `hn_get_user` (`user_not_found`); search empty-result message names applied filters."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.4.2 — 2026-05-05
8
+
9
+ ## Changed
10
+
11
+ - `hn_search_content`: `dateRange.start` and `dateRange.end` now reject unparseable date strings at the input boundary via a Zod `.refine()` check, instead of silently producing `NaN` Algolia numeric filters when downstream `new Date(…).getTime()` fails. New test covers the rejection path.
12
+ - `hn_search_content`: clarified `storyId` description to call out that it equals `id` for story hits and points to the parent story for comment hits. Tightened the empty-results `message` description to read more naturally.
13
+ - `hn_get_thread`: typo fix and clarity in two field descriptions — `commentId` → `comment's itemId` in the `depth` guidance, and `comments[]` description now spells out the BFS-by-rank order instead of leaning on the abbreviation.
14
+ - `CLAUDE.md`: synced agent protocol header from `0.4.0` to current.
15
+
16
+
17
+
18
+ ## Changed
19
+
20
+ - Bumped `@cyanheads/mcp-ts-core` from `^0.7.0` to `^0.8.17`. Brings the typed-error-contract API (`tool({ errors: […] })` + `ctx.fail(reason, …)` + `ctx.recoveryFor(reason)`), recovery-hint mirroring into `content[]`, the `Framework Antipatterns` devcheck step, two new project skills (`api-canvas`, `tool-defs-analysis`), and refinements to several existing skills. No runtime breaks.
21
+ - `hn_get_thread`: declared `errors: [{ reason: 'item_not_found', code: NotFound, when, recovery }]`. Replaced `notFound()` throw with `ctx.fail('item_not_found', …, { itemId, ...ctx.recoveryFor('item_not_found') })` so the recovery hint flows onto the wire and is mirrored into rendered text for `format()`-only clients.
22
+ - `hn_get_user`: same treatment for `user_not_found` — typed contract, `ctx.fail`, recovery spread.
23
+ - `hn_search_content`: empty-result responses now include an optional `message` field that names which filters were applied (`tags`, `author`, `minPoints`, `dateRange`) so the agent knows what to relax. Rendered as a recovery sentence when no hits, and as a `>` blockquote footer on non-empty pages whenever a message was generated. Output schema gains the `message?` field.
24
+ - `HnService.parseJsonBody`: HTML-error-body throw (rate-limited upstream returning 200 OK with HTML) now carries `data: { upstream, reason: 'upstream_html', recovery: { hint } }`, so service-layer failures expose the same shape `format()`-only clients get from the typed contract.
25
+ - Tool descriptions and field `.describe()` strings tightened across all four tools — sharper guidance on `count`/`offset`/`depth`/`maxComments`, and the `type` field now lists the actual HN item types.
26
+ - Bumped `@biomejs/biome` (2.4.13 → 2.4.14) and `tsc-alias` (1.8.16 → 1.8.17).
27
+
28
+ ## Added
29
+
30
+ - `scripts/check-framework-antipatterns.ts` and a matching `Framework Antipatterns` step in `devcheck` — flags SDK-coupling shortcuts that bypass framework primitives.
31
+ - `scripts/split-changelog.ts` — framework helper for splitting `CHANGELOG.md` into per-version files.
32
+ - Project skills synced from `mcp-ts-core@0.8.17`: added `api-canvas` (DataCanvas + spillover), `tool-defs-analysis` (read-only audit of MCP definition language); refreshed `add-service`, `add-tool`, `api-config`, `api-context`, `api-errors`, `api-linter`, `api-workers`, `design-mcp-server`, `field-test`, `maintenance`, `release-and-publish`, `report-issue-framework`, `report-issue-local`, `security-pass`, `setup`. Propagated to `.claude/skills/`.
33
+
34
+ ## Removed
35
+
36
+ - `dev:stdio` and `dev:http` package scripts — `bun --watch src/index.ts` is invoked directly.
@@ -0,0 +1,23 @@
1
+ ---
2
+ summary: "Maintenance. Framework `^0.8.17 → ^0.8.20` (bundles `hono` security patches GHSA-p77w-8qqv-26rm / GHSA-qp7p-654g-cw7p / GHSA-hm8q-7f3q-5f36). Engine bumps `bun >=1.3` / `node >=24`, Dockerfile base `oven/bun:1.3`. `@hono/otel` + `pino-pretty` moved to devDependencies. New `api-telemetry` skill."
3
+ breaking: false
4
+ security: true
5
+ ---
6
+
7
+ # 0.4.3 — 2026-05-11
8
+
9
+ Maintenance release — framework bump, runtime engine bump, dependency reorg. No application code changes.
10
+
11
+ ## Changed
12
+
13
+ - Bumped `@cyanheads/mcp-ts-core` from `^0.8.17` to `^0.8.20`. Brings: `ctx.auth.token` reaches handlers (0.8.18, [cyanheads/mcp-ts-core#121](https://github.com/cyanheads/mcp-ts-core/issues/121)); telemetry visualization docs + `api-telemetry` skill (0.8.19, [cyanheads/mcp-ts-core#125](https://github.com/cyanheads/mcp-ts-core/issues/125)); `mcp_tool_scopes` claim union and `MCP_AUTH_DISABLE_SCOPE_CHECKS` bypass for OIDC providers that can't inject scopes into `scope` (0.8.20, [cyanheads/mcp-ts-core#128](https://github.com/cyanheads/mcp-ts-core/issues/128)). Bundles `hono` security patches (GHSA-p77w-8qqv-26rm, GHSA-qp7p-654g-cw7p, GHSA-hm8q-7f3q-5f36). No surface this server exposes is affected, but the floor is now pinned to a patched `hono` peer. No runtime breaks for this server.
14
+ - **Engines:** `bun >=1.2.0 → >=1.3.0`, `node >=22.0.0 → >=24.0.0`. Mirrors the framework's new minimums.
15
+ - **Dockerfile:** base image `oven/bun:1 → oven/bun:1.3` (build + runtime stages).
16
+ - **Dependency reorg:** `@hono/otel` and `pino-pretty` moved from `dependencies` to `devDependencies`. Both are optional framework peers — this server doesn't emit OTel HTTP middleware traces and doesn't ship pretty-printed logs in production. Removing them from the runtime dependency set drops install size without affecting behavior.
17
+ - **Dependency refresh:** `@cyanheads/mcp-ts-core ^0.8.17 → ^0.8.20`, `@biomejs/biome ^2.4.14 → ^2.4.15`, `@types/node ^25.6.0 → ^25.6.2`, `@hono/otel ^1.1.1 → ^1.1.2` (now dev-only).
18
+
19
+ ## Added
20
+
21
+ - Project skill synced from `mcp-ts-core@0.8.19`: `api-telemetry` — catalog of every span, metric, attribute, completion-log field, env var, and runtime caveat the framework emits. Cross-linked from `api-utils` (now scoped to the helper API only) and from the `CLAUDE.md` skill index.
22
+ - `scripts/build-changelog.ts` resynced from upstream: adds `security: boolean` frontmatter flag that renders a `🛡️ Security` badge in the rollup, alongside the existing `breaking` flag.
23
+ - Refreshed skills synced from upstream (no version regressions): `api-auth` 1.0 → 1.1 (OIDC operator setup, claim-union table, bypass flag), `api-config` 1.3 → 1.4 (new `MCP_AUTH_DISABLE_SCOPE_CHECKS` env row), `api-utils` 2.1 → 2.2 (telemetry section points at the new `api-telemetry` skill), `maintenance` 2.0 → 2.1 (Phase C now resyncs pristine reference files like `changelog/template.md`), `report-issue-framework` 1.5 → 1.6 and `report-issue-local` 1.4 → 1.5 (terser issue-writing guidance, `bun 1.3.x` examples), `security-pass` 1.3 → 1.4 (bypass-in-production check), `setup` 1.6 → 1.7 (`bunx` over `npx`, substituted-name verification, `release-and-publish` in progression), `tool-defs-analysis` 1.0 → 1.1 (env vars no longer flagged as recovery-hint smell). All propagated to `.claude/skills/`.
@@ -0,0 +1,27 @@
1
+ ---
2
+ summary: "Enrichment release. Four new fields: `domain` on stories/search hits (hostname extracted from `url`), `highlights` on search hits (Algolia `_highlightResult` with `<em>…</em>` preserved), `isOp` on thread comments (author equals root item author), `omitted: { deleted, dead }` counters on threads. Closes #1, #2, #3, #4."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.5.0 — 2026-05-11
8
+
9
+ Enrichment release — surfaces signal that was being dropped on the floor. Four feature additions across three tools, no breaking changes. Closes [#1](https://github.com/cyanheads/hn-mcp-server/issues/1), [#2](https://github.com/cyanheads/hn-mcp-server/issues/2), [#3](https://github.com/cyanheads/hn-mcp-server/issues/3), [#4](https://github.com/cyanheads/hn-mcp-server/issues/4).
10
+
11
+ ## Added
12
+
13
+ - `hn_get_stories`, `hn_search_content`: new `domain` field on each result — bare hostname extracted from `url`, lowercased with leading `www.` stripped (e.g. `https://www.github.com/x` → `github.com`). Absent when `url` is missing or unparseable. Rendered as `(domain)` after the title in `format()` so the LLM and humans can pattern-match source at a glance instead of squinting at full URLs. Closes [#2](https://github.com/cyanheads/hn-mcp-server/issues/2).
14
+ - `hn_search_content`: new optional `highlights` object on each hit — projects Algolia's `_highlightResult` into `{ title?, text?, matchedWords[] }`. `title`/`text` preserve `<em>…</em>` markers around matched terms (other HTML stripped via the new `stripHtmlPreservingEm` helper); `text` falls back from `comment_text` to `story_text` to match the `text` mapping; `matchedWords` is the deduplicated union across all six searchable Algolia fields. Rendered as a `> match — …` footer alongside the raw title/body so structured consumers and `format()`-only clients both see what matched. Absent when `_highlightResult` is missing or no field produced a match. Closes [#1](https://github.com/cyanheads/hn-mcp-server/issues/1).
15
+ - `hn_get_thread`: new `isOp: boolean` field on each comment — true when the comment author equals the root item author (OP replying within their own thread), false when either author is missing. Rendered in `format()` as `**author (OP)**` in the comment header and as the literal `isOp:<bool>` token in the meta line. Closes [#3](https://github.com/cyanheads/hn-mcp-server/issues/3).
16
+ - `hn_get_thread`: new `omitted: { deleted, dead }` counters on the response — surfaces how many comments BFS traversal dropped because HN flagged them as moderated, so callers can tell a partial view apart from a `maxComments`-truncated one. Rendered as `(N deleted, M dead — omitted from this view)` footer when nonzero. Counts apply to the per-request BFS only; `filterLiveItems` (used by `hn_get_stories`, `hn_get_user`) continues to silently drop dead/deleted entries. Closes [#4](https://github.com/cyanheads/hn-mcp-server/issues/4).
17
+ - `extractDomain(url)` and `stripHtmlPreservingEm(html)` exported from `services/hn/hn-service.ts` — domain extraction reused by both `hn_get_stories` and `hn_search_content`; the EM-preserving stripper masks `<em>`/`</em>` with sentinel tokens before delegating to `stripHtml`, mirroring how code blocks are preserved.
18
+ - `AlgoliaHighlightValue` interface + `_highlightResult` field on `AlgoliaHit` in `services/hn/types.ts`.
19
+
20
+ ## Changed
21
+
22
+ - `hn_get_thread`: format() author line now reads `**author (OP)**` for OP comments instead of plain `**author**`. Meta line gains `isOp:<bool>` token.
23
+ - `hn_get_thread`: comment meta line gains `isOp:<bool>` token (required by the linter's format-parity rule for boolean schema fields).
24
+
25
+ ## Tests
26
+
27
+ - 147 passing (up from 111). New coverage: `extractDomain` and `stripHtmlPreservingEm` edge cases; domain derivation, omission, and rendering across `hn_get_stories` and `hn_search_content`; highlight mapping including comment-to-story fallback, dedup, and absence cases; thread `omitted` counting and `isOp` true/false/missing-author paths.
@@ -0,0 +1,24 @@
1
+ ---
2
+ summary: "`hn_get_thread` schema patch: `comments[].isOp` and `omitted` are now absence-by-default. `isOp` changed `z.boolean()` → `z.literal(true).optional()`; `omitted` made optional. Wire payload shrinks on the common case (no OP reply, no moderation truncation); `format()` output unchanged."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.5.1 — 2026-05-11
8
+
9
+ Patch to `hn_get_thread` — two response fields that were always present but rarely informative (`comments[].isOp` and `omitted`) are now absence-by-default and only emitted when they carry signal. The 0.5.0 shape required `isOp: boolean` on every comment and `omitted: { deleted, dead }` on every response, which on the common case (no OP reply, no moderation truncation) emitted `false` and `{ 0, 0 }` for zero information. Aligns these two fields with the rest of the schema — `title`, `url`, `score`, `text`, etc. are all absent-when-missing rather than `null`-filled. Wire payload shrinks across both fields; `format()` output is unchanged on the common case and identical on the signal case.
10
+
11
+ ## Changed
12
+
13
+ - `hn_get_thread`: `comments[].isOp` schema changed from `z.boolean()` to `z.literal(true).optional()`. Field is omitted from `structuredContent` when the comment is not an OP reply (including when either author is missing).
14
+ - `hn_get_thread`: `omitted` schema changed from required to `.optional()`. Field is omitted from `structuredContent` when no comments were dropped during BFS traversal. Present only when `deleted > 0 || dead > 0`.
15
+ - `hn_get_thread`: `format()` meta line emits the `| isOp:true` token only when the field is present and true. The `**author (OP)**` author suffix continues to render unchanged when `isOp: true`. `format()` already gated the omitted-summary footer on `> 0` in 0.5.0, so rendered output is unchanged.
16
+
17
+ ## Consumer contract
18
+
19
+ - Treat missing `comments[i].isOp` as "not OP" rather than "unknown". Truthy checks (`if (c.isOp)`, `c.isOp === true`) work identically to 0.5.0; only `c.isOp === false` flips behavior (and was always the wrong way to check).
20
+ - Treat missing `omitted` as `{ deleted: 0, dead: 0 }`. Same pattern.
21
+
22
+ ## Tests
23
+
24
+ - 147 passing. Updated assertions in three handler tests (`isOp: false` → `not.toHaveProperty('isOp')`), removed `isOp: false` from four format-test fixtures, strengthened the OP format test to verify `| isOp:true` appears for the OP comment and `isOp:false` never appears in rendered output. Updated two handler tests for `omitted` absence (`expect(result).not.toHaveProperty('omitted')`) and removed the now-redundant `omitted: { deleted: 0, dead: 0 }` lines from six format-test fixtures.
@@ -0,0 +1,24 @@
1
+ ---
2
+ summary: "@cyanheads/mcp-ts-core ^0.9.21 → ^0.10.6 — truncation enrichment signals on every tool, explicit server identity, hardened MCPB bundle packaging"
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.5.10 — 2026-06-12
8
+
9
+ ## Added
10
+
11
+ - **Truncation enrichment** — `hn_get_stories`, `hn_get_thread`, `hn_get_user`, and `hn_search_content` emit `truncated`/`shown`/`cap` enrichment fields via `ctx.enrich.truncated()` when a result is capped by its count/`maxComments`/`submissionCount` parameter.
12
+ - **`HEALTHCHECK`** — the Docker image now probes `/healthz` (30s interval) so orchestrators see container health.
13
+
14
+ ## Changed
15
+
16
+ - **`@cyanheads/mcp-ts-core` ^0.9.21 → ^0.10.6** — framework adoption.
17
+ - **Server identity** — `createApp()` now sets `name`/`title` to `hn-mcp-server` explicitly; `.codex-plugin` `displayName` drops the npm scope.
18
+ - **`bundle`** — runs `scripts/clean-mcpb.ts` after `mcpb pack`: official dev-dependency prune plus an exact-name strip of dependency-shipped agent docs (`skills/`, `.claude/`, `.agents/`, `SKILL.md`) nested under `node_modules/` that root-anchored `.mcpbignore` patterns cannot reach.
19
+ - **`lint:packaging`** — adds bundle-content guards (root dev dirs excluded, `.mcpbignore` patterns anchored, critical runtime paths preserved, built `.mcpb` free of agent-doc entries) and an identity check (`name`/`title`/manifest `display_name` equal the unscoped package name).
20
+ - **`check-framework-antipatterns`** — adds a `z.coerce.boolean()` env-flag rule (`Boolean("false")` is `true` — use `z.stringbool()`) and skips comment lines so documented mentions don't trip the scan.
21
+ - **`.mcpbignore`** — root dev-dir patterns anchored with a leading `/`; `.agents/` and `skills/` added.
22
+ - **Skill sync** — vendored skills resynced to the framework version; `add-export`, `add-provider`, and `techniques` added; `skills/README.md` added.
23
+ - **`hono` ^4.12.23 → ^4.12.25**, **`@types/node` ^25.9.1 → ^25.9.3**.
24
+ - **`typescript` ^6.0.3 → ^5.9.3** — pinned to 5.x (TS 6 not yet adopted); allowlisted in `devcheck` outdated.
@@ -0,0 +1,27 @@
1
+ ---
2
+ summary: "@cyanheads/mcp-ts-core ^0.10.6 → ^0.10.9 — check-dependency-specifiers + plugin-manifest devcheck guards, ctx.content collector, canvas SQL gate classification; dropped unused direct hono dependency; TypeScript 6 adopted"
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.5.11 — 2026-06-20
8
+
9
+ ## Changed
10
+
11
+ - **`@cyanheads/mcp-ts-core` ^0.10.6 → ^0.10.9** — framework adoption. Brings the `check-dependency-specifiers` devcheck step (rejects floating `latest`/`*`/dist-tag specifiers in `package.json` and `bun.lock`'s `workspaces` map), `lint:packaging` check 10 (validates `.claude-plugin`/`.codex-plugin` manifest descriptions, unscoped display identity, and full-name `npx -y` install args), the `ctx.content` collector for image/audio blocks, sharper canvas SQL gate classification (`SELECT`-shaped prepare failures now throw `invalid_sql` with DuckDB binder detail), fresh-scaffold guards in `build-changelog`/`devcheck`, a `check-skill-versions` worktree-deletion guard, and the `DuckdbProvider.describe()` filter-qualification fix.
12
+ - **`devcheck.config.json`** — added `packaging.pluginManifests: true` to opt into the new plugin-manifest checks.
13
+ - **`.codex-plugin/plugin.json`** — populated the previously empty `interface.longDescription`.
14
+ - **Skill sync** — vendored `skills/` resynced to the framework version (14 updated); `add-export` and `add-provider` pruned (removed upstream); `scripts/` maintenance helpers re-synced, adding `scripts/check-dependency-specifiers.ts`.
15
+ - **`typescript` ^5.9.3 → ^6.0.3** — TypeScript 6 adopted (reverses the 0.5.10 hold).
16
+
17
+ ## Removed
18
+
19
+ - **Unused direct `hono` dependency** — dropped from `package.json`. It was unused in source and escalated a transitive `hono` advisory into a false direct-dependency security-audit failure; `hono` remains available transitively via `@cyanheads/mcp-ts-core`.
20
+
21
+ ### Dependency bumps
22
+
23
+ - `@cyanheads/mcp-ts-core` ^0.10.6 → ^0.10.9
24
+ - `@biomejs/biome` ^2.4.16 → ^2.5.0
25
+ - `@types/node` ^25.9.3 → ^26.0.0
26
+ - `typescript` ^5.9.3 → ^6.0.3
27
+ - `vitest` ^4.1.8 → ^4.1.9