@cyanheads/mcp-ts-core 0.9.13 → 0.9.15
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.
- package/AGENTS.md +559 -0
- package/CLAUDE.md +8 -4
- package/README.md +33 -44
- package/changelog/0.9.x/0.9.14.md +31 -0
- package/changelog/0.9.x/0.9.15.md +52 -0
- package/changelog/template.md +1 -1
- package/dist/core/context.d.ts +119 -14
- package/dist/core/context.d.ts.map +1 -1
- package/dist/core/context.js +70 -1
- package/dist/core/context.js.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/linter/rules/enrichment-rules.d.ts +41 -0
- package/dist/linter/rules/enrichment-rules.d.ts.map +1 -0
- package/dist/linter/rules/enrichment-rules.js +204 -0
- package/dist/linter/rules/enrichment-rules.js.map +1 -0
- package/dist/linter/rules/index.d.ts +1 -0
- package/dist/linter/rules/index.d.ts.map +1 -1
- package/dist/linter/rules/index.js +1 -0
- package/dist/linter/rules/index.js.map +1 -1
- package/dist/linter/rules/schema-rules.d.ts +4 -0
- package/dist/linter/rules/schema-rules.d.ts.map +1 -1
- package/dist/linter/rules/schema-rules.js +2 -2
- package/dist/linter/rules/schema-rules.js.map +1 -1
- package/dist/linter/rules/tool-rules.d.ts.map +1 -1
- package/dist/linter/rules/tool-rules.js +4 -0
- package/dist/linter/rules/tool-rules.js.map +1 -1
- package/dist/mcp-server/tools/tool-registration.d.ts.map +1 -1
- package/dist/mcp-server/tools/tool-registration.js +7 -7
- package/dist/mcp-server/tools/tool-registration.js.map +1 -1
- package/dist/mcp-server/tools/utils/toolDefinition.d.ts +81 -7
- package/dist/mcp-server/tools/utils/toolDefinition.d.ts.map +1 -1
- package/dist/mcp-server/tools/utils/toolDefinition.js.map +1 -1
- package/dist/mcp-server/tools/utils/toolHandlerFactory.d.ts +23 -1
- package/dist/mcp-server/tools/utils/toolHandlerFactory.d.ts.map +1 -1
- package/dist/mcp-server/tools/utils/toolHandlerFactory.js +118 -9
- package/dist/mcp-server/tools/utils/toolHandlerFactory.js.map +1 -1
- package/dist/testing/index.d.ts +13 -0
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +21 -1
- package/dist/testing/index.js.map +1 -1
- package/dist/utils/internal/performance.d.ts +5 -1
- package/dist/utils/internal/performance.d.ts.map +1 -1
- package/dist/utils/internal/performance.js +10 -1
- package/dist/utils/internal/performance.js.map +1 -1
- package/dist/utils/telemetry/attributes.d.ts +2 -0
- package/dist/utils/telemetry/attributes.d.ts.map +1 -1
- package/dist/utils/telemetry/attributes.js +2 -0
- package/dist/utils/telemetry/attributes.js.map +1 -1
- package/package.json +5 -3
- package/scripts/build-changelog.ts +3 -1
- package/scripts/check-skills-sync.ts +42 -8
- package/skills/add-app-tool/SKILL.md +2 -2
- package/skills/add-export/SKILL.md +2 -2
- package/skills/add-service/SKILL.md +2 -2
- package/skills/add-tool/SKILL.md +85 -32
- package/skills/api-context/SKILL.md +68 -3
- package/skills/api-linter/SKILL.md +73 -2
- package/skills/design-mcp-server/SKILL.md +2 -1
- package/skills/git-wrapup/SKILL.md +22 -15
- package/skills/maintenance/SKILL.md +8 -7
- package/skills/orchestrations/SKILL.md +9 -5
- package/skills/orchestrations/workflows/maintenance-release.md +1 -1
- package/skills/polish-docs-meta/SKILL.md +1 -1
- package/skills/polish-docs-meta/references/agent-protocol.md +2 -2
- package/skills/polish-docs-meta/references/readme.md +3 -3
- package/skills/report-issue-framework/SKILL.md +8 -3
- package/skills/report-issue-local/SKILL.md +8 -3
- package/skills/setup/SKILL.md +5 -10
- package/templates/AGENTS.md +2 -1
- package/templates/CLAUDE.md +2 -1
- package/templates/_.mcpbignore +2 -0
- package/templates/changelog/template.md +1 -1
- package/templates/package.json +2 -1
- package/templates/src/mcp-server/tools/definitions/echo.tool.ts +10 -0
- package/dist/logs/combined.log +0 -4
- package/dist/logs/error.log +0 -2
- package/dist/logs/interactions.log +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: api-context
|
|
3
3
|
description: >
|
|
4
|
-
Canonical reference for the unified `Context` object passed to every tool and resource handler in `@cyanheads/mcp-ts-core`. Covers the full interface, all sub-APIs (`ctx.log`, `ctx.state`, `ctx.elicit`, `ctx.sample`, `ctx.progress`), and when to use each.
|
|
4
|
+
Canonical reference for the unified `Context` object passed to every tool and resource handler in `@cyanheads/mcp-ts-core`. Covers the full interface, all sub-APIs (`ctx.log`, `ctx.state`, `ctx.elicit`, `ctx.sample`, `ctx.progress`, `ctx.enrich`), and when to use each.
|
|
5
5
|
metadata:
|
|
6
6
|
author: cyanheads
|
|
7
|
-
version: "1.
|
|
7
|
+
version: "1.5"
|
|
8
8
|
audience: external
|
|
9
9
|
type: reference
|
|
10
10
|
---
|
|
@@ -57,6 +57,12 @@ interface Context {
|
|
|
57
57
|
// Raw URI — present only for resource handlers
|
|
58
58
|
readonly uri?: URL;
|
|
59
59
|
|
|
60
|
+
// Agent-facing success-path enrichment — accumulates notices, query echo, totals
|
|
61
|
+
// onto the request; reaches structuredContent + content[]. Always present (no-op
|
|
62
|
+
// when no `enrichment` block), strictly typed on HandlerContext<R, E> against the
|
|
63
|
+
// declared fields. Kind-tagged helpers: enrich.notice / .total / .echo.
|
|
64
|
+
readonly enrich: Enrich;
|
|
65
|
+
|
|
60
66
|
// Opt-in contract resolver — always present (returns {} when no contract is attached
|
|
61
67
|
// or the reason is unknown), strictly typed on HandlerContext<R> against declared reasons.
|
|
62
68
|
recoveryFor(reason: string): { recovery: { hint: string } } | {};
|
|
@@ -208,7 +214,7 @@ Use this only when downstream code is structured around `ctx.sessionId` and acce
|
|
|
208
214
|
|
|
209
215
|
### Capability-token model
|
|
210
216
|
|
|
211
|
-
Surfacing `sessionId` does not change the framework's capability-as-token rule (possession of an opaque ID grants access — see CLAUDE.md `# Core Rules`). It is an opt-in *discovery-scoping* axis, not an access boundary.
|
|
217
|
+
Surfacing `sessionId` does not change the framework's capability-as-token rule (possession of an opaque ID grants access — see CLAUDE.md/AGENTS.md `# Core Rules`). It is an opt-in *discovery-scoping* axis, not an access boundary.
|
|
212
218
|
|
|
213
219
|
- Tokens shared across sessions (e.g. `df_<uuid>` handed from Agent A to Agent B) still resolve on the receiving side. The lookup key is the token, not the session.
|
|
214
220
|
- Session-scoped *enumeration* (e.g. `dataframe_describe` returning only items registered by the current session) is a per-server pattern: maintain a session-keyed lookup of known names, gate list-all on it, but route direct lookups against the shared backing store.
|
|
@@ -520,6 +526,64 @@ The `≥5 words` lint rule on contract `recovery` (validated at lint time) makes
|
|
|
520
526
|
|
|
521
527
|
---
|
|
522
528
|
|
|
529
|
+
## `ctx.enrich`
|
|
530
|
+
|
|
531
|
+
Always present on `Context`. Accumulates agent-facing **success-path** context — empty-result notices, the query/filter as the server parsed it, pagination totals — onto the request. The framework merges it into `structuredContent`, advertises `output.extend(enrichment)` as the tool's `outputSchema`, and mirrors it into a `content[]` trailer. The success-path counterpart to `ctx.fail` / `ctx.recoveryFor`.
|
|
532
|
+
|
|
533
|
+
```ts
|
|
534
|
+
export const search = tool('search', {
|
|
535
|
+
description: 'Search the catalog.',
|
|
536
|
+
input: z.object({ query: z.string().describe('Search terms') }),
|
|
537
|
+
output: z.object({ items: z.array(z.string()).describe('Matching items') }),
|
|
538
|
+
enrichment: {
|
|
539
|
+
effectiveQuery: z.string().describe('Query as the server parsed it'),
|
|
540
|
+
totalCount: z.number().describe('Total matches before the limit'),
|
|
541
|
+
notice: z.string().optional().describe('Guidance when nothing matched'),
|
|
542
|
+
},
|
|
543
|
+
async handler(input, ctx) {
|
|
544
|
+
const res = await runSearch(input.query);
|
|
545
|
+
ctx.enrich.echo(res.parsed); // → effectiveQuery + "Query: …" trailer
|
|
546
|
+
ctx.enrich.total(res.total); // → totalCount + "N total" trailer
|
|
547
|
+
if (res.items.length === 0) ctx.enrich.notice(`No matches for "${input.query}".`);
|
|
548
|
+
return { items: res.items }; // enrichment never rides in the domain return
|
|
549
|
+
},
|
|
550
|
+
});
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
### Signature
|
|
554
|
+
|
|
555
|
+
```ts
|
|
556
|
+
// Loose (always present on Context — works without a block; service-callable):
|
|
557
|
+
ctx.enrich(fields: Record<string, unknown>): void
|
|
558
|
+
|
|
559
|
+
// Strict (HandlerContext<R, E> when the definition declares an enrichment block):
|
|
560
|
+
ctx.enrich(fields: Partial<z.infer<ZodObject<E>>>): void
|
|
561
|
+
|
|
562
|
+
// Kind-tagged field-helpers (always present) — write a conventional key and tag
|
|
563
|
+
// the content[] trailer rendering:
|
|
564
|
+
ctx.enrich.notice(text: string): void // writes `notice` → blockquote
|
|
565
|
+
ctx.enrich.total(count: number): void // writes `totalCount` → "N total"
|
|
566
|
+
ctx.enrich.echo(query: string): void // writes `effectiveQuery` → "Query: …"
|
|
567
|
+
ctx.enrich.delta({ field, before, after }): void // writes `{before, after}` → "field: before → after"
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
### Behavior
|
|
571
|
+
|
|
572
|
+
| Aspect | Detail |
|
|
573
|
+
|:-------|:-------|
|
|
574
|
+
| Accumulation | Each call merges its fields onto the request; later calls override earlier keys. |
|
|
575
|
+
| Both surfaces | Merged into `structuredContent` (validated against `output.extend(enrichment)`) and appended to `content[]` as a trailer — even when the tool defines no `format()`. |
|
|
576
|
+
| Domain payload untouched | `content[]` renders the handler's return via `format()` (or the JSON default); enrichment is a separate trailer, never double-rendered. The handler return must NOT carry enrichment fields. |
|
|
577
|
+
| Required-field guard | A required enrichment field never populated fails the effective-output parse — the bug surfaces loudly rather than dropping silently. |
|
|
578
|
+
| No block | Calling `ctx.enrich` on a tool that declared no `enrichment` is a silent no-op (values are stripped by the parse) — the price of service-layer callability. |
|
|
579
|
+
| Service usage | Services accepting `ctx: Context` can call `ctx.enrich(...)`; the value reaches `structuredContent` exactly as if the handler had. |
|
|
580
|
+
| `format-parity` | Enrichment lives outside `output`, so the `format-parity` lint never requires it in `format()`. |
|
|
581
|
+
| Trailer rendering | Per field: kind-tag if set (notice/total/echo/delta), else the definition's `enrichmentTrailer.render`/`label`, else `**key:** value` (objects/arrays `JSON.stringify`'d). A structured field with no `render` errors under `enrichment-trailer-render` — supply one so it renders as markdown; `structuredContent` keeps the full value regardless. |
|
|
582
|
+
|
|
583
|
+
See `add-tool`'s **Tool Response Design** and `skills/api-linter` (`enrichment-*` rules) for the full pattern. Test enrichment with `getEnrichment(ctx)` from `@cyanheads/mcp-ts-core/testing`.
|
|
584
|
+
|
|
585
|
+
---
|
|
586
|
+
|
|
523
587
|
## Quick reference
|
|
524
588
|
|
|
525
589
|
| Property | Type | Present when |
|
|
@@ -534,6 +598,7 @@ The `≥5 words` lint rule on contract `recovery` (validated at lint time) makes
|
|
|
534
598
|
| `ctx.log` | `ContextLogger` | Always |
|
|
535
599
|
| `ctx.state` | `ContextState` | Always (throws if `tenantId` missing) |
|
|
536
600
|
| `ctx.signal` | `AbortSignal` | Always |
|
|
601
|
+
| `ctx.enrich` | `Enrich` | Always; typed on `HandlerContext<R, E>` when an `enrichment` block is declared |
|
|
537
602
|
| `ctx.elicit` | `function \| undefined` | Client supports elicitation |
|
|
538
603
|
| `ctx.sample` | `function \| undefined` | Client supports sampling |
|
|
539
604
|
| `ctx.notifyResourceListChanged` | `function \| undefined` | Transport supports resource notifications |
|
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
MCP definition linter rules reference. Use when `bun run lint:mcp` or `bun run devcheck` reports a lint error or warning (`format-parity`, `schema-is-object`, `name-format`, `server-json-*`, etc.) and you need to understand the rule, its severity, and how to fix it. Every rule ID the linter emits has an entry in this doc.
|
|
5
5
|
metadata:
|
|
6
6
|
author: cyanheads
|
|
7
|
-
version: "1.
|
|
7
|
+
version: "1.5"
|
|
8
8
|
audience: external
|
|
9
9
|
type: reference
|
|
10
10
|
---
|
|
@@ -53,6 +53,7 @@ Grouped by family. Jump to any rule ID via its anchor.
|
|
|
53
53
|
| Handler body | `prefer-mcp-error-in-handler`, `prefer-error-factory`, `preserve-cause-on-rethrow`, `no-stringify-upstream-error` | [Handler body rules](#handler-body-rules) |
|
|
54
54
|
| Error contract (structural) | `error-contract-type`, `error-contract-empty`, `error-contract-entry-type`, `error-contract-code-type`, `error-contract-code-unknown`, `error-contract-code-unknown-error`, `error-contract-reason-required`, `error-contract-reason-format`, `error-contract-reason-unique`, `error-contract-when-required`, `error-contract-retryable-type`, `error-contract-recovery-required`, `error-contract-recovery-empty`, `error-contract-recovery-min-words` | [Error contract rules](#error-contract-rules) |
|
|
55
55
|
| Error contract (conformance) | `error-contract-conformance`, `error-contract-prefer-fail` | [Error contract rules](#error-contract-rules) |
|
|
56
|
+
| Enrichment | `enrichment-type`, `enrichment-empty`, `enrichment-field-type`, `enrichment-output-collision`, `enrichment-prefer-block`, `enrichment-trailer-render`, `enrichment-trailer-orphan`, `enrichment-trailer-unknown-field` | [Enrichment rules](#enrichment-rules) |
|
|
56
57
|
| server.json | ~40 rules prefixed `server-json-*` | [server.json rules](#server-json-rules) |
|
|
57
58
|
|
|
58
59
|
---
|
|
@@ -514,7 +515,7 @@ Heuristic source-text checks that scan `handler.toString()` for common error-han
|
|
|
514
515
|
|
|
515
516
|
Fires when a handler contains `throw new Error(...)`. Plain `Error` doesn't carry a JSON-RPC code — the framework's auto-classifier degrades to `InternalError`, hiding the actual failure mode.
|
|
516
517
|
|
|
517
|
-
Plain `Error` is acceptable for "don't care" cases where the specific code doesn't matter (per CLAUDE.md: "plain `Error` for don't-care cases"). This rule targets domain-specific failures that deserve a concrete code — upgrade those to factories or `ctx.fail`, and accept the warning for the rest.
|
|
518
|
+
Plain `Error` is acceptable for "don't care" cases where the specific code doesn't matter (per CLAUDE.md/AGENTS.md: "plain `Error` for don't-care cases"). This rule targets domain-specific failures that deserve a concrete code — upgrade those to factories or `ctx.fail`, and accept the warning for the rest.
|
|
518
519
|
|
|
519
520
|
**Fix:** use `McpError` or a factory for domain-specific failures:
|
|
520
521
|
|
|
@@ -708,6 +709,76 @@ The diagnostic message includes the declared reason(s) for the code so you can c
|
|
|
708
709
|
|
|
709
710
|
---
|
|
710
711
|
|
|
712
|
+
## Enrichment rules
|
|
713
|
+
|
|
714
|
+
Validate the `enrichment` block — the success-path counterpart to `errors[]`. Enrichment fields are merged into `structuredContent` and advertised as `output.extend(enrichment)`, so the linter guards the block's shape and its disjointness from `output`. See `api-context`'s `ctx.enrich` and `add-tool`'s **Tool Response Design**.
|
|
715
|
+
|
|
716
|
+
### enrichment-type
|
|
717
|
+
|
|
718
|
+
**Severity:** error
|
|
719
|
+
|
|
720
|
+
Fires when `enrichment` is present but isn't a plain object mapping field names to Zod schemas (a `ZodRawShape`) — e.g. an array or a primitive.
|
|
721
|
+
|
|
722
|
+
**Fix:** declare `enrichment: { <name>: <ZodType>, … }`.
|
|
723
|
+
|
|
724
|
+
### enrichment-empty
|
|
725
|
+
|
|
726
|
+
**Severity:** warning
|
|
727
|
+
|
|
728
|
+
Fires when `enrichment: {}` is declared with no fields — a no-op.
|
|
729
|
+
|
|
730
|
+
**Fix:** drop the field, or declare the agent-facing fields `ctx.enrich(...)` will populate.
|
|
731
|
+
|
|
732
|
+
### enrichment-field-type
|
|
733
|
+
|
|
734
|
+
**Severity:** error
|
|
735
|
+
|
|
736
|
+
Fires when an enrichment field's value isn't a Zod schema.
|
|
737
|
+
|
|
738
|
+
**Fix:** use a Zod type (`z.string().describe(…)`, `z.number().describe(…)`, …) for every enrichment field.
|
|
739
|
+
|
|
740
|
+
### enrichment-output-collision
|
|
741
|
+
|
|
742
|
+
**Severity:** error
|
|
743
|
+
|
|
744
|
+
Fires when an enrichment key matches an `output` key. The effective output schema is `output.extend(enrichment)`, so a collision silently overrides the `output` field.
|
|
745
|
+
|
|
746
|
+
**Fix:** rename one side so enrichment keys are disjoint from output keys.
|
|
747
|
+
|
|
748
|
+
### enrichment-prefer-block
|
|
749
|
+
|
|
750
|
+
**Severity:** warning
|
|
751
|
+
|
|
752
|
+
Advisory. Fires when a tool has **no** `enrichment` block but an `output` field whose name strongly signals agent-facing context (`notice`, `effectiveQuery`, `queryEcho`) rather than domain payload.
|
|
753
|
+
|
|
754
|
+
**Fix:** move the field into an `enrichment` block and populate it via `ctx.enrich(...)` — it reaches both client surfaces without a `format()` entry. Ignore if the field is genuinely domain data. Deliberately conservative — common domain fields like `totalCount` are not flagged.
|
|
755
|
+
|
|
756
|
+
### enrichment-trailer-render
|
|
757
|
+
|
|
758
|
+
**Severity:** error
|
|
759
|
+
|
|
760
|
+
Fires when a non-scalar (object/array) enrichment field has no `enrichmentTrailer.render`. It would `JSON.stringify` into a one-line blob in the `content[]` trailer (`structuredContent` keeps the full value either way). The `delta` shape (`z.object({ before, after })`, populated by `ctx.enrich.delta()`) is exempt — it renders natively as `field: before → after`.
|
|
761
|
+
|
|
762
|
+
**Fix:** add a renderer — `enrichmentTrailer: { <field>: { render: (v) => … } }` — use `ctx.enrich.delta()` for before/after state, or opt into the JSON blob explicitly with `render: (v) => JSON.stringify(v)`.
|
|
763
|
+
|
|
764
|
+
### enrichment-trailer-orphan
|
|
765
|
+
|
|
766
|
+
**Severity:** error
|
|
767
|
+
|
|
768
|
+
Fires when `enrichmentTrailer` is declared without an `enrichment` block — trailer config only renders enrichment fields.
|
|
769
|
+
|
|
770
|
+
**Fix:** add the `enrichment` block, or drop the `enrichmentTrailer`.
|
|
771
|
+
|
|
772
|
+
### enrichment-trailer-unknown-field
|
|
773
|
+
|
|
774
|
+
**Severity:** error
|
|
775
|
+
|
|
776
|
+
Fires when an `enrichmentTrailer` key doesn't match any declared `enrichment` field (a typo or drift the `keyof`-typed config already catches for TS authors).
|
|
777
|
+
|
|
778
|
+
**Fix:** rename the trailer key to a declared enrichment field, or remove it.
|
|
779
|
+
|
|
780
|
+
---
|
|
781
|
+
|
|
711
782
|
## Escape hatches
|
|
712
783
|
|
|
713
784
|
### Dynamic upstream data
|
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
Design the tool surface, resources, and service layer for a new MCP server. Use when starting a new server, planning a major feature expansion, or when the user describes a domain/API they want to expose via MCP. Produces a design doc at docs/design.md that drives implementation.
|
|
5
5
|
metadata:
|
|
6
6
|
author: cyanheads
|
|
7
|
-
version: "2.
|
|
7
|
+
version: "2.14"
|
|
8
8
|
audience: external
|
|
9
9
|
type: workflow
|
|
10
10
|
---
|
|
@@ -351,6 +351,7 @@ output: z.object({
|
|
|
351
351
|
- **Truncate large output with counts.** When a list exceeds a reasonable display size, show the top N and append "...and X more". Don't silently drop results.
|
|
352
352
|
- **Spill big tabular results to a queryable surface.** When a tool's row set can exceed any reasonable context budget — paginated APIs, streamed exports, big query results — pair an inline preview with a `DataCanvas` table holding the full set, returned as a token the agent can SQL. Compute distributions or refinement hints across the full result, not the preview, so aggregate signal stays honest. See `api-canvas` for the `spillover()` helper.
|
|
353
353
|
- **`format()` is the markdown twin of `structuredContent` — make both content-complete.** Different MCP clients forward different surfaces to the model: some (e.g., Claude Code) read `structuredContent` from `output`, others (e.g., Claude Desktop) read `content[]` from `format()`. Both must carry the same data so every client sees the same picture — `format()` just dresses it up with markdown. A thin `format()` that returns only a count or title leaves `content[]`-only clients blind to data that `structuredContent` clients can see. Render all fields the LLM needs, with structured markdown (headers, bold labels, lists) for readability.
|
|
354
|
+
- **Agent-facing context must reach both client surfaces — put it in `enrichment`.** `structuredContent` (from `output`) and `content[]` (from `format()`) are read by different clients. Empty-result notices, the query/filter as the server parsed it, and pagination totals — the context the agent *reasons with*, distinct from the domain payload — reach only `content[]` if hand-authored into `format()` text alone, leaving `structuredContent`-only clients (Claude Code) blind. (The reverse can't happen: `format-parity` drags every `output` field into `format()`, so `output`-authored context already reaches both.) An `enrichment` block — the success-path counterpart to `errors[]`, populated via `ctx.enrich(...)` — reaches both automatically: merged into `structuredContent`, advertised as `output.extend(enrichment)`, mirrored into a `content[]` trailer, no `format()` entry needed. How each field renders in that trailer is a per-tool call — a kind-tag (`notice`/`total`/`echo`/`delta`) when a canonical form fits, a domain key like `totalFound` otherwise, and an `enrichmentTrailer.render` for any structured (object/array) field so it doesn't ship as a JSON blob. See `add-tool`'s **Tool Response Design**.
|
|
354
355
|
|
|
355
356
|
#### Batch input design
|
|
356
357
|
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: git-wrapup
|
|
3
3
|
description: >
|
|
4
|
-
Land working-tree changes as
|
|
4
|
+
Land working-tree changes as logical commits — the work grouped by concern, topped by a release commit (version bump, changelog, regenerated artifacts) and an annotated tag. 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
5
|
metadata:
|
|
6
6
|
author: cyanheads
|
|
7
|
-
version: "1.
|
|
7
|
+
version: "1.2"
|
|
8
8
|
audience: external
|
|
9
9
|
type: workflow
|
|
10
10
|
---
|
|
11
11
|
|
|
12
12
|
## When to use
|
|
13
13
|
|
|
14
|
-
Working-tree or staged changes are ready to ship as a new version. This skill lands them as a
|
|
14
|
+
Working-tree or staged changes are ready to ship as a new version. This skill lands them as a stack of logical commits — the work grouped by concern, topped by a release commit (version + changelog + tree) — with an annotated tag. It does NOT push or publish — that's a separate step (`release-and-publish`).
|
|
15
15
|
|
|
16
16
|
Common triggers:
|
|
17
17
|
- Feature work, bug fixes, or dependency updates are done and tested
|
|
@@ -119,27 +119,34 @@ bun run test:all # or `bun run test` if no test:all script exists
|
|
|
119
119
|
|
|
120
120
|
**If either fails, halt.** Do not bypass verification to land the commit. Fix the issue first, then re-run from step 6.
|
|
121
121
|
|
|
122
|
-
### 7. Commit
|
|
122
|
+
### 7. Commit — group by concern, release artifacts on top
|
|
123
123
|
|
|
124
|
-
|
|
124
|
+
Do NOT `git add -A` into one commit. Group the working tree into a handful of logical commits — never one blob:
|
|
125
|
+
|
|
126
|
+
1. **The work — one commit per concern.** A feature spanning multiple layers splits by layer: runtime/logic, linter/tooling, docs/skills. Unrelated changes (two separate fixes, an incidental doc tweak) are their own commits. Work commits do not carry the version.
|
|
127
|
+
2. **The release commit — last, on top.** Version bumps (`package.json`, `server.json`, README badge, `CLAUDE.md`/`AGENTS.md`), the changelog entry, `CHANGELOG.md`, and `docs/tree.md` go in a single final commit that sits on top of the work stack — never mixed into a feature commit.
|
|
128
|
+
|
|
129
|
+
Stage each group explicitly, commit it, then move to the next — the release commit goes last:
|
|
125
130
|
|
|
126
131
|
```bash
|
|
127
|
-
git add -
|
|
132
|
+
git add <paths-for-this-concern>
|
|
128
133
|
git commit -m "<subject>"
|
|
134
|
+
# repeat per concern; version + changelog + tree are the final commit
|
|
129
135
|
```
|
|
130
136
|
|
|
131
|
-
**
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
- `
|
|
137
|
+
**The file is the atomic boundary:** NEVER split a single file's changes across commits. When one file serves two concerns, it ships whole in the commit of its dominant concern.
|
|
138
|
+
|
|
139
|
+
**Subject format:** Conventional Commits.
|
|
140
|
+
- Work commits (no version): `feat: hosted server endpoint`, `fix: handle empty SPARQL result sets`, `feat(linter): enrichment contract rules`, `docs: document the enrichment block`
|
|
141
|
+
- Release commit (subject leads with the version): `chore(release): 0.2.1 — empty SPARQL result handling`
|
|
135
142
|
|
|
136
143
|
**Rules:**
|
|
137
144
|
- Plain `-m` flag only — no heredoc, no command substitution
|
|
138
145
|
- No `Co-authored-by` or `Generated with` trailers
|
|
139
146
|
- No marketing adjectives ("comprehensive", "robust", "enhanced", "seamless", "improved")
|
|
140
|
-
-
|
|
147
|
+
- Each commit message stands alone for someone reading `git log` — no chat context, option numbers, or "as discussed"
|
|
141
148
|
|
|
142
|
-
**
|
|
149
|
+
**Right-size it.** "Group by concern" is not "always split." A genuinely single-concern change — one fix, a dependency bump, a small doc edit — is one work commit plus the release commit; when the change and its version bump are inseparable for a tiny patch, a single commit whose subject leads with the version is fine. The failure mode to prevent is the inverse: a large, multi-layer feature crammed into one commit alongside the release artifacts.
|
|
143
150
|
|
|
144
151
|
### 8. Create an annotated tag
|
|
145
152
|
|
|
@@ -183,8 +190,8 @@ Dependency bumps:
|
|
|
183
190
|
### 9. Verify end state
|
|
184
191
|
|
|
185
192
|
```bash
|
|
186
|
-
git log --oneline -
|
|
187
|
-
git show v<version> --stat | head -20 # confirm tag points at HEAD
|
|
193
|
+
git log --oneline -8 # confirm the commit stack: work commits + release commit on top
|
|
194
|
+
git show v<version> --stat | head -20 # confirm tag points at HEAD (the release commit)
|
|
188
195
|
git status # must be clean
|
|
189
196
|
```
|
|
190
197
|
|
|
@@ -211,7 +218,7 @@ If the working tree isn't clean or the tag doesn't point at HEAD, something went
|
|
|
211
218
|
- [ ] `docs/tree.md` regenerated if structure changed (`bun run tree`)
|
|
212
219
|
- [ ] `bun run devcheck` passes
|
|
213
220
|
- [ ] `bun run test:all` (or `test`) passes
|
|
214
|
-
- [ ]
|
|
221
|
+
- [ ] Work grouped into logical commits (large features split by layer); release artifacts (version + changelog + tree) committed separately on top, subject leading with the version
|
|
215
222
|
- [ ] Annotated tag `v<version>` with structured markdown message
|
|
216
223
|
- [ ] Working tree clean
|
|
217
224
|
- [ ] Nothing pushed — local only
|
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
Investigate, adopt, and verify dependency updates — with special handling for `@cyanheads/mcp-ts-core`. Captures what changed, understands why, cross-references against the codebase, adopts framework improvements, syncs project skills, and runs final checks. Supports two entry modes: run the full flow end-to-end, or review updates you already applied.
|
|
5
5
|
metadata:
|
|
6
6
|
author: cyanheads
|
|
7
|
-
version: "2.
|
|
7
|
+
version: "2.5"
|
|
8
8
|
audience: external
|
|
9
9
|
type: workflow
|
|
10
10
|
---
|
|
@@ -78,7 +78,7 @@ Scan specifically for:
|
|
|
78
78
|
| Config changes | New env vars, renamed keys, changed defaults |
|
|
79
79
|
| Linter rules | New definition-lint rules that may now flag existing tools/resources |
|
|
80
80
|
| New or materially-changed skills | Note new skills or workflow changes (renamed steps, new checklist items) worth surfacing at end-of-run. Don't auto-invoke — some skills (e.g. `security-pass`) are user-triggered. The per-version changelog entries (e.g. 0.6.14 calling out `skills/security-pass/ (v1.0)`) name what changed. |
|
|
81
|
-
| New template-scaffolded files | Compare `templates/` in the package against the project root. Files that `init` would create for a new project but don't exist in this project are adoption candidates — create them with project-specific values (version, name, description, env vars from `server.json`). Examples: `manifest.json`, `.mcpbignore`, `.codex-plugin/`, `.claude-plugin/`. Skip files the project has intentionally opted out of (documented in CLAUDE.md or a code comment). |
|
|
81
|
+
| New template-scaffolded files | Compare `templates/` in the package against the project root. Files that `init` would create for a new project but don't exist in this project are adoption candidates — create them with project-specific values (version, name, description, env vars from `server.json`). Examples: `manifest.json`, `.mcpbignore`, `.codex-plugin/`, `.claude-plugin/`. Skip files the project has intentionally opted out of (documented in CLAUDE.md/AGENTS.md or a code comment). |
|
|
82
82
|
| Changelog `agent-notes` | Read `agent-notes` frontmatter from each new per-version changelog file — these carry release-specific adoption instructions for downstream consumers (new files to create, fields to populate, one-time migration steps). Apply them alongside other adoption work in Step 6. |
|
|
83
83
|
|
|
84
84
|
Cross-reference each finding against the server's code. Collect adoption opportunities for Step 6.
|
|
@@ -103,7 +103,8 @@ Procedure:
|
|
|
103
103
|
- If missing in project `skills/`, copy the full directory
|
|
104
104
|
- If present, compare `metadata.version` — replace if the package version is newer
|
|
105
105
|
- If the local version is equal or newer, skip (local override)
|
|
106
|
-
3.
|
|
106
|
+
3. Leave skills in `skills/` that lack `metadata.audience: external` untouched — they're server-specific or sourced elsewhere, not framework-managed.
|
|
107
|
+
4. **Prune framework skills deleted upstream.** A skill in `skills/` that *carries* `metadata.audience: external` but is **absent** from the package was removed upstream (e.g. `migrate-mcp-ts-template`, removed in 0.9.12) and lingers because sync was previously add/update-only. Delete it from `skills/` (and from the agent mirrors in Phase B). The `audience: external` marker is the provenance: it scopes the prune to framework-managed skills, so a server's own skills — which never carry it — are never touched. Before deleting, scan the skill for local edits worth keeping; if any exist, reconcile or surface them rather than discarding silently.
|
|
107
108
|
|
|
108
109
|
**Skill diffs are adoption signal, not just sync output.** After replacing files in `skills/`, run `git diff skills/` to read what changed. Updated skill bodies describe new patterns, refined workflows, or new conventions — apply them to the codebase in Step 6 the same way you'd apply a framework API addition. The file copy is the *trigger*, not the work. The work is what the updated skill now says to do.
|
|
109
110
|
|
|
@@ -122,7 +123,7 @@ The `setup` skill instructs consumers to copy `skills/*` into their agent's skil
|
|
|
122
123
|
For each agent directory that exists:
|
|
123
124
|
|
|
124
125
|
1. For every directory in project `skills/`, copy it into the agent dir (overwrite on match, add if missing)
|
|
125
|
-
2. Do **not** delete skills in the agent dir that aren't in project `skills/` — they may be general-purpose skills sourced elsewhere (e.g., `code-security`, `cloudflare`, `changelog`)
|
|
126
|
+
2. Do **not** delete skills in the agent dir that aren't in project `skills/` — they may be general-purpose skills sourced elsewhere (e.g., `code-security`, `cloudflare`, `changelog`). **Exception:** a framework skill pruned in Phase A step 4 — delete that same-named directory from each agent dir too. Match by the specific name you just removed, never by a blanket "absent from `skills/`" sweep (which would catch the externally-sourced skills above).
|
|
126
127
|
|
|
127
128
|
If no agent directory exists, skip Phase B — the project hasn't opted in to per-agent skill copies.
|
|
128
129
|
|
|
@@ -154,7 +155,7 @@ Scripts in `scripts/` that aren't present in the package directory are project-s
|
|
|
154
155
|
|:--|:--|
|
|
155
156
|
| `templates/changelog/template.md` | `changelog/template.md` |
|
|
156
157
|
|
|
157
|
-
Apply the same compare-and-overwrite logic. Add new entries here only when a template is explicitly documented as pristine in the framework's CLAUDE.md or its own header.
|
|
158
|
+
Apply the same compare-and-overwrite logic. Add new entries here only when a template is explicitly documented as pristine in the framework's CLAUDE.md/AGENTS.md or its own header.
|
|
158
159
|
|
|
159
160
|
If the consumer customized a framework script or pristine reference (against guidance), the overwrite discards those changes. After the sync runs, diff `scripts/` and the affected template paths to surface replacements — review before committing. If a specific local customization needs to be preserved, revert that file using your git tools.
|
|
160
161
|
|
|
@@ -181,7 +182,7 @@ The consumer opted into the framework; its templates, skills, scripts, linter ru
|
|
|
181
182
|
|
|
182
183
|
| ❌ Not a valid reason to defer | ✅ Valid reason to defer |
|
|
183
184
|
|:-------------------------------|:-------------------------|
|
|
184
|
-
| "Larger change than fits this pass" | Code-commented or `CLAUDE.md`-documented local override that intentionally diverges from the framework convention |
|
|
185
|
+
| "Larger change than fits this pass" | Code-commented or `CLAUDE.md`/`AGENTS.md`-documented local override that intentionally diverges from the framework convention |
|
|
185
186
|
| "Marginal benefit / leaving as-is" | Breaking change with multiple migration paths that need user input |
|
|
186
187
|
| "Per-tool refactor — worth doing as a focused follow-up" | Feature genuinely doesn't apply (the surface doesn't exist in this server) |
|
|
187
188
|
| "Existing helper has rich domain messages we'd lose" | — (port the messages onto the framework path) |
|
|
@@ -221,7 +222,7 @@ Present a concise numbered summary to the user:
|
|
|
221
222
|
3. **Features adopted** — new framework APIs now in use
|
|
222
223
|
4. **Skills synced** — added/updated with versions (Phase A) and agent directories refreshed (Phase B)
|
|
223
224
|
5. **New/changed skills available** — skills that appeared in Phase A for the first time or had materially-changed step sequences. Frame as "consider running when the time is right" rather than immediate actions; the user decides when to invoke them.
|
|
224
|
-
6. **Open decisions** — genuinely ambiguous items only. Valid: breaking changes with multiple migration paths needing user input, framework changes that conflict with a code-commented or `CLAUDE.md`-documented local override, third-party adoptions where cost/benefit is close. **Not valid:** framework adoptions deferred for scope, effort, or marginal-benefit reasoning — those were already adopted in Step 6 and belong under "Features adopted." If this section is empty, that's the expected outcome of a clean framework upgrade.
|
|
225
|
+
6. **Open decisions** — genuinely ambiguous items only. Valid: breaking changes with multiple migration paths needing user input, framework changes that conflict with a code-commented or `CLAUDE.md`/`AGENTS.md`-documented local override, third-party adoptions where cost/benefit is close. **Not valid:** framework adoptions deferred for scope, effort, or marginal-benefit reasoning — those were already adopted in Step 6 and belong under "Features adopted." If this section is empty, that's the expected outcome of a clean framework upgrade.
|
|
225
226
|
7. **Status** — rebuild / devcheck / test results
|
|
226
227
|
|
|
227
228
|
## Checklist
|
|
@@ -69,7 +69,7 @@ The orchestrator owns the goals. Workflow phases are not "run skill X" — they
|
|
|
69
69
|
Before running a phase (or spawning a sub-agent for it), write down four things:
|
|
70
70
|
|
|
71
71
|
1. **Goal** — the verifiable end state this phase must produce. Concrete and testable: "v0.5.2 tag exists at HEAD with structured-markdown annotation; `bun run devcheck` green; `npm view <pkg>@0.5.2` resolves." Not fuzzy: "ran the release-and-publish skill."
|
|
72
|
-
2. **Primary sources** — the specific files, GH issues, and reference docs the sub-agent must read directly. Inlining content into the prompt is a paraphrase that loses nuance; agents grounded in the source catch details the orchestrator's summary missed. For GH issues, instruct `gh issue view N --comments` — body alone misses
|
|
72
|
+
2. **Primary sources** — the specific files, GH issues, and reference docs the sub-agent must read directly. Inlining content into the prompt is a paraphrase that loses nuance; agents grounded in the source catch details the orchestrator's summary missed. For GH issues, instruct both `gh issue view N --comments` (the comment thread) and the timeline cross-reference query in the Orient block (what references the issue, including cross-repo) — the body alone misses both. The orchestrator reads these sources too (to construct the prompt), but that's prompt construction, not a substitute for the sub-agent reading them.
|
|
73
73
|
3. **Path** — the Tier 1 skill(s) and steps that get to the goal. This is what gets handed to the sub-agent.
|
|
74
74
|
4. **Verification** — the read-only checks that confirm the goal was hit. Defined upfront, not as an afterthought.
|
|
75
75
|
|
|
@@ -91,6 +91,8 @@ Sub-agents are optional. Match the mechanism to your platform's capability — t
|
|
|
91
91
|
|
|
92
92
|
Phases, gates, goals, and constraints are identical across all three tiers — only the fanout mechanism changes. Use the most capable tier available, and don't hand-roll what the platform does natively (e.g., rolling concurrency). Choose by scope and capability, not by default.
|
|
93
93
|
|
|
94
|
+
**Model tier ≠ orchestration tier.** A higher orchestration tier is not automatically the right choice. On some platforms, programmatically-orchestrated or *nested* sub-agents (an agent spawning agents) silently run on a cheaper/downgraded model, while the strongest model is reachable only by sub-agents the **main loop spawns directly** (tier 2). When a phase needs the top model (heavy generation, design, framework adoption), prefer direct main-loop fanout even when a more "capable" orchestration primitive exists — the primitive can cost you the model. Verify the model your platform actually assigned via its UI/telemetry; never infer it from a sub-agent's transcript, which interleaves auxiliary calls (titles, summaries) on cheaper models and will mislead you.
|
|
95
|
+
|
|
94
96
|
The decision tree below is orthogonal to tier — it governs *whether* a given phase fans out, by target count and conflict risk:
|
|
95
97
|
|
|
96
98
|
| Situation | Strategy |
|
|
@@ -119,10 +121,12 @@ order. If any file does not exist, note it and continue.
|
|
|
119
121
|
available skills with descriptions and locations.
|
|
120
122
|
5. Read the skill file(s) for this task: `[Tier 1 skill paths]`.
|
|
121
123
|
6. Read the primary sources for this task directly — design docs (`docs/design.md`),
|
|
122
|
-
GH issues
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
GH issues, handoff documents, reference/gold-standard files. For a GH issue, read
|
|
125
|
+
both the comment thread and its cross-references — the body alone misses both:
|
|
126
|
+
- `gh issue view <N> --comments` — description + comment thread
|
|
127
|
+
- `gh api 'repos/{owner}/{repo}/issues/<N>/timeline' --paginate --jq '.[] | select(.event=="cross-referenced") | .source.issue | "\(.repository.full_name)#\(.number) — \(.title)"'` — issues/PRs that reference this one, including from other repos
|
|
128
|
+
List each source explicitly: `[primary source paths and gh commands]`. Skip this
|
|
129
|
+
step only if no primary source applies (rare).
|
|
126
130
|
|
|
127
131
|
Only after that, begin the task below.
|
|
128
132
|
|
|
@@ -133,7 +133,7 @@ Each sub-agent reads BOTH `skills/git-wrapup/SKILL.md` AND `skills/release-and-p
|
|
|
133
133
|
- No bypass → Phase 4 runs serially, orchestrator-driven, one target at a time
|
|
134
134
|
- No npm publish involved (private only) → non-issue
|
|
135
135
|
|
|
136
|
-
**Commit structure.**
|
|
136
|
+
**Commit structure.** Group the work by concern, then land the release artifacts (version bumps + changelog + regenerated `docs/tree.md`/`server.json`/`manifest.json`) as a `chore(release): <version> — <theme>` commit on top — same model as `git-wrapup` Step 7. A single-concern pass (just dep updates, or one framework adoption) is one work commit plus the release commit; a pass spanning multiple distinct concerns splits into per-concern work commits with the release commit last. Regenerated meta-drift is release-artifact-shaped — it rides in the release commit, never carved out as its own.
|
|
137
137
|
|
|
138
138
|
**Tag annotations are for end users.** Internal dev cleanup (lockfile refreshes, linter fixes, build config) belongs in the commit body, not the tag annotation.
|
|
139
139
|
|
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
Finalize documentation and project metadata for a ship-ready MCP server. Use after implementation is complete, tests pass, and devcheck is clean. Safe to run at any stage — each step checks current state and only acts on what still needs work.
|
|
5
5
|
metadata:
|
|
6
6
|
author: cyanheads
|
|
7
|
-
version: "2.
|
|
7
|
+
version: "2.5"
|
|
8
8
|
audience: external
|
|
9
9
|
type: workflow
|
|
10
10
|
---
|
|
@@ -71,11 +71,11 @@ These sections should remain intact unless you have a specific reason to change
|
|
|
71
71
|
- **Core Rules** — universal to all servers built on the framework
|
|
72
72
|
- **Errors section** — "handlers throw, framework catches" is universal
|
|
73
73
|
- **Imports section** — keep unless the alias convention was changed
|
|
74
|
-
- **Framework reference pointer** — the line directing agents to `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md`
|
|
74
|
+
- **Framework reference pointer** — the line directing agents to `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md` (or `AGENTS.md`)
|
|
75
75
|
|
|
76
76
|
## Pitfalls
|
|
77
77
|
|
|
78
|
-
- Don't duplicate the full framework CLAUDE.md into the project file. The project file covers server-specific conventions; the framework file covers the API. The pointer at the top connects them.
|
|
78
|
+
- Don't duplicate the full framework CLAUDE.md/AGENTS.md into the project file. The project file covers server-specific conventions; the framework file covers the API. The pointer at the top connects them.
|
|
79
79
|
- Don't remove `## Core Rules` even if it seems obvious — agents read this fresh each session.
|
|
80
80
|
- Don't add implementation details that change frequently. The agent protocol file should be stable — update it when the server's shape changes, not on every commit.
|
|
81
81
|
- Don't assume this is a one-time pass. The protocol file should be revisited whenever the server's surface area changes (tools added/removed, new services, config changes).
|
|
@@ -20,7 +20,7 @@ Framework badge ← solo spotlight row — `Built on @cy
|
|
|
20
20
|
## Configuration ← env var table + `.env.example` pointer
|
|
21
21
|
## Running the server ← dev, production, Workers/Docker
|
|
22
22
|
## Project structure ← directory/purpose table
|
|
23
|
-
## Development guide ← link to CLAUDE.md, key rules
|
|
23
|
+
## Development guide ← link to CLAUDE.md/AGENTS.md, key rules
|
|
24
24
|
## Contributing ← brief
|
|
25
25
|
## License ← one line
|
|
26
26
|
```
|
|
@@ -471,12 +471,12 @@ Directory/purpose table orienting contributors to the codebase.
|
|
|
471
471
|
|
|
472
472
|
### Development Guide
|
|
473
473
|
|
|
474
|
-
Brief — link to CLAUDE.md for full details. State 3-4 key rules. **Include the "validate → normalize → never fabricate" bullet** — it's the canonical anti-hallucination convention for external API wrappers and reinforces the framework's `no fabricated signal` principle.
|
|
474
|
+
Brief — link to CLAUDE.md/AGENTS.md for full details. State 3-4 key rules. **Include the "validate → normalize → never fabricate" bullet** — it's the canonical anti-hallucination convention for external API wrappers and reinforces the framework's `no fabricated signal` principle.
|
|
475
475
|
|
|
476
476
|
```markdown
|
|
477
477
|
## Development guide
|
|
478
478
|
|
|
479
|
-
See [`CLAUDE.md`](./CLAUDE.md) for development guidelines and architectural rules. The short version:
|
|
479
|
+
See [`CLAUDE.md`/`AGENTS.md`](./CLAUDE.md) for development guidelines and architectural rules. The short version:
|
|
480
480
|
|
|
481
481
|
- Handlers throw, framework catches — no `try/catch` in tool logic
|
|
482
482
|
- Use `ctx.log` for request-scoped logging, `ctx.state` for tenant-scoped storage
|
|
@@ -30,7 +30,12 @@ For general `gh` CLI workflows outside issue filing (PRs, workflows, API access)
|
|
|
30
30
|
4. **Search existing issues** — don't file duplicates:
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
|
-
gh issue list -R cyanheads/mcp-ts-core --search "your error message or keyword"
|
|
33
|
+
gh issue list -R cyanheads/mcp-ts-core --search "your error message or keyword" --state all
|
|
34
|
+
|
|
35
|
+
# Assess a close match before commenting — is it already linked to a fix or referenced elsewhere?
|
|
36
|
+
gh issue view <number> -R cyanheads/mcp-ts-core --comments
|
|
37
|
+
gh api 'repos/cyanheads/mcp-ts-core/issues/<number>/timeline' --paginate \
|
|
38
|
+
--jq '.[] | select(.event=="cross-referenced") | .source.issue | "\(.repository.full_name)#\(.number) — \(.title)"'
|
|
34
39
|
```
|
|
35
40
|
|
|
36
41
|
5. **For documentation- or contract-shaped requests, audit all three doc layers first** — proposals to add reference docs, public-API conventions, attribute/event catalogs, or stability commitments often duplicate surface that already exists. Check `src/` for behavior, `docs/` for human-facing reference, and `skills/` for agent-facing reference. Skill files marked `audience: external` are the framework's public contract — treat them as authoritative when evaluating whether a documentation gap exists. Also verify the constants or types you'd reference aren't already exported from `@cyanheads/mcp-ts-core` or one of its subpaths.
|
|
@@ -273,8 +278,8 @@ ISSUE
|
|
|
273
278
|
## Following Up
|
|
274
279
|
|
|
275
280
|
```bash
|
|
276
|
-
# Check issue status
|
|
277
|
-
gh issue view <number> -R cyanheads/mcp-ts-core
|
|
281
|
+
# Check issue status (with comment thread)
|
|
282
|
+
gh issue view <number> -R cyanheads/mcp-ts-core --comments
|
|
278
283
|
|
|
279
284
|
# Add context or respond to maintainer questions
|
|
280
285
|
gh issue comment <number> -R cyanheads/mcp-ts-core --body "Additional context..."
|
|
@@ -35,7 +35,12 @@ gh repo view --json nameWithOwner -q '.nameWithOwner'
|
|
|
35
35
|
2. **Search existing issues** — if a close match exists (same symptom, different tool; same tool, different symptom; closed issue that might cover the new case), add a comment on that issue instead of filing a new one — unless the symptom or scope is distinct enough to warrant separate tracking:
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
|
-
gh issue list --search "your error message or keyword"
|
|
38
|
+
gh issue list --search "your error message or keyword" --state all
|
|
39
|
+
|
|
40
|
+
# Assess a close match before commenting — is it already linked to a fix or referenced elsewhere?
|
|
41
|
+
gh issue view <number> --comments
|
|
42
|
+
gh api 'repos/{owner}/{repo}/issues/<number>/timeline' --paginate \
|
|
43
|
+
--jq '.[] | select(.event=="cross-referenced") | .source.issue | "\(.repository.full_name)#\(.number) — \(.title)"'
|
|
39
44
|
```
|
|
40
45
|
|
|
41
46
|
3. **Reproduce the issue** — confirm it's reproducible. Note the exact input, transport mode, and any relevant env vars.
|
|
@@ -280,8 +285,8 @@ When genuinely ambiguous, file against this server's repo and note that it might
|
|
|
280
285
|
## Following Up
|
|
281
286
|
|
|
282
287
|
```bash
|
|
283
|
-
# View issue details
|
|
284
|
-
gh issue view <number>
|
|
288
|
+
# View issue details (with comment thread)
|
|
289
|
+
gh issue view <number> --comments
|
|
285
290
|
|
|
286
291
|
# Add context
|
|
287
292
|
gh issue comment <number> --body "Additional findings..."
|
package/skills/setup/SKILL.md
CHANGED
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
Post-init orientation for an MCP server built on @cyanheads/mcp-ts-core. Use after running `@cyanheads/mcp-ts-core init` to understand the project structure, conventions, and skill sync model. Also use when onboarding to an existing project for the first time.
|
|
5
5
|
metadata:
|
|
6
6
|
author: cyanheads
|
|
7
|
-
version: "1.
|
|
7
|
+
version: "1.8"
|
|
8
8
|
audience: external
|
|
9
9
|
type: workflow
|
|
10
10
|
---
|
|
@@ -15,14 +15,9 @@ This skill assumes `bunx @cyanheads/mcp-ts-core init [name]` has already run. Th
|
|
|
15
15
|
|
|
16
16
|
## Agent Protocol File
|
|
17
17
|
|
|
18
|
-
The init CLI generates both `CLAUDE.md` and `AGENTS.md` with
|
|
18
|
+
The init CLI generates both `CLAUDE.md` and `AGENTS.md` with identical content — `CLAUDE.md` is read by Claude Code, `AGENTS.md` by Codex, Cursor, Windsurf, and other agents. **Keep both.** Shipping both keeps the project agent-agnostic, and they're cheap to hold in sync: edit one, then `cp CLAUDE.md AGENTS.md` (the framework keeps its own pair byte-identical the same way, enforced by `check-docs-sync`). Only delete one if you're certain the project will never be opened by the other family of agents.
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
- **All other agents** (Codex, Cursor, Windsurf, etc.) — keep `AGENTS.md`, delete `CLAUDE.md`
|
|
22
|
-
|
|
23
|
-
Both files serve the same purpose: project-specific agent instructions. Prefer committing one authoritative copy rather than trying to keep both in sync by hand.
|
|
24
|
-
|
|
25
|
-
For the full framework docs, read `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md` once per session. It contains the exports catalog, tool/resource/prompt contracts, error codes, context API, and common import patterns.
|
|
20
|
+
For the full framework docs, read `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md` (or its identical twin `AGENTS.md`) once per session. It contains the exports catalog, tool/resource/prompt contracts, error codes, context API, and common import patterns.
|
|
26
21
|
|
|
27
22
|
## Project Structure
|
|
28
23
|
|
|
@@ -155,12 +150,12 @@ Skip or reorder as the project calls for it. The agent protocol's "What's Next?"
|
|
|
155
150
|
|
|
156
151
|
## Checklist
|
|
157
152
|
|
|
158
|
-
- [ ] Agent protocol
|
|
153
|
+
- [ ] Agent protocol files kept — both `CLAUDE.md` and `AGENTS.md` present and in sync (or the unused one deliberately deleted)
|
|
159
154
|
- [ ] `bun install` run
|
|
160
155
|
- [ ] Dependencies updated (`bun update --latest`)
|
|
161
156
|
- [ ] Git repo initialized and initial commit made (`chore: scaffold from @cyanheads/mcp-ts-core`)
|
|
162
157
|
- [ ] Substituted server name verified in `package.json`, agent protocol file, and `server.json`
|
|
163
|
-
- [ ] Framework docs read (`node_modules/@cyanheads/mcp-ts-core/CLAUDE.md`)
|
|
158
|
+
- [ ] Framework docs read (`node_modules/@cyanheads/mcp-ts-core/CLAUDE.md` or `AGENTS.md`)
|
|
164
159
|
- [ ] Unused echo definitions cleaned up (and unregistered from `src/index.ts`)
|
|
165
160
|
- [ ] Skills copied to agent directory (`cp -R skills/* .claude/skills/` or equivalent)
|
|
166
161
|
- [ ] Project structure understood (definitions directories, entry point)
|
package/templates/AGENTS.md
CHANGED
|
@@ -309,7 +309,8 @@ When you complete a skill's checklist, check the boxes and add a completion time
|
|
|
309
309
|
| `npm run devcheck` | Lint + format + typecheck + security + changelog sync |
|
|
310
310
|
| `bun run audit:refresh` | Delete `bun.lock`, reinstall, and re-run `bun audit`. Use when `devcheck` flags a transitive advisory — Bun's `update` is sticky on transitive resolutions, so the advisory may be a stale-lockfile false positive. If it survives the refresh, it's real. |
|
|
311
311
|
| `npm run tree` | Generate directory structure doc |
|
|
312
|
-
| `npm run format` | Auto-fix formatting |
|
|
312
|
+
| `npm run format` | Auto-fix formatting (safe fixes only) |
|
|
313
|
+
| `npm run format:unsafe` | Also apply Biome's unsafe autofixes — review the diff; they can change behavior |
|
|
313
314
|
| `npm test` | Run tests |
|
|
314
315
|
| `npm run start:stdio` | Production mode (stdio) |
|
|
315
316
|
| `npm run start:http` | Production mode (HTTP) |
|
package/templates/CLAUDE.md
CHANGED
|
@@ -309,7 +309,8 @@ When you complete a skill's checklist, check the boxes and add a completion time
|
|
|
309
309
|
| `npm run devcheck` | Lint + format + typecheck + security + changelog sync |
|
|
310
310
|
| `bun run audit:refresh` | Delete `bun.lock`, reinstall, and re-run `bun audit`. Use when `devcheck` flags a transitive advisory — Bun's `update` is sticky on transitive resolutions, so the advisory may be a stale-lockfile false positive. If it survives the refresh, it's real. |
|
|
311
311
|
| `npm run tree` | Generate directory structure doc |
|
|
312
|
-
| `npm run format` | Auto-fix formatting |
|
|
312
|
+
| `npm run format` | Auto-fix formatting (safe fixes only) |
|
|
313
|
+
| `npm run format:unsafe` | Also apply Biome's unsafe autofixes — review the diff; they can change behavior |
|
|
313
314
|
| `npm test` | Run tests |
|
|
314
315
|
| `npm run start:stdio` | Production mode (stdio) |
|
|
315
316
|
| `npm run start:http` | Production mode (HTTP) |
|