@cyanheads/mcp-ts-core 0.5.4 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/CLAUDE.md +39 -1
  2. package/README.md +1 -1
  3. package/changelog/0.1.x/0.1.0.md +78 -0
  4. package/changelog/0.1.x/0.1.1.md +28 -0
  5. package/changelog/0.1.x/0.1.10.md +32 -0
  6. package/changelog/0.1.x/0.1.11.md +51 -0
  7. package/changelog/0.1.x/0.1.12.md +21 -0
  8. package/changelog/0.1.x/0.1.13.md +16 -0
  9. package/changelog/0.1.x/0.1.14.md +20 -0
  10. package/changelog/0.1.x/0.1.15.md +24 -0
  11. package/changelog/0.1.x/0.1.16.md +17 -0
  12. package/changelog/0.1.x/0.1.17.md +14 -0
  13. package/changelog/0.1.x/0.1.18.md +18 -0
  14. package/changelog/0.1.x/0.1.19.md +19 -0
  15. package/changelog/0.1.x/0.1.2.md +25 -0
  16. package/changelog/0.1.x/0.1.20.md +21 -0
  17. package/changelog/0.1.x/0.1.21.md +17 -0
  18. package/changelog/0.1.x/0.1.22.md +28 -0
  19. package/changelog/0.1.x/0.1.23.md +23 -0
  20. package/changelog/0.1.x/0.1.24.md +17 -0
  21. package/changelog/0.1.x/0.1.25.md +16 -0
  22. package/changelog/0.1.x/0.1.26.md +22 -0
  23. package/changelog/0.1.x/0.1.27.md +30 -0
  24. package/changelog/0.1.x/0.1.28.md +16 -0
  25. package/changelog/0.1.x/0.1.29.md +19 -0
  26. package/changelog/0.1.x/0.1.3.md +22 -0
  27. package/changelog/0.1.x/0.1.4.md +17 -0
  28. package/changelog/0.1.x/0.1.5.md +25 -0
  29. package/changelog/0.1.x/0.1.6.md +26 -0
  30. package/changelog/0.1.x/0.1.7.md +29 -0
  31. package/changelog/0.1.x/0.1.8.md +33 -0
  32. package/changelog/0.1.x/0.1.9.md +19 -0
  33. package/changelog/0.2.x/0.2.0.md +32 -0
  34. package/changelog/0.2.x/0.2.1.md +12 -0
  35. package/changelog/0.2.x/0.2.10.md +38 -0
  36. package/changelog/0.2.x/0.2.11.md +29 -0
  37. package/changelog/0.2.x/0.2.12.md +31 -0
  38. package/changelog/0.2.x/0.2.2.md +19 -0
  39. package/changelog/0.2.x/0.2.3.md +15 -0
  40. package/changelog/0.2.x/0.2.4.md +24 -0
  41. package/changelog/0.2.x/0.2.5.md +27 -0
  42. package/changelog/0.2.x/0.2.6.md +23 -0
  43. package/changelog/0.2.x/0.2.7.md +23 -0
  44. package/changelog/0.2.x/0.2.8.md +12 -0
  45. package/changelog/0.2.x/0.2.9.md +25 -0
  46. package/changelog/0.3.x/0.3.0.md +45 -0
  47. package/changelog/0.3.x/0.3.1.md +16 -0
  48. package/changelog/0.3.x/0.3.2.md +24 -0
  49. package/changelog/0.3.x/0.3.3.md +31 -0
  50. package/changelog/0.3.x/0.3.4.md +31 -0
  51. package/changelog/0.3.x/0.3.5.md +32 -0
  52. package/changelog/0.3.x/0.3.6.md +48 -0
  53. package/changelog/0.3.x/0.3.7.md +23 -0
  54. package/changelog/0.3.x/0.3.8.md +21 -0
  55. package/changelog/0.4.x/0.4.0.md +38 -0
  56. package/changelog/0.4.x/0.4.1.md +31 -0
  57. package/changelog/0.5.x/0.5.0.md +29 -0
  58. package/changelog/0.5.x/0.5.1.md +18 -0
  59. package/changelog/0.5.x/0.5.2.md +38 -0
  60. package/changelog/0.5.x/0.5.3.md +26 -0
  61. package/changelog/0.5.x/0.5.4.md +29 -0
  62. package/changelog/0.6.x/0.6.0.md +39 -0
  63. package/changelog/unreleased.md +40 -0
  64. package/dist/cli/init.js +1 -0
  65. package/dist/cli/init.js.map +1 -1
  66. package/dist/core/app.d.ts +13 -3
  67. package/dist/core/app.d.ts.map +1 -1
  68. package/dist/core/app.js +20 -13
  69. package/dist/core/app.js.map +1 -1
  70. package/dist/core/index.d.ts +1 -0
  71. package/dist/core/index.d.ts.map +1 -1
  72. package/dist/core/index.js.map +1 -1
  73. package/dist/core/serverManifest.d.ts +237 -0
  74. package/dist/core/serverManifest.d.ts.map +1 -0
  75. package/dist/core/serverManifest.js +310 -0
  76. package/dist/core/serverManifest.js.map +1 -0
  77. package/dist/core/worker.d.ts.map +1 -1
  78. package/dist/core/worker.js +2 -2
  79. package/dist/core/worker.js.map +1 -1
  80. package/dist/linter/rules/landing-rules.d.ts +15 -0
  81. package/dist/linter/rules/landing-rules.d.ts.map +1 -0
  82. package/dist/linter/rules/landing-rules.js +125 -0
  83. package/dist/linter/rules/landing-rules.js.map +1 -0
  84. package/dist/linter/types.d.ts +5 -2
  85. package/dist/linter/types.d.ts.map +1 -1
  86. package/dist/linter/validate.d.ts.map +1 -1
  87. package/dist/linter/validate.js +5 -0
  88. package/dist/linter/validate.js.map +1 -1
  89. package/dist/mcp-server/transports/http/httpTransport.d.ts +4 -3
  90. package/dist/mcp-server/transports/http/httpTransport.d.ts.map +1 -1
  91. package/dist/mcp-server/transports/http/httpTransport.js +47 -26
  92. package/dist/mcp-server/transports/http/httpTransport.js.map +1 -1
  93. package/dist/mcp-server/transports/http/httpTypes.d.ts +0 -12
  94. package/dist/mcp-server/transports/http/httpTypes.d.ts.map +1 -1
  95. package/dist/mcp-server/transports/http/landing-page.d.ts +48 -0
  96. package/dist/mcp-server/transports/http/landing-page.d.ts.map +1 -0
  97. package/dist/mcp-server/transports/http/landing-page.js +912 -0
  98. package/dist/mcp-server/transports/http/landing-page.js.map +1 -0
  99. package/dist/mcp-server/transports/http/serverCard.d.ts +67 -0
  100. package/dist/mcp-server/transports/http/serverCard.d.ts.map +1 -0
  101. package/dist/mcp-server/transports/http/serverCard.js +91 -0
  102. package/dist/mcp-server/transports/http/serverCard.js.map +1 -0
  103. package/dist/mcp-server/transports/manager.d.ts +3 -3
  104. package/dist/mcp-server/transports/manager.d.ts.map +1 -1
  105. package/dist/mcp-server/transports/manager.js +4 -4
  106. package/dist/mcp-server/transports/manager.js.map +1 -1
  107. package/dist/utils/formatting/html.d.ts +76 -0
  108. package/dist/utils/formatting/html.d.ts.map +1 -0
  109. package/dist/utils/formatting/html.js +111 -0
  110. package/dist/utils/formatting/html.js.map +1 -0
  111. package/dist/utils/formatting/index.d.ts +1 -0
  112. package/dist/utils/formatting/index.d.ts.map +1 -1
  113. package/dist/utils/formatting/index.js +1 -0
  114. package/dist/utils/formatting/index.js.map +1 -1
  115. package/dist/utils/index.d.ts +1 -1
  116. package/dist/utils/index.d.ts.map +1 -1
  117. package/dist/utils/index.js +1 -1
  118. package/dist/utils/index.js.map +1 -1
  119. package/package.json +5 -1
  120. package/scripts/build-changelog.ts +222 -0
  121. package/scripts/devcheck.ts +16 -1
  122. package/scripts/tree.ts +3 -0
  123. package/skills/add-app-tool/SKILL.md +2 -4
  124. package/skills/add-prompt/SKILL.md +2 -4
  125. package/skills/add-resource/SKILL.md +2 -4
  126. package/skills/add-service/SKILL.md +2 -4
  127. package/skills/add-tool/SKILL.md +6 -5
  128. package/skills/api-context/SKILL.md +2 -2
  129. package/skills/api-services/SKILL.md +1 -1
  130. package/skills/api-services/references/graph.md +1 -1
  131. package/skills/api-utils/SKILL.md +1 -1
  132. package/skills/api-utils/references/parsing.md +1 -1
  133. package/skills/api-utils/references/security.md +1 -1
  134. package/skills/design-mcp-server/SKILL.md +2 -2
  135. package/skills/maintenance/SKILL.md +12 -11
  136. package/skills/polish-docs-meta/SKILL.md +24 -9
  137. package/skills/release/SKILL.md +21 -7
  138. package/skills/setup/SKILL.md +4 -8
  139. package/templates/AGENTS.md +23 -1
  140. package/templates/CLAUDE.md +23 -1
  141. package/templates/changelog/unreleased.md +40 -0
  142. package/templates/package.json +3 -0
