@cyanheads/mcp-ts-core 0.1.4 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/CLAUDE.md +5 -1
  2. package/README.md +1 -1
  3. package/dist/core/app.d.ts +2 -0
  4. package/dist/core/app.d.ts.map +1 -1
  5. package/dist/core/app.js +19 -4
  6. package/dist/core/app.js.map +1 -1
  7. package/dist/core/context.d.ts +2 -2
  8. package/dist/core/context.d.ts.map +1 -1
  9. package/dist/core/context.js +9 -5
  10. package/dist/core/context.js.map +1 -1
  11. package/dist/mcp-server/resources/utils/resourceHandlerFactory.d.ts.map +1 -1
  12. package/dist/mcp-server/resources/utils/resourceHandlerFactory.js +4 -2
  13. package/dist/mcp-server/resources/utils/resourceHandlerFactory.js.map +1 -1
  14. package/dist/mcp-server/server.d.ts +6 -0
  15. package/dist/mcp-server/server.d.ts.map +1 -1
  16. package/dist/mcp-server/server.js +2 -11
  17. package/dist/mcp-server/server.js.map +1 -1
  18. package/dist/mcp-server/tasks/core/taskManager.js +1 -1
  19. package/dist/mcp-server/tasks/core/taskManager.js.map +1 -1
  20. package/dist/mcp-server/tools/tool-registration.d.ts.map +1 -1
  21. package/dist/mcp-server/tools/tool-registration.js +28 -12
  22. package/dist/mcp-server/tools/tool-registration.js.map +1 -1
  23. package/dist/mcp-server/tools/utils/toolHandlerFactory.d.ts.map +1 -1
  24. package/dist/mcp-server/tools/utils/toolHandlerFactory.js +12 -2
  25. package/dist/mcp-server/tools/utils/toolHandlerFactory.js.map +1 -1
  26. package/dist/mcp-server/transports/auth/authMiddleware.js +1 -1
  27. package/dist/mcp-server/transports/auth/authMiddleware.js.map +1 -1
  28. package/dist/mcp-server/transports/auth/lib/authUtils.d.ts.map +1 -1
  29. package/dist/mcp-server/transports/auth/lib/authUtils.js +3 -2
  30. package/dist/mcp-server/transports/auth/lib/authUtils.js.map +1 -1
  31. package/dist/mcp-server/transports/auth/lib/checkScopes.d.ts.map +1 -1
  32. package/dist/mcp-server/transports/auth/lib/checkScopes.js +4 -4
  33. package/dist/mcp-server/transports/auth/lib/checkScopes.js.map +1 -1
  34. package/dist/mcp-server/transports/http/httpTransport.d.ts.map +1 -1
  35. package/dist/mcp-server/transports/http/httpTransport.js +28 -18
  36. package/dist/mcp-server/transports/http/httpTransport.js.map +1 -1
  37. package/dist/mcp-server/transports/http/sessionStore.d.ts.map +1 -1
  38. package/dist/mcp-server/transports/http/sessionStore.js +23 -13
  39. package/dist/mcp-server/transports/http/sessionStore.js.map +1 -1
  40. package/dist/services/graph/core/GraphService.js +2 -2
  41. package/dist/services/graph/core/GraphService.js.map +1 -1
  42. package/dist/services/llm/providers/openrouter.provider.js +1 -1
  43. package/dist/services/llm/providers/openrouter.provider.js.map +1 -1
  44. package/dist/services/speech/core/speechMetrics.js +1 -1
  45. package/dist/services/speech/core/speechMetrics.js.map +1 -1
  46. package/dist/services/speech/providers/elevenlabs.provider.js +1 -1
  47. package/dist/services/speech/providers/elevenlabs.provider.js.map +1 -1
  48. package/dist/services/speech/providers/whisper.provider.js +1 -1
  49. package/dist/services/speech/providers/whisper.provider.js.map +1 -1
  50. package/dist/storage/core/StorageService.js +2 -2
  51. package/dist/storage/core/StorageService.js.map +1 -1
  52. package/dist/storage/core/storageValidation.d.ts.map +1 -1
  53. package/dist/storage/core/storageValidation.js +0 -13
  54. package/dist/storage/core/storageValidation.js.map +1 -1
  55. package/dist/utils/index.d.ts +2 -2
  56. package/dist/utils/index.d.ts.map +1 -1
  57. package/dist/utils/index.js +3 -3
  58. package/dist/utils/index.js.map +1 -1
  59. package/dist/utils/internal/error-handler/errorHandler.js +1 -1
  60. package/dist/utils/internal/error-handler/errorHandler.js.map +1 -1
  61. package/dist/utils/internal/performance.d.ts +10 -19
  62. package/dist/utils/internal/performance.d.ts.map +1 -1
  63. package/dist/utils/internal/performance.js +35 -118
  64. package/dist/utils/internal/performance.js.map +1 -1
  65. package/dist/utils/internal/requestContext.d.ts.map +1 -1
  66. package/dist/utils/internal/requestContext.js +13 -10
  67. package/dist/utils/internal/requestContext.js.map +1 -1
  68. package/dist/utils/telemetry/{semconv.d.ts → attributes.d.ts} +14 -129
  69. package/dist/utils/telemetry/attributes.d.ts.map +1 -0
  70. package/dist/utils/telemetry/{semconv.js → attributes.js} +27 -148
  71. package/dist/utils/telemetry/attributes.js.map +1 -0
  72. package/dist/utils/telemetry/index.d.ts +3 -3
  73. package/dist/utils/telemetry/index.d.ts.map +1 -1
  74. package/dist/utils/telemetry/index.js +3 -3
  75. package/dist/utils/telemetry/index.js.map +1 -1
  76. package/dist/utils/telemetry/instrumentation.d.ts.map +1 -1
  77. package/dist/utils/telemetry/instrumentation.js +23 -19
  78. package/dist/utils/telemetry/instrumentation.js.map +1 -1
  79. package/dist/utils/telemetry/metrics.d.ts +0 -64
  80. package/dist/utils/telemetry/metrics.d.ts.map +1 -1
  81. package/dist/utils/telemetry/metrics.js +0 -78
  82. package/dist/utils/telemetry/metrics.js.map +1 -1
  83. package/package.json +14 -14
  84. package/skills/add-test/SKILL.md +216 -0
  85. package/skills/api-utils/SKILL.md +5 -7
  86. package/skills/design-mcp-server/SKILL.md +153 -9
  87. package/skills/polish-docs-meta/SKILL.md +137 -0
  88. package/skills/polish-docs-meta/references/agent-protocol.md +78 -0
  89. package/skills/polish-docs-meta/references/package-meta.md +63 -0
  90. package/skills/polish-docs-meta/references/readme.md +183 -0
  91. package/skills/polish-docs-meta/references/server-json.md +142 -0
  92. package/skills/release/SKILL.md +102 -30
  93. package/skills/setup/SKILL.md +3 -2
  94. package/templates/.env.example +6 -1
  95. package/templates/AGENTS.md +3 -1
  96. package/templates/CLAUDE.md +3 -1
  97. package/templates/Dockerfile +84 -0
  98. package/templates/_.gitignore +6 -0
  99. package/templates/package.json +3 -0
  100. package/templates/src/mcp-server/tools/definitions/echo.tool.ts +2 -0
  101. package/dist/utils/telemetry/semconv.d.ts.map +0 -1
  102. package/dist/utils/telemetry/semconv.js.map +0 -1
