@cyanheads/mcp-ts-core 0.9.6 → 0.9.8

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 (49) hide show
  1. package/CLAUDE.md +3 -3
  2. package/README.md +12 -8
  3. package/biome.json +1 -1
  4. package/changelog/0.9.x/0.9.7.md +18 -0
  5. package/changelog/0.9.x/0.9.8.md +24 -0
  6. package/changelog/template.md +26 -0
  7. package/package.json +3 -4
  8. package/skills/add-app-tool/SKILL.md +6 -4
  9. package/skills/add-export/SKILL.md +10 -8
  10. package/skills/add-prompt/SKILL.md +15 -8
  11. package/skills/add-provider/SKILL.md +29 -12
  12. package/skills/add-resource/SKILL.md +20 -11
  13. package/skills/add-service/SKILL.md +15 -17
  14. package/skills/add-test/SKILL.md +50 -9
  15. package/skills/add-tool/SKILL.md +13 -6
  16. package/skills/api-auth/SKILL.md +3 -2
  17. package/skills/api-canvas/SKILL.md +43 -6
  18. package/skills/api-config/SKILL.md +6 -0
  19. package/skills/api-context/SKILL.md +9 -3
  20. package/skills/api-errors/SKILL.md +5 -5
  21. package/skills/api-linter/SKILL.md +32 -9
  22. package/skills/api-services/SKILL.md +1 -1
  23. package/skills/api-services/references/graph.md +1 -1
  24. package/skills/api-services/references/speech.md +1 -1
  25. package/skills/api-telemetry/SKILL.md +5 -5
  26. package/skills/api-testing/SKILL.md +9 -1
  27. package/skills/api-utils/SKILL.md +1 -1
  28. package/skills/api-workers/SKILL.md +12 -5
  29. package/skills/design-mcp-server/SKILL.md +20 -8
  30. package/skills/field-test/SKILL.md +9 -7
  31. package/skills/git-wrapup/SKILL.md +218 -0
  32. package/skills/maintenance/SKILL.md +8 -6
  33. package/skills/migrate-mcp-ts-template/SKILL.md +11 -7
  34. package/skills/multi-server-orchestration/SKILL.md +17 -5
  35. package/skills/multi-server-orchestration/references/greenfield-buildout.md +32 -2
  36. package/skills/multi-server-orchestration/references/maintenance-pass.md +11 -3
  37. package/skills/multi-server-orchestration/references/release-and-publish-pass.md +14 -25
  38. package/skills/multi-server-orchestration/references/wrapup-pass.md +15 -36
  39. package/skills/polish-docs-meta/SKILL.md +3 -1
  40. package/skills/polish-docs-meta/references/package-meta.md +1 -1
  41. package/skills/polish-docs-meta/references/readme.md +14 -1
  42. package/skills/release-and-publish/SKILL.md +20 -7
  43. package/skills/report-issue-framework/SKILL.md +5 -3
  44. package/skills/report-issue-local/SKILL.md +10 -5
  45. package/skills/setup/SKILL.md +13 -8
  46. package/skills/tool-defs-analysis/SKILL.md +6 -3
  47. package/templates/AGENTS.md +14 -6
  48. package/templates/CLAUDE.md +14 -6
  49. package/templates/changelog/template.md +26 -0
@@ -59,7 +59,7 @@ Fresh scaffolds register definitions directly in the entry point as shown above.
59
59
 
60
60
  - **Per-request `McpServer` factory**: a new server instance is created for each request. Required by SDK security advisory GHSA-345p-7cg4-v4c7.
61
61
  - **Env bindings refreshed per-request**: Cloudflare may rotate binding object references between requests; the handler re-injects them on every call.
62
- - **`ctx.waitUntil()` is documented but not yet called by the framework**: the `ExecutionContext` is received and passed through to `app.fetch` and `onScheduled`, but the framework does not currently call `ctx.waitUntil()` for telemetry flush. Spans complete synchronously within the request lifecycle.
62
+ - **OTel NodeSDK is disabled in Workers** — `canUseNodeSDK()` returns `false` for V8 isolates, so no OTLP spans or metrics are emitted. Structured logs via `ctx.log` still work. `OTEL_ENABLED=true` has no effect in Workers. `ctx.waitUntil()` is received and passed through to `app.fetch` and `onScheduled` but not called by the framework (nothing to flush asynchronously).
63
63
  - **Singleton app promise with retry-on-failure**: the framework init runs once; if it fails, the next request retries rather than leaving the Worker in a permanently broken state.
64
64
 
65
65
  ---
@@ -130,7 +130,7 @@ In Workers, only these storage providers are allowed:
130
130
  `filesystem`, `supabase`, and unknown provider types are not on the whitelist:
131
131
 
132
132
  - **`filesystem`** and unknown types throw `ConfigurationError` in serverless environments.
133
- - **`supabase`** does **not** silently fall back. The framework may validate Supabase credentials first, but Worker startup still fails with `ConfigurationError` because Supabase storage is not a supported serverless provider. Do not set `STORAGE_PROVIDER_TYPE=supabase` in a Worker.
133
+ - **`supabase`** does **not** silently fall back. The serverless provider whitelist check fires immediately at the top of `createStorageProvider()` — Supabase credentials are never validated. Worker startup fails with `ConfigurationError` because Supabase is not on the serverless whitelist. Do not set `STORAGE_PROVIDER_TYPE=supabase` in a Worker.
134
134
 
135
135
  Set `STORAGE_PROVIDER_TYPE` to one of the four whitelisted values to avoid unexpected behavior.
136
136
 
@@ -142,17 +142,24 @@ Set `STORAGE_PROVIDER_TYPE` to one of the four whitelisted values to avoid unexp
142
142
  compatibility_flags = ["nodejs_compat"]
143
143
  compatibility_date = "2025-09-01" # must be >= 2025-09-01
144
144
 
145
+ # Built-in storage providers require these exact binding names:
145
146
  [[kv_namespaces]]
146
- binding = "MY_CUSTOM_KV"
147
+ binding = "KV_NAMESPACE" # required for cloudflare-kv storage
147
148
  id = "..."
