@cyanheads/mcp-ts-core 0.12.9 → 0.13.1

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 (126) hide show
  1. package/AGENTS.md +22 -11
  2. package/CLAUDE.md +22 -11
  3. package/README.md +1 -1
  4. package/biome.json +1 -1
  5. package/changelog/0.13.x/0.13.0.md +48 -0
  6. package/changelog/0.13.x/0.13.1.md +56 -0
  7. package/changelog/template.md +7 -24
  8. package/{tsconfig.base.json → config/tsconfig.base.json} +2 -2
  9. package/dist/cli/init.js +2 -2
  10. package/dist/cli/init.js.map +1 -1
  11. package/dist/config/envValue.d.ts +18 -0
  12. package/dist/config/envValue.d.ts.map +1 -0
  13. package/dist/config/envValue.js +35 -0
  14. package/dist/config/envValue.js.map +1 -0
  15. package/dist/config/index.d.ts +8 -0
  16. package/dist/config/index.d.ts.map +1 -1
  17. package/dist/config/index.js +13 -7
  18. package/dist/config/index.js.map +1 -1
  19. package/dist/config/parseEnvConfig.d.ts +7 -0
  20. package/dist/config/parseEnvConfig.d.ts.map +1 -1
  21. package/dist/config/parseEnvConfig.js +9 -1
  22. package/dist/config/parseEnvConfig.js.map +1 -1
  23. package/dist/core/app.d.ts +82 -2
  24. package/dist/core/app.d.ts.map +1 -1
  25. package/dist/core/app.js +129 -6
  26. package/dist/core/app.js.map +1 -1
  27. package/dist/core/index.d.ts +1 -0
  28. package/dist/core/index.d.ts.map +1 -1
  29. package/dist/core/index.js.map +1 -1
  30. package/dist/core/worker.d.ts +6 -1
  31. package/dist/core/worker.d.ts.map +1 -1
  32. package/dist/core/worker.js.map +1 -1
  33. package/dist/linter/rules/resource-rules.js +9 -2
  34. package/dist/linter/rules/resource-rules.js.map +1 -1
  35. package/dist/linter/rules/tool-rules.js +4 -1
  36. package/dist/linter/rules/tool-rules.js.map +1 -1
  37. package/dist/linter/validate.js +2 -2
  38. package/dist/linter/validate.js.map +1 -1
  39. package/dist/mcp-server/types.d.ts +10 -3
  40. package/dist/mcp-server/types.d.ts.map +1 -1
  41. package/dist/mcp-server/types.js +4 -3
  42. package/dist/mcp-server/types.js.map +1 -1
  43. package/dist/services/canvas/core/sqlGate.d.ts.map +1 -1
  44. package/dist/services/canvas/core/sqlGate.js +27 -2
  45. package/dist/services/canvas/core/sqlGate.js.map +1 -1
  46. package/dist/utils/pagination/pagination.d.ts.map +1 -1
  47. package/dist/utils/pagination/pagination.js +4 -1
  48. package/dist/utils/pagination/pagination.js.map +1 -1
  49. package/dist/utils/parsing/frontmatterParser.d.ts +8 -7
  50. package/dist/utils/parsing/frontmatterParser.d.ts.map +1 -1
  51. package/dist/utils/parsing/frontmatterParser.js +91 -16
  52. package/dist/utils/parsing/frontmatterParser.js.map +1 -1
  53. package/framework-skills/README.md +40 -0
  54. package/{skills → framework-skills}/add-app-tool/SKILL.md +2 -2
  55. package/{skills → framework-skills}/add-resource/SKILL.md +2 -2
  56. package/{skills → framework-skills}/add-service/SKILL.md +2 -2
  57. package/{skills → framework-skills}/add-test/SKILL.md +2 -2
  58. package/{skills → framework-skills}/add-tool/SKILL.md +5 -5
  59. package/{skills → framework-skills}/api-config/SKILL.md +21 -3
  60. package/{skills → framework-skills}/api-context/SKILL.md +5 -3
  61. package/{skills → framework-skills}/api-linter/SKILL.md +4 -4
  62. package/{skills → framework-skills}/api-telemetry/SKILL.md +13 -10
  63. package/{skills → framework-skills}/code-simplifier/SKILL.md +12 -6
  64. package/{skills → framework-skills}/design-mcp-server/SKILL.md +2 -2
  65. package/{skills → framework-skills}/maintenance/SKILL.md +30 -21
  66. package/{skills → framework-skills}/orchestrations/SKILL.md +2 -2
  67. package/{skills → framework-skills}/orchestrations/workflows/field-test-fix.md +8 -8
  68. package/{skills → framework-skills}/orchestrations/workflows/fix-wrapup-release.md +5 -5
  69. package/{skills → framework-skills}/orchestrations/workflows/greenfield-build.md +11 -11
  70. package/{skills → framework-skills}/orchestrations/workflows/maintenance-release.md +12 -12
  71. package/{skills → framework-skills}/polish-docs-meta/SKILL.md +18 -10
  72. package/{skills → framework-skills}/polish-docs-meta/references/agent-protocol.md +1 -1
  73. package/{skills → framework-skills}/polish-docs-meta/references/readme.md +93 -73
  74. package/{skills → framework-skills}/release-and-publish/SKILL.md +12 -3
  75. package/{skills → framework-skills}/release-pr-review/SKILL.md +2 -2
  76. package/{skills → framework-skills}/report-issue-framework/SKILL.md +26 -25
  77. package/{skills → framework-skills}/report-issue-local/SKILL.md +28 -24
  78. package/{skills → framework-skills}/setup/SKILL.md +10 -8
  79. package/package.json +13 -13
  80. package/scripts/build.ts +2 -2
  81. package/scripts/check-framework-antipatterns.ts +1 -1
  82. package/scripts/check-skill-versions.ts +16 -9
  83. package/scripts/check-skills-sync.ts +64 -13
  84. package/scripts/clean-mcpb.ts +3 -3
  85. package/scripts/devcheck.ts +18 -15
  86. package/scripts/lint-packaging.ts +158 -24
  87. package/scripts/list-skills.ts +2 -2
  88. package/templates/.claude-plugin/plugin.json +5 -1
  89. package/templates/.env.example +5 -2
  90. package/templates/.github/CONTRIBUTING.md +4 -5
  91. package/templates/.github/ISSUE_TEMPLATE/bug_report.yml +5 -4
  92. package/templates/.github/ISSUE_TEMPLATE/config.yml +6 -1
  93. package/templates/.github/ISSUE_TEMPLATE/feature_request.yml +1 -2
  94. package/templates/AGENTS.md +31 -14
  95. package/templates/CLAUDE.md +31 -14
  96. package/templates/_.mcpbignore +1 -1
  97. package/templates/changelog/template.md +7 -24
  98. package/templates/package.json +3 -2
  99. package/templates/src/index.ts +10 -0
  100. package/templates/src/mcp-server/resources/definitions/echo-app-ui.app-resource.ts +1 -1
  101. package/skills/README.md +0 -38
  102. /package/{skills → framework-skills}/add-export/SKILL.md +0 -0
  103. /package/{skills → framework-skills}/add-prompt/SKILL.md +0 -0
  104. /package/{skills → framework-skills}/add-provider/SKILL.md +0 -0
  105. /package/{skills → framework-skills}/api-auth/SKILL.md +0 -0
  106. /package/{skills → framework-skills}/api-canvas/SKILL.md +0 -0
  107. /package/{skills → framework-skills}/api-errors/SKILL.md +0 -0
  108. /package/{skills → framework-skills}/api-mirror/SKILL.md +0 -0
  109. /package/{skills → framework-skills}/api-services/SKILL.md +0 -0
  110. /package/{skills → framework-skills}/api-services/references/graph.md +0 -0
  111. /package/{skills → framework-skills}/api-services/references/llm.md +0 -0
  112. /package/{skills → framework-skills}/api-services/references/speech.md +0 -0
  113. /package/{skills → framework-skills}/api-testing/SKILL.md +0 -0
  114. /package/{skills → framework-skills}/api-utils/SKILL.md +0 -0
  115. /package/{skills → framework-skills}/api-utils/references/formatting.md +0 -0
  116. /package/{skills → framework-skills}/api-utils/references/parsing.md +0 -0
  117. /package/{skills → framework-skills}/api-utils/references/security.md +0 -0
  118. /package/{skills → framework-skills}/api-workers/SKILL.md +0 -0
  119. /package/{skills → framework-skills}/field-test/SKILL.md +0 -0
  120. /package/{skills → framework-skills}/git-wrapup/SKILL.md +0 -0
  121. /package/{skills → framework-skills}/polish-docs-meta/references/package-meta.md +0 -0
  122. /package/{skills → framework-skills}/polish-docs-meta/references/server-json.md +0 -0
  123. /package/{skills → framework-skills}/security-pass/SKILL.md +0 -0
  124. /package/{skills → framework-skills}/techniques/SKILL.md +0 -0
  125. /package/{skills → framework-skills}/techniques/references/outline-on-overflow.md +0 -0
  126. /package/{skills → framework-skills}/tool-defs-analysis/SKILL.md +0 -0