@@ -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: "1.1"
7
+ version: "2.0"
8
8
  audience: external
9
9
  type: workflow
10
10
  ---
@@ -69,19 +69,160 @@ This is the raw material. Not everything becomes a tool.
69
69
  **Common traps:**
70
70
 
71
71
  - **Everything-is-a-tool**: "Fetch by ID" with no other params is a resource. Resources let clients inject context without a tool call.
72
- - **CRUD explosion**: Don't map every REST endpoint to a tool. One `update_task` beats `update_task_status` + `assign_task` + `update_task_fields`.
72
+ - **CRUD explosion**: Don't map every REST endpoint to a tool. Related operations on the same noun often belong in one tool with an `operation`/`mode` parameter (see Step 4).
73
73
  - **Ignoring resources**: If the server has reference data, schemas, or entities the LLM should read — expose them as resources.
74
+ - **1:1 endpoint mirroring**: API endpoints are designed for programmatic consumers. LLM tools should be designed for workflows — what an agent is *trying to accomplish*, not what HTTP calls happen under the hood.
74
75
 
75
76
  ### 4. Design Tools
76
77
 
77
- For each tool:
78
+ This is the highest-leverage step. Tool definitions — names, descriptions, parameters, output schemas — are the **entire interface contract** the LLM reads to decide whether and how to call a tool. Every field is context. Design accordingly.
79
+
80
+ #### Think in workflows, not endpoints
81
+
82
+ The unit of a tool is a *useful action*, not an API call. Ask: "What is the agent trying to accomplish?" — not "What endpoints does the API have?"
83
+
84
+ A single tool can call multiple APIs internally, apply local filtering, reshape data, and return enriched results. The LLM doesn't know or care about the underlying calls.
85
+
86
+ **Consolidation via operation/mode enum.** When a domain noun has several related operations that share parameters, consolidate into one tool with a discriminated parameter. This keeps the tool surface small and lets the LLM discover all capabilities in one place.
87
+
88
+ ```ts
89
+ // One tool for all branch operations — not five separate tools
90
+ const gitBranch = tool('git_branch', {
91
+ description: 'Manage branches: list, show current, create, delete, or rename.',
92
+ input: z.object({
93
+ operation: z.enum(['list', 'create', 'delete', 'rename', 'show-current'])
94
+ .describe('Branch operation to perform.'),
95
+ name: z.string().optional().describe('Branch name (required for create/delete/rename).'),
96
+ newName: z.string().optional().describe('New name (required for rename).'),
97
+ }),
98
+ // ...
99
+ });
100
+ ```
101
+
102
+ ```ts
103
+ // Workflow tool — search + local filter pipeline, not a raw API proxy
104
+ const findEligibleStudies = tool('clinicaltrials_find_eligible_studies', {
105
+ description: 'Matches patient demographics and medical profile to eligible clinical trials. '
106
+ + 'Filters by age, sex, conditions, location, and healthy volunteer status. '
107
+ + 'Returns ranked list of matching studies with eligibility explanations.',
108
+ // handler: listStudies() → filter by eligibility → rank by location proximity → slice
109
+ });
110
+ ```
111
+
112
+ **When to consolidate vs. split:**
113
+
114
+ | Consolidate (one tool) | Split (separate tools) |
115
+ |:------------------------|:-----------------------|
116
+ | Operations share the same noun and most parameters | Operations have fundamentally different inputs/outputs |
117
+ | Related CRUD on a single entity | Read-only lookup vs. multi-step workflow |
118
+ | Agent would naturally think of them together | Agent would use them in different contexts |
119
+
120
+ There is no fixed ceiling on tool count — tools need to earn their keep, but don't artificially limit the surface. If the domain genuinely has 20 distinct workflows, expose 20 tools.
121
+
122
+ #### Tool descriptions
123
+
124
+ The description is the LLM's primary signal for tool selection. It must answer: *what does this do, and when should I use it?*
125
+
126
+ - **Be concrete about capability.** "Search for clinical trial studies using queries and filters" beats "Interact with studies."
127
+ - **Include operational guidance when it matters.** If the tool has prerequisites, constraints, or gotchas the LLM needs to know, say so in the description. Don't add boilerplate workflow hints when the tool is self-explanatory.
128
+
129
+ ```ts
130
+ // Good — describes a prerequisite the LLM must know
131
+ description: 'Set the session working directory for all git operations. '
132
+ + 'This allows subsequent git commands to omit the path parameter.'
133
+
134
+ // Good — self-explanatory, no workflow hints needed
135
+ description: 'Show the working tree status including staged, unstaged, and untracked files.'
136
+
137
+ // Good — warns about constraints
138
+ description: 'Fetches trial results data for completed studies. '
139
+ + 'Only available for studies where hasResults is true.'
140
+ ```
141
+
142
+ Context-dependent: a simple read-only tool needs a one-line description. A tool with prerequisites, modes, or non-obvious behavior needs more. Match depth of description to complexity of tool.
143
+
144
+ #### Parameter descriptions
145
+
146
+ Every `.describe()` is prompt text the LLM reads. Parameters should convey: what the value is, what it affects, and (where non-obvious) how to use it well.
147
+
148
+ - **Constrain the type.** Enums and literals over free strings. Regex validation for formatted IDs. Ranges for numeric bounds.
149
+ - **Explain costs and tradeoffs** when a parameter choice has meaningful consequences.
150
+ - **Name alternative approaches** when a simpler path exists.
151
+ - **Include format patterns** for structured values, but don't pad descriptions with redundant examples.
152
+
153
+ ```ts
154
+ // Good — explains cost, recommends action, names the alternative
155
+ fields: z.array(z.string()).optional()
156
+ .describe('Specific fields to return (reduces payload size). '
157
+ + 'STRONGLY RECOMMENDED — without this, the full study record (~70KB each) is returned. '
158
+ + 'Use full data only when you need detailed eligibility criteria, locations, or results.'),
159
+
160
+ // Good — explains what the flag does AND how to override
161
+ autoExclude: z.boolean().default(true)
162
+ .describe('Automatically exclude lock files and generated files from diff output '
163
+ + 'to reduce context bloat. Set to false if you need to inspect these files.'),
164
+
165
+ // Good — names the format and gives one example
166
+ nctIds: z.union([z.string(), z.array(z.string()).max(5)])
167
+ .describe('A single NCT ID (e.g., "NCT12345678") or an array of up to 5 NCT IDs to fetch.'),
168
+ ```
169
+
170
+ #### Output design
171
+
172
+ The output schema and `format` function control what the LLM reads back. Design for the agent's *next decision*, not for a UI or an API consumer.
173
+
174
+ **Principles:**
175
+
176
+ - **Include IDs and references for chaining.** If the agent might act on a result, return the identifiers it needs for follow-up tool calls.
177
+ - **Curate vs. pass-through depends on domain.** Medical/scientific data — don't trim fields that could alter correctness. CRUD responses — return what the agent needs, not the full API payload. Match fidelity to consequence.
178
+ - **Surface what was done, not just results.** After a write operation, include the new state. (`git_commit` auto-includes post-commit `git status`. The LLM sees the repo state without an extra round trip.)
179
+ - **Communicate filtering.** If the tool silently excluded content, tell the LLM what was excluded and how to get it back. The agent can't act on what it doesn't know about.
180
+
181
+ ```ts
182
+ // git_diff — when lock files are filtered, the output tells the LLM
183
+ output: z.object({
184
+ diff: z.string().describe('Unified diff output.'),
185
+ excludedFiles: z.array(z.string()).optional()
186
+ .describe('Files automatically excluded from the diff (e.g., lock files). '
187
+ + 'Call again with autoExclude=false to include them.'),
188
+ }),
189
+ ```
190
+
191
+ - **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.
192
+ - **Use the `format` function for readable summaries** while keeping the full structured data in the output object for programmatic use.
193
+
194
+ #### Error messages as LLM guidance
195
+
196
+ When a tool throws, the error message is the agent's only signal for recovery. A good error message tells the LLM *what happened and what to do next*.
197
+
198
+ ```ts
199
+ // Bad — the LLM has no recovery path
200
+ throw new Error('Not found');
201
+
202
+ // Good — names both resolution options
203
+ "No session working directory set. Please specify a 'path' or use 'git_set_working_dir' first."
204
+
205
+ // Good — structured hint in error data
206
+ throw new McpError(JsonRpcErrorCode.Forbidden,
207
+ "Cannot perform 'reset --hard' on protected branch 'main' without explicit confirmation.",
208
+ { branch: 'main', operation: 'reset --hard', hint: 'Set the confirmed parameter to true to proceed.' },
209
+ );
210
+ ```
211
+
212
+ Think about the common failure modes for each tool and write error messages that guide recovery. This is part of the tool's interface design, not an afterthought.
213
+
214
+ #### Design table
215
+
216
+ Summarize each tool:
78
217
 