148
149
 
149
150
  [[r2_buckets]]
150
- binding = "MY_R2_BUCKET"
151
+ binding = "R2_BUCKET" # required for cloudflare-r2 storage
151
152
  bucket_name = "..."
153
+
154
+ [[d1_databases]]
155
+ binding = "DB" # required for cloudflare-d1 storage
156
+ database_id = "..."
152
157
  ```
153
158
 
154
159
  `nodejs_compat` is required for Node.js API shims (e.g., `process.env`, `Buffer`, `crypto`). The minimum `compatibility_date` activates the required shim set.
155
160
 
161
+ **Binding names for core storage are hardcoded** — the storage factory looks for `KV_NAMESPACE`, `R2_BUCKET`, and `DB` on `globalThis`. Using different binding names will cause a `ConfigurationError`. For custom (non-storage) bindings, use `extraObjectBindings` to map arbitrary binding names to `globalThis` keys.
162
+
156
163
  ---
157
164
 
158
165
  ## Workers-specific warnings
@@ -190,4 +197,4 @@ export function getServerConfig() {
190
197
 
191
198
  > `DuckDB canvas requires Node.js or Bun. Set CANVAS_PROVIDER_TYPE=none or omit it for Cloudflare Workers deployment.`
192
199
 
193
- Leave the env unset (or set to `none`) for Worker deployments. Tools that conditionally use canvas should check `if (!ctx.core.canvas) { ... }` and surface a clear "feature unavailable on this deployment" message. See `api-canvas` for the full DataCanvas reference.
200
+ Leave the env unset (or set to `none`) for Worker deployments. Tools that conditionally use canvas should check the module-level accessor (`if (!getCanvas()) { ... }`) and surface a clear "feature unavailable on this deployment" message. See `api-canvas` for the full DataCanvas reference and setup wiring pattern.
@@ -29,6 +29,14 @@ Gather before designing. Ask the user if not obvious from context:
29
29
 
30
30
  If the domain has a public API, read its docs before designing. For internal-only servers, skip API research and go straight to user goals. Don't design from vibes either way.
31
31
 
32
+ ## Server Naming
33
+
34
+ The server name (repo name, npm package, public identity) must communicate what it does at a glance. The test: can a human or agent scanning a server list tell what this server does from the name alone?
35
+
36
+ - **Use the canonical platform/brand name, not abbreviations.** `libofcongress-mcp-server` not `loc-mcp-server` ("loc" reads as lines-of-code or location). `federal-reserve-mcp-server` not `fred-mcp-server` ("fred" reads as a person's name).
37
+ - **Add a descriptive suffix when the base name is a non-obvious acronym.** Pattern: `{acronym}-{domain}-mcp-server` — e.g., `eia-energy-mcp-server`, `bls-labor-mcp-server`, `nhtsa-vehicle-safety-mcp-server`. Skip when the name is already self-descriptive (`earthquake-mcp-server`, `wikidata-mcp-server`).
38
+ - **The name becomes the tool prefix.** Every tool is `{prefix}_{verb}_{noun}`, so the server name shows up in every tool call an agent sees. A descriptive name gives agents domain context without reading the server's instructions.
39
+
32
40
  ## Steps
33
41
 
34
42
  ### 1. Research External Dependencies
@@ -53,6 +61,8 @@ When research is genuinely parallelizable (multiple independent APIs, several SD
53
61
  - **Pagination behavior** — verify token format, page size limits, and what happens when results exceed one page.
54
62
  - **Error shapes** — trigger real 400/404/429 responses to see the actual error format, not just what docs claim.
55
63
 
64
+ **Stopping condition:** at minimum, probe one list/search endpoint, one single-item GET, and one error case (force a 404 or 400). For large APIs with many resource types, add one probe per major noun. Stop when the response shapes and error envelope are confirmed.
65
+
56
66
  This step prevents building a service layer against assumed response shapes that don't match reality.
57
67
 
58
68
  ### 2. Map User Goals, Then Domain Operations
@@ -74,7 +84,7 @@ Then enumerate the underlying **domain operations** the system supports, grouped
74
84
  | Task | list (by project), get, create, update status, assign, comment |
75
85
  | User | list, get current |
76
86
 
77
- The user-goal list shapes the tool surface; the operation list fills in the gaps. Not every operation becomes a tool.
87
+ The user-goal list shapes the tool surface; the operation list fills in the gaps. Not every operation becomes a tool — an operation stays as raw material (not its own tool) when it's already fully covered by an existing tool's output, or when the only agents who'd use it are in scenarios outside this server's stated purpose.
78
88
 
79
89
  ### 3. Classify into MCP Primitives
80
90
 
@@ -482,12 +492,12 @@ What this server does, what system it wraps, who it's for.
482
492
 
483
493
  Each step is independently testable.
484
494
 
485
- <!-- Optional sections for API-wrapping servers: -->
486
- ## Domain Mapping <!-- nouns × operations → API endpoints -->
487
- ## Workflow Analysis <!-- how tools chain for real tasks -->
488
- ## Design Decisions <!-- rationale for consolidation, naming, tradeoffs -->
489
- ## Known Limitations <!-- inherent API/data constraints the server can't solve -->
490
- ## API Reference <!-- query language, pagination, rate limits -->
495
+ <!-- Optional sections include when the trigger fires: -->
496
+ ## Domain Mapping <!-- nouns × operations → API endpoints; include when ≥3 nouns each with ≥3 operations -->
497
+ ## Workflow Analysis <!-- how tools chain for real tasks; include when any tool makes ≥3 upstream calls -->
498
+ ## Design Decisions <!-- rationale for consolidation, naming, tradeoffs; include when a choice would otherwise be opaque -->
499
+ ## Known Limitations <!-- inherent API/data constraints the server can't solve; include when a constraint visibly caps utility -->
500
+ ## API Reference <!-- query language, pagination, rate limits; include when worth documenting -->
491
501
  ```
492
502
 
493
503
  Keep it concise. The design doc is a working reference, not a spec document — enough to orient a developer (or agent) implementing the server, not more.
