@cyanheads/mcp-ts-core 0.5.0 → 0.5.3
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 +3 -5
- package/README.md +2 -2
- package/dist/cli/init.js +8 -1
- package/dist/cli/init.js.map +1 -1
- package/dist/linter/rules/format-parity-rules.d.ts +37 -0
- package/dist/linter/rules/format-parity-rules.d.ts.map +1 -0
- package/dist/linter/rules/format-parity-rules.js +341 -0
- package/dist/linter/rules/format-parity-rules.js.map +1 -0
- package/dist/linter/rules/tool-rules.d.ts.map +1 -1
- package/dist/linter/rules/tool-rules.js +5 -0
- package/dist/linter/rules/tool-rules.js.map +1 -1
- package/dist/mcp-server/tools/utils/toolDefinition.d.ts +10 -9
- package/dist/mcp-server/tools/utils/toolDefinition.d.ts.map +1 -1
- package/dist/mcp-server/tools/utils/toolDefinition.js +2 -2
- package/dist/mcp-server/tools/utils/toolDefinition.js.map +1 -1
- package/package.json +3 -2
- package/scripts/check-docs-sync.ts +85 -0
- package/scripts/devcheck.ts +8 -0
- package/skills/add-tool/SKILL.md +6 -5
- package/skills/api-config/SKILL.md +1 -1
- package/skills/design-mcp-server/SKILL.md +3 -3
- package/skills/field-test/SKILL.md +2 -2
- package/skills/polish-docs-meta/SKILL.md +2 -2
- package/skills/polish-docs-meta/references/readme.md +217 -79
- package/skills/setup/SKILL.md +1 -1
- package/templates/AGENTS.md +5 -3
- package/templates/CLAUDE.md +5 -3
- package/templates/src/mcp-server/tools/definitions/echo.tool.ts +3 -2
- package/skills/devcheck/SKILL.md +0 -54
- package/skills/walkthrough-init/SKILL.md +0 -50
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolDefinition.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/utils/toolDefinition.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAErD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc,CAC7B,MAAM,SAAS,SAAS,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC,WAAW,CAAC,EAC9D,OAAO,SAAS,SAAS,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC,WAAW,CAAC;IAE/D,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,qCAAqC;IACrC,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,+EAA+E;IAC/E,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,8BAA8B;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB
|
|
1
|
+
{"version":3,"file":"toolDefinition.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/utils/toolDefinition.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAErD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc,CAC7B,MAAM,SAAS,SAAS,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC,WAAW,CAAC,EAC9D,OAAO,SAAS,SAAS,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC,WAAW,CAAC;IAE/D,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,qCAAqC;IACrC,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,+EAA+E;IAC/E,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,8BAA8B;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,YAAY,EAAE,CAAC;IACtD;;;OAGG;IACH,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAChG,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,MAAM,EAAE,OAAO,CAAC;IAChB,qEAAqE;IACrE,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,2CAA2C;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,gEAAgE;AAChE,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC;AAM/F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,IAAI,CAAC,MAAM,SAAS,SAAS,CAAC,WAAW,CAAC,EAAE,OAAO,SAAS,SAAS,CAAC,WAAW,CAAC,EAChG,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,GACrD,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAEjC"}
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
* ctx.log.info('Processing', { query: input.query });
|
|
29
29
|
* return { items: await search(input.query) };
|
|
30
30
|
* },
|
|
31
|
-
* // format() populates content[] — the
|
|
32
|
-
* //
|
|
31
|
+
* // format() populates content[] — the markdown twin of structuredContent.
|
|
32
|
+
* // Different clients read different surfaces; both must be content-complete.
|
|
33
33
|
* format: (result) => [{
|
|
34
34
|
* type: 'text',
|
|
35
35
|
* text: result.items.map(i => `**${i.id}**: ${i.name} (${i.status})`).join('\n'),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolDefinition.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/utils/toolDefinition.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"toolDefinition.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/utils/toolDefinition.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA4FH,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,UAAU,IAAI,CAClB,IAAY,EACZ,OAAsD;IAEtD,OAAO,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC;AAC9B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyanheads/mcp-ts-core",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"mcpName": "io.github.cyanheads/mcp-ts-core",
|
|
5
5
|
"description": "Agent-native TypeScript framework for building MCP servers. Build tools, not infrastructure. Declarative definitions with auth, multi-backend storage, OpenTelemetry, and first-class support for Node.js and Cloudflare Workers.",
|
|
6
6
|
"main": "dist/core/index.js",
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"files": [
|
|
9
9
|
"dist/",
|
|
10
10
|
"scripts/build.ts",
|
|
11
|
+
"scripts/check-docs-sync.ts",
|
|
11
12
|
"scripts/clean.ts",
|
|
12
13
|
"scripts/devcheck.ts",
|
|
13
14
|
"scripts/lint-mcp.ts",
|
|
@@ -250,7 +251,7 @@
|
|
|
250
251
|
},
|
|
251
252
|
"dependencies": {
|
|
252
253
|
"@hono/mcp": "^0.2.5",
|
|
253
|
-
"@hono/node-server": "^
|
|
254
|
+
"@hono/node-server": "^2.0.0",
|
|
254
255
|
"@modelcontextprotocol/ext-apps": "^1.6.0",
|
|
255
256
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
256
257
|
"@opentelemetry/api": "^1.9.1",
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Verifies that CLAUDE.md and AGENTS.md stay in sync. The init CLI
|
|
4
|
+
* ships both files byte-identical and each agent tool reads the file named for
|
|
5
|
+
* it — silent drift after edits leaves one agent on a stale protocol.
|
|
6
|
+
*
|
|
7
|
+
* Behavior:
|
|
8
|
+
* • Both exist, identical → pass
|
|
9
|
+
* • Both exist, drift → fail, print first divergent lines + fix hint
|
|
10
|
+
* • Only one exists → pass (report which file is present)
|
|
11
|
+
* • Neither exists → skip (not an mcp-ts-core project)
|
|
12
|
+
*
|
|
13
|
+
* Runs as a devcheck step and standalone: `bun run scripts/check-docs-sync.ts`.
|
|
14
|
+
*
|
|
15
|
+
* @module scripts/check-docs-sync
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
19
|
+
import { resolve } from 'node:path';
|
|
20
|
+
import process from 'node:process';
|
|
21
|
+
|
|
22
|
+
const CLAUDE_PATH = resolve('CLAUDE.md');
|
|
23
|
+
const AGENTS_PATH = resolve('AGENTS.md');
|
|
24
|
+
const MAX_DIFF_LINES = 20;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Line-by-line drift summary. Not a true unified diff — tools that move lines
|
|
28
|
+
* will show every shifted line as divergent, which is fine for the enforcement
|
|
29
|
+
* use case (the fix is always "reconcile both files" regardless).
|
|
30
|
+
*/
|
|
31
|
+
function summarizeDrift(a: string, b: string): string {
|
|
32
|
+
const aLines = a.split('\n');
|
|
33
|
+
const bLines = b.split('\n');
|
|
34
|
+
const max = Math.max(aLines.length, bLines.length);
|
|
35
|
+
const lines: string[] = [];
|
|
36
|
+
let drifts = 0;
|
|
37
|
+
|
|
38
|
+
for (let i = 0; i < max; i++) {
|
|
39
|
+
if (aLines[i] !== bLines[i]) {
|
|
40
|
+
drifts++;
|
|
41
|
+
if (drifts <= MAX_DIFF_LINES) {
|
|
42
|
+
const lineNo = String(i + 1).padStart(4);
|
|
43
|
+
if (aLines[i] !== undefined) lines.push(`${lineNo} - CLAUDE.md: ${aLines[i]}`);
|
|
44
|
+
if (bLines[i] !== undefined) lines.push(`${lineNo} + AGENTS.md: ${bLines[i]}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (drifts > MAX_DIFF_LINES) {
|
|
50
|
+
lines.push(` ... and ${drifts - MAX_DIFF_LINES} more diverging line(s)`);
|
|
51
|
+
}
|
|
52
|
+
return lines.join('\n');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const hasClaude = existsSync(CLAUDE_PATH);
|
|
56
|
+
const hasAgents = existsSync(AGENTS_PATH);
|
|
57
|
+
|
|
58
|
+
if (!hasClaude && !hasAgents) {
|
|
59
|
+
console.log('Skipped: neither CLAUDE.md nor AGENTS.md exists.');
|
|
60
|
+
process.exit(0);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (hasClaude !== hasAgents) {
|
|
64
|
+
const present = hasClaude ? 'CLAUDE.md' : 'AGENTS.md';
|
|
65
|
+
const absent = hasClaude ? 'AGENTS.md' : 'CLAUDE.md';
|
|
66
|
+
console.log(`${present} found. No ${absent} found — nothing to sync.`);
|
|
67
|
+
process.exit(0);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const claude = readFileSync(CLAUDE_PATH, 'utf-8');
|
|
71
|
+
const agents = readFileSync(AGENTS_PATH, 'utf-8');
|
|
72
|
+
|
|
73
|
+
if (claude === agents) {
|
|
74
|
+
console.log('CLAUDE.md and AGENTS.md are in sync.');
|
|
75
|
+
process.exit(0);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
console.error('CLAUDE.md and AGENTS.md have drifted:');
|
|
79
|
+
console.error('');
|
|
80
|
+
console.error(summarizeDrift(claude, agents));
|
|
81
|
+
console.error('');
|
|
82
|
+
console.error(
|
|
83
|
+
'Fix: edit both files together, or `cp CLAUDE.md AGENTS.md` (or reverse) if one is canonical.',
|
|
84
|
+
);
|
|
85
|
+
process.exit(1);
|
package/scripts/devcheck.ts
CHANGED
|
@@ -413,6 +413,14 @@ const ALL_CHECKS: Check[] = [
|
|
|
413
413
|
tip: (c) =>
|
|
414
414
|
`Fix definition errors reported above. See ${c.bold('validateDefinitions()')} docs for rule details.`,
|
|
415
415
|
},
|
|
416
|
+
{
|
|
417
|
+
name: 'Docs Sync',
|
|
418
|
+
flag: '--no-docs-sync',
|
|
419
|
+
canFix: false,
|
|
420
|
+
getCommand: () => ['bun', 'run', 'scripts/check-docs-sync.ts'],
|
|
421
|
+
tip: (c) =>
|
|
422
|
+
`Edit both files together, or run ${c.bold('cp CLAUDE.md AGENTS.md')} (or reverse) to resync.`,
|
|
423
|
+
},
|
|
416
424
|
{
|
|
417
425
|
name: 'Biome',
|
|
418
426
|
flag: '--no-lint',
|
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.6"
|
|
8
8
|
audience: external
|
|
9
9
|
type: reference
|
|
10
10
|
---
|
|
@@ -57,9 +57,10 @@ export const {{TOOL_EXPORT}} = tool('{{tool_name}}', {
|
|
|
57
57
|
return { /* output */ };
|
|
58
58
|
},
|
|
59
59
|
|
|
60
|
-
// format() populates MCP content[] — the
|
|
61
|
-
//
|
|
62
|
-
//
|
|
60
|
+
// format() populates MCP content[] — the markdown twin of structuredContent.
|
|
61
|
+
// Different clients read different surfaces (Claude Code → structuredContent,
|
|
62
|
+
// Claude Desktop → content[]), so both must carry the same data.
|
|
63
|
+
// Enforced at lint time: every field in `output` must appear in the rendered text.
|
|
63
64
|
format: (result) => {
|
|
64
65
|
const lines: string[] = [];
|
|
65
66
|
// Render each item with all relevant fields — not just a count or title.
|
|
@@ -312,7 +313,7 @@ Large payloads burn the agent's context window. Default to curated summaries; of
|
|
|
312
313
|
- [ ] JSDoc `@fileoverview` and `@module` header present
|
|
313
314
|
- [ ] Optional nested objects guarded for empty inner values from form-based clients (check `?.field` truthiness, not just object presence)
|
|
314
315
|
- [ ] `handler(input, ctx)` is pure — throws on failure, no try/catch
|
|
315
|
-
- [ ] `format()` renders
|
|
316
|
+
- [ ] `format()` renders every field in the output schema — enforced at lint time via sentinel injection, startup fails with `format-parity` errors otherwise. Different clients forward different surfaces (Claude Code → `structuredContent`, Claude Desktop → `content[]`); both must carry the same data. Primary fix: render the missing field in `format()` (use `z.discriminatedUnion` for list/detail variants). Escape hatch: if the output schema was over-typed for a genuinely dynamic upstream API, relax it (`z.object({}).passthrough()`) rather than maintaining aspirational typing
|
|
316
317
|
- [ ] If wrapping external API: output schema and `format()` preserve uncertainty from sparse upstream payloads instead of inventing concrete values
|
|
317
318
|
- [ ] `auth` scopes declared if the tool needs authorization
|
|
318
319
|
- [ ] `task: true` added if the tool is long-running
|
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
Reference for core and server configuration in `@cyanheads/mcp-ts-core`. Covers env var tables with defaults, priority order, server-specific Zod schema pattern, and Workers lazy-parsing requirement.
|
|
5
5
|
metadata:
|
|
6
6
|
author: cyanheads
|
|
7
|
-
version: "1.
|
|
7
|
+
version: "1.2"
|
|
8
8
|
audience: external
|
|
9
9
|
type: reference
|
|
10
10
|
---
|
|
@@ -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.4"
|
|
8
8
|
audience: external
|
|
9
9
|
type: workflow
|
|
10
10
|
---
|
|
@@ -201,7 +201,7 @@ output: z.object({
|
|
|
201
201
|
```
|
|
202
202
|
|
|
203
203
|
- **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.
|
|
204
|
-
- **`format()` is the
|
|
204
|
+
- **`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.
|
|
205
205
|
|
|
206
206
|
#### Batch input design
|
|
207
207
|
|
|
@@ -428,7 +428,7 @@ Execute the plan using the scaffolding skills:
|
|
|
428
428
|
- [ ] Parameter `.describe()` text explains what the value is, what it affects, and tradeoffs
|
|
429
429
|
- [ ] Input schemas use constrained types (enums, literals, regex) over free strings
|
|
430
430
|
- [ ] Output schemas designed for LLM's next action — chaining IDs, post-write state, filtering communicated
|
|
431
|
-
- [ ] `format()` renders all data the LLM needs — `content[]`
|
|
431
|
+
- [ ] `format()` renders all data the LLM needs — different clients forward different surfaces (Claude Code → `structuredContent`, Claude Desktop → `content[]`); both must carry the same data, not just a count or title
|
|
432
432
|
- [ ] Error messages guide recovery — name what went wrong and what to do next
|
|
433
433
|
- [ ] Annotations set correctly (`readOnlyHint`, `destructiveHint`, etc.)
|
|
434
434
|
- [ ] Tool surface is self-sufficient — a tool-only agent can accomplish everything the server is for
|
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
Exercise tools, resources, and prompts with real-world inputs to verify behavior end-to-end. Use after adding or modifying definitions, or when the user asks to test, try out, or verify their MCP surface. Calls each definition with realistic and adversarial inputs and produces a report of issues, pain points, and recommendations.
|
|
5
5
|
metadata:
|
|
6
6
|
author: cyanheads
|
|
7
|
-
version: "1.
|
|
7
|
+
version: "1.2"
|
|
8
8
|
audience: external
|
|
9
9
|
type: debug
|
|
10
10
|
---
|
|
@@ -36,7 +36,7 @@ For every tool, resource, and prompt, run through these categories:
|
|
|
36
36
|
| Category | What to test |
|
|
37
37
|
|:---------|:-------------|
|
|
38
38
|
| **Happy path** | Realistic input that should succeed. Verify output shape matches the output schema. Verify format function produces sensible content blocks. |
|
|
39
|
-
| **`structuredContent` parity** |
|
|
39
|
+
| **`structuredContent` parity** | The `format-parity` lint rule already asserts every terminal field in the output schema appears in `format()`'s rendered text (via sentinel injection at startup). Field testing layers real-data checks on top: are values rendered accurately (not just their labels)? Do conditional-render branches in `format()` still render every field when specific values are present? Does the content look right to a human reading the LLM's view? |
|
|
40
40
|
| **Variations** | Different valid input combinations — optional fields omitted, optional fields included, different enum values, min/max boundaries. |
|
|
41
41
|
| **Field selection / projection** | For tools with `fields`, `include`, `expand`, `view`, or similar parameters, call the tool with non-default selections. Verify the handler returns the requested fields and `format()` renders each requested field rather than a hardcoded summary subset. |
|
|
42
42
|
| **Edge cases** | Empty strings, zero values, very long inputs, special characters, Unicode. |
|
|
@@ -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.4"
|
|
8
8
|
audience: external
|
|
9
9
|
type: workflow
|
|
10
10
|
---
|
|
@@ -48,7 +48,7 @@ Capture: tool count, resource count, prompt count, service count, required env v
|
|
|
48
48
|
|
|
49
49
|
Read `references/readme.md` for structure and conventions. If `README.md` doesn't exist, create it from scratch. If it exists, diff the current content against the audit — update tool/resource/prompt tables, env var lists, and descriptions to match the actual surface area. Don't rewrite sections that are already accurate.
|
|
50
50
|
|
|
51
|
-
The header tagline (`<
|
|
51
|
+
The bold header tagline (the `<b>` text inside the first `<p>`) must match the `package.json` `description`. The surface count is a nested `<div>` inside the same `<p>`, separated by `•`.
|
|
52
52
|
|
|
53
53
|
### 3. Agent Protocol (CLAUDE.md / AGENTS.md)
|
|
54
54
|
|