79
218
  | Aspect | Decision |
80
219
  |:-------|:---------|
81
220
  | **Name** | `snake_case`, verb-noun: `search_papers`, `create_task`. Prefix with server domain if ambiguous. |
82
- | **Granularity** | One tool per user intent, not per API call. A tool can call multiple APIs internally. |
83
- | **Input schema** | What the LLM provides. `.describe()` on every field. Prefer enums/literals over free strings. Optional fields with defaults over required where reasonable. |
84
- | **Output schema** | What the LLM needs to see. Curate not a raw API dump. Design for the LLM's next decision, not for a UI. |
221
+ | **Granularity** | One tool per user-meaningful workflow, not per API call. Consolidate related operations with `operation`/`mode` enum. |
222
+ | **Description** | Concrete capability statement. Add operational guidance (prerequisites, constraints, gotchas) when non-obvious. |
223
+ | **Input schema** | `.describe()` on every field. Constrained types (enums, literals, regex). Explain costs/tradeoffs of parameter choices. |
224
+ | **Output schema** | Designed for the LLM's next action. Include chaining IDs. Communicate filtering. Post-write state where useful. |
225
+ | **Error messages** | Name what went wrong and what the LLM should do about it. Include hints for common recovery paths. |
85
226
  | **Annotations** | `readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`. Helps clients auto-approve safely. |
