@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
|
@@ -7,42 +7,47 @@ Structure and content guide for creating or updating a README for an MCP server
|
|
|
7
7
|
Use this section order. Omit sections that don't apply (e.g., skip Docker/Workers if the server doesn't deploy there).
|
|
8
8
|
|
|
9
9
|
```text
|
|
10
|
-
# {Server Name}
|
|
11
|
-
|
|
10
|
+
# {Server Name} ← centered HTML block
|
|
11
|
+
[Public hosted callout if present] ← centered HTML block, directly under badges
|
|
12
|
+
Badges row ← npm, Docker, Version, Framework, MCP SDK, License, TS, Bun, Coverage
|
|
12
13
|
---
|
|
13
|
-
## Tools
|
|
14
|
-
## Resources (if any)
|
|
15
|
-
##
|
|
16
|
-
##
|
|
17
|
-
##
|
|
18
|
-
##
|
|
19
|
-
##
|
|
20
|
-
##
|
|
21
|
-
##
|
|
22
|
-
##
|
|
23
|
-
## License ← one line
|
|
14
|
+
## Tools ← grouping sentence → summary table → per-tool subsections
|
|
15
|
+
## Resources and prompts (if any) ← single combined table (Type / Name / Description)
|
|
16
|
+
## Features ← framework bullets + domain-specific bullets
|
|
17
|
+
## Getting started ← hosted (if any), bunx/npx/docker configs, HTTP one-liner, prerequisites, install
|
|
18
|
+
## Configuration ← env var table + `.env.example` pointer
|
|
19
|
+
## Running the server ← dev, production, Workers/Docker
|
|
20
|
+
## Project structure ← directory/purpose table
|
|
21
|
+
## Development guide ← link to CLAUDE.md, key rules
|
|
22
|
+
## Contributing ← brief
|
|
23
|
+
## License ← one line
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
## Section Guide
|
|
27
27
|
|
|
28
28
|
### Title Block
|
|
29
29
|
|
|
30
|
-
Centered HTML. The `<h1>` is the server name — use the scoped package name if published under a scope (e.g., `@cyanheads/my-mcp-server`). The `<p>` is a bold one-liner: what the server wraps, key capabilities, transport/deployment options.
|
|
30
|
+
Centered HTML. The `<h1>` is the server name — use the scoped package name if published under a scope (e.g., `@cyanheads/my-mcp-server`). The `<p>` is a bold one-liner: what the server wraps, key capabilities, transport/deployment options. **Nest the surface count as a `<div>` inside the same `<p>`**, separated by `•` (U+2022 bullet) — not as a second `<p>`. This matches the shipping convention across `@cyanheads/*` servers.
|
|
31
31
|
|
|
32
32
|
```html
|
|
33
33
|
<div align="center">
|
|
34
34
|
<h1>@cyanheads/my-mcp-server</h1>
|
|
35
|
-
<p><b>MCP server for the Acme API
|
|
36
|
-
<
|
|
35
|
+
<p><b>MCP server for the Acme API — search projects, manage tasks, track teams. STDIO or Streamable HTTP.</b>
|
|
36
|
+
<div>7 Tools • 2 Resources • 1 Prompt</div>
|
|
37
|
+
</p>
|
|
37
38
|
</div>
|
|
38
39
|
|
|
39
40
|
<div align="center">
|
|
40
41
|
|
|
41
|
-
[](https://www.npmjs.com/package/my-mcp-server) [](./CHANGELOG.md) [](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) [](https://www.npmjs.com/package/@cyanheads/my-mcp-server) [](./CHANGELOG.md) [](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) [](https://modelcontextprotocol.io/)
|
|
43
|
+
|
|
44
|
+
[](./LICENSE) [](https://www.typescriptlang.org/) [](https://bun.sh/)
|
|
42
45
|
|
|
43
46
|
</div>
|
|
44
47
|
```
|
|
45
48
|
|
|
49
|
+
The header tagline must match the `package.json` `description`.
|
|
50
|
+
|
|
46
51
|
**Badge selection:** All badges use `style=flat-square`. Include what applies — don't add badges for things the server doesn't have:
|
|
47
52
|
|
|
48
53
|
| Badge | When to include |
|
|
@@ -51,19 +56,41 @@ Centered HTML. The `<h1>` is the server name — use the scoped package name if
|
|
|
51
56
|
| Docker | Published to ghcr.io or Docker Hub |
|
|
52
57
|
| Version | Always — link to CHANGELOG.md |
|
|
53
58
|
| Framework | Always — links to `@cyanheads/mcp-ts-core` on npm |
|
|
54
|
-
| MCP Spec | Always — link to the spec version implemented |
|
|
55
59
|
| MCP SDK | Always — show the `@modelcontextprotocol/sdk` version |
|
|
56
60
|
| License | Always |
|
|
57
|
-
| Status | Optional — Stable, Beta, etc. |
|
|
58
61
|
| TypeScript | Always |
|
|
59
|
-
| Bun | If using Bun |
|
|
62
|
+
| Bun | If using Bun (standard for this framework) |
|
|
63
|
+
| MCP Spec | Optional — rarely included; the SDK badge usually suffices |
|
|
64
|
+
| Status | Optional — Stable, Beta, etc. |
|
|
60
65
|
| Code Coverage | If coverage is tracked |
|
|
61
66
|
|
|
62
67
|
Add a `---` horizontal rule after the badge block.
|
|
63
68
|
|
|
69
|
+
### Public Hosted Callout (if present)
|
|
70
|
+
|
|
71
|
+
If a public hosted instance is available, **promote it to a top-level callout** immediately below the badge block — don't bury it inside Getting Started. This is the highest-value piece of information for a visitor who wants to try the server with zero install.
|
|
72
|
+
|
|
73
|
+
```html
|
|
74
|
+
<div align="center">
|
|
75
|
+
|
|
76
|
+
**Public Hosted Server:** [https://my-server.example.com/mcp](https://my-server.example.com/mcp)
|
|
77
|
+
|
|
78
|
+
</div>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Keep the full connection-config JSON block inside a `### Public Hosted Instance` subsection under Getting Started (covered below). This callout is just the visibility pointer.
|
|
82
|
+
|
|
64
83
|
### Tools
|
|
65
84
|
|
|
66
|
-
This is the most important section — it tells humans and LLMs exactly what the server exposes.
|
|
85
|
+
This is the most important section — it tells humans and LLMs exactly what the server exposes. Three layers: a **grouping framing sentence**, a summary table, then per-tool subsections for tools with non-trivial behavior.
|
|
86
|
+
|
|
87
|
+
**Grouping framing sentence:** Lead with one sentence that explains how the tool surface is organized. Richer than a bare count — tells the reader what mental model to apply. Examples:
|
|
88
|
+
|
|
89
|
+
- "Seventeen tools grouped by shape — workflow helpers orchestrate common flows end-to-end, primitive tools expose fine-grained CRUD, and the instruction tool returns procedural guidance merged with live account state."
|
|
90
|
+
- "Nine tools for working with PubMed and NCBI data:"
|
|
91
|
+
- "Five tools covering project lifecycle — discovery, task CRUD, and team analytics."
|
|
92
|
+
|
|
93
|
+
If the tools aren't meaningfully grouped, a single sentence count ("Seven tools for working with Acme data:") is acceptable.
|
|
67
94
|
|
|
68
95
|
**Summary table:**
|
|
69
96
|
|
|
@@ -79,8 +106,6 @@ Seven tools for working with Acme data:
|
|
|
79
106
|
| `get_task` | Fetch one or more tasks by ID, with full or summary data. |
|
|
80
107
|
```
|
|
81
108
|
|
|
82
|
-
Lead with a one-line count: "Seven tools for working with X data:" (or "Three tools", etc.).
|
|
83
|
-
|
|
84
109
|
**Per-tool subsections:**
|
|
85
110
|
|
|
86
111
|
Below the table, add a `### tool_name` subsection for each tool that has meaningful detail beyond its one-line description. Include:
|
|
@@ -110,34 +135,35 @@ Fetch one or more tasks by ID, with full data or concise summaries.
|
|
|
110
135
|
- Batch fetch up to 5 tasks at once
|
|
111
136
|
- Full data includes subtasks, comments, attachments, and history
|
|
112
137
|
- Partial success reporting when some tasks in a batch fail
|
|
113
|
-
|
|
114
|
-
[View detailed examples](./examples/get_task.md)
|
|
115
138
|
```
|
|
116
139
|
|
|
117
140
|
Skip the per-tool subsection for simple tools where the table description says everything (e.g., a `get_field_values` lookup tool).
|
|
118
141
|
|
|
119
|
-
### Resources (
|
|
142
|
+
### Resources and Prompts (combined)
|
|
143
|
+
|
|
144
|
+
**Use a single combined table with a `Type` column** rather than separate `## Resources` and `## Prompts` sections. This is the shipping convention — it scales better when a server has only 1 or 2 of each, and co-locates related content.
|
|
120
145
|
|
|
121
146
|
```markdown
|
|
122
|
-
## Resources
|
|
147
|
+
## Resources and prompts
|
|
123
148
|
|
|
124
|
-
|
|
|
125
|
-
|
|
126
|
-
| `acme://projects/{projectId}` | Project details by ID |
|
|
127
|
-
| `acme://tasks/{taskId}` | Task details by ID |
|
|
149
|
+
| Type | Name | Description |
|
|
150
|
+
|:---|:---|:---|
|
|
151
|
+
| Resource | `acme://projects/{projectId}` | Project details by ID |
|
|
152
|
+
| Resource | `acme://tasks/{taskId}` | Task details by ID |
|
|
153
|
+
| Prompt | `project_summary` | Summarize a project's status and open tasks |
|
|
128
154
|
```
|
|
129
155
|
|
|
130
|
-
|
|
156
|
+
Use singular ("Resource and prompt") if there's only one of each.
|
|
131
157
|
|
|
132
|
-
|
|
133
|
-
## Prompts
|
|
158
|
+
**Always include the tool-coverage note** directly under the table. Many MCP clients are tool-only and don't surface resources — this tells both the reader and downstream agents that the data is still reachable:
|
|
134
159
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
| `project_summary` | Summarize a project's status and open tasks |
|
|
160
|
+
```markdown
|
|
161
|
+
All resource data is also reachable via tools. Large collections (`projects`, `tasks`) are not exposed as resources — use the `list` operation on the corresponding tool instead.
|
|
138
162
|
```
|
|
139
163
|
|
|
140
|
-
|
|
164
|
+
If a prompt has an associated design doc or reference, link it in the same paragraph: `Design reference for the prompt: [\`docs/email-design-playbook.md\`](./docs/email-design-playbook.md).`
|
|
165
|
+
|
|
166
|
+
Derive all tool/resource/prompt rows directly from the actual definitions. Use the real names and descriptions from the Zod schemas.
|
|
141
167
|
|
|
142
168
|
### Features
|
|
143
169
|
|
|
@@ -146,90 +172,166 @@ Two subsection groups: framework capabilities, then domain-specific capabilities
|
|
|
146
172
|
```markdown
|
|
147
173
|
## Features
|
|
148
174
|
|
|
149
|
-
Built on [`@cyanheads/mcp-ts-core`](https://
|
|
175
|
+
Built on [`@cyanheads/mcp-ts-core`](https://www.npmjs.com/package/@cyanheads/mcp-ts-core):
|
|
150
176
|
|
|
151
|
-
- Declarative tool definitions — single file per
|
|
152
|
-
- Unified error handling
|
|
153
|
-
- Pluggable auth
|
|
177
|
+
- Declarative tool, resource, and prompt definitions — single file per primitive, framework handles registration and validation
|
|
178
|
+
- Unified error handling — handlers throw, framework catches, classifies, and formats
|
|
179
|
+
- Pluggable auth: `none`, `jwt`, `oauth`
|
|
154
180
|
- Swappable storage backends: `in-memory`, `filesystem`, `Supabase`, `Cloudflare KV/R2/D1`
|
|
155
181
|
- Structured logging with optional OpenTelemetry tracing
|
|
156
|
-
-
|
|
182
|
+
- STDIO and Streamable HTTP transports
|
|
157
183
|
|
|
158
184
|
Acme-specific:
|
|
159
185
|
|
|
160
186
|
- Type-safe client for the Acme v2 API
|
|
161
187
|
- Automatic cleaning and simplification of API responses for agent consumption
|
|
188
|
+
- Workflow tools parallelize related sub-requests under a configurable concurrency limit
|
|
162
189
|
```
|
|
163
190
|
|
|
164
191
|
### Getting Started
|
|
165
192
|
|
|
166
|
-
Lead with the lowest-friction option. If a public hosted instance exists, show that first. Then
|
|
193
|
+
Lead with the lowest-friction option. If a public hosted instance exists, show that first. Then the **three standard install configs in order — `bunx`, `npx`, `docker run`** — followed by the HTTP one-liner quickstart, then prerequisites and install steps.
|
|
167
194
|
|
|
168
|
-
|
|
169
|
-
## Getting Started
|
|
195
|
+
**Standard three-block pattern** (the house style across shipping `@cyanheads/*` servers):
|
|
170
196
|
|
|
171
|
-
|
|
197
|
+
```markdown
|
|
198
|
+
## Getting started
|
|
172
199
|
|
|
173
|
-
|
|
200
|
+
Add the following to your MCP client configuration file. See [`docs/api-key.md`](./docs/api-key.md) for how to generate an API key.
|
|
174
201
|
|
|
175
202
|
\`\`\`json
|
|
176
203
|
{
|
|
177
204
|
"mcpServers": {
|
|
178
205
|
"my-server": {
|
|
179
|
-
"type": "
|
|
180
|
-
"
|
|
206
|
+
"type": "stdio",
|
|
207
|
+
"command": "bunx",
|
|
208
|
+
"args": ["@cyanheads/my-mcp-server@latest"],
|
|
209
|
+
"env": {
|
|
210
|
+
"MCP_TRANSPORT_TYPE": "stdio",
|
|
211
|
+
"MCP_LOG_LEVEL": "info",
|
|
212
|
+
"ACME_API_KEY": "your-api-key"
|
|
213
|
+
}
|
|
181
214
|
}
|
|
182
215
|
}
|
|
183
216
|
}
|
|
184
217
|
\`\`\`
|
|
185
218
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
Add to your MCP client config (e.g., `claude_desktop_config.json`):
|
|
219
|
+
Or with npx (no Bun required):
|
|
189
220
|
|
|
190
221
|
\`\`\`json
|
|
191
222
|
{
|
|
192
223
|
"mcpServers": {
|
|
193
|
-
"my-
|
|
224
|
+
"my-server": {
|
|
194
225
|
"type": "stdio",
|
|
195
|
-
"command": "
|
|
196
|
-
"args": ["my-mcp-server@latest"],
|
|
226
|
+
"command": "npx",
|
|
227
|
+
"args": ["-y", "@cyanheads/my-mcp-server@latest"],
|
|
197
228
|
"env": {
|
|
198
|
-
"
|
|
199
|
-
"
|
|
229
|
+
"MCP_TRANSPORT_TYPE": "stdio",
|
|
230
|
+
"MCP_LOG_LEVEL": "info",
|
|
231
|
+
"ACME_API_KEY": "your-api-key"
|
|
200
232
|
}
|
|
201
233
|
}
|
|
202
234
|
}
|
|
203
235
|
}
|
|
204
236
|
\`\`\`
|
|
205
237
|
|
|
238
|
+
Or with Docker:
|
|
239
|
+
|
|
240
|
+
\`\`\`json
|
|
241
|
+
{
|
|
242
|
+
"mcpServers": {
|
|
243
|
+
"my-server": {
|
|
244
|
+
"type": "stdio",
|
|
245
|
+
"command": "docker",
|
|
246
|
+
"args": [
|
|
247
|
+
"run", "-i", "--rm",
|
|
248
|
+
"-e", "MCP_TRANSPORT_TYPE=stdio",
|
|
249
|
+
"-e", "ACME_API_KEY=your-api-key",
|
|
250
|
+
"ghcr.io/cyanheads/my-mcp-server:latest"
|
|
251
|
+
]
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
\`\`\`
|
|
256
|
+
|
|
257
|
+
For Streamable HTTP, set the transport and start the server:
|
|
258
|
+
|
|
259
|
+
\`\`\`sh
|
|
260
|
+
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 ACME_API_KEY=... bun run start:http
|
|
261
|
+
# Server listens at http://localhost:3010/mcp
|
|
262
|
+
\`\`\`
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Refer to "your MCP client configuration file" generically — don't prescribe `claude_desktop_config.json` by name. Different clients use different config paths and the server isn't client-specific.
|
|
266
|
+
|
|
267
|
+
**If a public hosted instance exists**, precede the three-block pattern with a `### Public Hosted Instance` subsection and wrap the local configs in a `### Self-Hosted / Local` subsection:
|
|
268
|
+
|
|
269
|
+
```markdown
|
|
270
|
+
### Public Hosted Instance
|
|
271
|
+
|
|
272
|
+
A public instance is available at `https://my-server.example.com/mcp` — no installation required. Point any MCP client at it via Streamable HTTP:
|
|
273
|
+
|
|
274
|
+
\`\`\`json
|
|
275
|
+
{
|
|
276
|
+
"mcpServers": {
|
|
277
|
+
"my-server": {
|
|
278
|
+
"type": "streamable-http",
|
|
279
|
+
"url": "https://my-server.example.com/mcp"
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
\`\`\`
|
|
284
|
+
|
|
285
|
+
### Self-Hosted / Local
|
|
286
|
+
|
|
287
|
+
[bunx / npx / docker blocks here]
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
**Prerequisites:** Include a Bun version line and any domain-specific setup (API key format, rate-limit tiers, required accounts). Don't just list Bun — readers need to know what else to prepare.
|
|
291
|
+
|
|
292
|
+
```markdown
|
|
206
293
|
### Prerequisites
|
|
207
294
|
|
|
208
|
-
- [Bun v1.2
|
|
295
|
+
- [Bun v1.3.2](https://bun.sh/) or higher (or Node.js v22+).
|
|
296
|
+
- An Acme API key — see [`docs/api-key.md`](./docs/api-key.md) for how to generate one.
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
**Installation:** Standard four steps (clone, cd, install, configure env):
|
|
209
300
|
|
|
301
|
+
```markdown
|
|
210
302
|
### Installation
|
|
211
303
|
|
|
212
304
|
1. **Clone the repository:**
|
|
305
|
+
|
|
213
306
|
\`\`\`sh
|
|
214
307
|
git clone https://github.com/cyanheads/my-mcp-server.git
|
|
215
308
|
\`\`\`
|
|
216
309
|
|
|
217
310
|
2. **Navigate into the directory:**
|
|
311
|
+
|
|
218
312
|
\`\`\`sh
|
|
219
313
|
cd my-mcp-server
|
|
220
314
|
\`\`\`
|
|
221
315
|
|
|
222
316
|
3. **Install dependencies:**
|
|
317
|
+
|
|
223
318
|
\`\`\`sh
|
|
224
319
|
bun install
|
|
225
320
|
\`\`\`
|
|
321
|
+
|
|
322
|
+
4. **Configure environment:**
|
|
323
|
+
|
|
324
|
+
\`\`\`sh
|
|
325
|
+
cp .env.example .env
|
|
326
|
+
# edit .env and set required vars
|
|
327
|
+
\`\`\`
|
|
226
328
|
```
|
|
227
329
|
|
|
228
|
-
Omit the
|
|
330
|
+
Omit the clone/install steps if the server is npm-only (not meant to be cloned).
|
|
229
331
|
|
|
230
332
|
### Configuration
|
|
231
333
|
|
|
232
|
-
Table of environment variables. Include framework vars only if the server uses non-default values.
|
|
334
|
+
Table of environment variables. Include framework vars only if the server uses non-default values. Mark required vars with bold **Required.** in the description rather than a separate column. **Close with a pointer to `.env.example`** for the full list of optional overrides.
|
|
233
335
|
|
|
234
336
|
```markdown
|
|
235
337
|
## Configuration
|
|
@@ -238,6 +340,7 @@ Table of environment variables. Include framework vars only if the server uses n
|
|
|
238
340
|
|:---------|:------------|:--------|
|
|
239
341
|
| `ACME_API_KEY` | **Required.** API key for the Acme service. | — |
|
|
240
342
|
| `ACME_BASE_URL` | API base URL. | `https://api.acme.com` |
|
|
343
|
+
| `ACME_TIMEOUT_MS` | Per-request timeout in milliseconds. | `60000` |
|
|
241
344
|
| `MCP_TRANSPORT_TYPE` | Transport: `stdio` or `http`. | `stdio` |
|
|
242
345
|
| `MCP_HTTP_PORT` | Port for HTTP server. | `3010` |
|
|
243
346
|
| `MCP_AUTH_MODE` | Auth mode: `none`, `jwt`, or `oauth`. | `none` |
|
|
@@ -245,74 +348,105 @@ Table of environment variables. Include framework vars only if the server uses n
|
|
|
245
348
|
| `LOGS_DIR` | Directory for log files (Node.js only). | `<project-root>/logs` |
|
|
246
349
|
| `STORAGE_PROVIDER_TYPE` | Storage backend. | `in-memory` |
|
|
247
350
|
| `OTEL_ENABLED` | Enable OpenTelemetry. | `false` |
|
|
351
|
+
|
|
352
|
+
See [`.env.example`](./.env.example) for the full list of optional overrides.
|
|
248
353
|
```
|
|
249
354
|
|
|
250
|
-
Source from the server config Zod schema and `.env.example`.
|
|
355
|
+
Source from the server config Zod schema and `.env.example`.
|
|
251
356
|
|
|
252
357
|
### Running the Server
|
|
253
358
|
|
|
254
|
-
Separate from Getting Started. Show build + run
|
|
359
|
+
Separate from Getting Started. Show dev, build + run, and Workers/Docker deployment if applicable.
|
|
255
360
|
|
|
256
361
|
```markdown
|
|
257
|
-
## Running the
|
|
362
|
+
## Running the server
|
|
363
|
+
|
|
364
|
+
### Local development
|
|
258
365
|
|
|
259
|
-
|
|
366
|
+
- **Hot-reload dev mode:**
|
|
367
|
+
|
|
368
|
+
\`\`\`sh
|
|
369
|
+
bun run dev:stdio
|
|
370
|
+
bun run dev:http
|
|
371
|
+
\`\`\`
|
|
260
372
|
|
|
261
373
|
- **Build and run the production version:**
|
|
374
|
+
|
|
262
375
|
\`\`\`sh
|
|
263
|
-
|
|
264
|
-
bun run
|
|
376
|
+
# One-time build
|
|
377
|
+
bun run rebuild
|
|
378
|
+
|
|
379
|
+
# Run the built server
|
|
380
|
+
bun run start:stdio
|
|
381
|
+
# or
|
|
382
|
+
bun run start:http
|
|
265
383
|
\`\`\`
|
|
266
384
|
|
|
267
385
|
- **Run checks and tests:**
|
|
386
|
+
|
|
268
387
|
\`\`\`sh
|
|
269
|
-
bun run devcheck
|
|
270
|
-
bun run test
|
|
388
|
+
bun run devcheck # Lint, format, typecheck, security
|
|
389
|
+
bun run test # Vitest test suite
|
|
390
|
+
bun run lint:mcp # Validate MCP definitions against spec
|
|
271
391
|
\`\`\`
|
|
272
392
|
|
|
393
|
+
### Docker
|
|
394
|
+
|
|
395
|
+
\`\`\`sh
|
|
396
|
+
docker build -t my-mcp-server .
|
|
397
|
+
docker run --rm -e ACME_API_KEY=your-key -p 3010:3010 my-mcp-server
|
|
398
|
+
\`\`\`
|
|
399
|
+
|
|
400
|
+
The Dockerfile defaults to HTTP transport, stateless session mode, and logs to `/var/log/my-mcp-server`. OpenTelemetry peer dependencies are installed by default — build with `--build-arg OTEL_ENABLED=false` to omit them.
|
|
401
|
+
|
|
273
402
|
### Cloudflare Workers
|
|
274
403
|
|
|
275
404
|
1. **Build the Worker bundle:**
|
|
405
|
+
|
|
276
406
|
\`\`\`sh
|
|
277
407
|
bun run build:worker
|
|
278
408
|
\`\`\`
|
|
279
409
|
|
|
280
410
|
2. **Deploy:**
|
|
411
|
+
|
|
281
412
|
\`\`\`sh
|
|
282
413
|
bun run deploy:prod
|
|
283
414
|
\`\`\`
|
|
284
415
|
```
|
|
285
416
|
|
|
286
|
-
Include the Docker or Workers subsection only if the server supports it.
|
|
417
|
+
Include the Docker or Workers subsection only if the server supports it. The Docker trailing paragraph (log directory, OTEL build arg) is important — it documents Dockerfile behavior that isn't obvious from the build command.
|
|
287
418
|
|
|
288
419
|
### Project Structure
|
|
289
420
|
|
|
290
421
|
Directory/purpose table orienting contributors to the codebase.
|
|
291
422
|
|
|
292
423
|
```markdown
|
|
293
|
-
## Project
|
|
424
|
+
## Project structure
|
|
294
425
|
|
|
295
426
|
| Directory | Purpose |
|
|
296
427
|
|:----------|:--------|
|
|
428
|
+
| `src/index.ts` | `createApp()` entry point — registers tools/resources/prompts and inits services. |
|
|
429
|
+
| `src/config` | Server-specific environment variable parsing and validation with Zod. |
|
|
297
430
|
| `src/mcp-server/tools` | Tool definitions (`*.tool.ts`). |
|
|
298
431
|
| `src/mcp-server/resources` | Resource definitions (`*.resource.ts`). |
|
|
432
|
+
| `src/mcp-server/prompts` | Prompt definitions (`*.prompt.ts`). |
|
|
299
433
|
| `src/services` | Domain service integrations. |
|
|
300
|
-
| `src/config` | Environment variable parsing and validation with Zod. |
|
|
301
434
|
| `tests/` | Unit and integration tests mirroring `src/`. |
|
|
302
435
|
```
|
|
303
436
|
|
|
304
437
|
### Development Guide
|
|
305
438
|
|
|
306
|
-
Brief — link to CLAUDE.md for full details. State
|
|
439
|
+
Brief — link to CLAUDE.md for full details. State 3-4 key rules. **Include the "validate → normalize → never fabricate" bullet** — it's the canonical anti-hallucination convention for external API wrappers and reinforces the framework's `no fabricated signal` principle.
|
|
307
440
|
|
|
308
441
|
```markdown
|
|
309
|
-
## Development
|
|
442
|
+
## Development guide
|
|
310
443
|
|
|
311
444
|
See [`CLAUDE.md`](./CLAUDE.md) for development guidelines and architectural rules. The short version:
|
|
312
445
|
|
|
313
446
|
- Handlers throw, framework catches — no `try/catch` in tool logic
|
|
314
|
-
- Use `ctx.log` for
|
|
315
|
-
- Register new tools and resources
|
|
447
|
+
- Use `ctx.log` for request-scoped logging, `ctx.state` for tenant-scoped storage
|
|
448
|
+
- Register new tools and resources via the barrels in `src/mcp-server/*/definitions/index.ts`
|
|
449
|
+
- Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields
|
|
316
450
|
```
|
|
317
451
|
|
|
318
452
|
### Contributing
|
|
@@ -320,7 +454,7 @@ See [`CLAUDE.md`](./CLAUDE.md) for development guidelines and architectural rule
|
|
|
320
454
|
```markdown
|
|
321
455
|
## Contributing
|
|
322
456
|
|
|
323
|
-
Issues and pull requests are welcome. Run checks before submitting:
|
|
457
|
+
Issues and pull requests are welcome. Run checks and tests before submitting:
|
|
324
458
|
|
|
325
459
|
\`\`\`sh
|
|
326
460
|
bun run devcheck
|
|
@@ -343,8 +477,12 @@ Apache-2.0 — see [LICENSE](LICENSE) for details.
|
|
|
343
477
|
- **Accuracy over aspiration.** Only document what exists. Don't describe planned features as if they're implemented.
|
|
344
478
|
- **Tools first.** The tool surface is the most important content. Lead with it.
|
|
345
479
|
- **Tables over prose** for structured data (tools, config, directories). Scannable and diff-friendly.
|
|
346
|
-
- **Two-layer tool docs.**
|
|
480
|
+
- **Two-layer tool docs.** Grouping sentence + summary table for quick scanning, per-tool subsections for detail. Skip subsections for trivial tools.
|
|
481
|
+
- **Combined resources + prompts.** Single table with a `Type` column, not separate sections.
|
|
482
|
+
- **Promote hosted instances.** If there's a public URL, put it in a top-level callout under the badges — not buried in Getting Started.
|
|
483
|
+
- **Three install configs.** `bunx`, `npx`, `docker run` in that order. Each as a complete MCP-client JSON block.
|
|
347
484
|
- **Real names from code.** Tool names, env vars, and URIs must match the source exactly. Copy from the definitions, don't paraphrase.
|
|
348
|
-
- **Lowest friction first.**
|
|
485
|
+
- **Lowest friction first.** Hosted instance > bunx > npx > docker > clone.
|
|
349
486
|
- **No badges unless publishing.** Badges for unpublished packages are noise.
|
|
487
|
+
- **Client-agnostic framing.** Say "your MCP client configuration file", not `claude_desktop_config.json`.
|
|
350
488
|
- **Keep it current.** Update the README whenever tools are added or removed.
|
package/skills/setup/SKILL.md
CHANGED
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
Post-init orientation for an MCP server built on @cyanheads/mcp-ts-core. Use after running `@cyanheads/mcp-ts-core init` to understand the project structure, conventions, and skill sync model. Also use when onboarding to an existing project for the first time.
|
|
5
5
|
metadata:
|
|
6
6
|
author: cyanheads
|
|
7
|
-
version: "1.
|
|
7
|
+
version: "1.3"
|
|
8
8
|
audience: external
|
|
9
9
|
type: workflow
|
|
10
10
|
---
|
package/templates/AGENTS.md
CHANGED
|
@@ -74,8 +74,10 @@ export const searchItems = tool('search_items', {
|
|
|
74
74
|
return { items };
|
|
75
75
|
},
|
|
76
76
|
|
|
77
|
-
// format() populates content[] — the
|
|
78
|
-
//
|
|
77
|
+
// format() populates content[] — the markdown twin of structuredContent.
|
|
78
|
+
// Different clients read different surfaces (Claude Code → structuredContent,
|
|
79
|
+
// Claude Desktop → content[]); both must carry the same data.
|
|
80
|
+
// Enforced at lint time: every field in `output` must appear in the rendered text.
|
|
79
81
|
format: (result) => [{
|
|
80
82
|
type: 'text',
|
|
81
83
|
text: result.items.map(i => `**${i.id}**: ${i.name}`).join('\n'),
|
|
@@ -293,7 +295,7 @@ import { getMyService } from '@/services/my-domain/my-service.js';
|
|
|
293
295
|
- [ ] JSDoc `@fileoverview` + `@module` on every file
|
|
294
296
|
- [ ] `ctx.log` for logging, `ctx.state` for storage
|
|
295
297
|
- [ ] Handlers throw on failure — error factories or plain `Error`, no try/catch
|
|
296
|
-
- [ ] `format()` renders all data the LLM needs — `content[]`
|
|
298
|
+
- [ ] `format()` renders all data the LLM needs — different clients forward different surfaces (Claude Code → `structuredContent`, Claude Desktop → `content[]`); both must carry the same data
|
|
297
299
|
- [ ] If wrapping external API: raw/domain/output schemas reviewed against real upstream sparsity/nullability before finalizing required vs optional fields
|
|
298
300
|
- [ ] If wrapping external API: normalization and `format()` preserve uncertainty; do not fabricate facts from missing upstream data
|
|
299
301
|
- [ ] If wrapping external API: tests include at least one sparse payload case with omitted upstream fields
|
package/templates/CLAUDE.md
CHANGED
|
@@ -74,8 +74,10 @@ export const searchItems = tool('search_items', {
|
|
|
74
74
|
return { items };
|
|
75
75
|
},
|
|
76
76
|
|
|
77
|
-
// format() populates content[] — the
|
|
78
|
-
//
|
|
77
|
+
// format() populates content[] — the markdown twin of structuredContent.
|
|
78
|
+
// Different clients read different surfaces (Claude Code → structuredContent,
|
|
79
|
+
// Claude Desktop → content[]); both must carry the same data.
|
|
80
|
+
// Enforced at lint time: every field in `output` must appear in the rendered text.
|
|
79
81
|
format: (result) => [{
|
|
80
82
|
type: 'text',
|
|
81
83
|
text: result.items.map(i => `**${i.id}**: ${i.name}`).join('\n'),
|
|
@@ -293,7 +295,7 @@ import { getMyService } from '@/services/my-domain/my-service.js';
|
|
|
293
295
|
- [ ] JSDoc `@fileoverview` + `@module` on every file
|
|
294
296
|
- [ ] `ctx.log` for logging, `ctx.state` for storage
|
|
295
297
|
- [ ] Handlers throw on failure — error factories or plain `Error`, no try/catch
|
|
296
|
-
- [ ] `format()` renders all data the LLM needs — `content[]`
|
|
298
|
+
- [ ] `format()` renders all data the LLM needs — different clients forward different surfaces (Claude Code → `structuredContent`, Claude Desktop → `content[]`); both must carry the same data
|
|
297
299
|
- [ ] If wrapping external API: raw/domain/output schemas reviewed against real upstream sparsity/nullability before finalizing required vs optional fields
|
|
298
300
|
- [ ] If wrapping external API: normalization and `format()` preserve uncertainty; do not fabricate facts from missing upstream data
|
|
299
301
|
- [ ] If wrapping external API: tests include at least one sparse payload case with omitted upstream fields
|
|
@@ -21,8 +21,9 @@ export const echoTool = tool('template_echo_message', {
|
|
|
21
21
|
return { message: input.message };
|
|
22
22
|
},
|
|
23
23
|
|
|
24
|
-
// format() populates MCP content[] — the
|
|
25
|
-
//
|
|
24
|
+
// format() populates MCP content[] — the markdown twin of structuredContent.
|
|
25
|
+
// Different clients read different surfaces (Claude Code → structuredContent,
|
|
26
|
+
// Claude Desktop → content[]); both must carry the same data.
|
|
26
27
|
// This echo tool is trivial; real tools should render every relevant field.
|
|
27
28
|
format: (result) => [{ type: 'text', text: result.message }],
|
|
28
29
|
});
|
package/skills/devcheck/SKILL.md
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: devcheck
|
|
3
|
-
description: >
|
|
4
|
-
Lint, format, typecheck, and verify the project is clean. Use after making changes, before committing, or when the user asks to verify quality.
|
|
5
|
-
metadata:
|
|
6
|
-
author: cyanheads
|
|
7
|
-
version: "1.3"
|
|
8
|
-
audience: external
|
|
9
|
-
type: workflow
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
## What It Runs
|
|
13
|
-
|
|
14
|
-
`bun run devcheck` runs a broader check suite than just lint + types. By default it includes local hygiene checks, MCP definition linting, Biome, TypeScript, and slow dependency/security checks unless `--fast` is passed. Tests are opt-in via `--test`.
|
|
15
|
-
|
|
16
|
-
| Check | Tool | Notes |
|
|
17
|
-
|:------|:-----|:------|
|
|
18
|
-
| TODOs / FIXMEs | `git grep` | Fails on tracked TODO/FIXME markers outside excluded files |
|
|
19
|
-
| Tracked secrets | `git ls-files` | Flags tracked `.env`, keys, credentials, and similar sensitive files |
|
|
20
|
-
| MCP definitions | `bun run scripts/lint-mcp.ts` | Validates tool/resource/prompt definitions against framework rules |
|
|
21
|
-
| Biome | `biome check` | Unified lint + format — read-only by default |
|
|
22
|
-
| TypeScript | `tsc --noEmit` | Full project type check |
|
|
23
|
-
| Unused dependencies | `depcheck` | Runs by default; network-free but slower on large repos |
|
|
24
|
-
| Security audit | `bun audit` | Runs by default unless `--fast` or `--no-audit` |
|
|
25
|
-
| Outdated dependencies | `bun outdated` | Runs by default unless `--fast` or `--no-deps` |
|
|
26
|
-
| Tests | `vitest run` | Off by default; enable with `bun run devcheck --test` |
|
|
27
|
-
|
|
28
|
-
To auto-fix lint/format issues, run `bun run format`.
|
|
29
|
-
|
|
30
|
-
## Steps
|
|
31
|
-
|
|
32
|
-
1. Run `bun run devcheck`
|
|
33
|
-
2. Read the failing checks in the summary and per-check output
|
|
34
|
-
3. Fix the reported issues
|
|
35
|
-
4. Re-run `bun run devcheck` until clean
|
|
36
|
-
5. If the change touches runtime behavior, also run `bun run devcheck --test` or `bun run test`
|
|
37
|
-
6. Do not consider this skill complete until the required commands exit successfully with no errors
|
|
38
|
-
|
|
39
|
-
## Common Issues
|
|
40
|
-
|
|
41
|
-
| Check | Error Type | Typical Fix |
|
|
42
|
-
|:------|:-----------|:------------|
|
|
43
|
-
| TODOs / FIXMEs | Tracked work markers | Resolve or remove the marker before committing |
|
|
44
|
-
| Tracked secrets | Sensitive files in git | Add to `.gitignore` and remove from the index |
|
|
45
|
-
| MCP definitions | Definition lint errors | Fix schema/name/annotation issues reported by `lint-mcp` |
|
|
46
|
-
| Biome | Lint/format errors | Run `bun run format` to auto-fix, or address the flagged rule manually |
|
|
47
|
-
| TypeScript | Type errors | Fix type mismatches, missing properties, incorrect generics |
|
|
48
|
-
| Security audit | Vulnerabilities in direct deps | Update or replace the affected dependency |
|
|
49
|
-
| Outdated deps | Stale package versions | Run `bun update` or allowlist intentionally pinned packages |
|
|
50
|
-
|
|
51
|
-
## Checklist
|
|
52
|
-
|
|
53
|
-
- [ ] `bun run devcheck` exits with no errors
|
|
54
|
-
- [ ] Tests run when needed (`bun run devcheck --test` or `bun run test`)
|