@cyanheads/mcp-ts-core 0.12.9 → 0.13.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/AGENTS.md +11 -10
- package/CLAUDE.md +11 -10
- package/README.md +1 -1
- package/biome.json +1 -1
- package/changelog/0.13.x/0.13.0.md +48 -0
- package/changelog/template.md +7 -24
- package/dist/cli/init.js +2 -2
- package/dist/cli/init.js.map +1 -1
- package/dist/config/envValue.d.ts +18 -0
- package/dist/config/envValue.d.ts.map +1 -0
- package/dist/config/envValue.js +35 -0
- package/dist/config/envValue.js.map +1 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +5 -7
- package/dist/config/index.js.map +1 -1
- package/dist/config/parseEnvConfig.d.ts +7 -0
- package/dist/config/parseEnvConfig.d.ts.map +1 -1
- package/dist/config/parseEnvConfig.js +9 -1
- package/dist/config/parseEnvConfig.js.map +1 -1
- package/dist/linter/validate.js +2 -2
- package/dist/linter/validate.js.map +1 -1
- package/framework-skills/README.md +40 -0
- package/{skills → framework-skills}/add-app-tool/SKILL.md +2 -2
- package/{skills → framework-skills}/add-resource/SKILL.md +2 -2
- package/{skills → framework-skills}/add-service/SKILL.md +2 -2
- package/{skills → framework-skills}/add-test/SKILL.md +2 -2
- package/{skills → framework-skills}/add-tool/SKILL.md +4 -4
- package/{skills → framework-skills}/api-config/SKILL.md +3 -1
- package/{skills → framework-skills}/api-context/SKILL.md +3 -3
- package/{skills → framework-skills}/api-linter/SKILL.md +4 -4
- package/{skills → framework-skills}/maintenance/SKILL.md +30 -21
- package/{skills → framework-skills}/orchestrations/SKILL.md +2 -2
- package/{skills → framework-skills}/orchestrations/workflows/field-test-fix.md +8 -8
- package/{skills → framework-skills}/orchestrations/workflows/fix-wrapup-release.md +5 -5
- package/{skills → framework-skills}/orchestrations/workflows/greenfield-build.md +11 -11
- package/{skills → framework-skills}/orchestrations/workflows/maintenance-release.md +12 -12
- package/{skills → framework-skills}/polish-docs-meta/SKILL.md +18 -10
- package/{skills → framework-skills}/polish-docs-meta/references/agent-protocol.md +1 -1
- package/{skills → framework-skills}/polish-docs-meta/references/readme.md +86 -70
- package/{skills → framework-skills}/release-pr-review/SKILL.md +2 -2
- package/{skills → framework-skills}/report-issue-framework/SKILL.md +25 -25
- package/{skills → framework-skills}/report-issue-local/SKILL.md +22 -24
- package/{skills → framework-skills}/setup/SKILL.md +10 -8
- package/package.json +8 -8
- package/scripts/check-framework-antipatterns.ts +1 -1
- package/scripts/check-skill-versions.ts +16 -9
- package/scripts/check-skills-sync.ts +64 -13
- package/scripts/clean-mcpb.ts +3 -3
- package/scripts/devcheck.ts +16 -13
- package/scripts/lint-packaging.ts +158 -24
- package/scripts/list-skills.ts +2 -2
- package/templates/.claude-plugin/plugin.json +5 -1
- package/templates/.env.example +1 -1
- package/templates/.github/CONTRIBUTING.md +4 -5
- package/templates/.github/ISSUE_TEMPLATE/bug_report.yml +5 -4
- package/templates/.github/ISSUE_TEMPLATE/config.yml +6 -1
- package/templates/.github/ISSUE_TEMPLATE/feature_request.yml +1 -2
- package/templates/AGENTS.md +15 -14
- package/templates/CLAUDE.md +15 -14
- package/templates/_.mcpbignore +1 -1
- package/templates/changelog/template.md +7 -24
- package/templates/package.json +3 -2
- package/templates/src/mcp-server/resources/definitions/echo-app-ui.app-resource.ts +1 -1
- package/skills/README.md +0 -38
- /package/{skills → framework-skills}/add-export/SKILL.md +0 -0
- /package/{skills → framework-skills}/add-prompt/SKILL.md +0 -0
- /package/{skills → framework-skills}/add-provider/SKILL.md +0 -0
- /package/{skills → framework-skills}/api-auth/SKILL.md +0 -0
- /package/{skills → framework-skills}/api-canvas/SKILL.md +0 -0
- /package/{skills → framework-skills}/api-errors/SKILL.md +0 -0
- /package/{skills → framework-skills}/api-mirror/SKILL.md +0 -0
- /package/{skills → framework-skills}/api-services/SKILL.md +0 -0
- /package/{skills → framework-skills}/api-services/references/graph.md +0 -0
- /package/{skills → framework-skills}/api-services/references/llm.md +0 -0
- /package/{skills → framework-skills}/api-services/references/speech.md +0 -0
- /package/{skills → framework-skills}/api-telemetry/SKILL.md +0 -0
- /package/{skills → framework-skills}/api-testing/SKILL.md +0 -0
- /package/{skills → framework-skills}/api-utils/SKILL.md +0 -0
- /package/{skills → framework-skills}/api-utils/references/formatting.md +0 -0
- /package/{skills → framework-skills}/api-utils/references/parsing.md +0 -0
- /package/{skills → framework-skills}/api-utils/references/security.md +0 -0
- /package/{skills → framework-skills}/api-workers/SKILL.md +0 -0
- /package/{skills → framework-skills}/code-simplifier/SKILL.md +0 -0
- /package/{skills → framework-skills}/design-mcp-server/SKILL.md +0 -0
- /package/{skills → framework-skills}/field-test/SKILL.md +0 -0
- /package/{skills → framework-skills}/git-wrapup/SKILL.md +0 -0
- /package/{skills → framework-skills}/polish-docs-meta/references/package-meta.md +0 -0
- /package/{skills → framework-skills}/polish-docs-meta/references/server-json.md +0 -0
- /package/{skills → framework-skills}/release-and-publish/SKILL.md +0 -0
- /package/{skills → framework-skills}/security-pass/SKILL.md +0 -0
- /package/{skills → framework-skills}/techniques/SKILL.md +0 -0
- /package/{skills → framework-skills}/techniques/references/outline-on-overflow.md +0 -0
- /package/{skills → framework-skills}/tool-defs-analysis/SKILL.md +0 -0
|
@@ -4,14 +4,14 @@ 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.11"
|
|
8
8
|
audience: external
|
|
9
9
|
type: workflow
|
|
10
10
|
---
|
|
11
11
|
|
|
12
12
|
## Context
|
|
13
13
|
|
|
14
|
-
This skill assumes `bunx @cyanheads/mcp-ts-core init [name]` has already run. The CLI created the project's `CLAUDE.md` and `AGENTS.md` for different agents, copied external skills to `skills/`, and scaffolded the directory structure with echo definitions as starting points. This skill covers what was created and what to do next.
|
|
14
|
+
This skill assumes `bunx @cyanheads/mcp-ts-core init [name]` has already run. The CLI created the project's `CLAUDE.md` and `AGENTS.md` for different agents, copied external skills to `framework-skills/`, and scaffolded the directory structure with echo definitions as starting points. This skill covers what was created and what to do next.
|
|
15
15
|
|
|
16
16
|
## Agent Protocol File
|
|
17
17
|
|
|
@@ -41,7 +41,7 @@ Dockerfile # Starter multi-stage image
|
|
|
41
41
|
server.json # MCP Registry publishing metadata
|
|
42
42
|
changelog/template.md # Format reference for per-version changelog files
|
|
43
43
|
scripts/ # build, clean, devcheck, lint-mcp, list-skills, build-changelog, tree, check-docs-sync
|
|
44
|
-
skills/
|
|
44
|
+
framework-skills/ # External skills copied from the package (source of truth)
|
|
45
45
|
src/
|
|
46
46
|
index.ts # createApp() entry point
|
|
47
47
|
mcp-server/
|
|
@@ -108,14 +108,14 @@ See the `add-tool`, `add-app-tool`, `add-resource`, `add-prompt`, `add-service`,
|
|
|
108
108
|
|
|
109
109
|
## Skill Sync
|
|
110
110
|
|
|
111
|
-
Copy all project skills into your agent's skill directory so they're available as context. `skills/` is the source of truth.
|
|
111
|
+
Copy all project skills into your agent's skill directory so they're available as context. `framework-skills/` is the source of truth. It is deliberately not `skills/`: Claude Code and Codex auto-load a plugin's root `skills/`, and these are development skills, not skills for the agents that install the server — leave `skills/` for those.
|
|
112
112
|
|
|
113
|
-
**Don't edit `skills/*/SKILL.md` or `skills/*/references/*`.** These are external skill files synced from `@cyanheads/mcp-ts-core` — the `maintenance` skill overwrites them on package updates, so local edits get lost. Project-specific agent context belongs in `CLAUDE.md` / `AGENTS.md`.
|
|
113
|
+
**Don't edit `framework-skills/*/SKILL.md` or `framework-skills/*/references/*`.** These are external skill files synced from `@cyanheads/mcp-ts-core` — the `maintenance` skill overwrites them on package updates, so local edits get lost. Project-specific agent context belongs in `CLAUDE.md` / `AGENTS.md`.
|
|
114
114
|
|
|
115
115
|
**For Claude Code:**
|
|
116
116
|
|
|
117
117
|
```bash
|
|
118
|
-
mkdir -p .claude/skills && cp -R skills/* .claude/skills/
|
|
118
|
+
mkdir -p .claude/skills && cp -R framework-skills/* .claude/skills/
|
|
119
119
|
```
|
|
120
120
|
|
|
121
121
|
**For other agents** (Codex, Cursor, Windsurf, etc.) — copy to the equivalent directory (e.g., `.codex/skills/`, `.cursor/skills/`).
|
|
@@ -138,7 +138,9 @@ Complete these one-time setup tasks:
|
|
|
138
138
|
| `.claude-plugin/plugin.json` | `description` | `lint:packaging` |
|
|
139
139
|
| `.codex-plugin/plugin.json` | `description`, `interface.shortDescription`, `interface.longDescription` | `lint:packaging` |
|
|
140
140
|
|
|
141
|
-
Fill the rest of the same blocks while you are in them — `package.json` `description` and `repository.url`, both plugin manifests' `author` / `homepage` / `repository`, the Codex manifest's `interface.developerName` / `category` / `websiteURL`, and `manifest.json` `description` / `author.name`. Nothing gates them, and every install surface reads them.
|
|
141
|
+
Fill the rest of the same blocks while you are in them — `package.json` `description` and `repository.url`, both plugin manifests' `author` / `homepage` / `repository` / `keywords`, the Codex manifest's `interface.developerName` / `category` / `websiteURL`, and `manifest.json` `description` / `author.name`. Nothing gates them, and every install surface reads them.
|
|
142
|
+
|
|
143
|
+
When the server takes a user-supplied value (an API key, a contact email, an instance URL), wire it into the plugin manifests the way each client delivers it — never as `"KEY": ""` in `env`, which `lint:packaging` rejects because the empty value replaces the user's exported key and is read as unset. In `.claude-plugin/plugin.json`, declare the option under `userConfig` (`type`, `title`, `description`; `sensitive: true` for keys and tokens; `required: true` or `default: ""`) and set `"KEY": "${user_config.<option>}"` in `env`. In `.codex-plugin/mcp.json`, list the variable name in `env_vars`. Mirror the `user_config` block you write in `manifest.json`.
|
|
142
144
|
|
|
143
145
|
A server that will never be published or installed as a plugin can drop the plugin-manifest gate instead — set `"packaging": { "pluginManifests": false }` in `devcheck.config.json`.
|
|
144
146
|
6. **Verify the scaffold builds clean** — `bun run devcheck`. Fix any issues before starting real work.
|
|
@@ -172,7 +174,7 @@ Skip or reorder as the project calls for it. The agent protocol's "What's Next?"
|
|
|
172
174
|
- [ ] Publishing identity populated (`server.json`, `package.json`, plugin manifests, `manifest.json`) — or the plugin-manifest gate opted out
|
|
173
175
|
- [ ] Framework docs read (`node_modules/@cyanheads/mcp-ts-core/CLAUDE.md` or `AGENTS.md`)
|
|
174
176
|
- [ ] Unused echo definitions cleaned up (and unregistered from `src/index.ts`)
|
|
175
|
-
- [ ] Skills copied to agent directory (`cp -R skills/* .claude/skills/` or equivalent)
|
|
177
|
+
- [ ] Skills copied to agent directory (`cp -R framework-skills/* .claude/skills/` or equivalent)
|
|
176
178
|
- [ ] Project structure understood (definitions directories, entry point)
|
|
177
179
|
- [ ] `bun run devcheck` passes
|
|
178
180
|
- [ ] Next: if new server, move on to `design-mcp-server` to plan the tool surface
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyanheads/mcp-ts-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"mcpName": "io.github.cyanheads/mcp-ts-core",
|
|
5
5
|
"description": "Agent-native TypeScript framework for MCP servers. Includes runtime infrastructure and agent skills for building, testing, and shipping servers.",
|
|
6
6
|
"files": [
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"scripts/list-skills.ts",
|
|
22
22
|
"scripts/release-github.ts",
|
|
23
23
|
"scripts/tree.ts",
|
|
24
|
-
"skills/",
|
|
24
|
+
"framework-skills/",
|
|
25
25
|
"templates/",
|
|
26
26
|
"AGENTS.md",
|
|
27
27
|
"CLAUDE.md",
|
|
@@ -189,7 +189,7 @@
|
|
|
189
189
|
"test:ui": "bunx vitest --ui",
|
|
190
190
|
"test:coverage": "bunx vitest run --coverage",
|
|
191
191
|
"audit": "bun audit",
|
|
192
|
-
"audit:fix": "bun audit
|
|
192
|
+
"audit:fix": "bun audit fix",
|
|
193
193
|
"audit:refresh": "rm -f bun.lock && bun install && bun audit",
|
|
194
194
|
"changelog:build": "bun run scripts/build-changelog.ts",
|
|
195
195
|
"changelog:check": "bun run scripts/build-changelog.ts --check",
|
|
@@ -197,9 +197,9 @@
|
|
|
197
197
|
"publish-mcp": "mcp-publisher login github -token \"$(security find-generic-password -a \"$USER\" -s mcp-publisher-github-pat -w)\" && mcp-publisher publish"
|
|
198
198
|
},
|
|
199
199
|
"devDependencies": {
|
|
200
|
-
"@biomejs/biome": "2.5.
|
|
200
|
+
"@biomejs/biome": "2.5.13",
|
|
201
201
|
"@cloudflare/vitest-pool-workers": "^0.22.0",
|
|
202
|
-
"@cloudflare/workers-types": "5.
|
|
202
|
+
"@cloudflare/workers-types": "5.20260910.1",
|
|
203
203
|
"@duckdb/node-api": "^1.5.5-r.4",
|
|
204
204
|
"@hono/otel": "^1.1.2",
|
|
205
205
|
"@opentelemetry/exporter-metrics-otlp-http": "^0.222.0",
|
|
@@ -214,7 +214,7 @@
|
|
|
214
214
|
"@socketsecurity/bun-security-scanner": "^1.1.2",
|
|
215
215
|
"@supabase/supabase-js": "^2.116.0",
|
|
216
216
|
"@types/bun": "^1.4.2",
|
|
217
|
-
"@types/node": "26.
|
|
217
|
+
"@types/node": "26.5.1",
|
|
218
218
|
"@types/papaparse": "^5.5.2",
|
|
219
219
|
"@types/sanitize-html": "^2.16.1",
|
|
220
220
|
"@types/validator": "^13.15.10",
|
|
@@ -247,7 +247,7 @@
|
|
|
247
247
|
"typescript-v6": "npm:typescript@^6.0.3",
|
|
248
248
|
"unpdf": "^1.8.1",
|
|
249
249
|
"validator": "^13.15.35",
|
|
250
|
-
"vite": "8.
|
|
250
|
+
"vite": "8.3.0",
|
|
251
251
|
"vitest": "^4.1.11"
|
|
252
252
|
},
|
|
253
253
|
"keywords": [
|
|
@@ -309,7 +309,7 @@
|
|
|
309
309
|
"hono": "^4.13.7",
|
|
310
310
|
"jose": "^6.2.12",
|
|
311
311
|
"pino": "^10.3.1",
|
|
312
|
-
"zod": "^4.6.
|
|
312
|
+
"zod": "^4.6.1"
|
|
313
313
|
},
|
|
314
314
|
"peerDependencies": {
|
|
315
315
|
"@duckdb/node-api": "^1.5.5-r.1",
|
|
@@ -152,6 +152,6 @@ for (const f of findings) {
|
|
|
152
152
|
console.error('');
|
|
153
153
|
}
|
|
154
154
|
console.error(
|
|
155
|
-
'See skills/api-linter/SKILL.md or scripts/check-framework-antipatterns.ts for rule rationale.',
|
|
155
|
+
'See framework-skills/api-linter/SKILL.md or scripts/check-framework-antipatterns.ts for rule rationale.',
|
|
156
156
|
);
|
|
157
157
|
process.exit(1);
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* @fileoverview Enforces the skill-versioning policy (#98 → #99): a change to a
|
|
4
|
-
* `skills/<name>/SKILL.md` body must bump `metadata.version` in the same edit.
|
|
4
|
+
* `framework-skills/<name>/SKILL.md` body must bump `metadata.version` in the same edit.
|
|
5
5
|
* Documenting the policy made the expectation visible; this check makes it stick.
|
|
6
6
|
* The triggering incident was 7 missed bumps across 2 consecutive releases — the
|
|
7
7
|
* kind of low-salience checklist item that needs tooling, not vigilance.
|
|
8
8
|
*
|
|
9
|
-
* For each `skills/<name>/SKILL.md` that differs from `HEAD` (working tree, staged
|
|
9
|
+
* For each `framework-skills/<name>/SKILL.md` that differs from `HEAD` (working tree, staged
|
|
10
10
|
* or not), it compares the frontmatter `metadata.version` and the body across
|
|
11
11
|
* `HEAD` → working tree. A changed body with an unchanged version is a violation.
|
|
12
12
|
* Whitespace-only body edits never trigger it (the policy's typo/whitespace
|
|
@@ -35,7 +35,7 @@ import { resolve } from 'node:path';
|
|
|
35
35
|
import process from 'node:process';
|
|
36
36
|
|
|
37
37
|
const ROOT = resolve('.');
|
|
38
|
-
const SKILL_MD_RE = /^skills\/[^/]+\/SKILL\.md$/;
|
|
38
|
+
const SKILL_MD_RE = /^framework-skills\/[^/]+\/SKILL\.md$/;
|
|
39
39
|
|
|
40
40
|
interface DevcheckConfig {
|
|
41
41
|
skillVersions?: { ignore?: string[] };
|
|
@@ -54,7 +54,7 @@ function loadIgnorePatterns(): string[] {
|
|
|
54
54
|
|
|
55
55
|
/** Match check-skills-sync semantics: full `<name>/SKILL.md` path or the bare `<name>`. */
|
|
56
56
|
function isIgnored(relPath: string, patterns: string[]): boolean {
|
|
57
|
-
const name = relPath.split('/')[1]; // skills/<name>/SKILL.md → <name>
|
|
57
|
+
const name = relPath.split('/')[1]; // framework-skills/<name>/SKILL.md → <name>
|
|
58
58
|
return patterns.some(
|
|
59
59
|
(p) => p === relPath || p === name || (name !== undefined && p === `${name}/SKILL.md`),
|
|
60
60
|
);
|
|
@@ -70,10 +70,17 @@ function changedSkillFiles(): string[] {
|
|
|
70
70
|
.filter((p) => SKILL_MD_RE.test(p));
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
/**
|
|
73
|
+
/**
|
|
74
|
+
* Content of a path at `HEAD`, or null when it didn't exist there (new file).
|
|
75
|
+
* A tree renamed from the pre-0.13 `skills/` reads its `HEAD` copy from the old
|
|
76
|
+
* path, so the release that carries the rename still checks every body edit.
|
|
77
|
+
*/
|
|
74
78
|
function headContent(relPath: string): string | null {
|
|
75
|
-
const
|
|
76
|
-
|
|
79
|
+
const show = (p: string) => spawnSync('git', ['show', `HEAD:${p}`], { encoding: 'utf-8' });
|
|
80
|
+
const result = show(relPath);
|
|
81
|
+
if (result.status === 0) return result.stdout;
|
|
82
|
+
const legacy = show(relPath.replace(/^framework-skills\//, 'skills/'));
|
|
83
|
+
return legacy.status === 0 ? legacy.stdout : null;
|
|
77
84
|
}
|
|
78
85
|
|
|
79
86
|
/** `metadata.version` from skill frontmatter, or null when absent/unparseable. */
|
|
@@ -95,8 +102,8 @@ function bodiesDiffer(a: string, b: string): boolean {
|
|
|
95
102
|
return a.replace(/\s+/g, '') !== b.replace(/\s+/g, '');
|
|
96
103
|
}
|
|
97
104
|
|
|
98
|
-
if (!existsSync(resolve(ROOT, 'skills'))) {
|
|
99
|
-
console.log('Skipped: no skills/ directory.');
|
|
105
|
+
if (!existsSync(resolve(ROOT, 'framework-skills'))) {
|
|
106
|
+
console.log('Skipped: no framework-skills/ directory.');
|
|
100
107
|
process.exit(0);
|
|
101
108
|
}
|
|
102
109
|
|
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* @fileoverview Verifies that `skills/` (canonical) has been propagated to the
|
|
3
|
+
* @fileoverview Verifies that `framework-skills/` (canonical) has been propagated to the
|
|
4
4
|
* local mirrors `.agents/skills/` and `.claude/skills/`. The maintenance skill
|
|
5
|
-
* updates `skills/` for downstream servers; the mirrors are what local agent
|
|
5
|
+
* updates `framework-skills/` for downstream servers; the mirrors are what local agent
|
|
6
6
|
* toolchains actually read, and silent drift means agents run on stale guidance.
|
|
7
7
|
*
|
|
8
|
-
* Propagation is one-way (`skills/` → mirrors), so missing or content-drifted
|
|
8
|
+
* Propagation is one-way (`framework-skills/` → mirrors), so missing or content-drifted
|
|
9
9
|
* files are reported. A skill that exists *only* in a mirror is left alone when
|
|
10
10
|
* it's externally sourced (globally installed, other tools), but flagged as
|
|
11
11
|
* stale when its `SKILL.md` carries `metadata.audience: external` — a framework
|
|
12
|
-
* skill removed from `skills/` upstream that the mirror never had pruned.
|
|
12
|
+
* skill removed from `framework-skills/` upstream that the mirror never had pruned.
|
|
13
13
|
*
|
|
14
14
|
* Behavior:
|
|
15
15
|
* • In sync → pass
|
|
16
16
|
* • Mirrors missing entirely → skip (no mirrors to sync)
|
|
17
17
|
* • Drift (missing or changed files) → exit 1 with details (devcheck demotes to warning)
|
|
18
18
|
* • Stale framework skill in mirror → exit 1 (mirror-only dir with audience: external)
|
|
19
|
+
* • Unmigrated pre-0.13 `skills/` → exit 1 with the `git mv` step
|
|
20
|
+
* • Leftover pre-0.13 `skills/` → exit 1 with the removal step (both trees present)
|
|
19
21
|
*
|
|
20
22
|
* Ignore specific skills or files via `devcheck.config.json`:
|
|
21
23
|
*
|
|
@@ -25,7 +27,7 @@
|
|
|
25
27
|
* }
|
|
26
28
|
* }
|
|
27
29
|
*
|
|
28
|
-
* Patterns match relative paths under `skills/`. A bare name like `add-tool`
|
|
30
|
+
* Patterns match relative paths under `framework-skills/`. A bare name like `add-tool`
|
|
29
31
|
* ignores the whole directory; `add-tool/SKILL.md` ignores a single file.
|
|
30
32
|
* `.DS_Store` and other OS cruft are ignored by default.
|
|
31
33
|
*
|
|
@@ -39,7 +41,13 @@ import { relative, resolve, sep } from 'node:path';
|
|
|
39
41
|
import process from 'node:process';
|
|
40
42
|
|
|
41
43
|
const ROOT = resolve('.');
|
|
42
|
-
const SKILLS_DIR = resolve(ROOT, 'skills');
|
|
44
|
+
const SKILLS_DIR = resolve(ROOT, 'framework-skills');
|
|
45
|
+
/**
|
|
46
|
+
* Where the tree lived before 0.13. Claude Code and Codex auto-load a plugin's
|
|
47
|
+
* root `skills/`, so a server shipping a plugin manifest handed its development
|
|
48
|
+
* skills to every installing agent — hence the move.
|
|
49
|
+
*/
|
|
50
|
+
const LEGACY_SKILLS_DIR = resolve(ROOT, 'skills');
|
|
43
51
|
const MIRRORS: { label: string; path: string }[] = [
|
|
44
52
|
{ label: '.agents/skills', path: resolve(ROOT, '.agents/skills') },
|
|
45
53
|
{ label: '.claude/skills', path: resolve(ROOT, '.claude/skills') },
|
|
@@ -95,11 +103,51 @@ function isFrameworkManaged(skillMdPath: string): boolean {
|
|
|
95
103
|
return /^\s*audience:\s*external\s*$/m.test(readFileSync(skillMdPath, 'utf-8'));
|
|
96
104
|
}
|
|
97
105
|
|
|
106
|
+
/** Skill directories under `root` whose `SKILL.md` carries `audience: external`. */
|
|
107
|
+
function frameworkManagedDirs(root: string): string[] {
|
|
108
|
+
return skillDirNames(root).filter((name) => isFrameworkManaged(resolve(root, name, 'SKILL.md')));
|
|
109
|
+
}
|
|
110
|
+
|
|
98
111
|
if (!existsSync(SKILLS_DIR)) {
|
|
99
|
-
|
|
112
|
+
const unmigrated = frameworkManagedDirs(LEGACY_SKILLS_DIR).length > 0;
|
|
113
|
+
if (unmigrated) {
|
|
114
|
+
console.log(
|
|
115
|
+
[
|
|
116
|
+
'skills/ still holds framework-managed skills and framework-skills/ is absent.',
|
|
117
|
+
'The framework moved its skill tree in 0.13.0: plugin hosts auto-load a root skills/,',
|
|
118
|
+
'which surfaced these development skills to every agent that installed the server.',
|
|
119
|
+
'',
|
|
120
|
+
'Fix: git mv skills framework-skills',
|
|
121
|
+
' then update the path in CLAUDE.md/AGENTS.md, .mcpbignore (/framework-skills/),',
|
|
122
|
+
' and .github/CONTRIBUTING.md, and regenerate docs/tree.md.',
|
|
123
|
+
].join('\n'),
|
|
124
|
+
);
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
console.log('Skipped: no framework-skills/ directory.');
|
|
100
128
|
process.exit(0);
|
|
101
129
|
}
|
|
102
130
|
|
|
131
|
+
// Both trees present. `init` run in place never overwrites an existing file, so an
|
|
132
|
+
// upgrade creates `framework-skills/` and leaves the old copies where a plugin host
|
|
133
|
+
// still auto-loads them. Only a name carried by both trees is a leftover — a `skills/`
|
|
134
|
+
// name of its own is the reserved server-published kind.
|
|
135
|
+
const canonicalDirs = new Set(skillDirNames(SKILLS_DIR));
|
|
136
|
+
const leftover = frameworkManagedDirs(LEGACY_SKILLS_DIR).filter((name) => canonicalDirs.has(name));
|
|
137
|
+
if (leftover.length > 0) {
|
|
138
|
+
console.log(
|
|
139
|
+
[
|
|
140
|
+
`skills/ still holds ${leftover.length} framework skill(s) that framework-skills/ also carries.`,
|
|
141
|
+
'Plugin hosts auto-load a root skills/, so those development skills still reach every',
|
|
142
|
+
'agent that installs the server.',
|
|
143
|
+
'',
|
|
144
|
+
`Fix: rm -rf ${leftover.map((name) => `skills/${name}`).join(' ')}`,
|
|
145
|
+
' Keep skills/ for skills the server publishes to the agents that use it.',
|
|
146
|
+
].join('\n'),
|
|
147
|
+
);
|
|
148
|
+
process.exit(1);
|
|
149
|
+
}
|
|
150
|
+
|
|
103
151
|
const presentMirrors = MIRRORS.filter((m) => existsSync(m.path));
|
|
104
152
|
if (presentMirrors.length === 0) {
|
|
105
153
|
console.log('Skipped: no skill mirrors (.agents/skills, .claude/skills) present.');
|
|
@@ -131,10 +179,9 @@ for (const mirror of presentMirrors) {
|
|
|
131
179
|
}
|
|
132
180
|
|
|
133
181
|
// Stale framework skills: a skill dir present only in a mirror (absent from
|
|
134
|
-
// canonical skills/) is fine when externally sourced, but stale when it carries
|
|
135
|
-
// `audience: external` — a framework skill removed from skills/ that was never
|
|
182
|
+
// canonical framework-skills/) is fine when externally sourced, but stale when it carries
|
|
183
|
+
// `audience: external` — a framework skill removed from framework-skills/ that was never
|
|
136
184
|
// pruned from the mirror. User/external skills (no marker) are left alone.
|
|
137
|
-
const canonicalDirs = new Set(skillDirNames(SKILLS_DIR));
|
|
138
185
|
const stale: Record<string, string[]> = {};
|
|
139
186
|
for (const mirror of presentMirrors) {
|
|
140
187
|
const staleHere = skillDirNames(mirror.path)
|
|
@@ -152,13 +199,15 @@ const totals = {
|
|
|
152
199
|
const driftCount = totals.missing + totals.drifted + totals.stale;
|
|
153
200
|
|
|
154
201
|
if (driftCount === 0) {
|
|
155
|
-
console.log(
|
|
202
|
+
console.log(
|
|
203
|
+
`framework-skills/ is in sync with ${presentMirrors.map((m) => m.label).join(' and ')}.`,
|
|
204
|
+
);
|
|
156
205
|
process.exit(0);
|
|
157
206
|
}
|
|
158
207
|
|
|
159
208
|
const lines: string[] = [];
|
|
160
209
|
lines.push(
|
|
161
|
-
`skills/ has drifted from ${presentMirrors.length > 1 ? 'mirrors' : 'its mirror'} ` +
|
|
210
|
+
`framework-skills/ has drifted from ${presentMirrors.length > 1 ? 'mirrors' : 'its mirror'} ` +
|
|
162
211
|
`(${totals.missing} missing, ${totals.drifted} changed, ${totals.stale} stale).`,
|
|
163
212
|
);
|
|
164
213
|
|
|
@@ -175,7 +224,9 @@ renderSection('Content differs in', drifted);
|
|
|
175
224
|
renderSection('Stale framework skill (deleted upstream) in', stale);
|
|
176
225
|
|
|
177
226
|
lines.push('');
|
|
178
|
-
lines.push(
|
|
227
|
+
lines.push(
|
|
228
|
+
'Fix: propagate framework-skills/ to the mirror(s) and delete stale framework skills from them,',
|
|
229
|
+
);
|
|
179
230
|
lines.push(
|
|
180
231
|
' or add entries to devcheck.config.json `skillsSync.ignore` to silence specific paths.',
|
|
181
232
|
);
|
package/scripts/clean-mcpb.ts
CHANGED
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
* 2. Exact-name strip of two entry classes nested under `node_modules/`,
|
|
10
10
|
* which root-anchored `.mcpbignore` patterns cannot reach by design
|
|
11
11
|
* (issues #146/#207):
|
|
12
|
-
* a. Dependency-shipped agent docs — `skills/`,
|
|
13
|
-
* trees and stray `SKILL.md` files (issue #230).
|
|
12
|
+
* a. Dependency-shipped agent docs — `framework-skills/`, `skills/`,
|
|
13
|
+
* `.claude/`, `.agents/` trees and stray `SKILL.md` files (issue #230).
|
|
14
14
|
* b. Platform-specific native bindings, which would otherwise lock the
|
|
15
15
|
* bundle to the build host's platform and push it past the 25 MB cap
|
|
16
16
|
* registries enforce (issue #274).
|
|
@@ -36,7 +36,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
36
36
|
* (post-bundle content check) — a unit test asserts the two are identical.
|
|
37
37
|
*/
|
|
38
38
|
export const AGENT_DOC_ENTRY =
|
|
39
|
-
/^node_modules\/.*(?:\/skills\/|\/\.claude\/|\/\.agents\/|\/SKILL\.md$)/;
|
|
39
|
+
/^node_modules\/.*(?:\/framework-skills\/|\/skills\/|\/\.claude\/|\/\.agents\/|\/SKILL\.md$)/;
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
42
|
* Platform-specific native binding packages, which must not ship in a bundle.
|
package/scripts/devcheck.ts
CHANGED
|
@@ -696,7 +696,7 @@ const ALL_CHECKS: Check[] = [
|
|
|
696
696
|
canFix: false,
|
|
697
697
|
getCommand: () => ['bun', 'run', 'scripts/lint-mcp.ts'],
|
|
698
698
|
tip: (c) =>
|
|
699
|
-
`Fix definition errors above — each diagnostic links to its rule in ${c.bold('skills/api-linter/SKILL.md')}.`,
|
|
699
|
+
`Fix definition errors above — each diagnostic links to its rule in ${c.bold('framework-skills/api-linter/SKILL.md')}.`,
|
|
700
700
|
},
|
|
701
701
|
{
|
|
702
702
|
name: 'Packaging',
|
|
@@ -771,16 +771,19 @@ const ALL_CHECKS: Check[] = [
|
|
|
771
771
|
name: 'Skills Sync',
|
|
772
772
|
flag: '--no-skills-sync',
|
|
773
773
|
canFix: false,
|
|
774
|
-
// Compares canonical skills/ against local mirrors (.agents/skills, .claude/skills).
|
|
775
|
-
// Skipped when skills/ or both mirrors are absent (non-mirrored projects)
|
|
776
|
-
//
|
|
777
|
-
//
|
|
774
|
+
// Compares canonical framework-skills/ against local mirrors (.agents/skills, .claude/skills).
|
|
775
|
+
// Skipped when framework-skills/ or both mirrors are absent (non-mirrored projects),
|
|
776
|
+
// except that a pre-0.13 `skills/` tree always runs — absent or alongside
|
|
777
|
+
// `framework-skills/` — so the script's migration message surfaces. Drift is demoted to
|
|
778
|
+
// a warning via isSuccess — intentional ignores live in devcheck.config.json
|
|
779
|
+
// `skillsSync.ignore`.
|
|
778
780
|
getCommand: () => {
|
|
779
|
-
const hasSkills = existsSync(path.join(ROOT_DIR, 'skills'));
|
|
781
|
+
const hasSkills = existsSync(path.join(ROOT_DIR, 'framework-skills'));
|
|
782
|
+
const hasLegacySkills = existsSync(path.join(ROOT_DIR, 'skills'));
|
|
780
783
|
const hasMirrors =
|
|
781
784
|
existsSync(path.join(ROOT_DIR, '.agents/skills')) ||
|
|
782
785
|
existsSync(path.join(ROOT_DIR, '.claude/skills'));
|
|
783
|
-
if (!hasSkills || !hasMirrors) return null;
|
|
786
|
+
if (!hasLegacySkills && (!hasSkills || !hasMirrors)) return null;
|
|
784
787
|
return ['bun', 'run', 'scripts/check-skills-sync.ts'];
|
|
785
788
|
},
|
|
786
789
|
isSuccess: (result) => {
|
|
@@ -789,18 +792,18 @@ const ALL_CHECKS: Check[] = [
|
|
|
789
792
|
return { success: true, warning: firstLine };
|
|
790
793
|
},
|
|
791
794
|
tip: (c) =>
|
|
792
|
-
`Propagate ${c.bold('skills/')} to ${c.bold('.agents/skills/')} and ${c.bold('.claude/skills/')}, or add entries to ${c.bold('devcheck.config.json')} ${c.bold('skillsSync.ignore')}.`,
|
|
795
|
+
`Propagate ${c.bold('framework-skills/')} to ${c.bold('.agents/skills/')} and ${c.bold('.claude/skills/')}, or add entries to ${c.bold('devcheck.config.json')} ${c.bold('skillsSync.ignore')}.`,
|
|
793
796
|
},
|
|
794
797
|
{
|
|
795
798
|
name: 'Skill Versions',
|
|
796
799
|
flag: '--no-skill-versions',
|
|
797
800
|
canFix: false,
|
|
798
|
-
// Flags skills/<name>/SKILL.md body changes (vs HEAD) that lack a metadata.version
|
|
799
|
-
// bump (#99). Skipped when skills/ is absent. Drift is demoted to a warning via
|
|
801
|
+
// Flags framework-skills/<name>/SKILL.md body changes (vs HEAD) that lack a metadata.version
|
|
802
|
+
// bump (#99). Skipped when framework-skills/ is absent. Drift is demoted to a warning via
|
|
800
803
|
// isSuccess — the typo/whitespace carve-out lives in devcheck.config.json
|
|
801
804
|
// `skillVersions.ignore`.
|
|
802
805
|
getCommand: () => {
|
|
803
|
-
if (!existsSync(path.join(ROOT_DIR, 'skills'))) return null;
|
|
806
|
+
if (!existsSync(path.join(ROOT_DIR, 'framework-skills'))) return null;
|
|
804
807
|
return ['bun', 'run', 'scripts/check-skill-versions.ts'];
|
|
805
808
|
},
|
|
806
809
|
isSuccess: (result) => {
|
|
@@ -903,7 +906,7 @@ const ALL_CHECKS: Check[] = [
|
|
|
903
906
|
{
|
|
904
907
|
name: 'Security Audit',
|
|
905
908
|
flag: '--no-audit',
|
|
906
|
-
canFix: false, // audit
|
|
909
|
+
canFix: false, // `audit fix` exists but often requires manual review.
|
|
907
910
|
slowCheck: true,
|
|
908
911
|
getCommand: () => [PM_CMD, 'audit'],
|
|
909
912
|
isSuccess: (result, _mode) => {
|
|
@@ -951,7 +954,7 @@ const ALL_CHECKS: Check[] = [
|
|
|
951
954
|
return true;
|
|
952
955
|
},
|
|
953
956
|
tip: (c) =>
|
|
954
|
-
`Direct dependency vulnerabilities found. Run ${c.bold(`${PM_CMD}
|
|
957
|
+
`Direct dependency vulnerabilities found. Run ${c.bold(`${PM_CMD} audit fix`)} or ${c.bold(`${PM_CMD} update <pkg>`)} to resolve.`,
|
|
955
958
|
},
|
|
956
959
|
{
|
|
957
960
|
name: 'Dependencies (Outdated)',
|