86
227
  | **Auth scopes** | `tool:noun:read`, `tool:noun:write`. Skip for read-only or stdio-only servers. |
87
228
 
@@ -180,10 +321,13 @@ Execute the plan using the scaffolding skills:
180
321
  - [ ] External APIs/dependencies researched and verified (docs fetched, SDKs identified)
181
322
  - [ ] Domain operations mapped (nouns + verbs)
182
323
  - [ ] Each operation classified as tool, resource, prompt, or excluded
183
- - [ ] Tool names follow verb-noun `snake_case` convention
184
- - [ ] Tool outputs designed for LLM consumption, not raw API passthrough
324
+ - [ ] Related operations consolidated (operation/mode enum) — not one tool per endpoint
325
+ - [ ] Tool descriptions are concrete and include operational guidance where non-obvious
326
+ - [ ] Parameter `.describe()` text explains what the value is, what it affects, and tradeoffs
327
+ - [ ] Input schemas use constrained types (enums, literals, regex) over free strings
328
+ - [ ] Output schemas designed for LLM's next action — chaining IDs, post-write state, filtering communicated
329
+ - [ ] Error messages guide recovery — name what went wrong and what to do next
185
330
  - [ ] Annotations set correctly (`readOnlyHint`, `destructiveHint`, etc.)
186
- - [ ] Input schemas use constrained types (enums, literals) where the domain allows
187
331
  - [ ] Resource URIs use `{param}` templates, pagination planned for large lists
188
332
  - [ ] Service layer planned (or explicitly skipped with reasoning)
189
333
  - [ ] Server config env vars identified
