@cyanheads/mcp-ts-core 0.5.4 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +39 -1
- package/README.md +1 -1
- package/changelog/0.1.x/0.1.0.md +78 -0
- package/changelog/0.1.x/0.1.1.md +28 -0
- package/changelog/0.1.x/0.1.10.md +32 -0
- package/changelog/0.1.x/0.1.11.md +51 -0
- package/changelog/0.1.x/0.1.12.md +21 -0
- package/changelog/0.1.x/0.1.13.md +16 -0
- package/changelog/0.1.x/0.1.14.md +20 -0
- package/changelog/0.1.x/0.1.15.md +24 -0
- package/changelog/0.1.x/0.1.16.md +17 -0
- package/changelog/0.1.x/0.1.17.md +14 -0
- package/changelog/0.1.x/0.1.18.md +18 -0
- package/changelog/0.1.x/0.1.19.md +19 -0
- package/changelog/0.1.x/0.1.2.md +25 -0
- package/changelog/0.1.x/0.1.20.md +21 -0
- package/changelog/0.1.x/0.1.21.md +17 -0
- package/changelog/0.1.x/0.1.22.md +28 -0
- package/changelog/0.1.x/0.1.23.md +23 -0
- package/changelog/0.1.x/0.1.24.md +17 -0
- package/changelog/0.1.x/0.1.25.md +16 -0
- package/changelog/0.1.x/0.1.26.md +22 -0
- package/changelog/0.1.x/0.1.27.md +30 -0
- package/changelog/0.1.x/0.1.28.md +16 -0
- package/changelog/0.1.x/0.1.29.md +19 -0
- package/changelog/0.1.x/0.1.3.md +22 -0
- package/changelog/0.1.x/0.1.4.md +17 -0
- package/changelog/0.1.x/0.1.5.md +25 -0
- package/changelog/0.1.x/0.1.6.md +26 -0
- package/changelog/0.1.x/0.1.7.md +29 -0
- package/changelog/0.1.x/0.1.8.md +33 -0
- package/changelog/0.1.x/0.1.9.md +19 -0
- package/changelog/0.2.x/0.2.0.md +32 -0
- package/changelog/0.2.x/0.2.1.md +12 -0
- package/changelog/0.2.x/0.2.10.md +38 -0
- package/changelog/0.2.x/0.2.11.md +29 -0
- package/changelog/0.2.x/0.2.12.md +31 -0
- package/changelog/0.2.x/0.2.2.md +19 -0
- package/changelog/0.2.x/0.2.3.md +15 -0
- package/changelog/0.2.x/0.2.4.md +24 -0
- package/changelog/0.2.x/0.2.5.md +27 -0
- package/changelog/0.2.x/0.2.6.md +23 -0
- package/changelog/0.2.x/0.2.7.md +23 -0
- package/changelog/0.2.x/0.2.8.md +12 -0
- package/changelog/0.2.x/0.2.9.md +25 -0
- package/changelog/0.3.x/0.3.0.md +45 -0
- package/changelog/0.3.x/0.3.1.md +16 -0
- package/changelog/0.3.x/0.3.2.md +24 -0
- package/changelog/0.3.x/0.3.3.md +31 -0
- package/changelog/0.3.x/0.3.4.md +31 -0
- package/changelog/0.3.x/0.3.5.md +32 -0
- package/changelog/0.3.x/0.3.6.md +48 -0
- package/changelog/0.3.x/0.3.7.md +23 -0
- package/changelog/0.3.x/0.3.8.md +21 -0
- package/changelog/0.4.x/0.4.0.md +38 -0
- package/changelog/0.4.x/0.4.1.md +31 -0
- package/changelog/0.5.x/0.5.0.md +29 -0
- package/changelog/0.5.x/0.5.1.md +18 -0
- package/changelog/0.5.x/0.5.2.md +38 -0
- package/changelog/0.5.x/0.5.3.md +26 -0
- package/changelog/0.5.x/0.5.4.md +29 -0
- package/changelog/0.6.x/0.6.0.md +39 -0
- package/changelog/unreleased.md +40 -0
- package/dist/cli/init.js +1 -0
- package/dist/cli/init.js.map +1 -1
- package/dist/core/app.d.ts +13 -3
- package/dist/core/app.d.ts.map +1 -1
- package/dist/core/app.js +20 -13
- package/dist/core/app.js.map +1 -1
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/serverManifest.d.ts +237 -0
- package/dist/core/serverManifest.d.ts.map +1 -0
- package/dist/core/serverManifest.js +310 -0
- package/dist/core/serverManifest.js.map +1 -0
- package/dist/core/worker.d.ts.map +1 -1
- package/dist/core/worker.js +2 -2
- package/dist/core/worker.js.map +1 -1
- package/dist/linter/rules/landing-rules.d.ts +15 -0
- package/dist/linter/rules/landing-rules.d.ts.map +1 -0
- package/dist/linter/rules/landing-rules.js +125 -0
- package/dist/linter/rules/landing-rules.js.map +1 -0
- package/dist/linter/types.d.ts +5 -2
- package/dist/linter/types.d.ts.map +1 -1
- package/dist/linter/validate.d.ts.map +1 -1
- package/dist/linter/validate.js +5 -0
- package/dist/linter/validate.js.map +1 -1
- package/dist/mcp-server/transports/http/httpTransport.d.ts +4 -3
- package/dist/mcp-server/transports/http/httpTransport.d.ts.map +1 -1
- package/dist/mcp-server/transports/http/httpTransport.js +47 -26
- package/dist/mcp-server/transports/http/httpTransport.js.map +1 -1
- package/dist/mcp-server/transports/http/httpTypes.d.ts +0 -12
- package/dist/mcp-server/transports/http/httpTypes.d.ts.map +1 -1
- package/dist/mcp-server/transports/http/landing-page.d.ts +48 -0
- package/dist/mcp-server/transports/http/landing-page.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/landing-page.js +912 -0
- package/dist/mcp-server/transports/http/landing-page.js.map +1 -0
- package/dist/mcp-server/transports/http/serverCard.d.ts +67 -0
- package/dist/mcp-server/transports/http/serverCard.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/serverCard.js +91 -0
- package/dist/mcp-server/transports/http/serverCard.js.map +1 -0
- package/dist/mcp-server/transports/manager.d.ts +3 -3
- package/dist/mcp-server/transports/manager.d.ts.map +1 -1
- package/dist/mcp-server/transports/manager.js +4 -4
- package/dist/mcp-server/transports/manager.js.map +1 -1
- package/dist/utils/formatting/html.d.ts +76 -0
- package/dist/utils/formatting/html.d.ts.map +1 -0
- package/dist/utils/formatting/html.js +111 -0
- package/dist/utils/formatting/html.js.map +1 -0
- package/dist/utils/formatting/index.d.ts +1 -0
- package/dist/utils/formatting/index.d.ts.map +1 -1
- package/dist/utils/formatting/index.js +1 -0
- package/dist/utils/formatting/index.js.map +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +5 -1
- package/scripts/build-changelog.ts +222 -0
- package/scripts/devcheck.ts +16 -1
- package/scripts/tree.ts +3 -0
- package/skills/add-app-tool/SKILL.md +2 -4
- package/skills/add-prompt/SKILL.md +2 -4
- package/skills/add-resource/SKILL.md +2 -4
- package/skills/add-service/SKILL.md +2 -4
- package/skills/add-tool/SKILL.md +6 -5
- package/skills/api-context/SKILL.md +2 -2
- package/skills/api-services/SKILL.md +1 -1
- package/skills/api-services/references/graph.md +1 -1
- package/skills/api-utils/SKILL.md +1 -1
- package/skills/api-utils/references/parsing.md +1 -1
- package/skills/api-utils/references/security.md +1 -1
- package/skills/design-mcp-server/SKILL.md +2 -2
- package/skills/maintenance/SKILL.md +12 -11
- package/skills/polish-docs-meta/SKILL.md +24 -9
- package/skills/release/SKILL.md +21 -7
- package/skills/setup/SKILL.md +4 -8
- package/templates/AGENTS.md +23 -1
- package/templates/CLAUDE.md +23 -1
- package/templates/changelog/unreleased.md +40 -0
- package/templates/package.json +3 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Generate CHANGELOG.md as a navigation index from per-version files.
|
|
4
|
+
*
|
|
5
|
+
* Source of truth: `changelog/<major.minor>.x/<version>.md` — each file opens with
|
|
6
|
+
* YAML frontmatter declaring:
|
|
7
|
+
* • summary (required) — ≤250-char headline, no markdown, one line
|
|
8
|
+
* • breaking (optional) — `true` flags releases with breaking changes
|
|
9
|
+
*
|
|
10
|
+
* The rollup is a thin **index**, not a copy of bodies — each entry is just a
|
|
11
|
+
* clickable header + one-line summary. Full content stays in the per-version files.
|
|
12
|
+
*
|
|
13
|
+
* Rendered rollup entry:
|
|
14
|
+
* ## [X.Y.Z](changelog/N.N.x/X.Y.Z.md) — YYYY-MM-DD · ⚠️ Breaking
|
|
15
|
+
*
|
|
16
|
+
* <summary>
|
|
17
|
+
*
|
|
18
|
+
* (The `· ⚠️ Breaking` badge only appears when `breaking: true`.)
|
|
19
|
+
*
|
|
20
|
+
* Modes:
|
|
21
|
+
* • default → regenerate CHANGELOG.md
|
|
22
|
+
* • --check → exit 1 if CHANGELOG.md differs from what would be generated
|
|
23
|
+
*
|
|
24
|
+
* Missing `summary`: warning (not failure) — the entry renders header-only.
|
|
25
|
+
* Summary > 250 chars, or malformed `breaking`: hard error.
|
|
26
|
+
*
|
|
27
|
+
* @module scripts/build-changelog
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
import { readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
31
|
+
import { resolve } from 'node:path';
|
|
32
|
+
import process from 'node:process';
|
|
33
|
+
|
|
34
|
+
const CHANGELOG_DIR = resolve('changelog');
|
|
35
|
+
const CHANGELOG_PATH = resolve('CHANGELOG.md');
|
|
36
|
+
const EXCLUDED_FILES = new Set(['unreleased.md', 'README.md']);
|
|
37
|
+
const SERIES_PATTERN = /^\d+\.\d+\.x$/;
|
|
38
|
+
const SUMMARY_MAX_LENGTH = 250;
|
|
39
|
+
|
|
40
|
+
const HEADER = `# Changelog
|
|
41
|
+
|
|
42
|
+
All notable changes to this project. Each entry links to its full per-version file in [changelog/](changelog/).
|
|
43
|
+
`;
|
|
44
|
+
|
|
45
|
+
interface VersionEntry {
|
|
46
|
+
path: string;
|
|
47
|
+
series: string;
|
|
48
|
+
version: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
interface Frontmatter {
|
|
52
|
+
breaking: boolean;
|
|
53
|
+
summary: string | null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Semver descending compare. Final releases rank above their prereleases
|
|
58
|
+
* (`0.6.0 > 0.6.0-rc.1 > 0.6.0-beta.1`). Prereleases compared lexicographically.
|
|
59
|
+
*/
|
|
60
|
+
function compareSemverDesc(a: string, b: string): number {
|
|
61
|
+
const parse = (v: string): [number[], string | null] => {
|
|
62
|
+
const [base, pre = null] = v.split('-', 2) as [string, string | undefined];
|
|
63
|
+
return [base.split('.').map(Number), pre ?? null];
|
|
64
|
+
};
|
|
65
|
+
const [aParts, aPre] = parse(a);
|
|
66
|
+
const [bParts, bPre] = parse(b);
|
|
67
|
+
for (let i = 0; i < 3; i++) {
|
|
68
|
+
const diff = (bParts[i] ?? 0) - (aParts[i] ?? 0);
|
|
69
|
+
if (diff !== 0) return diff;
|
|
70
|
+
}
|
|
71
|
+
if (aPre === bPre) return 0;
|
|
72
|
+
if (aPre === null) return -1;
|
|
73
|
+
if (bPre === null) return 1;
|
|
74
|
+
return bPre.localeCompare(aPre);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Parse minimal YAML frontmatter. Only recognizes `summary` and `breaking` —
|
|
79
|
+
* other keys are ignored, so the format stays extensible without touching the
|
|
80
|
+
* parser. Throws on malformed values we actually care about.
|
|
81
|
+
*/
|
|
82
|
+
function parseFrontmatter(content: string, fileLabel: string): Frontmatter {
|
|
83
|
+
const match = content.match(/^---\n([\s\S]*?)\n---\n?/);
|
|
84
|
+
if (!match) return { summary: null, breaking: false };
|
|
85
|
+
|
|
86
|
+
const block = match[1] as string;
|
|
87
|
+
|
|
88
|
+
// summary: quoted or bare, single line
|
|
89
|
+
let summary: string | null = null;
|
|
90
|
+
const summaryMatch = block.match(/^summary:\s*(.*)$/m);
|
|
91
|
+
if (summaryMatch) {
|
|
92
|
+
let raw = (summaryMatch[1] ?? '').trim();
|
|
93
|
+
if ((raw.startsWith('"') && raw.endsWith('"')) || (raw.startsWith("'") && raw.endsWith("'"))) {
|
|
94
|
+
raw = raw.slice(1, -1);
|
|
95
|
+
}
|
|
96
|
+
summary = raw.length > 0 ? raw : null;
|
|
97
|
+
}
|
|
98
|
+
if (summary !== null && summary.length > SUMMARY_MAX_LENGTH) {
|
|
99
|
+
throw new Error(
|
|
100
|
+
`${fileLabel}: summary is ${summary.length} chars, exceeds cap of ${SUMMARY_MAX_LENGTH}. Keep it tight — headline, not paragraph.`,
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// breaking: must be literal true/false if present
|
|
105
|
+
let breaking = false;
|
|
106
|
+
const breakingMatch = block.match(/^breaking:\s*(\S+)\s*$/m);
|
|
107
|
+
if (breakingMatch) {
|
|
108
|
+
const val = breakingMatch[1];
|
|
109
|
+
if (val !== 'true' && val !== 'false') {
|
|
110
|
+
throw new Error(`${fileLabel}: breaking must be 'true' or 'false', got '${val}'.`);
|
|
111
|
+
}
|
|
112
|
+
breaking = val === 'true';
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return { summary, breaking };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Extract the release date from the H1 heading. */
|
|
119
|
+
function extractDate(body: string, fileLabel: string): string {
|
|
120
|
+
const match = body.match(/^#\s+\S+\s+[—–-]\s+(\d{4}-\d{2}-\d{2})/m);
|
|
121
|
+
if (!match) {
|
|
122
|
+
throw new Error(
|
|
123
|
+
`${fileLabel}: H1 heading missing or malformed. Expected '# <version> — YYYY-MM-DD'.`,
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
return match[1] as string;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function renderEntry(entry: VersionEntry, fm: Frontmatter, date: string): string {
|
|
130
|
+
const link = `changelog/${entry.series}/${entry.version}.md`;
|
|
131
|
+
const breakingBadge = fm.breaking ? ' · ⚠️ Breaking' : '';
|
|
132
|
+
const header = `## [${entry.version}](${link}) — ${date}${breakingBadge}`;
|
|
133
|
+
if (fm.summary) {
|
|
134
|
+
return `${header}\n\n${fm.summary}\n`;
|
|
135
|
+
}
|
|
136
|
+
return `${header}\n`;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function collectVersionFiles(): VersionEntry[] {
|
|
140
|
+
const entries: VersionEntry[] = [];
|
|
141
|
+
for (const entry of readdirSync(CHANGELOG_DIR, { withFileTypes: true })) {
|
|
142
|
+
if (!entry.isDirectory() || !SERIES_PATTERN.test(entry.name)) continue;
|
|
143
|
+
const seriesDir = resolve(CHANGELOG_DIR, entry.name);
|
|
144
|
+
for (const file of readdirSync(seriesDir)) {
|
|
145
|
+
if (!file.endsWith('.md') || EXCLUDED_FILES.has(file)) continue;
|
|
146
|
+
entries.push({
|
|
147
|
+
version: file.replace(/\.md$/, ''),
|
|
148
|
+
series: entry.name,
|
|
149
|
+
path: resolve(seriesDir, file),
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return entries.sort((a, b) => compareSemverDesc(a.version, b.version));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function buildRollup(): { content: string; missingSummary: string[] } {
|
|
157
|
+
const entries = collectVersionFiles();
|
|
158
|
+
|
|
159
|
+
if (entries.length === 0) {
|
|
160
|
+
throw new Error(`No per-version changelog files found under ${CHANGELOG_DIR}/<major.minor>.x/`);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const missingSummary: string[] = [];
|
|
164
|
+
const sections: string[] = [];
|
|
165
|
+
|
|
166
|
+
for (const entry of entries) {
|
|
167
|
+
const fileLabel = `changelog/${entry.series}/${entry.version}.md`;
|
|
168
|
+
const content = readFileSync(entry.path, 'utf-8');
|
|
169
|
+
const fm = parseFrontmatter(content, fileLabel);
|
|
170
|
+
const date = extractDate(content, fileLabel);
|
|
171
|
+
|
|
172
|
+
if (!fm.summary) {
|
|
173
|
+
missingSummary.push(fileLabel);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
sections.push(renderEntry(entry, fm, date));
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return {
|
|
180
|
+
content: `${HEADER}\n${sections.join('\n')}`,
|
|
181
|
+
missingSummary,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function reportMissingSummaries(missing: string[]): void {
|
|
186
|
+
if (missing.length === 0) return;
|
|
187
|
+
const shown = missing.slice(0, 10);
|
|
188
|
+
const extra = missing.length - shown.length;
|
|
189
|
+
console.warn(`\nWarning: ${missing.length} file(s) missing 'summary' frontmatter:`);
|
|
190
|
+
for (const file of shown) console.warn(` - ${file}`);
|
|
191
|
+
if (extra > 0) console.warn(` ... and ${extra} more`);
|
|
192
|
+
console.warn(`\nBackfill these — see CLAUDE.md § Changelog for the frontmatter format.`);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function main(): void {
|
|
196
|
+
const checkOnly = process.argv.includes('--check');
|
|
197
|
+
const { content: generated, missingSummary } = buildRollup();
|
|
198
|
+
|
|
199
|
+
if (checkOnly) {
|
|
200
|
+
let existing = '';
|
|
201
|
+
try {
|
|
202
|
+
existing = readFileSync(CHANGELOG_PATH, 'utf-8');
|
|
203
|
+
} catch {
|
|
204
|
+
// missing file counts as drift
|
|
205
|
+
}
|
|
206
|
+
if (existing === generated) {
|
|
207
|
+
console.log('CHANGELOG.md is in sync with changelog/ directory.');
|
|
208
|
+
reportMissingSummaries(missingSummary);
|
|
209
|
+
process.exit(0);
|
|
210
|
+
}
|
|
211
|
+
console.error('CHANGELOG.md is out of sync with changelog/ directory.');
|
|
212
|
+
console.error('Fix: run `bun run changelog:build` to regenerate.');
|
|
213
|
+
reportMissingSummaries(missingSummary);
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
writeFileSync(CHANGELOG_PATH, generated);
|
|
218
|
+
console.log(`Wrote ${CHANGELOG_PATH} (${generated.split('\n').length - 1} lines).`);
|
|
219
|
+
reportMissingSummaries(missingSummary);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
main();
|
package/scripts/devcheck.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
2
|
import { type ChildProcess, spawn, spawnSync } from 'node:child_process';
|
|
3
|
-
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
4
4
|
import * as path from 'node:path';
|
|
5
5
|
import process from 'node:process';
|
|
6
6
|
import { fileURLToPath } from 'node:url';
|
|
@@ -421,6 +421,21 @@ const ALL_CHECKS: Check[] = [
|
|
|
421
421
|
tip: (c) =>
|
|
422
422
|
`Edit both files together, or run ${c.bold('cp CLAUDE.md AGENTS.md')} (or reverse) to resync.`,
|
|
423
423
|
},
|
|
424
|
+
{
|
|
425
|
+
name: 'Changelog Sync',
|
|
426
|
+
flag: '--no-changelog-sync',
|
|
427
|
+
canFix: false,
|
|
428
|
+
// --check exits non-zero if CHANGELOG.md drifts from changelog/*.md.
|
|
429
|
+
// Skipped cleanly when neither CHANGELOG.md nor changelog/ exists (non-mcp-ts-core projects).
|
|
430
|
+
getCommand: () => {
|
|
431
|
+
const hasChangelog = existsSync(path.join(ROOT_DIR, 'changelog'));
|
|
432
|
+
const hasRollup = existsSync(path.join(ROOT_DIR, 'CHANGELOG.md'));
|
|
433
|
+
if (!hasChangelog && !hasRollup) return null;
|
|
434
|
+
return ['bun', 'run', 'scripts/build-changelog.ts', '--check'];
|
|
435
|
+
},
|
|
436
|
+
tip: (c) =>
|
|
437
|
+
`Edit the per-version file in ${c.bold('changelog/')} and run ${c.bold('bun run changelog:build')} to regenerate ${c.bold('CHANGELOG.md')}.`,
|
|
438
|
+
},
|
|
424
439
|
{
|
|
425
440
|
name: 'Biome',
|
|
426
441
|
flag: '--no-lint',
|
package/scripts/tree.ts
CHANGED
|
@@ -39,6 +39,9 @@ const DEFAULT_IGNORE_PATTERNS: string[] = [
|
|
|
39
39
|
'coverage',
|
|
40
40
|
'logs',
|
|
41
41
|
'.husky/_',
|
|
42
|
+
// Directory-based changelog — keep series dirs visible (0.1.x/, 0.5.x/) for structural
|
|
43
|
+
// orientation, but collapse out the per-version files. Top-level unreleased.md stays.
|
|
44
|
+
'changelog/*/*.md',
|
|
42
45
|
];
|
|
43
46
|
|
|
44
47
|
interface ParsedArgs {
|
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
Scaffold an MCP App tool + UI resource pair. Use when the user asks to add a tool with interactive UI, create an MCP App, or build a visual/interactive tool.
|
|
5
5
|
metadata:
|
|
6
6
|
author: cyanheads
|
|
7
|
-
version: "1.
|
|
7
|
+
version: "1.3"
|
|
8
8
|
audience: external
|
|
9
9
|
type: reference
|
|
10
10
|
---
|
|
@@ -18,9 +18,7 @@ MCP Apps extend the standard tool pattern with an interactive HTML UI rendered i
|
|
|
18
18
|
|
|
19
19
|
Both builders are exported from `@cyanheads/mcp-ts-core`. They handle `_meta.ui.resourceUri`, the compat key (`ui/resourceUri`), and the correct MIME type (`text/html;profile=mcp-app`) automatically.
|
|
20
20
|
|
|
21
|
-
For the full API, Context interface, and error codes, read
|
|
22
|
-
|
|
23
|
-
node_modules/@cyanheads/mcp-ts-core/CLAUDE.md
|
|
21
|
+
For the full API, Context interface, and error codes, read `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md`.
|
|
24
22
|
|
|
25
23
|
## Steps
|
|
26
24
|
|
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
Scaffold a new MCP prompt template. Use when the user asks to add a prompt, create a reusable message template, or define a prompt for LLM interactions.
|
|
5
5
|
metadata:
|
|
6
6
|
author: cyanheads
|
|
7
|
-
version: "1.
|
|
7
|
+
version: "1.2"
|
|
8
8
|
audience: external
|
|
9
9
|
type: reference
|
|
10
10
|
---
|
|
@@ -15,9 +15,7 @@ Prompts use the `prompt()` builder from `@cyanheads/mcp-ts-core`. Each prompt li
|
|
|
15
15
|
|
|
16
16
|
Prompts are pure message templates — no `Context`, no auth, no side effects.
|
|
17
17
|
|
|
18
|
-
For the full `prompt()` API, read
|
|
19
|
-
|
|
20
|
-
node_modules/@cyanheads/mcp-ts-core/CLAUDE.md
|
|
18
|
+
For the full `prompt()` API, read `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md`.
|
|
21
19
|
|
|
22
20
|
## Steps
|
|
23
21
|
|
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
Scaffold a new MCP resource definition. Use when the user asks to add a resource, expose data via URI, or create a readable endpoint.
|
|
5
5
|
metadata:
|
|
6
6
|
author: cyanheads
|
|
7
|
-
version: "1.
|
|
7
|
+
version: "1.3"
|
|
8
8
|
audience: external
|
|
9
9
|
type: reference
|
|
10
10
|
---
|
|
@@ -15,9 +15,7 @@ Resources use the `resource()` builder from `@cyanheads/mcp-ts-core`. Each resou
|
|
|
15
15
|
|
|
16
16
|
**Tool coverage.** Not all MCP clients expose resources — many are tool-only (Claude Code, Cursor, most chat UIs). Before adding a resource, verify the same data is reachable via the tool surface — either through a dedicated tool, included in another tool's output, or bundled into a broader tool. A resource whose data has no tool path is invisible to a large share of agents.
|
|
17
17
|
|
|
18
|
-
For the full `resource()` API, pagination utilities, and `Context` interface, read
|
|
19
|
-
|
|
20
|
-
node_modules/@cyanheads/mcp-ts-core/CLAUDE.md
|
|
18
|
+
For the full `resource()` API, pagination utilities, and `Context` interface, read `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md`.
|
|
21
19
|
|
|
22
20
|
## Steps
|
|
23
21
|
|
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
Scaffold a new service integration. Use when the user asks to add a service, integrate an external API, or create a reusable domain module with its own initialization and state.
|
|
5
5
|
metadata:
|
|
6
6
|
author: cyanheads
|
|
7
|
-
version: "1.
|
|
7
|
+
version: "1.3"
|
|
8
8
|
audience: external
|
|
9
9
|
type: reference
|
|
10
10
|
---
|
|
@@ -15,9 +15,7 @@ Services use the init/accessor pattern: initialized once in `createApp`'s `setup
|
|
|
15
15
|
|
|
16
16
|
Service methods receive `Context` for correlated logging (`ctx.log`) and tenant-scoped storage (`ctx.state`). Convention: `ctx.elicit` and `ctx.sample` should only be called from tool handlers, not from services.
|
|
17
17
|
|
|
18
|
-
For the full service pattern, `CoreServices`, and `Context` interface, read
|
|
19
|
-
|
|
20
|
-
node_modules/@cyanheads/mcp-ts-core/CLAUDE.md
|
|
18
|
+
For the full service pattern, `CoreServices`, and `Context` interface, read `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md`.
|
|
21
19
|
|
|
22
20
|
## Steps
|
|
23
21
|
|
package/skills/add-tool/SKILL.md
CHANGED
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
Scaffold a new MCP tool definition. Use when the user asks to add a tool, create a new tool, or implement a new capability for the server.
|
|
5
5
|
metadata:
|
|
6
6
|
author: cyanheads
|
|
7
|
-
version: "1.
|
|
7
|
+
version: "1.7"
|
|
8
8
|
audience: external
|
|
9
9
|
type: reference
|
|
10
10
|
---
|
|
@@ -13,9 +13,7 @@ metadata:
|
|
|
13
13
|
|
|
14
14
|
Tools use the `tool()` builder from `@cyanheads/mcp-ts-core`. Each tool lives in `src/mcp-server/tools/definitions/` with a `.tool.ts` suffix and is registered into `createApp()` in `src/index.ts`. Some larger repos later add `definitions/index.ts` barrels; match the pattern already used by the project you're editing.
|
|
15
15
|
|
|
16
|
-
For the full `tool()` API, `Context` interface, and error codes, read
|
|
17
|
-
|
|
18
|
-
node_modules/@cyanheads/mcp-ts-core/CLAUDE.md
|
|
16
|
+
For the full `tool()` API, `Context` interface, and error codes, read `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md`.
|
|
19
17
|
|
|
20
18
|
## Steps
|
|
21
19
|
|
|
@@ -164,6 +162,8 @@ async handler(input, ctx) {
|
|
|
164
162
|
},
|
|
165
163
|
```
|
|
166
164
|
|
|
165
|
+
**Note on the `try/catch`:** this is the deliberate exception to the "logic throws, framework catches" rule. Per-item isolation is the whole point of partial-success batch tools — one failed item must not abort the batch, and the framework's partial-success telemetry (below) depends on seeing a populated `failed` array. Don't remove it to conform to the handler-level rule.
|
|
166
|
+
|
|
167
167
|
Single-item tools don't need this — they either succeed or throw. The partial success question only arises with array inputs.
|
|
168
168
|
|
|
169
169
|
**Telemetry:** The framework automatically detects this pattern — when a handler result contains a non-empty `failed` array, the span gets `mcp.tool.partial_success`, `mcp.tool.batch.succeeded_count`, and `mcp.tool.batch.failed_count` attributes. No manual instrumentation needed.
|
|
@@ -242,7 +242,8 @@ import { serviceUnavailable } from '@cyanheads/mcp-ts-core/errors';
|
|
|
242
242
|
throw serviceUnavailable(`arXiv API returned HTTP ${status}. Retry in a few seconds.`);
|
|
243
243
|
|
|
244
244
|
// Structured hint for programmatic recovery
|
|
245
|
-
|
|
245
|
+
import { invalidParams } from '@cyanheads/mcp-ts-core/errors';
|
|
246
|
+
throw invalidParams(
|
|
246
247
|
`Date range exceeds 90-day API limit. Narrow the range or split into multiple queries.`,
|
|
247
248
|
{ maxDays: 90, requestedDays: daysBetween },
|
|
248
249
|
);
|
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
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.
|
|
5
5
|
metadata:
|
|
6
6
|
author: cyanheads
|
|
7
|
-
version: "1.
|
|
7
|
+
version: "1.1"
|
|
8
8
|
audience: external
|
|
9
9
|
type: reference
|
|
10
10
|
---
|
|
@@ -181,7 +181,7 @@ if (ctx.elicit) {
|
|
|
181
181
|
await produceOutput(result.content?.format as string, result.content?.includeHeaders as boolean);
|
|
182
182
|
} else {
|
|
183
183
|
// 'decline' or 'cancel' — user opted out
|
|
184
|
-
throw
|
|
184
|
+
throw invalidRequest('User declined input');
|
|
185
185
|
}
|
|
186
186
|
}
|
|
187
187
|
```
|
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
API reference for built-in service providers (LLM, Speech, Graph). Use when looking up service interfaces, provider capabilities, or integration patterns.
|
|
5
5
|
metadata:
|
|
6
6
|
author: cyanheads
|
|
7
|
-
version: "1.
|
|
7
|
+
version: "1.3"
|
|
8
8
|
audience: external
|
|
9
9
|
type: reference
|
|
10
10
|
---
|
|
@@ -111,7 +111,7 @@ const path = await graphService.shortestPath('user:alice', 'user:charlie', conte
|
|
|
111
111
|
algorithm: 'bfs',
|
|
112
112
|
maxLength: 4,
|
|
113
113
|
});
|
|
114
|
-
if (path)
|
|
114
|
+
if (path) context.log.info(`${path.vertices.length} hops`);
|
|
115
115
|
|
|
116
116
|
// Check reachability
|
|
117
117
|
const connected = await graphService.pathExists('user:alice', 'user:charlie', context, 3);
|
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
API reference for all utilities exported from `@cyanheads/mcp-ts-core/utils`. Use when looking up utility method signatures, options, peer dependencies, or usage patterns.
|
|
5
5
|
metadata:
|
|
6
6
|
author: cyanheads
|
|
7
|
-
version: "2.
|
|
7
|
+
version: "2.1"
|
|
8
8
|
audience: external
|
|
9
9
|
type: reference
|
|
10
10
|
---
|
|
@@ -249,7 +249,7 @@ Matches `--- ... ---` at the very start of the document. An empty `---\n---` blo
|
|
|
249
249
|
```ts
|
|
250
250
|
const { frontmatter, content, hasFrontmatter } = await frontmatterParser.parse<SkillMeta>(markdown);
|
|
251
251
|
if (hasFrontmatter) {
|
|
252
|
-
|
|
252
|
+
logger.info({ name: frontmatter.name, version: frontmatter.version }, 'parsed frontmatter');
|
|
253
253
|
}
|
|
254
254
|
```
|
|
255
255
|
|
|
@@ -147,7 +147,7 @@ rateLimiter.check(`api:${ctx.tenantId}`, ctx);
|
|
|
147
147
|
// Check status without consuming a request
|
|
148
148
|
const status = rateLimiter.getStatus('api:tenant-123');
|
|
149
149
|
if (status) {
|
|
150
|
-
|
|
150
|
+
logger.info(`${status.remaining} requests left, resets at ${new Date(status.resetTime)}`);
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
// Runtime reconfiguration
|
|
@@ -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.5"
|
|
8
8
|
audience: external
|
|
9
9
|
type: workflow
|
|
10
10
|
---
|
|
@@ -271,7 +271,7 @@ throw new Error('Not found');
|
|
|
271
271
|
"No session working directory set. Please specify a 'path' or use 'git_set_working_dir' first."
|
|
272
272
|
|
|
273
273
|
// Good — structured hint in error data
|
|
274
|
-
throw
|
|
274
|
+
throw forbidden(
|
|
275
275
|
"Cannot perform 'reset --hard' on protected branch 'main' without explicit confirmation.",
|
|
276
276
|
{ branch: 'main', operation: 'reset --hard', hint: 'Set the confirmed parameter to true to proceed.' },
|
|
277
277
|
);
|
|
@@ -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: "1.
|
|
7
|
+
version: "1.4"
|
|
8
8
|
audience: external
|
|
9
9
|
type: workflow
|
|
10
10
|
---
|
|
@@ -50,13 +50,18 @@ Do not redo this investigation inline — the `changelog` skill handles tag-form
|
|
|
50
50
|
|
|
51
51
|
### 4. Framework review (`@cyanheads/mcp-ts-core`)
|
|
52
52
|
|
|
53
|
-
If `@cyanheads/mcp-ts-core` was updated, do a deeper pass beyond what the `changelog` skill covers. Read
|
|
53
|
+
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.
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
Example — `0.5.2 → 0.5.4` means reading two new version files:
|
|
56
|
+
|
|
57
|
+
- `node_modules/@cyanheads/mcp-ts-core/changelog/0.5.x/0.5.3.md`
|
|
58
|
+
- `node_modules/@cyanheads/mcp-ts-core/changelog/0.5.x/0.5.4.md`
|
|
59
|
+
|
|
60
|
+
Cross-series updates span multiple directories — e.g., `0.4.1 → 0.5.2` reads `0.5.x/0.5.0.md`, `0.5.x/0.5.1.md`, `0.5.x/0.5.2.md`. Enumerate the series directories under `node_modules/@cyanheads/mcp-ts-core/changelog/` to find the relevant files.
|
|
58
61
|
|
|
59
|
-
|
|
62
|
+
If the per-version directory isn't present (pre-0.5.5 releases, or downstream package that hasn't adopted the convention), fall back to the monolithic rollup at `node_modules/@cyanheads/mcp-ts-core/CHANGELOG.md` and extract the relevant sections manually.
|
|
63
|
+
|
|
64
|
+
Scan specifically for:
|
|
60
65
|
|
|
61
66
|
| Area | Adoption Check |
|
|
62
67
|
|:-----|:---------------|
|
|
@@ -70,11 +75,7 @@ Extract entries between the old and new version. Scan specifically for:
|
|
|
70
75
|
|
|
71
76
|
Cross-reference each finding against the server's code. Collect adoption opportunities for Step 6.
|
|
72
77
|
|
|
73
|
-
**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
|
|
74
|
-
|
|
75
|
-
```bash
|
|
76
|
-
node_modules/@cyanheads/mcp-ts-core/templates/CLAUDE.md
|
|
77
|
-
```
|
|
78
|
+
**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`.
|
|
78
79
|
|
|
79
80
|
Skip the mechanical diff — consumer customizations create too much noise to filter. Instead, read end-to-end with fresh eyes, mentally comparing against the current `CLAUDE.md`. Look for: new conventions, updated skill references, expanded checklists, new callouts, clearer explanations, restructured sections. Present findings; let the user cherry-pick what to adopt. Never auto-merge — the consumer's file is theirs.
|
|
80
81
|
|
|
@@ -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: "1.
|
|
7
|
+
version: "1.5"
|
|
8
8
|
audience: external
|
|
9
9
|
type: workflow
|
|
10
10
|
---
|
|
@@ -118,22 +118,37 @@ frozenLockfile = false
|
|
|
118
118
|
bun = true
|
|
119
119
|
```
|
|
120
120
|
|
|
121
|
-
### 9.
|
|
121
|
+
### 9. Changelog
|
|
122
122
|
|
|
123
|
-
|
|
123
|
+
Directory-based, grouped by minor series using the `.x` semver-wildcard convention: per-version files live in `changelog/<major.minor>.x/<version>.md` (e.g. `changelog/0.1.x/0.1.0.md`), work-in-progress in `changelog/unreleased.md` at the top level, and `CHANGELOG.md` is a rollup artifact regenerated by `bun run changelog:build`. Devcheck's `Changelog Sync` step enforces that `CHANGELOG.md` stays in sync.
|
|
124
|
+
|
|
125
|
+
If `changelog/` doesn't exist, create the structure:
|
|
126
|
+
|
|
127
|
+
1. Make the `changelog/` directory
|
|
128
|
+
2. Create `changelog/unreleased.md` from the template (H1 `# Unreleased` + empty Added/Changed/Fixed sections)
|
|
129
|
+
3. If the server already has a shipped version (e.g. 0.1.0), create the series directory and initial entry: `changelog/0.1.x/0.1.0.md` with H1 `# 0.1.0 — YYYY-MM-DD`, concrete version and date
|
|
130
|
+
4. Run `bun run changelog:build` to generate `CHANGELOG.md`
|
|
131
|
+
|
|
132
|
+
Per-version file format:
|
|
124
133
|
|
|
125
134
|
```markdown
|
|
126
|
-
|
|
135
|
+
---
|
|
136
|
+
summary: One-line headline for the rollup index — ≤250 chars, no markdown
|
|
137
|
+
breaking: false
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
# 0.1.0 — YYYY-MM-DD
|
|
127
141
|
|
|
128
|
-
|
|
142
|
+
Optional narrative intro (1-3 sentences).
|
|
129
143
|
|
|
130
|
-
|
|
144
|
+
## Added
|
|
131
145
|
|
|
132
|
-
### Added
|
|
133
146
|
- [list tools, resources, prompts, key capabilities]
|
|
134
147
|
```
|
|
135
148
|
|
|
136
|
-
|
|
149
|
+
**Frontmatter:** `summary` is required (powers the CHANGELOG.md index), `breaking` is optional and defaults to `false` (set `true` for releases requiring consumer code changes).
|
|
150
|
+
|
|
151
|
+
Never hand-edit `CHANGELOG.md` — it's a build artifact. Never use `[Unreleased]` as a version header in a released file.
|
|
137
152
|
|
|
138
153
|
### 10. `LICENSE`
|
|
139
154
|
|
|
@@ -181,7 +196,7 @@ Both must pass clean.
|
|
|
181
196
|
- [ ] `server.json` matches official MCP schema, versions synced, env vars current
|
|
182
197
|
- [ ] GitHub repo description matches `package.json` description; topics ↔ keywords in sync
|
|
183
198
|
- [ ] `bunfig.toml` present
|
|
184
|
-
- [ ] `CHANGELOG.md`
|
|
199
|
+
- [ ] `changelog/` directory present with per-version files; `CHANGELOG.md` rollup regenerated and in sync
|
|
185
200
|
- [ ] `LICENSE` file present
|
|
186
201
|
- [ ] `Dockerfile` OCI labels and runtime config accurate (if present)
|
|
187
202
|
- [ ] `docs/tree.md` regenerated
|
package/skills/release/SKILL.md
CHANGED
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
Verify release readiness and publish. The git wrapup protocol handles version bumps, changelog, README, commits, and tagging during the coding session. This skill verifies nothing was missed, runs final checks, and presents the irreversible publish commands.
|
|
5
5
|
metadata:
|
|
6
6
|
author: cyanheads
|
|
7
|
-
version: "1.
|
|
7
|
+
version: "1.4"
|
|
8
8
|
audience: internal
|
|
9
9
|
type: workflow
|
|
10
10
|
---
|
|
@@ -34,13 +34,27 @@ The wrapup protocol bumps versions, but sometimes a file gets missed. **Search f
|
|
|
34
34
|
|
|
35
35
|
Fix any mismatches. A grep for the **old** version is the fastest way to find stragglers.
|
|
36
36
|
|
|
37
|
-
### 3.
|
|
37
|
+
### 3. Release-ize the Changelog Entry
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
The changelog is directory-based, grouped by minor series using the `.x` semver-wildcard convention: per-version files live at `changelog/<major.minor>.x/<version>.md` (e.g. `changelog/0.5.x/0.5.4.md`), work-in-progress entries go in `changelog/unreleased.md` at the top level, and `CHANGELOG.md` is an auto-generated rollup (`bun run changelog:build`).
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
If the wrapup already converted `unreleased.md` to the version file, verify it. Otherwise release-ize it now:
|
|
42
|
+
|
|
43
|
+
1. Determine the series: `0.5.5` → `0.5.x/`. Create the directory if it doesn't exist: `mkdir -p changelog/<series>`
|
|
44
|
+
2. `git mv changelog/unreleased.md changelog/<series>/<version>.md`
|
|
45
|
+
3. Update the H1: `# Unreleased` → `# <version> — <date>` (em-dash, ISO date)
|
|
46
|
+
4. **Fill in the frontmatter** at the top of the file:
|
|
47
|
+
- `summary:` — one-line headline, ≤250 chars, no markdown. Write it like a GitHub Release title. Required.
|
|
48
|
+
- `breaking:` — set to `true` if this release requires consumer code changes (API removal, signature change, config rename). Defaults to `false`. Renders `· ⚠️ Breaking` in the rollup when true.
|
|
49
|
+
5. Verify content:
|
|
50
|
+
- Sections grouped correctly (Added / Changed / Fixed / Removed)
|
|
51
|
+
- Accurately reflects what shipped — cross-reference with `git log` since the last tag
|
|
52
|
+
- If this release absorbed pre-release versions (e.g., `0.6.0-beta.1`), confirm their sub-headers are preserved in the final file
|
|
53
|
+
- **Issue/PR references use full URLs**, not bare `#NN`. GitHub's auto-link only renders inside its own UI; these files are read from `node_modules` too, where bare `#NN` is dead text. Use `[#38](https://github.com/<owner>/<repo>/issues/38)` (or `/pull/NN` for PRs). Only link numbers verified via `gh issue view NN` / `gh pr view NN` — never speculate on future numbers, since GitHub will happily resolve `#42` to whatever unrelated item already owns 42 and pull its title into timeline previews.
|
|
54
|
+
6. Create a fresh empty `changelog/unreleased.md` from the template (frontmatter stub with empty `summary`, `breaking: false`)
|
|
55
|
+
7. Regenerate the rollup: `bun run changelog:build` — warnings about missing summaries are expected during the legacy-file backfill period but should not include this release
|
|
56
|
+
|
|
57
|
+
Never hand-edit `CHANGELOG.md` — it's a build artifact. Devcheck's `Changelog Sync` step will fail if it drifts.
|
|
44
58
|
|
|
45
59
|
### 4. Verify README.md
|
|
46
60
|
|
|
@@ -117,7 +131,7 @@ mcp-publisher publish
|
|
|
117
131
|
|
|
118
132
|
- [ ] Version consistent across all files (package.json, server.json ×3, CLAUDE.md, README.md, templates)
|
|
119
133
|
- [ ] No stale old-version references found in repo
|
|
120
|
-
- [ ]
|
|
134
|
+
- [ ] `changelog/<major.minor>.x/<version>.md` has concrete version and date; `changelog/unreleased.md` reset; `CHANGELOG.md` regenerated via `bun run changelog:build`
|
|
121
135
|
- [ ] README.md current — feature counts, badges, descriptions, examples
|
|
122
136
|
- [ ] Modified skill versions bumped in YAML frontmatter
|
|
123
137
|
- [ ] `docs/tree.md` current (if structure changed)
|