package/AGENTS.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Developer Protocol
2
2
 
3
3
  **Package:** `@cyanheads/mcp-ts-core`
4
- **Version:** 0.12.9
4
+ **Version:** 0.13.1
5
5
  **Engines:** Bun ≥1.4.0, Node ≥24.0.0
6
6
  **MCP SDK:** `@modelcontextprotocol/server` ^2.0.0 (protocol revisions 2026-07-28 and 2025-*)
7
- **Zod:** ^4.6.0
7
+ **Zod:** ^4.6.1
8
8
  **GitHub:** [cyanheads/mcp-ts-core](https://github.com/cyanheads/mcp-ts-core)
9
9
  **npm:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core)
10
10
  **Docker:** [ghcr.io/cyanheads/mcp-ts-core](https://ghcr.io/cyanheads/mcp-ts-core)
@@ -22,7 +22,7 @@ This package serves two consumer paths. When making changes, know which audience
22
22
  | **Direct package import** — existing project pulls in the package | `bun add @cyanheads/mcp-ts-core` → `import { createApp, tool, z } from '@cyanheads/mcp-ts-core'` | Public API surface (`src/`) — existing consumers feel changes immediately on upgrade |
23
23
  | **Init-scaffolded server** — fresh project bootstrapped from this repo's templates | `bunx @cyanheads/mcp-ts-core init [name]` copies `templates/` into the new directory | `templates/` — only affects newly scaffolded servers, not existing ones |
24
24
 
25
- Both paths share the same public API. Init copies starter `package.json`, configs (`tsconfig`, `biome.json`, `vitest.config.ts`, `devcheck.config.json`, `bunfig.toml`), `.env.example`, `Dockerfile`, `LICENSE`, `.gitattributes`, `CLAUDE.md`/`AGENTS.md`, `.github/` (issue forms, `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`, `SECURITY.md`), example definitions and tests, framework `scripts/`, and external-audience `skills/`. `_`-prefixed files (e.g. `_.gitignore`) drop the prefix on copy. Existing files are never overwritten; `init` without a name scaffolds in place (upgrade flow). After init, consult the `setup` skill.
25
+ Both paths share the same public API. Init copies starter `package.json`, configs (`tsconfig`, `biome.json`, `vitest.config.ts`, `devcheck.config.json`, `bunfig.toml`), `.env.example`, `Dockerfile`, `LICENSE`, `.gitattributes`, `CLAUDE.md`/`AGENTS.md`, `.github/` (issue forms, `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`, `SECURITY.md`), example definitions and tests, framework `scripts/`, and external-audience `framework-skills/`. `_`-prefixed files (e.g. `_.gitignore`) drop the prefix on copy. Existing files are never overwritten; `init` without a name scaffolds in place (upgrade flow). After init, consult the `setup` skill.
26
26
 
27
27
  ---
28
28
 
@@ -45,13 +45,13 @@ Both paths share the same public API. Init copies starter `package.json`, config
45
45
 
46
46
  | Subpath | Key Exports | Purpose |
47
47
  |:--------|:------------|:--------|
48
- | `@cyanheads/mcp-ts-core` | `createApp`, `tool`, `resource`, `prompt`, `appTool`, `appResource`, `APP_RESOURCE_MIME_TYPE`, `headerParam`, `Context`, `createFail`, `createRecoveryFor`, `TypedFail`, `TypedRecoveryFor`, `ReasonOf`, `HandlerContext`, `Enrich`, `EnrichHelpers`, `TypedEnrich`, `ContentCollect`, `ContentBlock`, `z`, `completable`, `isCompletable`, `CompleteCallback`, `CompleteResourceTemplateCallback`, `CacheHint`, `CacheHints`, `CacheScope` | Main entry point |
48
+ | `@cyanheads/mcp-ts-core` | `createApp`, `tool`, `resource`, `prompt`, `appTool`, `appResource`, `APP_RESOURCE_MIME_TYPE`, `headerParam`, `Context`, `createFail`, `createRecoveryFor`, `TypedFail`, `TypedRecoveryFor`, `ReasonOf`, `HandlerContext`, `Enrich`, `EnrichHelpers`, `TypedEnrich`, `ContentCollect`, `ContentBlock`, `z`, `inputRequired`, `completable`, `isCompletable`, `CompleteCallback`, `CompleteResourceTemplateCallback`, `CacheHint`, `CacheHints`, `CacheScope`, `SessionMode`, `ResolvedSessionMode` | Main entry point |
49
49
  | `/worker` | `createWorkerHandler`, `CloudflareBindings` | Cloudflare Workers entry |
50
50
  | `/tools` | `ToolDefinition`, `AnyToolDefinition`, `ToolAnnotations` | Tool definition types |
51
51
  | `/resources` | `ResourceDefinition`, `AnyResourceDefinition` | Resource definition types |
52
52
  | `/prompts` | `PromptDefinition` | Prompt definition type |
53
53
  | `/errors` | `McpError`, `JsonRpcErrorCode`, `notFound`, `validationError`, `unauthorized`, ... | Error types, codes, and factory functions |
54
- | `/config` | `AppConfig`, `config`, `parseConfig`, `parseEnvConfig`, `resetConfig`, `ConfigSchema`, `FRAMEWORK_NAME`, `FRAMEWORK_VERSION` | Zod-validated config, framework identity, env-var helper |
54
+ | `/config` | `AppConfig`, `config`, `parseConfig`, `parseEnvConfig`, `resetConfig`, `normalizeEnv`, `ConfigSchema`, `FRAMEWORK_NAME`, `FRAMEWORK_VERSION` | Zod-validated config, framework identity, env-var helpers |
55
55
  | `/auth` | `checkScopes` | Dynamic scope checking |
56
56
  | `/storage` | `StorageService` | Storage abstraction |
57
57
  | `/storage/types` | `IStorageProvider` | Provider interface |
@@ -106,9 +106,13 @@ await createApp({
106
106
  extensions: { // SEP-2133 extensions advertised in capabilities
107
107
  'vendor/my-extension': { /* extension config */ },
108
108
  },
109
+ sessionMode: 'stateless', // session posture in code, not in a Dockerfile
109
110
  setup(core) { // runs after core services init, before transport starts
110
111
  initMyService(core.config, core.storage);
111
112
  },
113
+ async teardown(core) { // the setup() counterpart — runs on every shutdown path
114
+ await closeMyService();
115
+ },
112
116
  });
113
117
  ```
114
118
 
@@ -116,6 +120,10 @@ await createApp({
116
120
 
117
121
  **Identity fields** — Optional `title`, `websiteUrl`, `description`, `icons` (SEP-973) pass through to the SDK's `initialize` serverInfo and to the server manifest, keeping the `/.well-known/mcp.json` server card and landing page consistent with what `initialize` reports. Explicit `description` wins over `MCP_SERVER_DESCRIPTION`/package.json.
118
122
 
123
+ **`sessionMode`** — `SessionMode | { default?: SessionMode; require?: 'stateful' }`; the bare string is shorthand for `{ default }`. Declares the HTTP session posture in `src/` instead of leaving it to a deployment's `MCP_SESSION_MODE`, which still wins whenever it carries a meaningful value — an empty string and a whole-value unsubstituted `${…}` placeholder read as unset, so both fall through to the option rather than to the schema default (`auto`). `require: 'stateful'` fails startup with a `ConfigurationError` when the resolved HTTP mode is `stateless`: declare it on a server whose tools ask the caller for input mid-handler, since under `stateless` a 2025-era client's round trip is refused unconditionally and the tool is unusable rather than merely guarded. Never refuses a stdio start. Workers are outside this contract (`MCP_SESSION_MODE` is not in `CORE_ENV_BINDINGS`).
124
+
125
+ **`teardown(core)`** — the `setup()` counterpart, awaited inside `shutdown()` after the transport stops accepting requests and before core services are disposed and the logger closes, so the hook can still log and still reach `core.storage`. Runs exactly once per shutdown, on the signal path, the stdin-EOF path, and a direct `ServerHandle.shutdown()` alike; an error it raises is logged and never blocks the exit, and on the signal and EOF paths a hook that never settles is cut by the shutdown ceiling (exit 1 on a signal, 0 on EOF). Register whatever the framework cannot see — a `fs.watch`, an open socket, a `setInterval` nobody `unref()`'d. Node/Bun only; `createWorkerHandler` does not accept it, because an isolate is evicted without notice.
126
+
119
127
  **Also available** — `landing` (`LandingConfig`, HTTP transport only: landing-page config, all fields optional), `context: { exposeStatelessSessionId }` (populate `ctx.sessionId` from the SDK's per-request token in stateless HTTP mode; default `false`), `eventBus` (the `ServerEventBus` backing `subscriptions/listen`; defaults to an in-process bus — supply one for a multi-isolate or multi-process runtime, Workers most of all), and `cacheHints` (2026-07-28 `ttlMs`/`cacheScope` per cacheable operation — see Adding a Resource for the per-resource override).
120
128
 
121
129
  ### Cloudflare Workers — `createWorkerHandler(options)`
@@ -151,7 +159,7 @@ interface CoreServices {
151
159
  canvas?: DataCanvas; // present when CANVAS_PROVIDER_TYPE=duckdb; never on Workers
152
160
  llmProvider?: ILlmProvider;
153
161
  speechService?: SpeechService;
154
- supabase?: SupabaseClient;
162
+ supabase?: SupabaseClientHandle;
155
163
  }
156
164
 
157
165
  interface ServerHandle {
@@ -160,6 +168,8 @@ interface ServerHandle {
160
168
  }
161
169
  ```
162
170
 
171
+ **Exit contract.** `shutdown()` is exit-free and unbounded: it also serves the startup-failure rollback and direct calls from embedders and tests, so ending the process belongs to the handlers. `SIGTERM`, `SIGINT`, and stdin EOF each run that same shutdown and then exit explicitly. A signal exits 0 once the shutdown settles and 1 when the 10 s ceiling fires, after a warning naming the step that never settled; stdin EOF exits 0 either way, unchanged. The ceiling bounds the shutdown as a whole rather than any single await, so a step that settles inside it is never truncated. A second signal mid-shutdown reaches no handler (shutdown detaches them as it starts) and terminates on the OS default, 143 / 130 — the operator's force-kill escape hatch. `uncaughtException` / `unhandledRejection` exit 1.
172
+
163
173
  ---
164
174
 
165
175
  ## Server Structure
@@ -404,7 +414,7 @@ Available factories: `invalidParams`, `invalidRequest`, `notFound`, `forbidden`,
404
414
 
405
415
  For HTTP responses from upstream APIs, use `httpErrorFromResponse(response, { service, data })` from `/utils` — maps the full status table (401/403/408/422/429/5xx) and captures body + `Retry-After`.
406
416
 
407
- **Auto-classification.** Plain `Error`, `ZodError`, and any other thrown value are caught and classified automatically. Resolution order: `McpError` code (preserved as-is) → JS constructor name (`TypeError` → `ValidationError`) → provider patterns (HTTP status codes, AWS errors, DB errors) → common message patterns → `AbortError` name → `InternalError` fallback.
417
+ **Auto-classification.** Plain `Error`, `ZodError`, and any other thrown value are caught and classified automatically. Resolution order: `McpError` code (preserved as-is) → SDK `ConnectionClosed` (→ `RequestCancelled`) → JS constructor name (`TypeError` → `ValidationError`) → provider patterns (HTTP status codes, AWS errors, DB errors) → common message patterns → `AbortError` name (→ `Timeout`) → `InternalError` fallback.
408
418
 
409
419
  **Error-path parity.** Tool errors: `content[]` carries markdown with `data.recovery.hint`; `structuredContent.error` carries `{ code, message, data? }`. No `_meta.error`. Resources re-throw via JSON-RPC error envelope.
410
420
 
@@ -506,11 +516,11 @@ Detailed method signatures, options, and examples live in skill files. Read the
506
516
 
507
517
  ### Skill versioning
508
518
 
509
- Each `skills/<name>/SKILL.md` carries `metadata.version` in frontmatter. The `maintenance` skill's Phase A uses this to sync consumer copies — replaces the **entire skill directory** as one unit. Without a version bump, Phase A skips the skill (content-hash backstop catches drift, but noisier).
519
+ Each `framework-skills/<name>/SKILL.md` carries `metadata.version` in frontmatter. The `maintenance` skill's Phase A uses this to sync consumer copies — replaces the **entire skill directory** as one unit. Without a version bump, Phase A skips the skill (content-hash backstop catches drift, but noisier).
510
520
 
511
- **Policy:** Bump `metadata.version` when changing any file under `skills/<name>/` — SKILL.md is the single version knob for the directory. Typo/whitespace fixes exempt. One bump per release cycle suffices. Enforced by `bun run devcheck` (`scripts/check-skill-versions.ts`): a SKILL.md body change vs `HEAD` without a `metadata.version` bump surfaces as a warning; whitespace-only edits never trigger it, and a genuine typo fix opts out via `devcheck.config.json` `skillVersions.ignore`.
521
+ **Policy:** Bump `metadata.version` when changing any file under `framework-skills/<name>/` — SKILL.md is the single version knob for the directory. Typo/whitespace fixes exempt. One bump per release cycle suffices. Enforced by `bun run devcheck` (`scripts/check-skill-versions.ts`): a SKILL.md body change vs `HEAD` without a `metadata.version` bump surfaces as a warning; whitespace-only edits never trigger it, and a genuine typo fix opts out via `devcheck.config.json` `skillVersions.ignore`.
512
522
 
513
- Skills live in `skills/<name>/SKILL.md`; the full list is discoverable via the agent's skill registry at session start.
523
+ Skills live in `framework-skills/<name>/SKILL.md`; the full list is discoverable via the agent's skill registry at session start. The directory is deliberately not `skills/`: Claude Code and Codex auto-load a plugin's root `skills/`, and these are development-time skills, not skills for the agents that use a server. `skills/` stays free for that second kind.
514
524
 
515
525
  ---
516
526
 
@@ -542,7 +552,8 @@ Skills live in `skills/<name>/SKILL.md`; the full list is discoverable via the a
542
552
  | `bun run build` | Build library output (`scripts/build.ts`) |
543
553
  | `bun run rebuild` | Clean and rebuild (`scripts/clean.ts` + `build`) |
544
554
  | `bun run devcheck` | **Use often.** Biome lint/format, typecheck, MCP definition + packaging lint, docs/skills/changelog sync checks, secrets + antipattern scans, `bun audit`, `bun outdated` |
545
- | `bun run audit:refresh` | Delete `bun.lock`, reinstall, re-audit. Use when `devcheck` flags a transitive advisory stale lockfile can mask already-patched deps. If advisory survives, it's real. |
555
+ | `bun run audit:fix` | `bun audit fix` upgrade vulnerable packages to the lowest safe version within existing ranges (`--dry-run` previews, `--latest` rewrites ranges). First response to a transitive advisory; then `bun update <name>`, then `bun dedupe` |
556
+ | `bun run audit:refresh` | Delete `bun.lock` and reinstall. Last resort after `audit:fix`, `bun update <name>`, and `bun dedupe` — re-resolves every ranged dep and rewrites the lockfile as `lockfileVersion: 2` |
546
557
  | `bun run lint:mcp` | Validate MCP definitions against spec |
547
558
  | `bun run format` | Auto-fix Biome lint/format issues (safe fixes only) |
548
559
  | `bun run format:unsafe` | Also apply Biome's unsafe autofixes — review the diff; they can change behavior, not just formatting |
package/CLAUDE.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Developer Protocol
2
2
 
3
3
  **Package:** `@cyanheads/mcp-ts-core`
4
- **Version:** 0.12.9
4
+ **Version:** 0.13.1
5
5
  **Engines:** Bun ≥1.4.0, Node ≥24.0.0
6
6
  **MCP SDK:** `@modelcontextprotocol/server` ^2.0.0 (protocol revisions 2026-07-28 and 2025-*)
7
- **Zod:** ^4.6.0
7
+ **Zod:** ^4.6.1
8
8
  **GitHub:** [cyanheads/mcp-ts-core](https://github.com/cyanheads/mcp-ts-core)
9
9
  **npm:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core)
10
10
  **Docker:** [ghcr.io/cyanheads/mcp-ts-core](https://ghcr.io/cyanheads/mcp-ts-core)
@@ -22,7 +22,7 @@ This package serves two consumer paths. When making changes, know which audience
22
22
  | **Direct package import** — existing project pulls in the package | `bun add @cyanheads/mcp-ts-core` → `import { createApp, tool, z } from '@cyanheads/mcp-ts-core'` | Public API surface (`src/`) — existing consumers feel changes immediately on upgrade |
23
23
  | **Init-scaffolded server** — fresh project bootstrapped from this repo's templates | `bunx @cyanheads/mcp-ts-core init [name]` copies `templates/` into the new directory | `templates/` — only affects newly scaffolded servers, not existing ones |
24
24
 
25
- Both paths share the same public API. Init copies starter `package.json`, configs (`tsconfig`, `biome.json`, `vitest.config.ts`, `devcheck.config.json`, `bunfig.toml`), `.env.example`, `Dockerfile`, `LICENSE`, `.gitattributes`, `CLAUDE.md`/`AGENTS.md`, `.github/` (issue forms, `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`, `SECURITY.md`), example definitions and tests, framework `scripts/`, and external-audience `skills/`. `_`-prefixed files (e.g. `_.gitignore`) drop the prefix on copy. Existing files are never overwritten; `init` without a name scaffolds in place (upgrade flow). After init, consult the `setup` skill.
25
+ Both paths share the same public API. Init copies starter `package.json`, configs (`tsconfig`, `biome.json`, `vitest.config.ts`, `devcheck.config.json`, `bunfig.toml`), `.env.example`, `Dockerfile`, `LICENSE`, `.gitattributes`, `CLAUDE.md`/`AGENTS.md`, `.github/` (issue forms, `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`, `SECURITY.md`), example definitions and tests, framework `scripts/`, and external-audience `framework-skills/`. `_`-prefixed files (e.g. `_.gitignore`) drop the prefix on copy. Existing files are never overwritten; `init` without a name scaffolds in place (upgrade flow). After init, consult the `setup` skill.
26
26
 
27
27
  ---
28
28
 
@@ -45,13 +45,13 @@ Both paths share the same public API. Init copies starter `package.json`, config
45
45
 
46
46
  | Subpath | Key Exports | Purpose |
47
47
  |:--------|:------------|:--------|
48
- | `@cyanheads/mcp-ts-core` | `createApp`, `tool`, `resource`, `prompt`, `appTool`, `appResource`, `APP_RESOURCE_MIME_TYPE`, `headerParam`, `Context`, `createFail`, `createRecoveryFor`, `TypedFail`, `TypedRecoveryFor`, `ReasonOf`, `HandlerContext`, `Enrich`, `EnrichHelpers`, `TypedEnrich`, `ContentCollect`, `ContentBlock`, `z`, `completable`, `isCompletable`, `CompleteCallback`, `CompleteResourceTemplateCallback`, `CacheHint`, `CacheHints`, `CacheScope` | Main entry point |
48
+ | `@cyanheads/mcp-ts-core` | `createApp`, `tool`, `resource`, `prompt`, `appTool`, `appResource`, `APP_RESOURCE_MIME_TYPE`, `headerParam`, `Context`, `createFail`, `createRecoveryFor`, `TypedFail`, `TypedRecoveryFor`, `ReasonOf`, `HandlerContext`, `Enrich`, `EnrichHelpers`, `TypedEnrich`, `ContentCollect`, `ContentBlock`, `z`, `inputRequired`, `completable`, `isCompletable`, `CompleteCallback`, `CompleteResourceTemplateCallback`, `CacheHint`, `CacheHints`, `CacheScope`, `SessionMode`, `ResolvedSessionMode` | Main entry point |
49
49
  | `/worker` | `createWorkerHandler`, `CloudflareBindings` | Cloudflare Workers entry |
50
50
  | `/tools` | `ToolDefinition`, `AnyToolDefinition`, `ToolAnnotations` | Tool definition types |
51
51
  | `/resources` | `ResourceDefinition`, `AnyResourceDefinition` | Resource definition types |
52
52
  | `/prompts` | `PromptDefinition` | Prompt definition type |
53
53
  | `/errors` | `McpError`, `JsonRpcErrorCode`, `notFound`, `validationError`, `unauthorized`, ... | Error types, codes, and factory functions |
54
- | `/config` | `AppConfig`, `config`, `parseConfig`, `parseEnvConfig`, `resetConfig`, `ConfigSchema`, `FRAMEWORK_NAME`, `FRAMEWORK_VERSION` | Zod-validated config, framework identity, env-var helper |
54
+ | `/config` | `AppConfig`, `config`, `parseConfig`, `parseEnvConfig`, `resetConfig`, `normalizeEnv`, `ConfigSchema`, `FRAMEWORK_NAME`, `FRAMEWORK_VERSION` | Zod-validated config, framework identity, env-var helpers |
55
55
  | `/auth` | `checkScopes` | Dynamic scope checking |
56
56
  | `/storage` | `StorageService` | Storage abstraction |
57
57
  | `/storage/types` | `IStorageProvider` | Provider interface |
@@ -106,9 +106,13 @@ await createApp({
106
106
  extensions: { // SEP-2133 extensions advertised in capabilities
107
107
  'vendor/my-extension': { /* extension config */ },
108
108
  },
109
+ sessionMode: 'stateless', // session posture in code, not in a Dockerfile
109
110
  setup(core) { // runs after core services init, before transport starts
110
111
  initMyService(core.config, core.storage);
111
112
  },
113
+ async teardown(core) { // the setup() counterpart — runs on every shutdown path
114
+ await closeMyService();
115
+ },
112
116
  });
113
117
  ```
114
118
 
@@ -116,6 +120,10 @@ await createApp({
116
120
 
117
121
  **Identity fields** — Optional `title`, `websiteUrl`, `description`, `icons` (SEP-973) pass through to the SDK's `initialize` serverInfo and to the server manifest, keeping the `/.well-known/mcp.json` server card and landing page consistent with what `initialize` reports. Explicit `description` wins over `MCP_SERVER_DESCRIPTION`/package.json.
118
122
 
123
+ **`sessionMode`** — `SessionMode | { default?: SessionMode; require?: 'stateful' }`; the bare string is shorthand for `{ default }`. Declares the HTTP session posture in `src/` instead of leaving it to a deployment's `MCP_SESSION_MODE`, which still wins whenever it carries a meaningful value — an empty string and a whole-value unsubstituted `${…}` placeholder read as unset, so both fall through to the option rather than to the schema default (`auto`). `require: 'stateful'` fails startup with a `ConfigurationError` when the resolved HTTP mode is `stateless`: declare it on a server whose tools ask the caller for input mid-handler, since under `stateless` a 2025-era client's round trip is refused unconditionally and the tool is unusable rather than merely guarded. Never refuses a stdio start. Workers are outside this contract (`MCP_SESSION_MODE` is not in `CORE_ENV_BINDINGS`).
124
+
125
+ **`teardown(core)`** — the `setup()` counterpart, awaited inside `shutdown()` after the transport stops accepting requests and before core services are disposed and the logger closes, so the hook can still log and still reach `core.storage`. Runs exactly once per shutdown, on the signal path, the stdin-EOF path, and a direct `ServerHandle.shutdown()` alike; an error it raises is logged and never blocks the exit, and on the signal and EOF paths a hook that never settles is cut by the shutdown ceiling (exit 1 on a signal, 0 on EOF). Register whatever the framework cannot see — a `fs.watch`, an open socket, a `setInterval` nobody `unref()`'d. Node/Bun only; `createWorkerHandler` does not accept it, because an isolate is evicted without notice.
126
+
119
127
  **Also available** — `landing` (`LandingConfig`, HTTP transport only: landing-page config, all fields optional), `context: { exposeStatelessSessionId }` (populate `ctx.sessionId` from the SDK's per-request token in stateless HTTP mode; default `false`), `eventBus` (the `ServerEventBus` backing `subscriptions/listen`; defaults to an in-process bus — supply one for a multi-isolate or multi-process runtime, Workers most of all), and `cacheHints` (2026-07-28 `ttlMs`/`cacheScope` per cacheable operation — see Adding a Resource for the per-resource override).
120
128
 
121
129
  ### Cloudflare Workers — `createWorkerHandler(options)`
@@ -151,7 +159,7 @@ interface CoreServices {
151
159
  canvas?: DataCanvas; // present when CANVAS_PROVIDER_TYPE=duckdb; never on Workers
152
160
  llmProvider?: ILlmProvider;
153
161
  speechService?: SpeechService;
154
- supabase?: SupabaseClient;
162
+ supabase?: SupabaseClientHandle;
155
163
  }
156
164
 
157
165
  interface ServerHandle {
@@ -160,6 +168,8 @@ interface ServerHandle {
160
168
  }
161
169
  ```
162
170
 
171
+ **Exit contract.** `shutdown()` is exit-free and unbounded: it also serves the startup-failure rollback and direct calls from embedders and tests, so ending the process belongs to the handlers. `SIGTERM`, `SIGINT`, and stdin EOF each run that same shutdown and then exit explicitly. A signal exits 0 once the shutdown settles and 1 when the 10 s ceiling fires, after a warning naming the step that never settled; stdin EOF exits 0 either way, unchanged. The ceiling bounds the shutdown as a whole rather than any single await, so a step that settles inside it is never truncated. A second signal mid-shutdown reaches no handler (shutdown detaches them as it starts) and terminates on the OS default, 143 / 130 — the operator's force-kill escape hatch. `uncaughtException` / `unhandledRejection` exit 1.
172
+
163
173
  ---
164
174
 
165
175
  ## Server Structure
@@ -404,7 +414,7 @@ Available factories: `invalidParams`, `invalidRequest`, `notFound`, `forbidden`,
404
414
 
405
415
  For HTTP responses from upstream APIs, use `httpErrorFromResponse(response, { service, data })` from `/utils` — maps the full status table (401/403/408/422/429/5xx) and captures body + `Retry-After`.
406
416
 
407
- **Auto-classification.** Plain `Error`, `ZodError`, and any other thrown value are caught and classified automatically. Resolution order: `McpError` code (preserved as-is) → JS constructor name (`TypeError` → `ValidationError`) → provider patterns (HTTP status codes, AWS errors, DB errors) → common message patterns → `AbortError` name → `InternalError` fallback.
417
+ **Auto-classification.** Plain `Error`, `ZodError`, and any other thrown value are caught and classified automatically. Resolution order: `McpError` code (preserved as-is) → SDK `ConnectionClosed` (→ `RequestCancelled`) → JS constructor name (`TypeError` → `ValidationError`) → provider patterns (HTTP status codes, AWS errors, DB errors) → common message patterns → `AbortError` name (→ `Timeout`) → `InternalError` fallback.
408
418
 
409
419
  **Error-path parity.** Tool errors: `content[]` carries markdown with `data.recovery.hint`; `structuredContent.error` carries `{ code, message, data? }`. No `_meta.error`. Resources re-throw via JSON-RPC error envelope.
410
420
 
@@ -506,11 +516,11 @@ Detailed method signatures, options, and examples live in skill files. Read the
506
516
 
507
517
  ### Skill versioning
508
518
 
509
- Each `skills/<name>/SKILL.md` carries `metadata.version` in frontmatter. The `maintenance` skill's Phase A uses this to sync consumer copies — replaces the **entire skill directory** as one unit. Without a version bump, Phase A skips the skill (content-hash backstop catches drift, but noisier).
519
+ Each `framework-skills/<name>/SKILL.md` carries `metadata.version` in frontmatter. The `maintenance` skill's Phase A uses this to sync consumer copies — replaces the **entire skill directory** as one unit. Without a version bump, Phase A skips the skill (content-hash backstop catches drift, but noisier).
510
520
 
511
- **Policy:** Bump `metadata.version` when changing any file under `skills/<name>/` — SKILL.md is the single version knob for the directory. Typo/whitespace fixes exempt. One bump per release cycle suffices. Enforced by `bun run devcheck` (`scripts/check-skill-versions.ts`): a SKILL.md body change vs `HEAD` without a `metadata.version` bump surfaces as a warning; whitespace-only edits never trigger it, and a genuine typo fix opts out via `devcheck.config.json` `skillVersions.ignore`.
521
+ **Policy:** Bump `metadata.version` when changing any file under `framework-skills/<name>/` — SKILL.md is the single version knob for the directory. Typo/whitespace fixes exempt. One bump per release cycle suffices. Enforced by `bun run devcheck` (`scripts/check-skill-versions.ts`): a SKILL.md body change vs `HEAD` without a `metadata.version` bump surfaces as a warning; whitespace-only edits never trigger it, and a genuine typo fix opts out via `devcheck.config.json` `skillVersions.ignore`.
512
522
 
513
- Skills live in `skills/<name>/SKILL.md`; the full list is discoverable via the agent's skill registry at session start.
523
+ Skills live in `framework-skills/<name>/SKILL.md`; the full list is discoverable via the agent's skill registry at session start. The directory is deliberately not `skills/`: Claude Code and Codex auto-load a plugin's root `skills/`, and these are development-time skills, not skills for the agents that use a server. `skills/` stays free for that second kind.
514
524
 
515
525
  ---
516
526
 
@@ -542,7 +552,8 @@ Skills live in `skills/<name>/SKILL.md`; the full list is discoverable via the a
542
552
  | `bun run build` | Build library output (`scripts/build.ts`) |
543
553
  | `bun run rebuild` | Clean and rebuild (`scripts/clean.ts` + `build`) |
544
554
  | `bun run devcheck` | **Use often.** Biome lint/format, typecheck, MCP definition + packaging lint, docs/skills/changelog sync checks, secrets + antipattern scans, `bun audit`, `bun outdated` |
545
- | `bun run audit:refresh` | Delete `bun.lock`, reinstall, re-audit. Use when `devcheck` flags a transitive advisory stale lockfile can mask already-patched deps. If advisory survives, it's real. |
555
+ | `bun run audit:fix` | `bun audit fix` upgrade vulnerable packages to the lowest safe version within existing ranges (`--dry-run` previews, `--latest` rewrites ranges). First response to a transitive advisory; then `bun update <name>`, then `bun dedupe` |
556
+ | `bun run audit:refresh` | Delete `bun.lock` and reinstall. Last resort after `audit:fix`, `bun update <name>`, and `bun dedupe` — re-resolves every ranged dep and rewrites the lockfile as `lockfileVersion: 2` |
546
557
  | `bun run lint:mcp` | Validate MCP definitions against spec |
547
558
  | `bun run format` | Auto-fix Biome lint/format issues (safe fixes only) |
548
559
  | `bun run format:unsafe` | Also apply Biome's unsafe autofixes — review the diff; they can change behavior, not just formatting |
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  <div align="center">
8
8
 
9
- [![Version](https://img.shields.io/badge/Version-0.12.9-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![MCP Spec](https://img.shields.io/badge/MCP%20Spec-2026--07--28-8A2BE2.svg?style=flat-square)](https://modelcontextprotocol.io/specification/2026-07-28)
9
+ [![Version](https://img.shields.io/badge/Version-0.13.1-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![MCP Spec](https://img.shields.io/badge/MCP%20Spec-2026--07--28-8A2BE2.svg?style=flat-square)](https://modelcontextprotocol.io/specification/2026-07-28)
10
10
 
11
11
  [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^2.0.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![TypeScript](https://img.shields.io/badge/TypeScript-^7.0.2-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.4.0%2B-blueviolet.svg?style=flat-square)](https://bun.sh/)
12
12
 
package/biome.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://biomejs.dev/schemas/2.5.12/schema.json",
2
+ "$schema": "https://biomejs.dev/schemas/2.5.13/schema.json",
3
3
  "vcs": {
4
4
  "enabled": true,
5
5
  "clientKind": "git",
@@ -0,0 +1,48 @@
1
+ ---
2
+ summary: "The framework's skill tree moves from skills/ to framework-skills/, so a server that ships a plugin manifest no longer hands its development skills to every installing agent; consumers migrate with a git mv plus path updates. Empty and unsubstituted ${…} env values now read as unset on both config paths."
3
+ breaking: true
4
+ security: false
5
+ agent-notes: |
6
+ Two one-time steps for a consumer upgrading from an earlier release.
7
+
8
+ 1. Move the skill tree: `git mv skills framework-skills`, then update the path
9
+ in `CLAUDE.md`/`AGENTS.md`, `.mcpbignore` (`/framework-skills/`), and
10
+ `.github/CONTRIBUTING.md`, and regenerate `docs/tree.md`. `bun run devcheck`
11
+ reports an unmigrated tree until this is done. The agent mirrors
12
+ (`.claude/skills/`, `.agents/skills/`) keep their names — plugin hosts do
13
+ not scan them.
14
+ 2. Drop any per-server `z.preprocess` guard that maps a `${…}` placeholder or
15
+ an empty string to `undefined`. Both config paths now do it.
16
+ ---
17
+
18
+ # 0.13.0 — 2026-09-13
19
+
20
+ ## Added
21
+
22
+ - **`lint:packaging` check 11 — MCPB `user_config` wiring** — every declared option must be referenced from `mcp_config` as `${user_config.<key>}`, every reference must be declared, no other `${…}` may appear besides the host's path placeholders, and an optional string option needs `"default": ""`.
23
+ - **Check 10 rejects an empty plugin `env` value** — the client sets the entry on the child process, so `""` replaces a key the user exported. A `${user_config.<option>}` reference in `.claude-plugin/plugin.json` must name a declared `userConfig` option; Codex forwards a host variable only when `env_vars` names it.
24
+
25
+ ## Changed
26
+
27
+ - **The framework's skill tree moved from `skills/` to `framework-skills/`** ([#428](https://github.com/cyanheads/mcp-ts-core/issues/428)) — Claude Code and Codex auto-load a plugin's root `skills/`, so a server shipping `.claude-plugin/` or `.codex-plugin/` handed its development skills to every agent that installed it. No runtime API changed; the break is the path, and `check-skills-sync` reports an unmigrated tree until a consumer moves it (see `agent-notes`).
28
+ - **`parseEnvConfig` and the framework's own config read an empty string and a whole-value `${…}` placeholder as unset** ([#427](https://github.com/cyanheads/mcp-ts-core/issues/427)) — an optional field stays `undefined`, a defaulted field takes its default, and a required field fails as missing rather than as a format error against the literal text. A value that merely contains `${…}` is kept; `parseEnvConfig` previously did not strip empty strings.
29
+ - **`audit:fix` runs `bun audit fix`** ([#363](https://github.com/cyanheads/mcp-ts-core/issues/363)) — `bun audit` has no `--fix` flag, so the script ran a read-only audit and exited `0` having changed nothing. The `maintenance` skill's transitive-advisory triage now leads with it, then `bun update <name>`, then `bun dedupe`, with `audit:refresh` last ([#366](https://github.com/cyanheads/mcp-ts-core/issues/366)).
30
+ - **The scaffolded app UI imports `@modelcontextprotocol/ext-apps@2`** ([#424](https://github.com/cyanheads/mcp-ts-core/issues/424)) — the package depends on `^2.0.0`.
31
+ - **Scaffolded issue forms accept blank issues, and this repo's forms link the private advisory form** — a vulnerability had no route in but a public issue.
32
+ - Shipped skills: `add-app-tool` 1.5, `add-resource` 1.6, `add-service` 1.10, `add-test` 1.7, `add-tool` 2.24, `api-config` 1.17, `api-context` 2.3, `api-linter` 1.14, `maintenance` 2.7, `orchestrations` 1.9, `polish-docs-meta` 2.15, `release-pr-review` 1.1, `report-issue-framework` 1.10, `report-issue-local` 1.8, `setup` 1.11.
33
+
34
+ ## Fixed
35
+
36
+ - **`templates/.env.example` names all three `MCP_SESSION_MODE` values and `auto` as the default** ([#384](https://github.com/cyanheads/mcp-ts-core/issues/384)).
37
+ - **`changelog/template.md` no longer prescribes a tag format `git-wrapup` forbids** ([#348](https://github.com/cyanheads/mcp-ts-core/issues/348)) — the tag-annotation spec is owned by `release-and-publish`.
38
+ - **The `report-issue-framework` and `report-issue-local` feature templates carry the form's required `Use case` field** ([#353](https://github.com/cyanheads/mcp-ts-core/issues/353)) — both led with a `## Proposal` heading that is not a form field.
39
+ - **The scaffolded agent-protocol checklist names the unscoped repo name for plugin display fields** ([#382](https://github.com/cyanheads/mcp-ts-core/issues/382)) — it said "package name", which `lint:packaging` rejects for a scoped package.
40
+
41
+ ## Dependencies
42
+
43
+ - `zod` ^4.6.0 → ^4.6.1
44
+ - `@biomejs/biome` 2.5.12 → 2.5.13
45
+ - `@cloudflare/workers-types` 5.20260905.1 → 5.20260910.1
46
+ - `@types/node` 26.4.0 → 26.5.1
47
+ - `vite` 8.2.2 → 8.3.0
48
+ - `vitest`, `@vitest/ui`, `@vitest/coverage-istanbul` held at 4.1.11 pending `@cloudflare/vitest-pool-workers` support ([#420](https://github.com/cyanheads/mcp-ts-core/issues/420))
@@ -0,0 +1,56 @@
1
+ ---
2
+ summary: "Five polynomial-time regexes become linear scans, two of them on client-supplied input. createApp gains a sessionMode option and a teardown hook, and SIGTERM/SIGINT now end the process explicitly instead of waiting for the event loop to drain."
3
+ breaking: false
4
+ security: true
5
+ agent-notes: |
6
+ Three adoption steps for a consumer upgrading from 0.13.0.
7
+
8
+ 1. `MCP_SESSION_MODE` is now set actively in the scaffold's
9
+ `templates/.env.example` (`stateless`) rather than commented out at `auto`.
10
+ An upgrade never rewrites an existing server's `.env.example` — set the
11
+ value there deliberately, and prefer `stateful` on a server whose tools
12
+ gate on `ctx.requestInput`. Declaring it in `src/` via
13
+ `createApp({ sessionMode })` is the durable form.
14
+ 2. Move service cleanup into `createApp({ teardown })`. A service that
15
+ allocates a watcher, socket, or non-`unref()`'d timer in `setup()` and
16
+ exposes its own `shutdown()` had nothing calling it; the hook is that
17
+ call. Signal shutdown now exits explicitly, so an unreleased ref'd handle
18
+ no longer hangs the process either — but it is cut, not closed.
19
+ 3. The tsconfig move only affects a project that extends a root config **by
20
+ path** (`…/mcp-ts-core/tsconfig.base.json`); retarget it to
21
+ `config/tsconfig.base.json`. A project extending the published
22
+ `@cyanheads/mcp-ts-core/tsconfig.base.json` subpath — the scaffold's own
23
+ form — needs no change.
24
+ ---
25
+
26
+ # 0.13.1 — 2026-09-13
27
+
28
+ ## Added
29
+
30
+ - **`createApp({ sessionMode })` declares the HTTP session posture in `src/`** ([#376](https://github.com/cyanheads/mcp-ts-core/issues/376)) — `SessionMode | { default?: SessionMode; require?: 'stateful' }`, the bare string being shorthand for `{ default }`. `MCP_SESSION_MODE` still wins over `default` whenever it carries a meaningful value; an empty string and a whole-value unsubstituted `${…}` placeholder read as unset and fall through to the option rather than to the schema default.
31
+ - **`require: 'stateful'` fails startup instead of degrading** ([#376](https://github.com/cyanheads/mcp-ts-core/issues/376)) — a `ConfigurationError` naming the conflicting env value, raised before any service is constructed, when the resolved HTTP mode is `stateless`. Declare it on a server whose tools gate on `ctx.requestInput`, which a 2025-era HTTP client cannot answer under `stateless`. Never refuses a stdio start.
32
+ - **`createApp({ teardown })`, the `setup()` counterpart** ([#435](https://github.com/cyanheads/mcp-ts-core/issues/435)) — awaited inside `shutdown()` after the transport stops accepting requests and before core services are disposed and the logger closes, so the hook can still log and still reach `core.storage`. Runs once per shutdown on the signal, stdin-EOF, and direct `ServerHandle.shutdown()` paths alike; an error it raises is logged and never blocks the exit. Node/Bun only — `createWorkerHandler` omits it, because an isolate is evicted without notice.
33
+ - **`SessionMode` and `ResolvedSessionMode` on the root barrel; `normalizeEnv` on `/config`** — the seeding decision needs the same verdict `parseConfig` reaches on an empty or placeholder value, so the rule is exported rather than re-implemented at the call site.
34
+
35
+ ## Changed
36
+
37
+ - **`SIGTERM` and `SIGINT` end the process explicitly** ([#435](https://github.com/cyanheads/mcp-ts-core/issues/435)) — exit `0` once shutdown settles, `1` when the 10 s ceiling fires, after a warning naming the cleanup step that never settled. The ceiling bounds the shutdown as a whole, so a step that settles inside it is never truncated. A second signal mid-shutdown still terminates on the OS default (`143` / `130`), and `ServerHandle.shutdown()` stays exit-free and unbounded.
38
+ - **The four project tsconfigs live in `config/`** ([#432](https://github.com/cyanheads/mcp-ts-core/issues/432)) — `tsconfig.json` stays at the root and extends `./config/tsconfig.base.json`. The published `./tsconfig.base.json` subpath is retargeted through the export map, not renamed, so a consumer extending it is untouched.
39
+ - **Both `.env.example` files set `MCP_SESSION_MODE=stateless`** ([#376](https://github.com/cyanheads/mcp-ts-core/issues/376)) — actively, where the root file carried `auto` and the template left the line commented. Stateless fits the data-API shape the scaffold targets; `ctx.state` is tenant-scoped storage, not the session store, so caching across calls is unaffected.
40
+ - **`code-simplifier` 1.5** ([#433](https://github.com/cyanheads/mcp-ts-core/issues/433)) — Phase 1 takes a named path, module, or whole codebase as its scope, not only the working-tree diff. Adds the *Pass-through layers* deletion test and *Test-only reach* dimensions, with the framework's init/accessor pair, definition→service split, and config-selected provider interfaces exempted.
41
+ - **`report-issue-local` 1.9 and `report-issue-framework` 1.11 document the blocked-by labels** ([#436](https://github.com/cyanheads/mcp-ts-core/issues/436)) — `blocked-by-framework` for a server fix waiting on a released `@cyanheads/mcp-ts-core` change, `blocked-by-sdk` for one waiting on `@modelcontextprotocol/sdk`.
42
+ - **Skill upkeep** — `release-and-publish` 2.17 writes the annotated tag from a file (`-F`) rather than `-m`, whose backticks were command substitution, and waits for npm to serve the new version before `publish-mcp`; `polish-docs-meta` 2.16's README reference pins the Overview opener, the Features shape, and which deployment subsections apply, and `maintenance` 2.8 re-audits `README.md` when that reference changes; `api-telemetry` 1.9, `api-config` 1.18, `api-context` 2.4, `add-tool` 2.25, and `design-mcp-server` 2.26 carry the two new options and the corrected `MCP_SESSION_MODE=stateless` behavior (the 2025-era shim runs and its capability gate refuses — it is not disabled).
43
+
44
+ ## Fixed
45
+
46
+ - **`FrontmatterParser.parse`'s JSDoc examples** — `content` for a `---\n…\n---\n\n# Body` document is `'# Body'`; two examples documented a leading newline the parser never produced.
47
+ - **`MCP_HTTP_HOST` in the scaffold's env comment** — `127.0.0.1`, matching the schema default, where the comment said `localhost`.
48
+
49
+ ## Security
50
+
51
+ - **Five polynomial-time regexes replaced with linear-time scans** ([#431](https://github.com/cyanheads/mcp-ts-core/issues/431)) — CodeQL `js/polynomial-redos`. Two run on input a client chooses and become index walks: `stripSqlComments`, over the SQL sent to a canvas query tool, and `frontmatterParser`'s fence match, over any markdown a server hands `parse()` — at the 1 MiB default body cap either pinned the event loop for minutes. `encodeCursor` and the two linter URI-template helpers stay regexes, narrowed so they cannot backtrack; neither has client-reachable input.
52
+ - **One deliberate divergence on a malformed URI template** — the linter helpers now read `{{{{a}` as a literal `{{{` followed by the expression `{a}`, where the old patterns took the whole run as one expression body. RFC 6570 has no nested expressions, so no well-formed template changes, and admitting `{` into the body is exactly what let a run of them backtrack.
53
+
54
+ ## Dependencies
55
+
56
+ - `openai` `^7.10.0` → `^7.15.0`
@@ -117,30 +117,13 @@ security: false
117
117
  in that unrelated item's metadata.
118
118
 
119
119
  TAG ANNOTATIONS — the annotated tag body renders as the GitHub Release body
120
- via `gh release create --notes-from-tag`. The tag is a derivative of this
121
- changelog entry a condensed, scannable version, not a copy. Format:
122
-
123
- <theme omit version number, GitHub prepends it>
124
- blank line
125
- <1-2 sentence context: what this release does>
126
- blank line
127
- Dependency bumps: ← section header
128
- ← blank line
129
- - `@cyanheads/mcp-ts-core` ^0.9.1 → ^0.9.6 ← bullet
130
- ← blank line
131
- Changed: ← only sections with entries
132
- ← blank line
133
- - `format()` output includes `query` in text mode
134
- ← blank line
135
- Added:
136
- ← blank line
137
- - `manifest.json` scaffolded for MCPB bundle support
138
- - Install badges (Claude Desktop, Cursor, VS Code)
139
- ← blank line
140
- <N> tests pass; `bun run devcheck` clean. ← footer
141
-
142
- Never a flat comma-separated string. Always structured markdown with
143
- sections. The tag must scan well as a rendered GitHub Release page.
120
+ via `gh release create --notes-from-tag`. It is a condensed digest of this
121
+ entry, never a copy, and its format is owned by the `release-and-publish`
122
+ skill (step 4, "Create the annotated tag"): the entry's `summary:` as the
123
+ theme line without the version, flat headline bullets — no Keep-a-Changelog
124
+ section headers, no gates line — at most one deps line, issue backlinks,
125
+ and the changelog link last. In release-PR mode the `git-wrapup` skill
126
+ authors that digest as the PR body's `## Changes` and the tag copies it.
144
127
  -->
145
128
 
146
129
  ## Added
@@ -14,7 +14,7 @@
14
14
 
15
15
  "esModuleInterop": true,
16
16
 
17
- "outDir": "./dist",
17
+ "outDir": "../dist",
18
18
  "declaration": true,
19
19
  "declarationMap": true,
20
20
  "sourceMap": true,
@@ -34,7 +34,7 @@
34
34
  "allowJs": false,
35
35
 
36
36
  "paths": {
37
- "@/*": ["./src/*"]
37
+ "@/*": ["../src/*"]
38
38
  }
39
39
  }
40
40
  }
package/dist/cli/init.js CHANGED
@@ -9,7 +9,7 @@ import { basename, dirname, extname, join, relative } from 'node:path';
9
9
  import { fileURLToPath } from 'node:url';
10
10
  const PACKAGE_ROOT = join(dirname(fileURLToPath(import.meta.url)), '..', '..');
11
11
  const TEMPLATES_DIR = join(PACKAGE_ROOT, 'templates');
12
- const SKILLS_DIR = join(PACKAGE_ROOT, 'skills');
12
+ const SKILLS_DIR = join(PACKAGE_ROOT, 'framework-skills');
13
13
  const SCRIPTS_DIR = join(PACKAGE_ROOT, 'scripts');
14
14
  const PACKAGE_JSON = JSON.parse(readFileSync(join(PACKAGE_ROOT, 'package.json'), 'utf-8'));
15
15
  /**
@@ -152,7 +152,7 @@ function copyExternalSkills(dest, created, skipped) {
152
152
  continue;
153
153
  const skillFiles = walkDir(join(SKILLS_DIR, dir.name));
154
154
  for (const srcPath of skillFiles) {
155
- const relPath = join('skills', dir.name, relative(join(SKILLS_DIR, dir.name), srcPath));
155
+ const relPath = join('framework-skills', dir.name, relative(join(SKILLS_DIR, dir.name), srcPath));
156
156
  const destPath = join(dest, relPath);
157
157
  copyIfAbsent(srcPath, destPath, relPath, created, skipped);
158
158
  }
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @fileoverview Normalizes raw environment values before schema validation,
3
+ * so "nothing was provided" reads the same whether the variable is unset,
4
+ * empty, or an install-time placeholder nobody substituted.
5
+ * @module src/config/envValue
6
+ */
7
+ /**
8
+ * Returns `undefined` for a value that carries no configuration: an empty or
9
+ * whitespace-only string, or an unsubstituted whole-value placeholder. An
10
+ * optional field then stays unset, a defaulted field takes its default, and a
11
+ * required field fails as missing rather than as a format error against the
12
+ * literal text. Anything else — including a longer string that merely
13
+ * contains `${…}` — passes through unchanged.
14
+ */
15
+ export declare const emptyStringAsUndefined: (val: unknown) => unknown;
16
+ /** Applies {@link emptyStringAsUndefined} to every entry of an env map. */
17
+ export declare const normalizeEnv: (env: Record<string, string | undefined>) => Record<string, string | undefined>;
18
+ //# sourceMappingURL=envValue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envValue.d.ts","sourceRoot":"","sources":["../../src/config/envValue.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,QAAS,OAAO,KAAG,OAIrD,CAAC;AAEF,2EAA2E;AAC3E,eAAO,MAAM,YAAY,QAClB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,KACtC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAMnC,CAAC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * @fileoverview Normalizes raw environment values before schema validation,
3
+ * so "nothing was provided" reads the same whether the variable is unset,
4
+ * empty, or an install-time placeholder nobody substituted.
5
+ * @module src/config/envValue
6
+ */
7
+ /**
8
+ * A whole-value `${…}` reference — `${user_config.api_key}`, `${API_KEY}` —
9
+ * that an install-time host (an MCPB manifest, a plugin manifest) forwarded
10
+ * verbatim because nothing substituted it.
11
+ */
12
+ const UNSUBSTITUTED_PLACEHOLDER = /^\$\{[^}]+\}$/;
13
+ /**
14
+ * Returns `undefined` for a value that carries no configuration: an empty or
15
+ * whitespace-only string, or an unsubstituted whole-value placeholder. An
16
+ * optional field then stays unset, a defaulted field takes its default, and a
17
+ * required field fails as missing rather than as a format error against the
18
+ * literal text. Anything else — including a longer string that merely
19
+ * contains `${…}` — passes through unchanged.
20
+ */
21
+ export const emptyStringAsUndefined = (val) => {
22
+ if (typeof val !== 'string')
23
+ return val;
24
+ const trimmed = val.trim();
25
+ return trimmed === '' || UNSUBSTITUTED_PLACEHOLDER.test(trimmed) ? undefined : val;
26
+ };
27
+ /** Applies {@link emptyStringAsUndefined} to every entry of an env map. */
28
+ export const normalizeEnv = (env) => {
29
+ const out = {};
30
+ for (const [key, value] of Object.entries(env)) {
31
+ out[key] = emptyStringAsUndefined(value);
32
+ }
33
+ return out;
34
+ };
35
+ //# sourceMappingURL=envValue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envValue.js","sourceRoot":"","sources":["../../src/config/envValue.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;GAIG;AACH,MAAM,yBAAyB,GAAG,eAAe,CAAC;AAElD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,GAAY,EAAW,EAAE;IAC9D,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC;IACxC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,OAAO,OAAO,KAAK,EAAE,IAAI,yBAAyB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC;AACrF,CAAC,CAAC;AAEF,2EAA2E;AAC3E,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,GAAuC,EACH,EAAE;IACtC,MAAM,GAAG,GAAuC,EAAE,CAAC;IACnD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,GAAG,CAAC,GAAG,CAAC,GAAG,sBAAsB,CAAC,KAAK,CAAuB,CAAC;IACjE,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC,CAAC"}
@@ -393,6 +393,14 @@ declare const config: {
393
393
  * Export the runtime configuration, parser, and schema, plus a static AppConfig type.
394
394
  */
395
395
  export type AppConfig = z.infer<typeof ConfigSchema>;
396
+ /**
397
+ * The normalization `parseConfig` applies to every environment value before
398
+ * schema validation. Exported so a caller deciding whether a variable carries
399
+ * configuration reaches the same verdict this module does — an empty string and
400
+ * an unsubstituted `${…}` placeholder both read as unset — instead of
401
+ * re-implementing those rules and disagreeing with the parser.
402
+ */
403
+ export { normalizeEnv } from './envValue.js';
396
404
  export { parseEnvConfig } from './parseEnvConfig.js';
397
405
  export { ConfigSchema, config, parseConfig, resetConfig };
398
406
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAUxB,wEAAwE;AACxE,eAAO,MAAM,cAAc,2BAA2B,CAAC;AACvD,eAAO,MAAM,iBAAiB,QAAkC,CAAC;AAgCjE,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAoWd,CAAC;AAGL,QAAA,MAAM,WAAW,kBAAmB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgMrE,CAAC;AAIF;;;;;;;;GAQG;AACH,QAAA,MAAM,WAAW,kBAAmB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,KAAG,IAExE,CAAC;AAEF;;;;;;GAMG;AACH,QAAA,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuBV,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAErD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAWxB,wEAAwE;AACxE,eAAO,MAAM,cAAc,2BAA2B,CAAC;AACvD,eAAO,MAAM,iBAAiB,QAAkC,CAAC;AAyBjE,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAoWd,CAAC;AAGL,QAAA,MAAM,WAAW,kBAAmB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmMrE,CAAC;AAIF;;;;;;;;GAQG;AACH,QAAA,MAAM,WAAW,kBAAmB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,KAAG,IAExE,CAAC;AAEF;;;;;;GAMG;AACH,QAAA,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuBV,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAErD;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC"}