@@ -512,7 +522,7 @@ The table surfaces design questions early: should the elicit happen before or af
512
522
 
513
523
  ### 9. Confirm and Proceed
514
524
 
515
- If the user has already authorized implementation (e.g., "build me a ___ server"), proceed directly to scaffolding using the design doc as the plan. Otherwise, present the design doc to the user for review before implementing.
525
+ If the user has already authorized implementation — any message that contains both a design request and a build/implement verb in the same clause (e.g., "build me a ___ server", "design and implement a ___") — proceed directly to scaffolding using the design doc as the plan. Otherwise, present the design doc to the user for review before implementing.
516
526
 
517
527
  ## After Design
518
528
 
@@ -530,6 +540,7 @@ Execute the plan using the scaffolding skills:
530
540
  Items without an `If …:` prefix apply to every design. Conditional items only apply when the trigger fires — otherwise skip them.
531
541
 
532
542
  - [ ] External APIs/dependencies researched and verified (docs fetched, SDKs identified)
543
+ - [ ] **If wrapping an external API:** live API probed (at minimum: one list/search, one single-item GET, one error case)
533
544
  - [ ] User goals enumerated first (3–10 outcomes agents will accomplish, scaled to domain size), then domain operations mapped as raw material
534
545
  - [ ] Each operation classified as tool, resource, prompt, or excluded
535
546
  - [ ] Catastrophically irreversible operations excluded from the tool surface (stay in vendor UI) — not just `destructiveHint`
@@ -553,6 +564,7 @@ Items without an `If …:` prefix apply to every design. Conditional items only
553
564
  - [ ] **If a parameter determines blast radius:** safe default set (e.g., `mode: 'preview'`, `dryRun: true`, `confirmCount` required)
554
565
  - [ ] **App tools default to no.** If one was proposed, verified there's a real human-in-the-loop in an MCP Apps-capable client justifying the iframe/CSP/`format()`-twin maintenance cost — otherwise dropped in favor of a standard tool
555
566
  - [ ] **If the server exposes resources:** URIs use `{param}` templates, pagination planned for large lists
567
+ - [ ] **If the server is itself the source of truth (no external API):** state lifecycle planned — tenant-scoped vs. global, TTLs, what survives restart, storage backend chosen
556
568
  - [ ] **If the server has external deps or shared state:** service layer planned (or explicitly skipped with reasoning)
557
569
  - [ ] **If services wrap external APIs:** resilience planned (retry boundary, backoff, parse classification)
558
570
  - [ ] **If exposing a SQL/analytical workspace over tabular data is in scope:** DataCanvas considered (`api-canvas` skill) as one option before designing custom analytical state — register / query / export tools accepting an optional `canvas_id`, with `ctx.core.canvas?` reads
@@ -19,7 +19,7 @@ Unit tests (`add-test` skill) verify handler logic with mocked context. Field te
19
19
 
20
20
  This skill drives an HTTP server because curl + JSON-RPC is the most reliable harness for shell-based agents. The same handlers run on both transports — only the framing differs — so HTTP exercises the full functional surface.
21
21
 
22
- **Stdio coverage is a boot check only.** Run `bun run rebuild && bun run start:stdio`, confirm the startup logs look clean (banner, expected tool/resource counts, no errors/warnings, no missing-config gripes), then kill it. Pino logs go to stderr in stdio mode (stdout is reserved for JSON-RPC), so they print straight to the terminal when you run interactively. No need to call tools over stdio — the HTTP pass already covered handler behavior.
22
+ **Stdio coverage is a boot check only — run this before Step 1.** Run `bun run rebuild && bun run start:stdio`, confirm the startup logs look clean (banner, expected tool/resource counts, no errors/warnings, no missing-config gripes), then kill it. Pino logs go to stderr in stdio mode (stdout is reserved for JSON-RPC), so they print straight to the terminal when you run interactively. No need to call tools over stdio — the HTTP pass already covered handler behavior.
23
23
 
24
24
  ---
25
25
 
@@ -193,7 +193,7 @@ Capture `pid`, `url`, `port`, `log` from the `mcp_start` output — every later
193
193
 
194
194
  - `MCP_HTTP_PORT` is a *starting* port — the server auto-increments if taken. Helper parses the real URL from the log (`HTTP transport listening at ...`).
195
195
  - If `bun run rebuild` fails, stop. Don't field-test broken code — fix the build first.
196
- - If a server is already listening on the project's port (`lsof -i :<port>`), confirm with the user before killing it; it may be their own session.
196
+ - If a server is already listening on the project's port (`lsof -i :<port>`), confirm with the user before killing it; it may be their own session. If the user isn't available to confirm, abort the field test and surface the port conflict in your response.
197
197
 
198
198
  ### 2. Initialize the session
199
199
 