@@ -0,0 +1,45 @@
1
+ ---
2
+ summary: MCP Apps integration — appTool and appResource builders, _meta passthrough, linter pairing rules, template echo app, and comprehensive test coverage
3
+ breaking: false
4
+ ---
5
+
6
+ # 0.3.0 — 2026-04-06
7
+
8
+ MCP Apps integration — `appTool()` and `appResource()` builders, `_meta` passthrough, linter rules for app tool/resource pairing, template examples, and comprehensive test coverage.
9
+
10
+ ## Added
11
+
12
+ - **MCP Apps builders** — `appTool()` and `appResource()` convenience builders (`src/mcp-server/apps/appBuilders.ts`). `appTool()` auto-populates `_meta.ui.resourceUri` and the backwards-compat `ui/resourceUri` key. `appResource()` defaults `mimeType` to `text/html;profile=mcp-app` and `annotations.audience` to `['user']`. Both re-exported from the main entry point.
13
+ - **`APP_RESOURCE_MIME_TYPE` constant** — Exported from main entry point, matches `@modelcontextprotocol/ext-apps/server` without requiring the peer dep.
14
+ - **`_meta` passthrough** — `ResourceDefinition` and `TaskToolDefinition` interfaces now accept `_meta`. Tool and resource registration passes `_meta` through to the SDK.
15
+ - **Linter: `_meta.ui` validation** — New rules `meta-ui-type`, `meta-ui-resource-uri-required`, and `meta-ui-resource-uri-scheme` validate tool `_meta.ui` fields at startup.
16
+ - **Linter: app tool ↔ resource pairing** — `lintAppToolResourcePairing()` cross-checks that every tool declaring `_meta.ui.resourceUri` has a matching registered resource. Warns on mismatch. Supports RFC 6570 URI template matching.
17
+ - **Template: echo app** — `templates/src/mcp-server/tools/definitions/echo-app.app-tool.ts` and `templates/src/mcp-server/resources/definitions/echo-app-ui.app-resource.ts` demonstrate the full MCP Apps pattern for scaffolded servers.
18
+ - **`add-app-tool` skill** — Step-by-step guide for scaffolding MCP App tool + UI resource pairs.
19
+
20
+ ## Fixed
21
+
22
+ - **`appTool()` clobbered `extraMeta.ui` fields** — The builder overwrote caller-supplied `_meta.ui` sub-fields (e.g. `visibility`) with only `{ resourceUri }`. Now merges `extraMeta.ui` fields with the auto-populated `resourceUri` (which still wins over any `extraMeta.ui.resourceUri`).
23
+ - **Linter false positive on `{+path}` URI templates** — `lintAppToolResourcePairing()` replaced all RFC 6570 expressions with `[^/]+`, causing `{+var}` (reserved expansion) and `{/var}` (path segments) to fail matching URIs containing `/`. Now uses `.+` for slash-expanding operators.
24
+ - **Template echo app missing CSP allowlist** — The scaffolded echo app resource imports `@modelcontextprotocol/ext-apps` from `unpkg.com` but did not declare `_meta.ui.csp.resourceDomains`. Hosts enforcing deny-by-default CSP would block the import. Added `resourceDomains: ['https://unpkg.com']` to the template and skill doc.
25
+ - **CSP field name casing** — Corrected `resource_domains` (snake_case) to `resourceDomains` (camelCase) in JSDoc examples and tests to match the `McpUiResourceCsp` interface from `@modelcontextprotocol/ext-apps`.
26
+
27
+ ## Tests
28
+
29
+ - `appBuilders.test.ts` — 414 lines covering `appTool()` and `appResource()` field passthrough, `_meta` population, defaults, and edge cases.
30
+ - `tool-rules.test.ts` — 285 lines covering `lintToolDefinition` `_meta.ui` validation and `lintAppToolResourcePairing` cross-check.
31
+ - `validate.test.ts` — +195 lines for `_meta.ui` rules and app tool ↔ resource pairing in the integration linter.
32
+ - `resource-registration.test.ts` — +39 lines for `_meta` passthrough to `server.resource`.
33
+ - `tool-registration.test.ts` — +62 lines for `_meta` passthrough to `server.registerTool` and `registerToolTask`.
34
+ - `mcp-apps.int.test.ts` — 258-line end-to-end integration test covering builder output → linter validation → handler execution → format output.
35
+ - `template-echo-app.app-tool.test.ts` — 115-line smoke test for the echo app tool pattern.
36
+ - `echo-app-ui.app-resource.test.ts` — 95-line smoke test for the echo app UI resource pattern.
37
+
38
+ ## Dependencies
39
+
40
+ - `dotenv` 17.4.0 → 17.4.1
41
+ - `hono` 4.12.10 → 4.12.11
42
+ - `@cloudflare/workers-types` ^4.20260403.1 → ^4.20260405.1
43
+ - `msw` ^2.12.14 → ^2.13.0
44
+ - `vite` 8.0.3 → 8.0.5
45
+ - `biome.json` schema 2.4.9 → 2.4.10
@@ -0,0 +1,16 @@
1
+ ---
2
+ summary: Promote @opentelemetry/api to direct dependency, add structural test guarding against eager optional peer dep imports
3
+ breaking: false
4
+ ---
5
+
6
+ # 0.3.1 — 2026-04-06
7
+
8
+ Promoted `@opentelemetry/api` to a direct dependency and added a structural test to prevent eager imports of optional peer deps.
9
+
10
+ ## Fixed
11
+
12
+ - **`@opentelemetry/api` promoted to direct dependency** — Moved from optional `peerDependencies` to `dependencies`. The package is eagerly imported in `errorHandler.js` and other source files, causing `ERR_MODULE_NOT_FOUND` crashes for consumers who don't install it (e.g., `bunx` invocations). Removed the corresponding `peerDependenciesMeta` entry. Closes #21.
13
+
14
+ ## Tests
15
+
16
+ - **Optional peer dep import guard** — New structural test (`tests/unit/packaging/optional-peer-deps.test.ts`) scans all source files and fails if any optional peer dependency is eagerly imported (value import). Only `import type` and dynamic `import()` are allowed for optional deps. Relies on `verbatimModuleSyntax: true` to distinguish type-only from value imports.
@@ -0,0 +1,24 @@
1
+ ---
2
+ summary: Richer GET /mcp status response — protocolVersions, extensions, framework homepage, mcpServerHomepage config field
3
+ breaking: false
4
+ ---
5
+
6
+ # 0.3.2 — 2026-04-06
7
+
8
+ Richer HTTP status response and `mcpServerHomepage` config field.
9
+
10
+ ## Added
11
+
12
+ - **`mcpServerHomepage` config field** — Opt-in server homepage URL via `MCP_SERVER_HOMEPAGE` env var. Surfaced in the `GET /mcp` status response under `server.homepage`. No automatic fallback from `pkg.homepage` — must be explicitly set.
13
+ - **`protocolVersions` in status response** — `GET /mcp` now includes the list of supported MCP protocol versions.
14
+ - **`extensions` in status response** — `GET /mcp` now reports which SEP-2133 extensions are active (currently advertises `io.modelcontextprotocol/ui` when present).
15
+ - **Framework homepage in status response** — `GET /mcp` `framework` section now includes `homepage` linking to the GitHub repo.
16
+
17
+ ## Changed
18
+
19
+ - **`DefinitionCounts` → `ServerMeta`** — Internal refactor: `DefinitionCounts` wrapped into a `ServerMeta` interface that carries both definition counts and extensions. Threaded through `composeServices()` → `TransportManager` → `createHttpApp`/`startHttpTransport`. No public API change — `DefinitionCounts` type still exported.
20
+
21
+ ## Dependencies
22
+
23
+ - `dotenv` 17.4.0 → 17.4.1
24
+ - `hono` 4.12.10 → 4.12.11
@@ -0,0 +1,31 @@
1
+ ---
2
+ summary: Static-URI resource registration fix — ResourceRegistry uses SDK string overload for non-template URIs, MCP Apps template cleanup, dependency updates
3
+ breaking: false
4
+ ---
5
+
6
+ # 0.3.3 — 2026-04-08
7
+
8
+ Static-URI resource registration fix, MCP Apps template cleanup, and dependency/security updates.
9
+
10
+ ## Fixed
11
+
12
+ - **Static-URI resources register through the SDK exact-resource path** — `ResourceRegistry` now registers resources without URI template variables via `server.resource(name, uriString, ...)` instead of always wrapping them in `ResourceTemplate`. This prevents static resources from being double-listed by clients that merge `resources/list` and `resources/templates/list`, and restores automatic discoverability for static `ui://` resources without a manual `list()` callback. Closes #30.
13
+ - **MCP Apps static UI template no longer teaches the workaround** — Removed the redundant `list()` callback from the scaffolded `echo-app-ui` resource and aligned the integration/smoke tests with the corrected static-resource behavior.
14
+
15
+ ## Tests
16
+
17
+ - Added regression coverage to ensure static URIs use the SDK string overload while templated URIs still register via `ResourceTemplate`.
18
+ - Updated MCP Apps integration and smoke tests to assert that static `ui://` resources do not require a manual `list()` callback.
19
+
20
+ ## Dependencies
21
+
22
+ - `@hono/node-server` 1.19.12 → 1.19.13
23
+ - `hono` 4.12.11 → 4.12.12
24
+ - `@cloudflare/workers-types` ^4.20260405.1 → ^4.20260408.1
25
+ - `@supabase/supabase-js` ^2.101.1 → ^2.102.1
26
+ - `@vitest/coverage-istanbul` 4.1.2 → 4.1.3
27
+ - `@vitest/ui` 4.1.2 → 4.1.3
28
+ - `msw` ^2.13.0 → ^2.13.2
29
+ - `openai` ^6.33.0 → ^6.34.0
30
+ - `vite` 8.0.5 → 8.0.7
31
+ - `vitest` ^4.1.2 → ^4.1.3
@@ -0,0 +1,31 @@
1
+ ---
2
+ summary: MCP Apps resource metadata and read-time formatting fixes, skill and template guidance refresh, minor dependency updates
3
+ breaking: false
4
+ ---
5
+
6
+ # 0.3.4 — 2026-04-08
7
+
8
+ MCP Apps resource metadata/read-time formatting fixes, skill/template guidance refresh, and minor dependency updates.
9
+
10
+ ## Fixed
11
+
12
+ - **`appResource()` now mirrors definition `_meta.ui` into `resources/read` content items** — MCP Apps hosts now receive CSP and permissions metadata on the returned content item even when callers rely on the default app resource formatter. Content-item `_meta.ui` still overrides app-level defaults when both are present.
13
+ - **Non-JSON resource strings preserve raw text in the default formatter** — `resource()` string results for non-JSON MIME types (including `text/html;profile=mcp-app`) are no longer JSON-quoted. JSON MIME types still stringify string payloads so JSON responses remain valid.
14
+ - **MCP Apps examples and tests use the correct CSP field names** — corrected lingering `resource_domains` examples to `resourceDomains` and aligned permissions examples with the current `@modelcontextprotocol/ext-apps` shape.
15
+ - **Echo app template applies host theming/style context** — scaffolded app HTML now listens for `onhostcontextchanged`, applies host theme/fonts/style variables, and hydrates the initial host context after connect.
16
+
17
+ ## Changed
18
+
19
+ - **Skill docs aligned with the current scaffold layout and Bun-first workflow** — add-tool/resource/prompt/service/test, setup, devcheck, maintenance, field-test, and related skills now reflect direct registration in `src/index.ts` by default, `bun run` commands, richer field-test coverage, and sparse-upstream-data guidance.
20
+ - **README API overview clarified `appResource()` behavior** — documentation now calls out that the builder applies the MCP Apps MIME type and mirrors `_meta.ui` into read content items.
21
+
22
+ ## Tests
23
+
24
+ - Added coverage for `appResource()` read-content `_meta.ui` mirroring and override behavior.
25
+ - Added regression tests for raw string passthrough on non-JSON resource MIME types and JSON encoding for JSON string payloads.
26
+ - Updated MCP Apps integration and smoke tests to assert raw HTML output, read-time CSP metadata, and host-context plumbing.
27
+
28
+ ## Dependencies
29
+
30
+ - `@cloudflare/workers-types` ^4.20260408.1 → ^4.20260409.1
31
+ - `vite` 8.0.7 → 8.0.8
@@ -0,0 +1,32 @@
1
+ ---
2
+ summary: Skill doc improvements for add-test and design-mcp-server, add-app-tool added to consumer templates, dependency updates
3
+ breaking: false
4
+ ---
5
+
6
+ # 0.3.5 — 2026-04-13
7
+
8
+ Skill doc improvements, template updates for `add-app-tool`, and dependency updates.
9
+
10
+ ## Changed
11
+
12
+ - **`add-test` skill updated test location guidance** — when a repo has existing tests, match that layout; when no tests exist, default to a root `tests/` directory mirroring `src/` structure.
13
+ - **`design-mcp-server` skill refined description guidance** — consolidated multiline string concatenation into single-line descriptions, added "don't leak implementation details" principle, tightened description length advice.
14
+ - **Consumer templates add `add-app-tool` skill** — CLAUDE.md and AGENTS.md templates now list the `add-app-tool` skill in the workflow steps and skill table.
15
+ - **Consumer template version bumped to 0.1.1.**
16
+ - **README updated** — runtime description now reads "Bun/Node/Cloudflare Workers", development commands updated (`rebuild`, `test:all`), removed `dev:stdio`/`dev:http` from the quick-reference block.
17
+
18
+ ## Dependencies
19
+
20
+ - `@biomejs/biome` 2.4.10 → 2.4.11
21
+ - `@cloudflare/workers-types` ^4.20260409.1 → ^4.20260413.1
22
+ - `@hono/node-server` 1.19.13 → 1.19.14
23
+ - `@supabase/supabase-js` ^2.102.1 → ^2.103.0
24
+ - `@types/bun` ^1.3.11 → ^1.3.12
25
+ - `@types/node` ^25.5.2 → ^25.6.0
26
+ - `@vitest/coverage-istanbul` 4.1.3 → 4.1.4
27
+ - `@vitest/ui` 4.1.3 → 4.1.4
28
+ - `bun-types` ^1.3.11 → ^1.3.12
29
+ - `dotenv` 17.4.1 → 17.4.2
30
+ - `typedoc` ^0.28.18 → ^0.28.19
31
+ - `unpdf` ^1.4.0 → ^1.5.0
32
+ - `vitest` ^4.1.3 → ^4.1.4
@@ -0,0 +1,48 @@
1
+ ---
2
+ summary: Security patches for critical protobufjs and moderate hono advisories, OTel peer dep range alignment, dependency sweep to latest
3
+ breaking: false
4
+ ---
5
+
6
+ # 0.3.6 — 2026-04-19
7
+
8
+ Security patches for two transitive/direct advisories, dependency sweep to latest, and skill guidance on tool description structure.
9
+
10
+ ## Security
11
+
12
+ - **Patched critical protobufjs advisory** (GHSA-xq3m-2v4x-88gg, CVSS 9.4) — added `protobufjs: 7.5.5` to `resolutions` to override the vulnerable 7.5.4 pulled transitively by `@grpc/proto-loader` through the OTel gRPC exporters.
13
+ - **Patched moderate hono advisory** (GHSA-458j-xx4x-4375, hono/jsx SSR HTML injection) — bumped `hono` 4.12.12 → 4.12.14 in both direct dependencies and resolutions.
14
+
15
+ ## Added
16
+
17
+ - **`design-mcp-server` skill — single-paragraph tool description guidance** — new bullet recommends packing operational guidance into one cohesive paragraph rather than bullet lists or blank-line-separated sections, since descriptions render inline in most clients and operation-by-operation bullets duplicate info that lives in the `operation` enum's `.describe()` (#33).
18
+ - **`add-tool` skill — template comment** — mirrors the single-paragraph guidance as a comment above `description:` in the scaffold so authors see it at scaffold time.
19
+
20
+ ## Changed
21
+
22
+ - **OpenTelemetry peer dependency ranges aligned with dev deps** — `^0.215.0` for `instrumentation-http`, `exporter-metrics-otlp-http`, `exporter-trace-otlp-http`, `sdk-node`; `^0.61.0` for `instrumentation-pino`; `^2.7.0` for `resources`, `sdk-metrics`, `sdk-trace-node`. Consumers pinned to 0.214/2.6 ranges will need to update.
23
+ - **Other peer dependency minimums refreshed** — `@supabase/supabase-js` ^2.99.3 → ^2.103.3, `openai` ^6.32.0 → ^6.34.0, `sanitize-html` ^2.17.2 → ^2.17.3, `unpdf` ^1.4.0 → ^1.6.0, `validator` ^13.15.26 → ^13.15.35, `js-yaml` ^4.1.0 → ^4.1.1.
24
+ - **Dropped `@types/diff` devDependency** — `diff` 9.0.0 ships its own TypeScript types; the `@types/diff` stub is deprecated.
25
+
26
+ ## Dependencies
27
+
28
+ - `@biomejs/biome` 2.4.11 → 2.4.12
29
+ - `@cloudflare/workers-types` ^4.20260413.1 → ^4.20260418.1
30
+ - `@hono/node-server` ^1.19.13 → ^1.19.14
31
+ - `@modelcontextprotocol/ext-apps` ^1.5.0 → ^1.6.0
32
+ - `@opentelemetry/exporter-metrics-otlp-http` ^0.214.0 → ^0.215.0
33
+ - `@opentelemetry/exporter-trace-otlp-http` ^0.214.0 → ^0.215.0
34
+ - `@opentelemetry/instrumentation-http` ^0.214.0 → ^0.215.0
35
+ - `@opentelemetry/instrumentation-pino` ^0.60.0 → ^0.61.0
36
+ - `@opentelemetry/resources` ^2.6.1 → ^2.7.0
37
+ - `@opentelemetry/sdk-metrics` ^2.6.1 → ^2.7.0
38
+ - `@opentelemetry/sdk-node` ^0.214.0 → ^0.215.0
39
+ - `@opentelemetry/sdk-trace-node` ^2.6.1 → ^2.7.0
40
+ - `@supabase/supabase-js` ^2.103.0 → ^2.103.3
41
+ - `diff` 8.0.4 → 9.0.0 (resolution + peer)
42
+ - `dotenv` ^17.4.1 → ^17.4.2
43
+ - `fast-check` ^4.6.0 → ^4.7.0
44
+ - `hono` 4.12.12 → 4.12.14 (direct + resolution)
45
+ - `msw` ^2.13.2 → ^2.13.4
46
+ - `sanitize-html` ^2.17.2 → ^2.17.3
47
+ - `typescript` ^6.0.2 → ^6.0.3
48
+ - `unpdf` ^1.5.0 → ^1.6.0
@@ -0,0 +1,23 @@
1
+ ---
2
+ summary: Fix pino-redact crash on Node 25 when AbortSignal in log payload — sanitizeLogBindings, 14 new tests
3
+ breaking: false
4
+ ---
5
+
6
+ # 0.3.7 — 2026-04-19
7
+
8
+ Fixes a crash introduced on Node 25+ when passing the handler `Context` object as log bindings to `fetchWithTimeout` / `withRetry` (or any logger call).
9
+
10
+ ## Fixed
11
+
12
+ - **Logger: pino-redact crash on Node 25 when context includes `AbortSignal`** (#32) — `@pinojs/redact`'s wildcard traversal (`*.*.field`) invokes `AbortSignal.aborted` with a non-branded receiver, which Node 25 now rejects with `TypeError: The AbortSignal.aborted getter can only be used on instances of AbortSignal`. Every tool/resource call whose log payload contained `ctx.signal` (or any non-plain-prototype object) crashed before fetch completion. Fix: a new `sanitizeLogBindings` step wired into pino's `formatters.log` strips functions and non-plain-prototype instances (`AbortSignal`, `Map`, `Set`, storage handles, etc.), converts `Date`/`URL` to strings, preserves primitives/plain objects/arrays/`Error` instances, and caps recursion depth at 4. Runs before redact traversal, so sensitive-field redaction continues to work unchanged.
13
+ - **Logger: `err` field no longer pre-serialized before pino sees it** — the manual `pino.stdSerializers.err(error)` call in `Logger.log` produced an object with `pinoErrProto` that the sanitizer would reject. The raw `Error` is now passed through, letting pino's default `err` serializer run *after* `formatters.log`.
14
+
15
+ ## Changed
16
+
17
+ - **`fetchWithTimeout` / `withRetry` JSDoc** — clarified that the `context` / `options.context` parameter represents log bindings, and noted that passing the handler `Context` directly is safe (the logger sanitizes non-serializable fields). The ergonomic example pattern is unchanged.
18
+
19
+ ## Tests
20
+
21
+ - **9 new sanitizer unit tests** — primitive/plain-object passthrough; `AbortSignal` stripping with a `Proxy` trip-wire asserting `aborted` is never accessed; function/method-handle stripping; `Date`/`URL` conversion; recursive non-plain-object stripping; `Map`/`Set` drop; `Error` instance preservation; circular reference survival; depth-cap truncation.
22
+ - **`fast-check` fuzz (200 runs)** — mixed-shape bindings (primitives, plain objects, `AbortSignal`, `Map`, `Set`, `Promise`, `Date`, `URL`, `Error`, functions) asserting no throws and JSON-serializable output.
23
+ - **5 new logger integration tests** — end-to-end verification with real pino: framework `Context`-like object through `logger.info`; `fetchWithTimeout` with ctx-like bindings; `withRetry` with ctx-like bindings; sensitive-field redaction still applies after sanitization; `Error` with `.cause` chain serializes correctly through pino's `err` serializer after `formatters.log` runs.
@@ -0,0 +1,21 @@
1
+ ---
2
+ summary: Fix doubled Error prefix in tool/resource error content — McpError.message now carries original message verbatim, operation context preserved in logs
3
+ breaking: false
4
+ ---
5
+
6
+ # 0.3.8 — 2026-04-19
7
+
8
+ Fixes a visible-in-content error formatting bug that surfaces on every non-`McpError` throw from a tool handler.
9
+
10
+ ## Fixed
11
+
12
+ - **Tool error content no longer has doubled `Error:` prefix** (#34) — previously, `ErrorHandler.handleError` wrapped non-`McpError` messages as `"Error in {operation}: {message}"` and stored that string as the `McpError.message`. The tool handler factory then prepended `"Error: "` when building the content block, producing `"Error: Error in tool:my_tool: something went wrong"`. `ErrorHandler.handleError` now stores the original error message on the `McpError` unchanged; the operation context is still preserved in the log line (`logger.error(\`Error in ${operation}: ...\`)`) and the `operation` field of `logContext`, where it belongs. Tool content now reads `"Error: something went wrong"`.
13
+ - **Resource error `McpError.message` no longer embeds URI-like operation token** — `resourceHandlerFactory` previously wrapped classified errors as `"Error in resource:{name}: {message}"`. The `resource:{name}:` segment read as a URI scheme and added three colons in a row when the resource name contained any separator. Resource errors now surface the original classified message; the SDK still logs with full context when it catches the thrown `McpError`.
14
+
15
+ ## Changed
16
+
17
+ - **`McpError.message` contract for framework-wrapped errors** — when `ErrorHandler.handleError` wraps a non-`McpError` throw, the resulting `McpError.message` is now the original error's message verbatim (previously prefixed with `"Error in {operation}: "`). Log output is unchanged — the operation-prefixed form still appears in the `logger.error` first argument and `logContext.operation`. Server code that pattern-matched on the old prefix in `McpError.message` (e.g., `err.message.includes('Error in')`) should switch to reading `logContext.operation` or the `operation` from the error data.
18
+
19
+ ## Tests
20
+
21
+ - Updated three assertions that encoded the old wrapped-message format: `errorHandler.test.ts` (`handleError` wraps generic Error), `prompt-registration.test.ts` (failing prompt generation), and `dateParser.test.ts` (`parseDateStringDetailed` wraps unexpected errors). All 2213 tests pass.
@@ -0,0 +1,38 @@
1
+ ---
2
+ summary: Modernized testing surface — createMockLogger, createInMemoryStorage, custom Vitest matchers, Vitest 4 projects config, shared test helpers
3
+ breaking: false
4
+ ---
5
+
6
+ # 0.4.0 — 2026-04-19
7
+
8
+ Modernizes the testing surface: new public helpers under `/testing`, custom Vitest matchers, Vitest 4 `projects` config, and consolidated test infrastructure. No behavior changes to the framework runtime.
9
+
10
+ ## Added
11
+
12
+ - **`createMockLogger()`** (`@cyanheads/mcp-ts-core/testing`) — returns a `ContextLogger` whose calls are recorded on an inspectable `calls` array. Complements `createMockContext()` for unit-testing code that accepts a `ContextLogger` standalone.
13
+ - **`createInMemoryStorage(options?)`** (`@cyanheads/mcp-ts-core/testing`) — returns a real `StorageService` backed by `InMemoryProvider`. Uses the production code path, so tenant isolation, TTL, key validation, and list pagination all match live behavior — no hand-rolled fake required when unit-testing services that depend on storage.
14
+ - **`MockContextLogger` type export** — the shape returned by `createMockLogger()`.
15
+ - **Vitest 4 `projects` config** — `vitest.config.ts` now splits `unit`, `compliance`, `smoke`, and `fuzz` into filterable projects. Run individually with `bun run test:unit|test:smoke|test:fuzz|test:compliance` or all at once with `bun run test`.
16
+ - **Custom Vitest matchers** — `toBeMcpError(code?)` and `toHaveJsonRpcCode(code)` for MCP-aware assertions. Registered globally in `tests/setup.ts`.
17
+ - **Shared test helpers** — `tests/helpers/context-helpers.ts` centralizes `createMockLogger`, `createFakeStorage`, `makeRequestContext`, and `makeContextDeps` (previously duplicated across multiple test files).
18
+ - **`templates/vitest.config.ts`** — scaffolded consumer servers now ship the `projects` pattern with a `unit` project active and commented examples for `smoke`, `fuzz`, and `integration` projects.
19
+
20
+ ## Changed
21
+
22
+ - **`tests/setup.ts`** — now registers the custom matchers before tests run. Same pre-mock behavior otherwise (MCP SDK stdio/mcp modules + chrono-node).
23
+ - **`tests/unit/context.test.ts` / `tests/unit/testing/mockContextFidelity.test.ts`** — refactored to use the shared helpers; ~100 lines of duplicated fake-storage scaffolding removed.
24
+
25
+ ## Fixed
26
+
27
+ - **`tests/unit/mcp-server/transports/auth/lib/checkScopes.test.ts`** — latent `vi.mock` hoisting bug (bare `const mockConfig` declared above the mock factory) was masked by the old import chain. `@/testing` now transitively imports `@/config` via `StorageService → logger → config`, which surfaced the reference error. Migrated to the `vi.hoisted` pattern.
28
+
29
+ ## Removed
30
+
31
+ - **`tests/helpers/mock-server.ts`, `tests/helpers/mock-handlers.ts`** — dead MSW infrastructure; no test imported them.
32
+ - **`msw` devDependency** — unused after removing the helpers.
33
+
34
+ ## Tests
35
+
36
+ - Suite grew from 2213 → 2230 tests (+17 net). 136 files pass, 1 skipped. Runtime ~8–10s.
37
+ - New coverage: `tests/unit/helpers/matchers.test.ts` (11 tests) and `tests/unit/testing/exports.test.ts` (6 tests).
38
+ - `bun run devcheck --test` fully green: typecheck, biome, depcheck, security, outdated, and all tests.
@@ -0,0 +1,31 @@
1
+ ---
2
+ summary: Full OTel instrumentation for MCP prompts — spans, six new metrics, ATTR_MCP_PROMPT_* constants, active-requests gauge coverage
3
+ breaking: false
4
+ ---
5
+
6
+ # 0.4.1 — 2026-04-19
7
+
8
+ Closes the OTel observability gap for MCP prompts. Tools and resources already had full instrumentation (span, counter, duration histogram, error counter, byte histograms); prompts only had a structured duration log. Prompts can now do meaningful work (conditional logic, async data fetches, multi-message assembly), so they get the same instrumentation depth. All three handler types are now symmetric.
9
+
10
+ ## Added
11
+
12
+ - **Prompt OTel span** — `prompt_generation:{name}` with attributes `code.function.name`, `code.namespace=mcp-prompts`, `mcp.prompt.input_bytes`, `mcp.prompt.output_bytes`, `mcp.prompt.message_count`, `mcp.prompt.duration_ms`, `mcp.prompt.success`, and `mcp.prompt.error_code` (on failure).
13
+ - **Prompt OTel metrics** (#24) — six new instruments, eagerly initialized at startup via `initHandlerMetrics()`:
14
+ - `mcp.prompt.generations` (Counter, `{generations}`)
15
+ - `mcp.prompt.duration` (Histogram, `ms`)
16
+ - `mcp.prompt.errors` (Counter, `{errors}`) — includes `mcp.prompt.error_category` dimension (`upstream`/`server`/`client`, matching tool instrumentation)
17
+ - `mcp.prompt.input_bytes` (Histogram, `bytes`)
18
+ - `mcp.prompt.output_bytes` (Histogram, `bytes`)
19
+ - `mcp.prompt.message_count` (Histogram, `{messages}`)
20
+ - **`ATTR_MCP_PROMPT_*` constants** in `src/utils/telemetry/attributes.ts` — `NAME`, `INPUT_BYTES`, `OUTPUT_BYTES`, `MESSAGE_COUNT`, `DURATION_MS`, `SUCCESS`, `ERROR_CODE`, `ERROR_CATEGORY`.
21
+ - **Active-requests gauge includes prompts** — `mcp.requests.active` now covers tool, resource, and prompt handler executions. Gauge description updated accordingly.
22
+
23
+ ## Changed
24
+
25
+ - **`measurePromptGeneration` signature** — accepts an optional third argument (`inputPayload: unknown`) for input-byte measurement. Backward-compatible (parameter is optional). `PromptRegistry.registerPrompt` now passes the validated args payload.
26
+ - **`performance.ts` fileoverview** — removed stale "Prompts get structured logs only" language; reflects new three-way symmetry.
27
+
28
+ ## Tests
29
+
30
+ - **10 new test cases** in `tests/unit/utils/internal/performance.test.ts` mirroring the tool/resource suites: success metrics + returned messages, OTel counter + histogram on success, input/output/message-count histograms, OTel error counter + `logger.error` on failure, `McpError` code capture, generic (non-`McpError`) errors, active-requests gauge inc/dec, code namespace + function name span attributes, zero message count when generate returns a non-array.
31
+ - Full suite: 2239 passed / 10 skipped (pre-existing skips), 0 regressions.
@@ -0,0 +1,29 @@
1
+ ---
2
+ summary: Actionable startup errors — ZodError converted to ConfigurationError banner, parseEnvConfig helper, maintenance skill rewrite, dep sync
3
+ breaking: false
4
+ ---
5
+
6
+ # 0.5.0 — 2026-04-20
7
+
8
+ Fixes the "raw ZodError on startup" UX problem (#35) at the framework level — every consumer server now gets an actionable configuration error banner instead of a JSON dump with a stack trace when env vars are missing. Adds an opt-in `parseEnvConfig` helper for env-var-aware error messages, rewrites the `maintenance` skill around the real workflow, and cleans up package.json resolutions after `bun update --latest`.
9
+
10
+ ## Added
11
+
12
+ - **`parseEnvConfig(schema, envMap, env?)`** (#35) — new export from `/config`. Maps schema paths to env var names so validation errors name the actual variable at fault (`MY_API_KEY is missing`) instead of the internal Zod path (`apiKey: expected string`). Opt-in; servers that keep calling `schema.parse(process.env)` still benefit from framework-level error formatting. Fully tested (7 cases covering valid input, defaults, single/multi missing vars, fallback to path, default `process.env`).
13
+ - **Framework-level ZodError conversion at startup** (#35) — `composeServices` now wraps the `setup(core)` invocation in a `try/catch`. A `ZodError` propagating up is converted to a `ConfigurationError` (via `configurationError()`), and `createApp` prints a formatted banner to `stderr` and exits with code `1`. Full stack trace is gated behind `DEBUG=true`. Banner uses ASCII dividers for universal log-capture compatibility. `McpError` instances from `setup()` pass through unchanged; non-Zod errors are preserved.
14
+ - **`skills/maintenance/SKILL.md`** — rewritten (v1.2 → v1.3) around the two-mode flow: (A) full dependency-update workflow and (B) post-update review. Step 3 delegates to the `changelog` skill, Step 4 adds a framework-specific adoption-check table plus a fresh-read template review, Step 5 introduces a two-phase skill sync (package → project → agent dirs), Step 7 uses `bun run rebuild` (preferred over `bun run build`).
15
+
16
+ ## Changed
17
+
18
+ - **Dependencies updated** — `@cloudflare/workers-types` → `^4.20260420.1`, `@supabase/supabase-js` (dev + peer) → `^2.104.0`, `bun-types` → `^1.3.13`, `vite` → `8.0.9`.
19
+ - **`package.json` resolutions cleanup** — removed six redundant pins (`@hono/node-server`, `chrono-node`, `diff`, `dotenv`, `hono`, `zod`) that duplicated direct or peer dependencies. Bumped two stale transitive pins: `brace-expansion` `1.1.13 → 1.1.14`, `path-to-regexp` `8.4.0 → 8.4.2`. Kept six security/compat pins at latest-in-major (`flatted`, `handlebars`, `lodash`, `picomatch`, `protobufjs`, `yaml`). Lockfile shrank by 92 lines confirming the redundancy was real.
20
+ - **Framework `CLAUDE.md` / `AGENTS.md`** — expanded `runtimeCaps` inline definition, added `parseEnvConfig` to the `/config` exports table, added auth scope naming convention table, elevated form-client safety to the Adding a Tool section, clarified server-config precedence (`package.json` → `name`/`version`), modernized the Commands table (`rebuild`, `format`, corrected `build`/`devcheck` descriptions), replaced the post-commit "Publishing" paragraph with a pointer to the `release` skill. Removed the standalone "Code Navigation" and "Subagent Rules" sections (moved to the global system prompt).
21
+ - **Template `CLAUDE.md` / `AGENTS.md`** — removed the First Session Bun-migration step (kept dual-compat), added a "Runtime:" note above the Commands table (both `npm run` and `bun run` work), updated `server-config.ts` example to use `parseEnvConfig`, expanded the forbidden `z.*` list, updated the maintenance skill description, added `add-app-tool` to the skill list in `AGENTS.md` (sync fix).
22
+ - **`skills/api-config/SKILL.md`** — updated server-config example to use `parseEnvConfig`.
23
+ - **`skills/setup/SKILL.md`** — added `npx` prefix, clarified bootstrap (creates dir) vs. Phase B refresh (existing only).
24
+ - **`README.md`** — fixed `rebuild` description (`clean + build`), removed stale `template_echo_app` row (absorbed into `template_data_explorer`), corrected `devcheck` description to include MCP definition linting + audit + outdated.
25
+
26
+ ## Tests
27
+
28
+ - **9 new test cases**: 7 in `tests/unit/config/parseEnvConfig.test.ts` (valid parsing, defaults, env var names in errors, multiple missing vars, fallback to path, default `process.env` source), 2 in `tests/unit/core/app.test.ts` (ZodError from `setup()` converts to `ConfigurationError`, non-Zod errors pass through unchanged).
29
+ - Full suite: **2248 passed** / 10 skipped, 0 regressions. `bun run devcheck` green (typecheck, biome, depcheck, security, outdated, all tests). 0 vulnerabilities, 0 outdated after dep sync.
@@ -0,0 +1,18 @@
1
+ ---
2
+ summary: Documentation polish — README conventions rewrite for polish-docs-meta skill, retroactive version bumps for api-config and setup skills
3
+ breaking: false
4
+ ---
5
+
6
+ # 0.5.1 — 2026-04-20
7
+
8
+ Documentation polish. Rewrites the README conventions reference in the `polish-docs-meta` skill around the shipping house style observed in `@cyanheads/mailchimp-mcp-server` and `@cyanheads/pubmed-mcp-server`, and fixes two missed skill version bumps from the 0.5.0 release so consumer sync picks up the updated content.
9
+
10
+ ## Changed
11
+
12
+ - **`skills/polish-docs-meta/references/readme.md`** (v1.3 → v1.4) — rewrote the README conventions reference to match the shipping house style. Promoted "Public Hosted Instance" to a top-level callout under the badges; collapsed separate `## Resources` and `## Prompts` sections into a single combined `## Resources and prompts` table with a `Type` column; added the mandatory tool-coverage boilerplate ("All resource data is also reachable via tools…"); standardized the surface count as a nested `<div>` inside the tagline `<p>` using the `•` separator; codified the three-block Getting Started pattern (`bunx` → `npx` → `docker run`) plus HTTP one-liner quickstart; added a tool-grouping framing sentence convention; added the `.env.example` pointer after the Configuration table; added the "validate → normalize → never fabricate" bullet to the Development Guide short-version list; de-prescribed `claude_desktop_config.json` in favor of generic "your MCP client configuration file"; added a Dockerfile-behavior note (log directory + `OTEL_ENABLED` build arg); made the MCP Spec badge optional (SDK badge already encodes the relevant version).
13
+ - **`skills/polish-docs-meta/SKILL.md`** step 2 — clarified that the bold header tagline (the `<b>` text inside the first `<p>`) is what must match `package.json` description, distinct from the nested count `<div>`.
14
+
15
+ ## Fixed
16
+
17
+ - **`skills/api-config/SKILL.md`** (v1.1 → v1.2) — retroactive version bump. Content was updated in the 0.5.0 release (442a10a, `parseEnvConfig` example in the server-config pattern) but the frontmatter version was not bumped, blocking consumer projects from picking up the change via the skill sync model. No content changes in this release.
18
+ - **`skills/setup/SKILL.md`** (v1.2 → v1.3) — retroactive version bump. Content was updated in the 0.5.0 release (442a10a, added `npx` prefix and clarified bootstrap vs. Phase B refresh) but the frontmatter version was not bumped. No content changes in this release.
@@ -0,0 +1,38 @@
1
+ ---
2
+ summary: format-parity lint rule enforces format/structuredContent coverage at startup — sentinel injection, 16 new tests, example tools updated
3
+ breaking: false
4
+ ---
5
+
6
+ # 0.5.2 — 2026-04-20
7
+
8
+ Closes a recurring class of silent bugs by enforcing format/structuredContent parity at lint time. Every terminal field in a tool's `output` schema must now be rendered by `format()` — since most LLM clients (Claude Code, VS Code Copilot, Cursor, Windsurf) only forward `content[]` to the model, a field that exists in `structuredContent` but never appears in `format()`'s rendered text is invisible to the LLM. The check runs inside `validateDefinitions()` so it's picked up automatically by `createApp()` startup, `bun run lint:mcp`, and `bun run devcheck`.
9
+
10
+ ## Added
11
+
12
+ - **`format-parity` lint rule** (`src/linter/rules/format-parity-rules.ts`) — verifies `format()` output covers every terminal path in `def.output`. Mechanism: walks the output schema, builds a synthetic value where every leaf is a distinctive sentinel (unique string, large prime-range number, first enum variant, etc.), invokes `def.format(synthetic)` once, and asserts each sentinel or the field's key name appears in the rendered text. Works across all `ContentBlock` variants — text, image, audio, resource — by recursively collecting every primitive value reachable inside the content array (so image `data`/`mimeType` and resource `uri`/`text` are checked the same as text-block `text`). Emits one **error** per missing path — blocks startup. Deterministic, dependency-free, no fuzzing required. Strict match for strings/numbers; permissive (sentinel or key-name) match for booleans/enums/literals. Skipped when `format` is absent (default JSON formatter renders everything) or when the output schema fails `schema-serializable`. Graceful degradation: if `format()` throws on the synthetic sample, emits a `format-parity-threw` warning instead of failing hard, prompting the author to make `format()` total.
13
+ - **16 new test cases** in `tests/unit/linter/format-parity-rules.test.ts` — happy path (top-level + nested array-of-objects), missing fields (top-level, deep nested, multiple separate errors), wrappers (optional treated as present), permissive matching (boolean via key-name label, enum via first variant), non-text content blocks (image, resource), graceful degradation (format throws, non-object output), and integration through `lintToolDefinition`.
14
+
15
+ ## Changed
16
+
17
+ - **`src/linter/rules/tool-rules.ts`** — `lintToolDefinition` now invokes `lintFormatParity` when the output schema is a valid ZodObject and a `format` function is present. Skipped when the schema fails `schema-serializable` (synthetic sample would misbehave).
18
+ - **`examples/mcp-server/tools/definitions/template-async-countdown.tool.ts`** — rewrote `format()` to unconditionally render all seven output fields (`success`, `message`, `wasCancelled`, `progress`, `duration`, `startedAt`, `completedAt`). Previously branched on `result.success`, hiding `wasCancelled` and `progress` in one branch and `startedAt`/`completedAt` in the other — which the new lint rule correctly flagged as parity violations.
19
+ - **`examples/mcp-server/tools/definitions/template-echo-message.tool.ts`** — `format()` now renders `originalMessage` and `formattedMessage` (previously only rendered `mode`, `repeatCount`, and a preview of `repeatedMessage`). Smoke test updated to assert the new fields.
20
+ - **`examples/mcp-server/tools/definitions/template-code-review-sampling.tool.ts`** — `format()` now renders `code`, `language`, and `tokenUsage.requested`/`tokenUsage.actual` in addition to `focus` and `review`. The reviewed code block is appended as a fenced code block so the LLM can reason about what was reviewed, not just the review text. Smoke test updated.
21
+ - **`CLAUDE.md` / `AGENTS.md`** — updated the `format` guidance in the Adding a Tool section to state that parity is now enforced at lint time.
22
+ - **`templates/CLAUDE.md` / `templates/AGENTS.md`** — added the lint-enforcement note to the scaffolded tool snippet so new servers internalize the contract from the first tool they write.
23
+ - **`README.md`** — expanded the Definition linter feature bullet to name format-parity as one of the enforced checks.
24
+ - **`skills/add-tool/SKILL.md`** (v1.4 → v1.5) — updated the `format()` checklist item to reference the lint rule, and added the enforcement comment to the inline template snippet.
25
+ - **`skills/field-test/SKILL.md`** (v1.1 → v1.2) — reframed the `structuredContent` parity check now that the lint rule covers the mechanical case. Field testing now focuses on what lint can't: real-data accuracy, conditional-render branches under specific values, and human-readable quality of the model's view.
26
+
27
+ ## Removed
28
+
29
+ - **`skills/devcheck/`** — deleted. The skill was a thin restatement of CLAUDE.md's Commands table plus "run `bun run devcheck`, read output, fix, re-run" — no non-obvious content. The command itself prints a self-documenting summary with per-check output, and CLAUDE.md already flags it as "use often." Removing the skill trims downstream consumer sync noise. References to the command throughout other skills remain as plain `bun run devcheck` mentions.
30
+ - **`skills/walkthrough-init/`** — deleted. Internal debug skill (`audience: internal`, `type: debug`) that documented a one-off "trace the onboarding chain and report broken links" audit. Not something run regularly — the same audit can be performed ad-hoc by reading `CLAUDE.md` and following the chain manually. Removing cuts dead weight from the skills directory.
31
+
32
+ ## Fixed
33
+
34
+ - **`tests/helpers/matchers.ts`** — removed an unused `biome-ignore lint/suspicious/noExplicitAny` suppression that Biome now flags as no-op (the surrounding JSDoc block already documents why `any` is required to mirror Vitest's `Assertion<T = any>`).
35
+
36
+ ## Tests
37
+
38
+ - Full suite: **2264 passed** / 10 skipped, 0 regressions (2248 pre-change + 16 new parity tests, 2 existing smoke tests updated for expanded template `format()` output). Integration: **98 passed**. `bun run devcheck` green across all 8 checks (lint-mcp, biome, typescript, depcheck, audit, outdated).
@@ -0,0 +1,26 @@
1
+ ---
2
+ summary: Dual-surface format-parity messaging, docs-sync devcheck step — CLAUDE.md/AGENTS.md drift detection, @hono/node-server v2
3
+ breaking: false
4
+ ---
5
+
6
+ # 0.5.3 — 2026-04-20
7
+
8
+ Two small-but-visible fixes for agent-facing surfaces: the `format-parity` lint diagnostic is reframed around dual-surface parity (some clients read `structuredContent`, others read `content[]`; both must carry the full picture), and `devcheck` now catches `CLAUDE.md` / `AGENTS.md` drift at check-time rather than letting it rot silently between edits.
9
+
10
+ ## Changed
11
+
12
+ - **`format-parity` diagnostic (#37)** — rewrote the error message and every prose echo across docs, skills, and templates. The old wording ("Either render it in `format()` or remove it from the output schema") framed the two fixes as equal-weight alternatives and claimed `structuredContent` is "programmatic use only." Both are wrong: some MCP clients (e.g., Claude Code) forward `structuredContent` to the model, others (e.g., Claude Desktop) forward `content[]`, and dropping a field from `output` strips it from the first group. The new message names the surface split explicitly, establishes that `format()` is the markdown-rendered twin of `structuredContent` (not a separate payload), makes rendering in `format()` the primary fix, and demotes schema relaxation (`z.object({}).passthrough()`) to a narrow escape hatch for genuinely dynamic upstream APIs. Affected files: `src/linter/rules/format-parity-rules.ts`, `src/mcp-server/tools/utils/toolDefinition.ts`, `CLAUDE.md`, `AGENTS.md`, `README.md`, `templates/CLAUDE.md`, `templates/AGENTS.md`, `templates/src/mcp-server/tools/definitions/echo.tool.ts`.
13
+ - **`skills/add-tool/SKILL.md`** (v1.5 → v1.6) — updated the format completeness checklist item and the inline code comment to match the dual-surface framing.
14
+ - **`skills/design-mcp-server/SKILL.md`** (v2.3 → v2.4) — updated the tool-design section and the final checklist around `format()` completeness to reflect dual-surface parity.
15
+ - **`@hono/node-server`** bumped `^1.19.14` → `^2.0.0` (major). No code changes required on the consumer side; integration tests all green.
16
+
17
+ ## Added
18
+
19
+ - **`scripts/check-docs-sync.ts` (#36)** — standalone script that verifies `CLAUDE.md` and `AGENTS.md` stay byte-identical. Four-state behavior: both identical (pass), drift (fail with line-numbered divergence and fix hint), only one present (pass with informational message — `"CLAUDE.md found. No AGENTS.md found — nothing to sync."`), neither present (skip). The init CLI ships both files byte-identical since each agent tool reads the file named for it — without a check, they drift silently after edits and only surface when the other agent runs against a stale protocol. Observed in the wild in multiple downstream servers (e.g., `pubmed-mcp-server` had `AGENTS.md` at `Version: 2.3.11` while `CLAUDE.md` was at `2.4.0`).
20
+ - **`Docs Sync` devcheck step** (`scripts/devcheck.ts`) — wires the new script into the standard devcheck flow with the `--no-docs-sync` opt-out flag. Only fails on actual drift between two present files; single-file repos pass cleanly without warnings. Consumers get the check automatically after `bun update`.
21
+ - **Init CLI registration** (`src/cli/init.ts`) — added `check-docs-sync.ts` to `SCAFFOLD_SCRIPTS` so new consumer projects scaffolded via `npx @cyanheads/mcp-ts-core init` receive the script. Also added to the `package.json` `files` array so it ships in the npm package.
22
+
23
+ ## Tests
24
+
25
+ - Full suite: **2264 passed** / 10 skipped, 0 regressions. All 16 `format-parity` tests still pass (the lint rule's behavior is unchanged — only the diagnostic text was rewritten). CLI init tests pass.
26
+ - `bun run devcheck` green across all 7 non-network checks including the new `Docs Sync` step (22ms; CLAUDE.md / AGENTS.md confirmed in sync).
@@ -0,0 +1,29 @@
1
+ ---
2
+ summary: Lint rule discoverability — reference doc covering every rule, diagnostic breadcrumbs, fix dangling devcheck tip
3
+ breaking: false
4
+ ---
5
+
6
+ # 0.5.4 — 2026-04-20
7
+
8
+ Closes the "what is this lint rule?" discoverability gap. When `bun run devcheck` reports a diagnostic like `format-parity` or `server-json-name-format`, agents were going searching for docs and coming up empty — rule IDs weren't indexed anywhere, and the `MCP Definitions` devcheck tip dangled at a nonexistent `validateDefinitions()` docs target. This release adds a single reference doc covering every rule, wires a breadcrumb into every diagnostic, and fixes the dangling tip.
9
+
10
+ ## Added
11
+
12
+ - **`skills/api-linter/SKILL.md`** (v1.0) — reference covering every rule ID across the 7 rule families. Per-rule sub-headers for the 20 varied rules (format-parity, schema, name, tool, resource, prompt) so the anchor matches the rule ID exactly; tabular index for the 40 `server-json-*` rules. Includes escape-hatch guidance (when to use `z.object({}).passthrough()` instead of fighting `format-parity`) and an "adding a new rule" workflow for extenders.
13
+ - **Diagnostic breadcrumb** (`src/linter/validate.ts`) — every `LintDiagnostic` now has `See: skills/api-linter/SKILL.md#<rule>` appended to `message`. Applies uniformly across `bun run lint:mcp`, `bun run devcheck`, and `createApp()` startup. Family mapping: `server-json-*` → `#server-json-rules`, everything else → literal rule ID.
14
+
15
+ ## Fixed
16
+
17
+ - **`MCP Definitions` devcheck tip** (`scripts/devcheck.ts`) — replaced the dangling `See validateDefinitions() docs for rule details` with `each diagnostic links to its rule in skills/api-linter/SKILL.md`. The old tip promised docs that never existed.
18
+ - **Incomplete regex escaping in devcheck color helper** (`scripts/devcheck.ts`) — the `esc()` helper used `code.replace('[', '\\[')` with a string literal first arg, which only replaces the first occurrence. Flagged by CodeQL as `js/incomplete-sanitization` (high severity, CWE-20/80/116) in every downstream server scaffolded from this template. Not exploitable in practice — every call site passes a hardcoded ANSI escape code with exactly one `[` — but the pattern is a footgun if `esc()` is ever called with a different input, and the alert was generating noise across the consumer fleet. Fixed to escape all regex metacharacters: `code.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')`.
19
+
20
+ ## Changed
21
+
22
+ - **`Dependencies (Outdated)` devcheck tip** (`scripts/devcheck.ts`) — surfaces the `maintenance` skill next to `bun update`. The skill already exists and is purpose-built for post-update changelog investigation, but agents weren't being pointed at it when they hit the check.
23
+ - **`CLAUDE.md` + `AGENTS.md`** — added `api-linter` to the skills reference table and a skill pointer in the Startup validation bullet.
24
+ - **`docs/tree.md`** — listed the new skill directory.
25
+ - **README version badge** — bumped from stale `0.5.2` to `0.5.4`.
26
+
27
+ ## Tests
28
+
29
+ - Full suite: **2264 passed** / 10 skipped, no regressions. Existing linter tests match messages via `toContain` / `stringContaining`, so the appended breadcrumb is transparent.
@@ -0,0 +1,39 @@
1
+ ---
2
+ summary: Landing page + SEP-1649 Server Card at /, unified server manifest, directory-based changelog system
3
+ breaking: false
4
+ ---
5
+
6
+ # 0.6.0 — 2026-04-21
7
+
8
+ Every HTTP-mode mcp-ts-core server now serves three coordinated surfaces from a single manifest: an HTML landing page at `/`, a SEP-1649 Server Card at `/.well-known/mcp.json`, and the existing `/mcp` status JSON. Zero config required — manifest values flow from `AppConfig`, the definition registries, and `package.json`; optional `landing` config tunes the hero, footer, and brand accent. A new directory-based changelog replaces the monolithic `CHANGELOG.md` with one file per release so agents can read only the versions between old and new.
9
+
10
+ Closes [#38](https://github.com/cyanheads/mcp-ts-core/issues/38). Deferred polish items (OG image, inspector deep link, sticky ToC, startup timestamp) remain tracked in [#39](https://github.com/cyanheads/mcp-ts-core/issues/39).
11
+
12
+ ## Added
13
+
14
+ - **HTML landing page at `/`** (`src/mcp-server/transports/http/landing-page.ts`) — self-contained HTML with inlined tokens + primitives (shadcn-inspired), dark mode via `prefers-color-scheme`, zero external assets, <1KB inline JS for clipboard copy. Hero renders server name + clickable version badge + pre-release pill + tagline + auth-status banner + connect snippets (Claude Desktop, `mcp-remote`, `curl`). Sections for Tools/Resources/Prompts with per-definition cards (schema `<details>`, JSON-RPC invocation snippet, "view source" links when `repoRoot` is set). Auto-polish from detected signals: GitHub link cluster, npm/Docker registry links, tool name grouping by shared prefix, section counts. OpenGraph + JSON-LD in `<head>` and `<link rel="alternate">` pointing at the Server Card.
15
+ - **SEP-1649 Server Card at `/.well-known/mcp.json`** (`src/mcp-server/transports/http/serverCard.ts`) — machine-readable discovery document. Emits spec-required headers (`Content-Type: application/json`, `X-Content-Type-Options: nosniff`, `Cache-Control: max-age=3600`, `Access-Control-Allow-Origin: *`). Collision-safe: skips mount when `MCP_HTTP_ENDPOINT_PATH` is `/.well-known/mcp.json`.
16
+ - **`buildServerManifest()`** (`src/core/serverManifest.ts`) — pure function that produces the single source of truth consumed by all three surfaces. Takes config + definition arrays, returns `ServerManifest` with server identity, transport, protocol versions, capabilities, definitions, framework, auth, and landing sections. GitHub repo auto-detection from `mcpServerHomepage`, pre-release parsing on version, package.json scope → npm URL derivation.
17
+ - **`LandingConfig`** (exported from `@cyanheads/mcp-ts-core`) — consumer-facing config: `enabled`, `tagline`, `logo`, `links`, `theme.accent`, `repoRoot`, `changelogUrl`, `requireAuth`, `attribution`. All fields optional; sane defaults for everything.
18
+ - **`landing-rules` linter family** (`src/linter/rules/landing-rules.ts`) — startup-time validation of content limits (tagline ≤120 chars, logo ≤24KB when data URI, max 6 links, `repoRoot` matches `^https://github\.com/[^/]+/[^/]+/?$`). Fails loudly at `createApp()` rather than silently at render time.
19
+ - **`html` tagged-template util** (`src/utils/formatting/html.ts`) — auto-escaping HTML builder with `SafeHtml`, `escapeHtml`, and `unsafeRaw` for vetted input. Used internally by the landing renderer and exported for future UI surfaces.
20
+ - **Directory-based changelog system** (`changelog/<major.minor>.x/<version>.md`) — one file per released version, shipped in the npm package so agents reading `node_modules/@cyanheads/mcp-ts-core/changelog/0.6.x/0.6.0.md` can inspect a specific version without parsing the monolith. Work-in-progress entries live in `changelog/unreleased.md`. `CHANGELOG.md` becomes an auto-generated navigation index (header + link + one-line summary per release).
21
+ - **`bun run changelog:build`** + **`changelog:check`** (`scripts/build-changelog.ts`) — regenerate the rollup from per-version files; `--check` exits non-zero on drift. Wired into devcheck as the new `Changelog Sync` step. Per-version frontmatter: `summary` (required, ≤250 chars, no markdown), `breaking` (optional, default `false`, renders a `· ⚠️ Breaking` badge in the rollup).
22
+ - **`scripts/split-changelog.ts`** — one-time migration tool that parsed the legacy monolithic `CHANGELOG.md` and split every `## <version>` section into the new directory structure, preserving bodies and inferring dates. Retained for archaeology.
23
+
24
+ ## Changed
25
+
26
+ - **`ServerMeta` → `ServerManifest`** (internal) — the `ComposedApp` field name changed from `meta` to `manifest`; the type moved from `src/mcp-server/transports/http/httpTypes.ts` to `src/core/serverManifest.ts` and expanded from 2 fields (`definitionCounts`, `extensions`) to a full manifest covering server identity, transport, protocol, capabilities, framework, auth, definitions, and landing config. Not a breaking change for consumers — `ServerMeta` was never exported.
27
+ - **`GET /mcp` status JSON** — now sourced from the shared manifest instead of re-reading config + `SUPPORTED_PROTOCOL_VERSIONS` inline. Output shape is identical; the refactor ensures `/mcp`, `/.well-known/mcp.json`, and `/` cannot drift.
28
+ - **Skills updated to reference the directory-based changelog**: `maintenance` (v1.4) reads per-version files between old/new rather than a monolith; `polish-docs-meta` (v1.5) and `release` (v1.3) document the release-ize flow (`git mv changelog/unreleased.md changelog/<series>/<version>.md`, fill frontmatter, regenerate).
29
+ - **Skill docs consistency pass** — `add-tool` (v1.7), `add-app-tool` (v1.3), `add-prompt` (v1.2), `add-resource` (v1.3), `add-service` (v1.3), `setup` (v1.4), `api-utils` (v2.1), `api-services` (v1.3), `api-context` (v1.1), `design-mcp-server` (v2.5): inlined the `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md` reference as prose (was a 4-space indented block treated as code), replaced lingering `new McpError(JsonRpcErrorCode.*, ...)` examples with the error-factory idiom (`invalidParams()`, `invalidRequest()`, `forbidden()`), and swapped `console.log` examples for structured `logger.info`. `add-tool` also adds a note explaining why the per-item partial-success `try/catch` is the deliberate exception to "logic throws, framework catches."
30
+ - **CLAUDE.md + AGENTS.md (root and templates)** — added a top-level `## Changelog` section documenting the directory-based format, frontmatter fields, and pre-release consolidation rule. New `changelog:build` / `changelog:check` rows in the Commands table.
31
+ - **`docs/tree.md`** — regenerated to show `changelog/`, new scripts, `serverManifest.ts`, landing/server-card modules, and `templates/changelog/`.
32
+
33
+ ## Fixed
34
+
35
+ - **`ctx.log` examples in skill references** (`api-services/references/graph.md`, `api-utils/references/parsing.md`, `api-utils/references/security.md`) — replaced `console.log` calls that escaped the "no console" rule with structured `ctx.log.info` / `logger.info` calls.
36
+
37
+ ## Tests
38
+
39
+ - **+5 new test suites** for the manifest + landing surfaces: `serverManifest.test.ts` (368 lines), `landing-rules.test.ts` (118 lines), `landing-page.test.ts` (497 lines), `serverCard.test.ts` (142 lines), `html.test.ts` (141 lines). HTTP transport tests extended to cover the `/`, `/.well-known/mcp.json`, and `landing.enabled=false` paths. Full suite green.
@@ -0,0 +1,40 @@
1
+ ---
2
+ # Required. One-line headline describing the release. Max 250 chars. No markdown.
3
+ # This line is what the CHANGELOG.md rollup shows — write it like a GitHub Release title.
4
+ summary: ""
5
+
6
+ # Set to `true` only if this release has breaking changes (API removals, signature
7
+ # changes, config renames, anything that requires consumer code changes on update).
8
+ # Flagged as ⚠️ Breaking in the rollup.
9
+ breaking: false
10
+ ---
11
+
12
+ # Unreleased
13
+
14
+ <!--
15
+ Optional narrative intro — 1-3 sentences framing the release theme. Delete if not needed.
16
+
17
+ Linking issues/PRs: use full URLs so the link works everywhere (GitHub web UI,
18
+ npm/node_modules reads, local editors). GitHub's bare `#NN` auto-link only
19
+ resolves inside its own UI.
20
+
21
+ [#38](https://github.com/cyanheads/mcp-ts-core/issues/38) ← issue
22
+ [#42](https://github.com/cyanheads/mcp-ts-core/pull/42) ← PR
23
+
24
+ Only link numbers you've verified exist (via `gh issue view NN` or
25
+ `gh pr view NN`). Never speculate on a future number — `#42` for "my
26
+ upcoming PR" will quietly resolve to whatever real item already owns 42,
27
+ and GitHub timeline previews will pull in that unrelated item's title.
28
+ -->
29
+
30
+ ## Added
31
+
32
+ -
33
+
34
+ ## Changed
35
+
36
+ -
37
+
38
+ ## Fixed
39
+
40
+ -