@@ -0,0 +1,137 @@
1
+ ---
2
+ name: polish-docs-meta
3
+ description: >
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
+ metadata:
6
+ author: cyanheads
7
+ version: "1.0"
8
+ audience: external
9
+ type: workflow
10
+ ---
11
+
12
+ ## When to Use
13
+
14
+ - Server implementation is functionally complete (tools, resources, prompts, services all working)
15
+ - `bun run devcheck` passes, tests pass
16
+ - You're preparing for first commit, first release, or making the repo public
17
+ - User says "polish", "polish docs", "finalize", "make it ship-ready", "clean up docs", or similar
18
+ - Re-running after adding/removing tools, resources, or other surface area changes
19
+
20
+ Prefer running after implementation is complete, but safe to re-run at any point — steps are idempotent.
21
+
22
+ ## Prerequisites
23
+
24
+ - [ ] All tools/resources/prompts implemented and registered
25
+ - [ ] `bun run devcheck` passes
26
+ - [ ] Tests pass (`npm test`)
27
+
28
+ If these aren't met, address them first.
29
+
30
+ ## Steps
31
+
32
+ ### 1. Audit the Surface Area
33
+
34
+ Read all tool, resource, and prompt definitions. Build a mental model of what the server actually does — names, descriptions, input/output shapes, auth scopes. This inventory drives every document below.
35
+
36
+ Read:
37
+ - `src/index.ts` (what's registered in `createApp()`)
38
+ - All files in `src/mcp-server/tools/definitions/`
39
+ - All files in `src/mcp-server/resources/definitions/`
40
+ - All files in `src/mcp-server/prompts/definitions/`
41
+ - All files in `src/services/` (if any)
42
+ - `src/config/server-config.ts` (if any)
43
+
44
+ Capture: tool count, resource count, prompt count, service count, required env vars.
45
+
46
+ ### 2. README.md
47
+
48
+ 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.
49
+
50
+ ### 3. Agent Protocol (CLAUDE.md / AGENTS.md)
51
+
52
+ Update the project's agent protocol file to reflect the actual server.
53
+
54
+ Read `references/agent-protocol.md` for the full update checklist, then review the current file and address what's stale or missing:
55
+
56
+ - If a "First Session" onboarding block is still present, remove it
57
+ - If example patterns still use generic/template names (e.g., `searchItems`, `itemData`), replace with real definitions from this server
58
+ - If server-specific skills were added, update the skills table
59
+ - Verify the structure diagram matches the actual directory layout
60
+ - If custom scripts were added to `package.json`, update the commands table
61
+
62
+ ### 4. `.env.example`
63
+
64
+ Compare `.env.example` against the server config Zod schema. Add any missing server-specific vars with a comment and default (if any). Remove vars for features that no longer exist. Group by category. Preserve existing framework vars that are still relevant.
65
+
66
+ ### 5. `package.json` Metadata
67
+
68
+ Check for empty or placeholder metadata fields. Read `references/package-meta.md` for which fields matter and why. Fill in anything still missing — skip fields that are already correct.
69
+
70
+ Key fields: `description`, `repository`, `author`, `homepage`, `bugs`, `keywords`.
71
+
72
+ ### 6. `CHANGELOG.md`
73
+
74
+ If `CHANGELOG.md` doesn't exist, create it with an initial entry. If it exists, verify the latest entry reflects the current state:
75
+
76
+ ```markdown
77
+ # Changelog
78
+
79
+ ## 0.1.0 — YYYY-MM-DD
80
+
81
+ Initial release.
82
+
83
+ ### Added
84
+ - [list tools, resources, prompts, key capabilities]
85
+ ```
86
+
87
+ Use a concrete version and date. Never `[Unreleased]`.
88
+
89
+ ### 7. `LICENSE`
90
+
91
+ Confirm a license file exists. If not, ask the user which license to use (default: Apache-2.0, matching the scaffolded `package.json`). Create the file.
92
+
93
+ ### 8. `Dockerfile`
94
+
95
+ If a `Dockerfile` exists, verify the OCI labels and runtime config match the actual server:
96
+
97
+ - `org.opencontainers.image.title` matches the package name
98
+ - `org.opencontainers.image.description` is filled in (not empty placeholder)
99
+ - `org.opencontainers.image.source` points to the real repository URL (add if missing)
100
+ - Log directory path in `mkdir` and `LOGS_DIR` uses the correct server name
101
+
102
+ If no `Dockerfile` exists and the server is deployed via HTTP transport, consider scaffolding one — the template is available via `npx @cyanheads/mcp-ts-core init`.
103
+
104
+ ### 9. `docs/tree.md`
105
+
106
+ Regenerate the directory structure:
107
+
108
+ ```bash
109
+ bun run tree
110
+ ```
111
+
112
+ Review the output for anything unexpected (leftover files, missing directories).
113
+
114
+ ### 10. Final Verification
115
+
116
+ Run the full check suite one last time:
117
+
118
+ ```bash
119
+ bun run devcheck
120
+ npm test
121
+ ```
122
+
123
+ Both must pass clean.
124
+
125
+ ## Checklist
126
+
127
+ - [ ] Surface area audited — tool/resource/prompt/service inventory built
128
+ - [ ] `README.md` accurate — tool/resource tables, config, descriptions match actual code
129
+ - [ ] Agent protocol file accurate — no stale template content, real examples, structure matches reality
130
+ - [ ] `.env.example` in sync with server config schema
131
+ - [ ] `package.json` metadata complete (`description`, `repository`, `author`, `keywords`)
132
+ - [ ] `CHANGELOG.md` exists with current entry
133
+ - [ ] `LICENSE` file present
134
+ - [ ] `Dockerfile` OCI labels and runtime config accurate (if present)
135
+ - [ ] `docs/tree.md` regenerated
136
+ - [ ] `bun run devcheck` passes
137
+ - [ ] `npm test` passes
@@ -0,0 +1,78 @@
1
+ # Finalizing the Agent Protocol File
2
+
3
+ Guide for updating the project's `CLAUDE.md` or `AGENTS.md` to reflect the actual server. The file may still contain scaffolded template content (onboarding blocks, generic examples) or may have been partially updated — review the current state and address what's stale or missing.
4
+
5
+ ## What to Update
6
+
7
+ ### 1. Strip the "First Session" Block (if present)
8
+
9
+ The scaffolded template includes a `## First Session` section with one-time onboarding steps. If this section is still present, delete it entirely (header through the `---` separator after it). If it's already been removed, skip this step.
10
+
11
+ **What it looks like:**
12
+
13
+ ```markdown
14
+ ## First Session
15
+
16
+ > **Remove this section** from CLAUDE.md / AGENTS.md after completing these steps.
17
+
18
+ 1. **Read the framework API** — ...
19
+ 2. **Run the `setup` skill** — ...
20
+ 3. **Design the server** — ...
21
+
22
+ ---
23
+ ```
24
+
25
+ ### 2. Replace Example Patterns with Real Definitions
26
+
27
+ Check the Patterns section for generic template examples (e.g., `searchItems`, `itemData`, `reviewCode`). If still present, replace them with actual tool/resource/prompt definitions from the server — or the most representative ones if there are many. If the examples already reflect real definitions, verify they're still accurate.
28
+
29
+ Pick examples that:
30
+ - Show the most common or important capability
31
+ - Demonstrate any non-trivial patterns the server uses (e.g., `ctx.state`, `ctx.elicit`, `task: true`, services)
32
+ - Include a handler with real business logic, not just passthrough
33
+
34
+ Keep 1-2 examples per primitive type (tool, resource, prompt). Don't list every definition — the README handles that.
35
+
36
+ ### 3. Update the Structure Diagram
37
+
38
+ Compare the structure diagram against the actual directory layout. If it still reflects the generic template or has fallen out of date:
39
+
40
+ - Add directories/files that exist but aren't listed (e.g., `config/server-config.ts`, service directories, `worker.ts`)
41
+ - Remove entries for directories that don't exist (e.g., if no prompts were added, remove the prompts line)
42
+ - Verify nesting and naming match reality
43
+
44
+ ### 4. Update the Context Table
45
+
46
+ Review the `ctx` feature table. Remove rows for features the server doesn't use (e.g., `ctx.elicit`, `ctx.sample` if no tools call them). Add any custom context usage that's become important. The table should reflect what this server actually uses, not the full framework surface.
47
+
48
+ ### 5. Update Server Config Example
49
+
50
+ If the server has a `server-config.ts`, check whether the Patterns section still shows a generic config example. If so, replace it with the actual schema (or a representative subset). If the server has no custom config, remove the config example entirely.
51
+
52
+ ### 6. Update the Skills Table
53
+
54
+ Check for server-specific skills added to `skills/` that aren't in the table yet. Add any missing entries. Remove framework skills the server doesn't use (rare — most are useful).
55
+
56
+ ### 7. Update the Commands Table
57
+
58
+ Compare the commands table against `package.json` scripts. Add any custom scripts that are missing. Remove or rename entries that no longer match. The table should reflect the current `scripts` block.
59
+
60
+ ### 8. Update the Checklist
61
+
62
+ Review the checklist for completeness. Add server-specific items that are missing (e.g., required env vars, external service dependencies, custom naming conventions). Remove items that don't apply to this server.
63
+
64
+ ## What to Preserve
65
+
66
+ These sections should remain intact unless you have a specific reason to change them:
67
+
68
+ - **Core Rules** — universal to all servers built on the framework
69
+ - **Errors section** — the three-level escalation pattern is universal
70
+ - **Imports section** — keep unless the alias convention was changed
71
+ - **Framework reference pointer** — the line directing agents to `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md`
72
+
73
+ ## Pitfalls
74
+
75
+ - Don't duplicate the full framework CLAUDE.md into the project file. The project file covers server-specific conventions; the framework file covers the API. The pointer at the top connects them.
76
+ - Don't remove `## Core Rules` even if it seems obvious — agents read this fresh each session.
77
+ - Don't add implementation details that change frequently. The agent protocol file should be stable — update it when the server's shape changes, not on every commit.
78
+ - Don't assume this is a one-time pass. The protocol file should be revisited whenever the server's surface area changes (tools added/removed, new services, config changes).
@@ -0,0 +1,63 @@
1
+ # package.json Metadata
2
+
3
+ Fields that may still be empty or generic from scaffolding. Check each one and fill in anything that's missing or placeholder.
4
+
5
+ ## Fields to Check
6
+
7
+ | Field | Default / Scaffolded | What It Should Be |
8
+ |:------|:---------------------|:------------------|
9
+ | `name` | `{{PACKAGE_NAME}}` (substituted by init) | Verify it's correct. Use scoped name if publishing (`@org/my-server`). |
10
+ | `version` | `0.1.0` | Keep for initial development. Bump via the `release` skill. |
11
+ | `description` | `""` (empty) | One sentence: what the server does and what it wraps. Appears on npm and in `npm search`. |
12
+ | `repository` | _(often missing)_ | `{ "type": "git", "url": "https://github.com/org/repo.git" }` |
13
+ | `homepage` | _(often missing)_ | Repository URL or docs URL. |
14
+ | `bugs` | _(often missing)_ | `{ "url": "https://github.com/org/repo/issues" }` |
15
+ | `author` | _(often missing)_ | `"Name <email>"` or `{ "name": "...", "email": "..." }` |
16
+ | `keywords` | `["mcp", "mcp-server", "model-context-protocol"]` | Add domain-specific keywords. Keep the MCP ones. |
17
+ | `license` | `Apache-2.0` | Change if using a different license. Must match the LICENSE file. |
18
+
19
+ ## Fields That Should Be Correct
20
+
21
+ These are set by `init` and generally don't need changes. Verify they're present and correct:
22
+
23
+ | Field | Value | Why |
24
+ |:------|:------|:----|
25
+ | `type` | `"module"` | ESM — required by the framework |
26
+ | `main` | `"dist/index.js"` | Entry point after build |
27
+ | `types` | `"dist/index.d.ts"` | TypeScript declarations |
28
+ | `files` | `["dist/"]` | What npm publishes |
29
+ | `engines` | `{ "node": ">=22.0.0" }` | Minimum Node version |
30
+ | `scripts` | _(various)_ | Build, dev, test scripts |
31
+ | `dependencies` | `@cyanheads/mcp-ts-core`, `pino-pretty` | Core framework + log formatting |
32
+
33
+ ## Keywords
34
+
35
+ Good keywords improve npm discoverability. Include:
36
+
37
+ 1. The base MCP keywords (already scaffolded): `mcp`, `mcp-server`, `model-context-protocol`
38
+ 2. The domain: `project-management`, `task-tracking`, `acme-api`
39
+ 3. The transport if non-default: `http`, `sse`, `cloudflare-workers`
40
+
41
+ Example:
42
+
43
+ ```json
44
+ "keywords": [
45
+ "mcp",
46
+ "mcp-server",
47
+ "model-context-protocol",
48
+ "acme",
49
+ "project-management",
50
+ "task-tracking"
51
+ ]
52
+ ```
53
+
54
+ ## Publishing Checklist
55
+
56
+ If publishing to npm, also verify these (skip for private/internal servers):
57
+
58
+ - `name` doesn't conflict with an existing package
59
+ - `publishConfig.access` is `"public"` (already set by init for scoped packages)
60
+ - `files` includes everything needed at runtime (`dist/` is correct for most servers)
61
+ - `bin` is set if the server should be runnable via `npx` (add `"bin": { "my-server": "dist/index.js" }`)
62
+
63
+ The `bin` field is the most commonly missed one. Without it, `npx my-server` won't work — the client config must use `node dist/index.js` instead.
@@ -0,0 +1,183 @@
1
+ # README.md Conventions for MCP Servers
2
+
3
+ Structure and content guide for creating or updating a README for an MCP server built on `@cyanheads/mcp-ts-core`. If a README already exists, use this as a reference to audit and improve it — don't blindly rewrite sections that are already accurate.
4
+
5
+ ## Structure
6
+
7
+ Use this section order. Omit sections that don't apply (e.g., skip Docker if the server doesn't ship a container image).
8
+
9
+ ```text
10
+ # {Server Name}
11
+
12
+ One-line description of what the server does.
13
+
14
+ ## Overview
15
+ ## Features (tool/resource table)
16
+ ## Installation
17
+ ## Configuration
18
+ ## Usage
19
+ ## Docker (if Dockerfile present)
20
+ ## Development
21
+ ## License
22
+ ```
23
+
24
+ ## Section Guide
25
+
26
+ ### Title + Description
27
+
28
+ The `h1` is the server name. Follow it with a single sentence or short paragraph explaining what the server wraps and who it's for. Include badges if publishing to npm.
29
+
30
+ ```markdown
31
+ # my-mcp-server
32
+
33
+ MCP server for the Acme API — exposes project management, task tracking, and team operations to LLM clients.
34
+
35
+ [![npm](https://img.shields.io/npm/v/my-mcp-server)](https://www.npmjs.com/package/my-mcp-server)
36
+ ```
37
+
38
+ ### Overview
39
+
40
+ 2-4 sentences expanding on the description. What system does it wrap? What can the LLM do through it? What's the value proposition?
41
+
42
+ Avoid marketing language. State what it does, not why it's amazing.
43
+
44
+ ### Features
45
+
46
+ A table of tools and resources is the most useful thing a README can provide. It tells both humans and LLMs exactly what the server exposes.
47
+
48
+ **Tools table:**
49
+
50
+ ```markdown
51
+ ### Tools
52
+
53
+ | Tool | Description | Key Inputs |
54
+ |:-----|:------------|:-----------|
55
+ | `search_projects` | Search projects by name or status | `query`, `status?` |
56
+ | `create_task` | Create a new task in a project | `projectId`, `title`, `description?` |
57
+ | `update_task` | Update task status or assignment | `taskId`, `status?`, `assignee?` |
58
+ ```
59
+
60
+ **Resources table (if any):**
61
+
62
+ ```markdown
63
+ ### Resources
64
+
65
+ | URI Pattern | Description |
66
+ |:------------|:------------|
67
+ | `acme://projects/{projectId}` | Project details by ID |
68
+ | `acme://tasks/{taskId}` | Task details by ID |
69
+ ```
70
+
71
+ **Prompts table (if any):**
72
+
73
+ ```markdown
74
+ ### Prompts
75
+
76
+ | Prompt | Description |
77
+ |:-------|:------------|
78
+ | `project_summary` | Summarize a project's status and open tasks |
79
+ ```
80
+
81
+ Derive these tables directly from the actual tool/resource/prompt definitions. Use the real names and descriptions from the Zod schemas.
82
+
83
+ ### Installation
84
+
85
+ Show the install command and minimum viable configuration.
86
+
87
+ ```markdown
88
+ ## Installation
89
+
90
+ \`\`\`bash
91
+ npm install my-mcp-server
92
+ \`\`\`
93
+
94
+ ### MCP Client Configuration
95
+
96
+ Add to your MCP client config (e.g., `claude_desktop_config.json`):
97
+
98
+ \`\`\`json
99
+ {
100
+ "mcpServers": {
101
+ "my-mcp-server": {
102
+ "command": "npx",
103
+ "args": ["my-mcp-server"],
104
+ "env": {
105
+ "ACME_API_KEY": "your-api-key"
106
+ }
107
+ }
108
+ }
109
+ }
110
+ \`\`\`
111
+ ```
112
+
113
+ If the server supports HTTP transport, show that config too.
114
+
115
+ ### Configuration
116
+
117
+ Table of environment variables. Include framework vars only if the server uses non-default values.
118
+
119
+ ```markdown
120
+ ## Configuration
121
+
122
+ | Variable | Required | Default | Description |
123
+ |:---------|:---------|:--------|:------------|
124
+ | `ACME_API_KEY` | Yes | — | API key for the Acme service |
125
+ | `ACME_BASE_URL` | No | `https://api.acme.com` | API base URL |
126
+ | `MCP_TRANSPORT_TYPE` | No | `stdio` | Transport: `stdio` or `http` |
127
+ | `MCP_LOG_LEVEL` | No | `info` | Log level |
128
+ ```
129
+
130
+ Source this from the server config Zod schema and `.env.example`.
131
+
132
+ ### Usage
133
+
134
+ Brief examples of how an LLM (or human via MCP client) would use the server. Show 1-2 tool calls with example inputs/outputs if it helps understanding. Keep it short — the tool descriptions should be self-explanatory.
135
+
136
+ ### Development
137
+
138
+ Commands table for contributors.
139
+
140
+ ```markdown
141
+ ## Development
142
+
143
+ | Command | Purpose |
144
+ |:--------|:--------|
145
+ | `npm run build` | Compile TypeScript |
146
+ | `npm run dev:stdio` | Dev mode (stdio, watch) |
147
+ | `npm run dev:http` | Dev mode (HTTP, watch) |
148
+ | `bun run devcheck` | Lint + format + typecheck |
149
+ | `npm test` | Run tests |
150
+ ```
151
+
152
+ ### Docker
153
+
154
+ Include only if a `Dockerfile` exists. Show how to build and run the image.
155
+
156
+ ```markdown
157
+ ## Docker
158
+
159
+ \`\`\`bash
160
+ docker build -t my-mcp-server .
161
+ docker run -p 3010:3010 -e MY_API_KEY=your-key my-mcp-server
162
+ \`\`\`
163
+ ```
164
+
165
+ Keep it minimal — the Dockerfile's defaults handle transport, port, and log config. Only document env vars the user must provide.
166
+
167
+ ### License
168
+
169
+ One line referencing the LICENSE file.
170
+
171
+ ```markdown
172
+ ## License
173
+
174
+ Apache-2.0 — see [LICENSE](LICENSE) for details.
175
+ ```
176
+
177
+ ## Principles
178
+
179
+ - **Accuracy over aspiration.** Only document what exists. Don't describe planned features as if they're implemented.
180
+ - **Tables over prose** for structured data (tools, config, commands). Scannable and diff-friendly.
181
+ - **Real names from code.** Tool names, env vars, and URIs should match the source exactly. Copy from the definitions, don't paraphrase.
182
+ - **No badges unless publishing.** Badges for unpublished packages are noise.
183
+ - **Keep it current.** The README should be updated whenever tools are added or removed. The `polish-docs-meta` skill handles both initial creation and subsequent updates.