@@ -251,7 +251,7 @@ Treat any hit as a `ux` finding in the report. The authoring rule lives under *T
251
251
  | Resource declared an `errors: [...]` contract | Error contract (resource): trigger ≥1 declared failure mode by reading a URI that exercises it. Resources re-throw errors at the JSON-RPC level — verify `error.code` matches the contract entry and `error.data.reason` is the declared reason. (Resources don't use the `result.isError` envelope — they fail the request itself.) |
252
252
  | Mutator (write/update/delete/append/patch verbs, or `destructiveHint: true`) | Mutator response observability: run an intentionally-ambiguous input (typo path, wrong ID, already-deleted target). Confirm the response carries enough state (pre/post values, state-change discriminator) for the agent to detect intent-effect divergence without re-fetching. |
253
253
 
254
- **Resources.** Happy path, not-found URI, `list` if defined, pagination if used.
254
+ **Resources.** Happy path, not-found URI (use a syntactically valid but non-existent ID — e.g., substitute a fake ID into the URI template), `list` if defined, pagination if used.
255
255
  **Prompts.** Happy path, defaults omitted, skim message quality.
256
256
 
257
257
  **Sampling for large servers.** If more than 15 tools, run the universal battery on all, but pick roughly 30–40% for situational testing. Weight toward: write-shaped tools, complex schemas, external deps. List which ones you skipped in the report.
@@ -285,7 +285,7 @@ mcp_stop <pid> <log>
285
285
  rm -f /tmp/<project-name>-field-test-<ID>.sh
286
286
  ```
287
287
 
288
- Kills the background server, removes the server log, then removes the helper script itself. Do this *before* writing the report so nothing leaks into the next session.
288
+ Kills the background server, removes the server log, then removes the helper script itself. Do this *before* writing the report so nothing leaks into the next session. If `mcp_stop` warns the PID is still alive after SIGKILL, note it in the report and proceed — don't block on a zombie process.
289
289
 
290
290
  ### 7. Report
291
291
 
@@ -332,13 +332,15 @@ End with:
332
332
 
333
333
  ## Checklist
334
334
 
335
- - [ ] Server built and started; real port parsed from log
335
+ - [ ] Stdio boot check completed `bun run rebuild && bun run start:stdio` shows clean startup (banner, expected counts, no errors)
336
+ - [ ] HTTP server built and started; real port parsed from log
336
337
  - [ ] Session initialized; `notifications/initialized` sent
337
338
  - [ ] Catalog surfaced and presented; descriptions audited for leaks (implementation details, meta-coaching, consumer-aware phrasing)
338
- - [ ] Universal battery run on every definition
339
+ - [ ] Universal battery run on every definition (happy path, parity, input error)
339
340
  - [ ] Situational categories applied only when triggered
341
+ - [ ] **If >15 tools:** sampled 30–40% for situational testing; skipped definitions listed in report
340
342
  - [ ] **If a tool declared an `errors: [...]` contract:** ≥1 declared failure mode triggered; `result.structuredContent.error.code` and `data.reason` verified against the contract entry
341
343
  - [ ] **If a resource declared an `errors: [...]` contract:** ≥1 declared failure mode triggered; top-level JSON-RPC `error.code` and `error.data.reason` verified against the contract entry
342
344
  - [ ] External-state / auth-gated tools handled explicitly (run, skip, or confirm)
343
- - [ ] Server stopped; state file removed
345
+ - [ ] Server stopped; server log and helper script removed
344
346
  - [ ] Report: summary paragraph → grouped findings → numbered options
@@ -0,0 +1,218 @@
1
+ ---
2
+ name: git-wrapup
3
+ description: >
4
+ Land working-tree changes as a versioned release commit with an annotated tag — version bump, changelog, regenerate derived artifacts, verify, commit, tag. Stops at "committed and tagged locally" — no push, no publish. The release-and-publish skill picks up from here. Distilled from the git_wrapup_instructions protocol.
5
+ metadata:
6
+ author: cyanheads
7
+ version: "1.0"
8
+ audience: external
9
+ type: workflow
10
+ ---
11
+
12
+ ## When to use
13
+
14
+ Working-tree or staged changes are ready to ship as a new version. This skill lands them as a single atomic commit with an annotated tag. It does NOT push or publish — that's a separate step (`release-and-publish`).
15
+
16
+ Common triggers:
17
+ - Feature work, bug fixes, or dependency updates are done and tested
18
+ - A maintenance or polish pass left changes in the working tree
19
+ - An orchestrator says "wrapup this project"
20
+
21
+ ## Pre-wrapup gate checklist
22
+
23
+ Every item must be true before starting wrapup. Committing means releasing — a commit only happens when the work is ready to ship, not just "the edits are done." Each item is a goal to verify.
24
+
25
+ - [ ] **Changes exist** — uncommitted files or commits since the last tag
26
+ - [ ] **Work is complete** — no half-finished features, no "I'll add the test later," no TODO placeholders. The diff represents a shippable unit.
27
+ - [ ] **Code simplified** — if the diff spans more than ~50 changed lines or touches 3+ source files, the `code-simplifier` skill has been run across the changes
28
+ - [ ] **`bun run devcheck` passes** — typecheck + lint clean
29
+ - [ ] **`bun run rebuild` succeeds** — full clean build from scratch
30
+ - [ ] **All tests pass** — `bun run test:all` (or `bun run test`). New tests and regression tests added as needed for the changes being shipped.
31
+ - [ ] **Fixes verified** — bug fixes validated, generally via `bun run rebuild` and field-testing. Not just written — confirmed to resolve the described behavior.
32
+ - [ ] **No known regressions** — the changes don't break existing functionality
33
+ - [ ] **GH issues updated** — issues addressed by this work commented with what landed and any follow-ups needed. Concise. Backlinked as needed.
34
+ - [ ] **Docs updated** — surgical updates to existing docs as needed. New docs for new features. No large rewrites for documentation that's still accurate.
35
+
36
+ If any gate is red, fix it before proceeding. This skill re-verifies build + tests in step 6, but starting wrapup on a broken tree wastes the version number and creates a revert-or-amend situation.
37
+
38
+ After all gates pass, spawn dedicated agents to handle the wrapup (this skill) and publish (`release-and-publish`). These are separate agents from the ones that did the editing work.
39
+
40
+ ## Steps
41
+
42
+ ### 1. Review the diff
43
+
44
+ Understand what's about to ship before touching version numbers:
45
+
46
+ ```bash
47
+ git status
48
+ git log v<latest-tag>..HEAD --oneline # commits since last release
49
+ git diff --stat # uncommitted changes
50
+ git diff # review the actual content
51
+ ```
52
+
53
+ If the working tree is clean AND there are no commits since the last tag, halt — nothing to wrap up.
54
+
55
+ ### 2. Determine the new version
56
+
57
+ Read the current version from `package.json`. Apply the intended bump:
58
+
59
+ | Bump | When |
60
+ |:-----|:-----|
61
+ | **patch** | Bug fixes, dependency updates, metadata changes, docs |
62
+ | **minor** | New tools, new features, new env vars, behavioral changes |
63
+ | **major** | Breaking changes to tool schemas, removed tools, incompatible config |
64
+
65
+ Default to **patch** unless the diff clearly warrants minor or major.
66
+
67
+ ### 3. Bump version everywhere
68
+
69
+ Every file that declares a version must be updated. Skip any file that doesn't exist in the project. For `@cyanheads/mcp-ts-core` projects:
70
+
71
+ - `package.json` — `version`
72
+ - `server.json` — top-level `version` AND every `packages[].version` entry
73
+ - `manifest.json` (if present) — `version`. Verify `name` is the bare package name (e.g. `bls-mcp-server`, not `@cyanheads/bls-mcp-server`)
74
+ - `README.md` — version badge
75
+ - `CLAUDE.md` / `AGENTS.md` — if they pin a version string
76
+ - `Dockerfile` — OCI labels if they pin the version
77
+
78
+ Catch stragglers (replace the placeholder with the actual current version string, e.g. `0.9.7`):
79
+
80
+ ```bash
81
+ grep -rn "0.9.7" . --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=changelog
82
+ ```
83
+
84
+ Resolve hits case by case — historical changelog entries are correct as-is; everything else should match the new version.
85
+
86
+ ### 4. Author the changelog
87
+
88
+ Create `changelog/<major.minor>.x/<version>.md`. Use `changelog/template.md` as the format reference — never edit, rename, or move that file.
89
+
90
+ **Frontmatter (required):**
91
+
92
+ ```yaml
93
+ ---
94
+ summary: "<one-line headline, ≤350 chars, no markdown>"
95
+ breaking: false # true if consumers must change code to upgrade
96
+ security: false # true if this release contains a security fix
97
+ ---
98
+ ```
99
+
100
+ **Body:** Section order follows Keep a Changelog — Added / Changed / Deprecated / Removed / Fixed / Security. Include only sections with entries. Delete empty sections.
101
+
102
+ **Tone:** Terse, fact-dense. Lead each bullet with the symbol or concept in **bold**. One sentence per bullet by default. See the authoring guide in `changelog/template.md` for full conventions.
103
+
104
+ ### 5. Regenerate derived artifacts
105
+
106
+ ```bash
107
+ bun run changelog:build # rebuilds CHANGELOG.md rollup from per-version files
108
+ bun run tree # regenerates docs/tree.md — run when files were added, removed, or moved in src/
109
+ ```
110
+
111
+ Both scripts are idempotent — safe to run even if nothing changed.
112
+
113
+ ### 6. Run the verification gate
114
+
115
+ The tree being committed must pass verification. Both must succeed:
116
+
117
+ ```bash
118
+ bun run devcheck
119
+ bun run test:all # or `bun run test` if no test:all script exists
120
+ ```
121
+
122
+ **If either fails, halt.** Do not bypass verification to land the commit. Fix the issue first, then re-run from step 6.
123
+
124
+ ### 7. Commit
125
+
126
+ Stage everything and create ONE atomic commit. Version bumps ride with the change that warrants them — the version bump is not a separate commit.
127
+
128
+ ```bash
129
+ git add -A
130
+ git commit -m "<subject>"
131
+ ```
132
+
133
+ **Subject format:** Conventional Commits. Examples:
134
+ - `feat: 0.1.5 — hosted server endpoint`
135
+ - `fix: 0.2.1 — handle empty SPARQL result sets`
136
+ - `chore(deps): 0.3.2 — mcp-ts-core ^0.9.1 → ^0.9.6`
137
+
138
+ **Rules:**
139
+ - Plain `-m` flag only — no heredoc, no command substitution
140
+ - No `Co-authored-by` or `Generated with` trailers
141
+ - No marketing adjectives ("comprehensive", "robust", "enhanced", "seamless", "improved")
142
+ - The commit message must stand alone for someone reading `git log` — no references to chat context, option numbers, or "as discussed"
143
+
144
+ **When to split into multiple commits:** Only when the working tree contains genuinely independent concerns (e.g., two unrelated bug fixes in unrelated files). NEVER split a single file's changes across commits.
145
+
146
+ ### 8. Create an annotated tag
147
+
148
+ ```bash
149
+ git tag -a v<version> -m "<tag message with embedded newlines>"
150
+ ```
151
+
152
+ Use `-m` with embedded newlines in the string (the commit `-m`-only constraint applies here too — no heredoc). The tag message renders as the GitHub Release body via `--notes-from-tag`. It must be structured markdown, not a flat string. Format:
153
+
154
+ ```
155
+ <theme — omit version number, GitHub prepends v<VERSION>:>
156
+
157
+ <1-2 sentence context: what this release does>
158
+
159
+ <Sections — Keep a Changelog names, only those with entries>
160
+
161
+ Added:
162
+
163
+ - <bullet>
164
+
165
+ Changed:
166
+
167
+ - <bullet>
168
+
169
+ <dep arrows if applicable>
170
+
171
+ Dependency bumps:
172
+
173
+ - `pkg` ^old → ^new
174
+
175
+ <N> tests pass; `bun run devcheck` clean.
176
+ ```
177
+
178
+ **Rules:**
179
+ - Subject line omits the version number (GitHub prepends `v<VERSION>:` to the release title)
180
+ - Not a CHANGELOG copy — terse, scannable
181
+ - No marketing adjectives
182
+ - Length is earned — two-line tags are fine for small patches
183
+
184
+ ### 9. Verify end state
185
+
186
+ ```bash
187
+ git log --oneline -1 # confirm commit subject
188
+ git show v<version> --stat | head -20 # confirm tag points at HEAD
189
+ git status # must be clean
190
+ ```
191
+
192
+ If the working tree isn't clean or the tag doesn't point at HEAD, something went wrong — investigate before proceeding.
193
+
194
+ **Do NOT push.** This skill stops here. Use the `release-and-publish` skill for the push + publish workflow.
195
+
196
+ ## Constraints
197
+
198
+ - **Local only.** No `git push`, no remote operations
199
+ - **Never stash.** Not for quick checks, not for testing, not for any reason
200
+ - **Never destructive.** No `git reset --hard`, `git restore .`, `git clean -f`, `git checkout -- .`
201
+ - **Bash git only** when running inside orchestrated sub-agents (git-mcp-server session state leaks across parallel agents)
202
+ - If `v<version>` already exists as a tag, **halt and report the conflict** — include the version string, existing tag SHA, and current HEAD SHA so the caller can resolve it. Do not delete or move tags without explicit authorization
203
+
204
+ ## Checklist
205
+
206
+ - [ ] Diff reviewed end-to-end before version bump
207
+ - [ ] Version bumped in every declaring file (`package.json`, `server.json`, `manifest.json`, README badge, `CLAUDE.md`/`AGENTS.md` if they pin a version)
208
+ - [ ] GH issues addressed by this work commented with what landed (if working from GH issues)
209
+ - [ ] Docs updated for any new or changed features
210
+ - [ ] Changelog authored at `changelog/<major.minor>.x/<version>.md`
211
+ - [ ] `CHANGELOG.md` rollup regenerated (`bun run changelog:build`)
212
+ - [ ] `docs/tree.md` regenerated if structure changed (`bun run tree`)
213
+ - [ ] `bun run devcheck` passes
214
+ - [ ] `bun run test:all` (or `test`) passes
215
+ - [ ] One atomic commit in Conventional Commits format
216
+ - [ ] Annotated tag `v<version>` with structured markdown message
217
+ - [ ] Working tree clean
218
+ - [ ] Nothing pushed — local only
@@ -48,11 +48,11 @@ Capture the `↑ package old → new` lines from stdout — these feed Step 3. A
48
48
 
49
49
  Invoke the **`changelog`** skill with the captured list of updated packages. It resolves each repo, fetches release notes (or CHANGELOG entries) between old and new versions, and cross-references changes against actual imports in `src/`. Output per package: what changed, impact on this project, action items.
50
50
 
51
- Do not redo this investigation inline — the `changelog` skill handles tag-format detection, monorepo patterns, and fallbacks.
51
+ Do not redo this investigation inline — the `changelog` skill handles tag-format detection, monorepo patterns, and fallbacks. If the skill cannot resolve a package (private repo, no tags, no CHANGELOG), note it in Step 8 under "Open decisions" and proceed.
52
52
 
53
53
  ### 4. Framework review (`@cyanheads/mcp-ts-core`)
54
54
 
55
- **Skill-version paradox.** If `node_modules/@cyanheads/mcp-ts-core/skills/maintenance/SKILL.md`'s `version` exceeds the one running, run Step 5 Phase A first and re-invoke `maintenance` — otherwise feature-adoption rows added in the new version silently don't surface.
55
+ **Skill-version paradox.** If `node_modules/@cyanheads/mcp-ts-core/skills/maintenance/SKILL.md`'s `version` exceeds the one running, run Step 5 Phase A first and re-invoke `maintenance` — otherwise feature-adoption rows added in the new version silently don't surface. After Phase A, confirm the running skill version matches the package before continuing. If the session still has the old skill loaded, exit and restart.
56
56
 
57
57
  If `@cyanheads/mcp-ts-core` was updated, do a deeper pass beyond what the `changelog` skill covers. The framework ships a **directory-based changelog** grouped by minor series (`.x` semver-wildcard convention) — one file per released version at `node_modules/@cyanheads/mcp-ts-core/changelog/<major.minor>.x/<version>.md`. Read only the files between old and new rather than scanning a monolithic file.
58
58
 
@@ -84,7 +84,7 @@ Cross-reference each finding against the server's code. Collect adoption opportu
84
84
 
85
85
  **Template review.** The framework also ships `templates/CLAUDE.md` and `templates/AGENTS.md` as scaffolding for consumer agent protocol files. The consumer's `CLAUDE.md`/`AGENTS.md` was copied at init time and has since diverged (local customizations, echo replacements, server-specific sections). Read the upstream template fresh at `node_modules/@cyanheads/mcp-ts-core/templates/CLAUDE.md`.
86
86
 
87
- Read the upstream template end-to-end, mentally comparing against the current `CLAUDE.md`/`AGENTS.md`. Apply framework-authored updates directly — new skill references in the skills table, new entries in the "What's Next?" section, updated convention callouts, clarified patterns. These are factual updates, not taste decisions; the consumer's agent protocol file is meant to track the framework's. Only surface a decision when a template change conflicts with a section the consumer has intentionally customized (server-specific domain context, bespoke checklists, etc.) in that case, note the conflict and ask.
87
+ Read the upstream template end-to-end, mentally comparing against the current `CLAUDE.md`/`AGENTS.md`. Apply framework-authored updates directly — new skill references in the skills table, new entries in the "What's Next?" section, updated convention callouts, clarified patterns. These are factual updates, not taste decisions; the consumer's agent protocol file is meant to track the framework's. Only surface a decision when a template change conflicts with a section the consumer has intentionally customized — a section is "intentionally customized" when it contains server-specific domain context, bespoke checklists, or content that doesn't originate from the template. In that case, note the conflict and ask.
88
88
 
89
89
  ### 5. Sync project skills and scripts
90
90
 
@@ -205,7 +205,7 @@ bun run test
205
205
 
206
206
  `rebuild` (clean + build) catches API surface and type-alignment issues that `devcheck` alone may miss — module resolution, path aliases, post-build processing. `devcheck` includes `bun audit` and `bun outdated`, so no separate audit step is needed.
207
207
 
208
- In **Mode B**, the user already ran rebuild + test before invoking this skill, but run them again here — Step 6 made code changes that need verification.
208
+ In **Mode B**, the user already ran rebuild + test before invoking this skill, but run them again here — Step 6 made code changes that need re-verification.
209
209
 
210
210
  Fix anything that fails. Re-run until clean.
211
211
 
@@ -226,13 +226,15 @@ Present a concise numbered summary to the user:
226
226
  ## Checklist
227
227
 
228
228
  - [ ] Update applied (`bun update --latest`) — Mode A, or already done by user — Mode B
229
+ - [ ] Skill-version paradox checked — if package maintenance skill version > running version, Phase A run first and skill re-invoked
229
230
  - [ ] `changelog` skill invoked for each updated package
230
231
  - [ ] Framework CHANGELOG reviewed if `@cyanheads/mcp-ts-core` was updated
231
- - [ ] Every applicable framework adoption opportunity applied in this pass — no scope/effort/marginal-benefit deferrals; third-party adoptions evaluated on cost/benefit
232
+ - [ ] Framework `CLAUDE.md`/`AGENTS.md` template reviewed; applicable updates applied or conflicts surfaced
233
+ - [ ] Step 6 complete — all applicable framework adoption sites updated; third-party adoption decisions recorded
232
234
  - [ ] Project `skills/` synced from package (Phase A), with a change report
233
235
  - [ ] Agent skill directories (`.claude/skills/`, `.agents/skills/`, etc.) refreshed from project `skills/` (Phase B)
234
236
  - [ ] Framework `scripts/` and pristine reference files resynced from package via content-hash compare (Phase C), with a change report; diffs reviewed before committing
235
- - [ ] `bun run rebuild` succeeds
237
+ - [ ] `bun run rebuild` succeeds (re-run after Step 6, even in Mode B)
236
238
  - [ ] `bun run devcheck` passes (includes audit + outdated)
237
239
  - [ ] `bun run test` passes
238
240
  - [ ] Numbered summary presented to user
@@ -20,7 +20,7 @@ For the full exports catalog, see `CLAUDE.md` → Exports Reference.
20
20
  ## Steps
21
21
 
22
22
  1. **Install the package**: `bun add @cyanheads/mcp-ts-core`
23
- 2. **Search for all `@/` imports** across `src/` that reference framework internals
23
+ 2. **Search for all `@/` imports** across `src/` that reference framework internals: `grep -rn "from '@/" src/`
24
24
  3. **Rewrite each import** using the mapping table below
25
25
  4. **Identify framework source files** now provided by the package (see candidates below) — review each for server-specific additions before cleaning up
26
26
  5. **Update entry point** (`src/index.ts`) to use `createApp()` from the package and the project's chosen registration pattern (fresh scaffold default: direct imports in `src/index.ts`)
@@ -52,9 +52,9 @@ These are the actual `@/` import paths used in framework source. Rewrite any tha
52
52
 
53
53
  | Old `@/` import | New package import |
54
54
  |:----------------|:-------------------|
55
- | `@/mcp-server/tools/utils/toolDefinition.js` | `@cyanheads/mcp-ts-core/tools` or `@cyanheads/mcp-ts-core` (for `tool()` builder) |
56
- | `@/mcp-server/resources/utils/resourceDefinition.js` | `@cyanheads/mcp-ts-core/resources` or `@cyanheads/mcp-ts-core` (for `resource()` builder) |
57
- | `@/mcp-server/prompts/utils/promptDefinition.js` | `@cyanheads/mcp-ts-core/prompts` or `@cyanheads/mcp-ts-core` (for `prompt()` builder) |
55
+ | `@/mcp-server/tools/utils/toolDefinition.js` | `@cyanheads/mcp-ts-core/tools` (types only: `ToolDefinition`, `AnyToolDefinition`) or `@cyanheads/mcp-ts-core` (for the `tool()` builder) |
56
+ | `@/mcp-server/resources/utils/resourceDefinition.js` | `@cyanheads/mcp-ts-core/resources` (types only: `ResourceDefinition`, `AnyResourceDefinition`) or `@cyanheads/mcp-ts-core` (for the `resource()` builder) |
57
+ | `@/mcp-server/prompts/utils/promptDefinition.js` | `@cyanheads/mcp-ts-core/prompts` (types only: `PromptDefinition`) or `@cyanheads/mcp-ts-core` (for the `prompt()` builder) |
58
58
  | `@/mcp-server/tasks/utils/taskToolDefinition.js` | `@cyanheads/mcp-ts-core/tasks` |
59
59
 
60
60
  ### Utils
@@ -90,7 +90,9 @@ After rewriting imports, these directories and files are candidates for cleanup
90
90
 
91
91
  **Preserve:** server-specific code under `mcp-server/tools/definitions/`, `mcp-server/resources/definitions/`, `mcp-server/prompts/definitions/`, the server's own `services/`, and `config/server-config.ts`.
92
92
 
93
- Framework directories (typically safe to clean up in full verify no server-specific files were added):
93
+ A file is server-specific if it doesn't appear in the `mcp-ts-template` repo at its path. Modified framework files should be extracted to a server-specific location (e.g., `src/utils/my-project/`) before deletion.
94
+
95
+ Framework directories (typically safe to remove in full — verify no server-specific files were added):
94
96
 
95
97
  - `src/core/` (app, context, worker)
96
98
  - `src/cli/`
@@ -113,7 +115,7 @@ Framework files within directories that contain server code:
113
115
 
114
116
  ## Entry point rewrite
115
117
 
116
- Replace the fork's `src/index.ts` with the scaffold-default direct-registration pattern:
118
+ Rewrite the `createApp()` call and its surrounding imports to use the package. Preserve the project's existing barrel structure and registration pattern if present:
117
119
 
118
120
  ```ts
119
121
  #!/usr/bin/env node
@@ -153,6 +155,8 @@ If the migrated project already has `definitions/index.ts` barrels and you want
153
155
  - [ ] `tsconfig.json` extends `@cyanheads/mcp-ts-core/tsconfig.base.json`
154
156
  - [ ] `biome.json` extends `@cyanheads/mcp-ts-core/biome`
155
157
  - [ ] `vitest.config.ts` spreads from `@cyanheads/mcp-ts-core/vitest.config`
156
- - [ ] Framework source files cleaned up from `src/`
158
+ - [ ] Framework-only directories removed (`src/core/`, `src/cli/`, `src/types-global/`, `src/storage/`, `src/utils/`, `src/testing/`, framework service subdirs)
159
+ - [ ] Framework files within mixed directories removed (`server.ts`, `transports/`, `roots/`, tasks infra, `*/utils/` dirs, `*-registration.ts` files)
160
+ - [ ] `vitest.config.ts` includes `@/` alias: `resolve: { alias: { '@/': new URL('./src/', import.meta.url).pathname } }`
157
161
  - [ ] Server-specific `@/` imports (own tools, services) still work
158
162
  - [ ] `bun run devcheck` passes
@@ -28,11 +28,11 @@ Read this SKILL.md end-to-end first — the concepts, orient block, and hard rul
28
28
  |:----------------|:---------------------------|
29
29
  | **Greenfield build-out** | Echo definitions still present in `src/mcp-server/{tools,resources,prompts}/definitions/`, no real services in `src/services/`, no released changelog files under `changelog/<minor>.x/`, `package.json` version is `0.0.0` or unset |
30
30
  | **Maintenance pass** | Real tool/resource definitions present, framework deps installed, `bun outdated` reports updates available, at least one prior release tagged |
31
- | **Release pass** | Working tree has uncommitted/staged work, OR `git log v<latest-tag>..HEAD` shows commits since the last release that warrant a new version, OR the user explicitly asks to "ship", "release", or do a version bump |
31
+ | **Wrap-up / release pass** | Working tree has uncommitted/staged work, OR `git log v<latest-tag>..HEAD` shows commits since the last release that warrant a new version, OR the user explicitly asks to "ship", "release", or do a version bump. If the user explicitly wants to publish to npm/registries → release-and-publish pass; if local-only → wrap-up pass |
32
32
  | **Neither** | None of the above match cleanly — surface the state to the user, ask what they want |
33
33
 
34
34
  3. **Pick the reference** from the References table below. Each reference contains its scenario's phase pattern, per-sub-agent prompt bodies, scenario-specific gotchas, and checklist.
35
- 4. **Surface the plan to the user** before kicking off the first fanout: scenario, target list, phase summary, gotchas in play. Get explicit authorization before any phase that commits, tags, pushes, or creates remote resources.
35
+ 4. **Surface the plan to the user** before kicking off the first fanout: scenario, target list, phase summary, gotchas in play. Get explicit authorization before any phase that commits, tags, pushes, or creates remote resources. Non-destructive phases (read, analyze, write files, devcheck) proceed without additional check-ins after the initial plan approval.
36
36
 
37
37
  ## References
38
38
 
@@ -40,8 +40,8 @@ Read this SKILL.md end-to-end first — the concepts, orient block, and hard rul
40
40
  |:---------|:----------|:-----|
41
41
  | **Greenfield build-out** | `references/greenfield-buildout.md` | New server(s) from `bunx @cyanheads/mcp-ts-core init` driven through design → build → first release |
42
42
  | **Maintenance pass** | `references/maintenance-pass.md` | Existing server(s) need `bun update --latest`, changelog investigation, framework adoption, and verification — optionally followed by a commit/push |
43
- | **Wrap-up pass** | `references/wrapup-pass.md` | Existing server(s) with committed/staged work to land locally as a new commit + annotated tag — verification → optional doc review → wrap-up (version + changelog + commit + tag) — **local only, no push**. Distilled from `git_wrapup_instructions` |
44
- | **Release-and-publish pass** | `references/release-and-publish-pass.md` | Existing server(s) have committed/staged work that needs to ship as a new version end-to-end — verification → README polish → wrap-up (version + changelog + commit + tag) → publish (npm / MCP Registry / GHCR via the `release-and-publish` skill) → optional GH issue closure. Disambiguated from the standalone `release-and-publish` skill, which is the single-target publish step this reference invokes per target |
43
+ | **Wrap-up pass** | `references/wrapup-pass.md` | Existing server(s) with committed/staged work to land locally as a new commit + annotated tag — verification → optional doc review → wrap-up (version + changelog + commit + tag) — **local only, no push**. Sub-agents execute the standalone `git-wrapup` skill per target |
44
+ | **Release-and-publish pass** | `references/release-and-publish-pass.md` | Existing server(s) have committed/staged work that needs to ship as a new version end-to-end — verification → README polish → wrap-up → publish → optional GH issue closure. Sub-agents execute the standalone `git-wrapup` then `release-and-publish` skills per target |
45
45
 
46
46
  **Mental model — scenarios are related but never auto-chain.** A maintenance pass often produces work worth wrapping up; a wrap-up commonly precedes a release; a greenfield build-out ends with what's effectively a release. Useful for orienting around what comes next conceptually — but **each scenario requires its own explicit user authorization to invoke**. The orchestrator never advances from one to the next on its own. Pick the reference for the current scope; if more work follows, wait for the user to direct it.
47
47
 
@@ -122,4 +122,16 @@ These commonly bite across all scenarios. Scenario-specific gotchas live in thei
122
122
 
123
123
  ## Extending the pattern
124
124
 
125
- When a new scenario emerges that's worth codifying (security-pass fanout across N servers, framework-wide migration, etc.), author a new reference at `references/<scenario>.md` and add a row to the table above. The reference should follow the shape of the existing two: scope, pre-flight, phase table, phase details, scenario-specific gotchas, checklist. The concepts/orient/rules/gotchas in this SKILL.md don't need to be restated — the reference assumes the reader started here.
125
+ When a new scenario emerges that's worth codifying (security-pass fanout across N servers, framework-wide migration, etc.), author a new reference at `references/<scenario>.md` and add a row to the table above. The reference should follow the shape of the existing references (e.g., `greenfield-buildout.md`): scope, pre-flight, phase table, phase details, scenario-specific gotchas, checklist. The concepts/orient/rules/gotchas in this SKILL.md don't need to be restated — the reference assumes the reader started here.
126
+
127
+ ## Pre-flight Checklist
128
+
129
+ Applies to all scenarios — verify before picking a reference and kicking off the first fanout.
130
+
131
+ - [ ] Target list captured with absolute paths and per-target metadata
132
+ - [ ] Scenario identified from intent + state; confirmed with user if ambiguous
133
+ - [ ] Reference selected from the table above
134
+ - [ ] `scripts/list-skills.ts` + `list-skills` package script present in each target
135
+ - [ ] Plan surfaced to user: scenario, targets, phase summary, active gotchas
136
+ - [ ] User authorization captured for any phase that commits, tags, pushes, or creates remote resources
137
+ - [ ] Scenario reference read in full before first fanout