@cyanheads/mcp-ts-core 0.2.11 → 0.2.12
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 +6 -2
- package/README.md +1 -1
- package/dist/utils/telemetry/instrumentation.js +1 -1
- package/dist/utils/telemetry/instrumentation.js.map +1 -1
- package/package.json +10 -9
- package/skills/add-resource/SKILL.md +1 -0
- package/skills/add-tool/SKILL.md +32 -0
- package/skills/api-testing/SKILL.md +35 -0
- package/skills/api-workers/SKILL.md +1 -0
- package/templates/CLAUDE.md +1 -0
package/CLAUDE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Agent Protocol
|
|
2
2
|
|
|
3
|
-
**Package:** `@cyanheads/mcp-ts-core` · **Version:** 0.2.
|
|
3
|
+
**Package:** `@cyanheads/mcp-ts-core` · **Version:** 0.2.12
|
|
4
4
|
**npm:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) · **Docker:** [ghcr.io/cyanheads/mcp-ts-core](https://ghcr.io/cyanheads/mcp-ts-core)
|
|
5
5
|
|
|
6
6
|
> **Developer note:** Never assume. Read related files and docs before making changes. Read full file content for context. Never edit a file before reading it.
|
|
@@ -73,6 +73,9 @@ await createApp({
|
|
|
73
73
|
tools: allToolDefinitions,
|
|
74
74
|
resources: allResourceDefinitions,
|
|
75
75
|
prompts: allPromptDefinitions,
|
|
76
|
+
extensions: { // SEP-2133 extensions advertised in capabilities
|
|
77
|
+
'vendor/my-extension': { /* extension config */ },
|
|
78
|
+
},
|
|
76
79
|
setup(core) { // runs after core services init, before transport starts
|
|
77
80
|
initMyService(core.config, core.storage);
|
|
78
81
|
},
|
|
@@ -219,7 +222,7 @@ export const myResource = resource('myscheme://{itemId}/data', {
|
|
|
219
222
|
});
|
|
220
223
|
```
|
|
221
224
|
|
|
222
|
-
Handler receives `(params, ctx)` — URI on `ctx.uri` if needed. Large lists must use `extractCursor`/`paginateArray` from `/utils`.
|
|
225
|
+
Handler receives `(params, ctx)` — URI on `ctx.uri` if needed. Optional `size` (bytes) for content size metadata. Large lists must use `extractCursor`/`paginateArray` from `/utils`.
|
|
223
226
|
|
|
224
227
|
---
|
|
225
228
|
|
|
@@ -461,6 +464,7 @@ Detailed method signatures, options, and examples live in skill files. Read the
|
|
|
461
464
|
## Code Style & Checklist
|
|
462
465
|
|
|
463
466
|
- **Validation:** Zod schemas, all fields need `.describe()`. Schemas must be JSON-Schema-serializable — avoid `z.custom()`, `z.date()`, `z.transform()`, `z.bigint()`, `z.symbol()`, `z.void()`, `z.map()`, `z.set()`, `z.function()`, `z.nan()` (the linter catches these at startup)
|
|
467
|
+
- **Form-client safety:** Form-based MCP clients (MCP Inspector, web UIs) send optional object fields with empty-string inner values instead of `undefined`. Don't reject with `.min(1)` on optional fields — guard for meaningful values in the handler (`if (input.dateRange?.minDate && input.dateRange?.maxDate)`). Test with both omitted and empty-value payloads.
|
|
464
468
|
- **Logging:** Framework auto-instruments all handler calls. `ctx.log` for domain-specific logging in handlers, global `logger` for lifecycle/background
|
|
465
469
|
- **Errors:** handlers throw — error factories (`notFound()`, `validationError()`, etc.) when the code matters, plain `Error` for don't-care cases. Framework catches and classifies. `ErrorHandler.tryCatch` for services only.
|
|
466
470
|
- **Secrets:** server config only — no hardcoded credentials
|
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
<div align="center">
|
|
7
7
|
|
|
8
|
-
[](./CHANGELOG.md) [](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-11-25/changelog.mdx) [](https://modelcontextprotocol.io/) [](./LICENSE)
|
|
9
9
|
|
|
10
10
|
[](https://www.typescriptlang.org/) [](https://bun.sh/)
|
|
11
11
|
|
|
@@ -158,7 +158,7 @@ export async function initializeOpenTelemetry() {
|
|
|
158
158
|
sdk = new NodeSDK({
|
|
159
159
|
resource,
|
|
160
160
|
spanProcessors,
|
|
161
|
-
...(metricReader && { metricReader }),
|
|
161
|
+
...(metricReader && { metricReaders: [metricReader] }),
|
|
162
162
|
sampler: new TraceIdRatioBasedSampler(config.openTelemetry.samplingRatio),
|
|
163
163
|
instrumentations: [
|
|
164
164
|
new HttpInstrumentation({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrumentation.js","sourceRoot":"","sources":["../../../src/utils/telemetry/instrumentation.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"instrumentation.js","sourceRoot":"","sources":["../../../src/utils/telemetry/instrumentation.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyanheads/mcp-ts-core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.12",
|
|
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",
|
|
@@ -144,11 +144,12 @@
|
|
|
144
144
|
"@hono/node-server": "1.19.12",
|
|
145
145
|
"chrono-node": "2.9.0",
|
|
146
146
|
"diff": "8.0.4",
|
|
147
|
-
"dotenv": "17.
|
|
147
|
+
"dotenv": "17.4.0",
|
|
148
148
|
"brace-expansion": "1.1.13",
|
|
149
149
|
"flatted": "3.4.2",
|
|
150
150
|
"handlebars": "4.7.9",
|
|
151
|
-
"hono": "4.12.
|
|
151
|
+
"hono": "4.12.10",
|
|
152
|
+
"lodash": "4.18.1",
|
|
152
153
|
"path-to-regexp": "8.4.0",
|
|
153
154
|
"picomatch": "2.3.2",
|
|
154
155
|
"yaml": "1.10.3",
|
|
@@ -156,7 +157,7 @@
|
|
|
156
157
|
},
|
|
157
158
|
"devDependencies": {
|
|
158
159
|
"@biomejs/biome": "2.4.10",
|
|
159
|
-
"@cloudflare/workers-types": "^4.
|
|
160
|
+
"@cloudflare/workers-types": "^4.20260403.1",
|
|
160
161
|
"@hono/otel": "^1.1.1",
|
|
161
162
|
"@opentelemetry/instrumentation-http": "^0.214.0",
|
|
162
163
|
"@opentelemetry/exporter-metrics-otlp-http": "^0.214.0",
|
|
@@ -171,7 +172,7 @@
|
|
|
171
172
|
"@types/bun": "^1.3.11",
|
|
172
173
|
"@types/diff": "^8.0.0",
|
|
173
174
|
"@types/js-yaml": "^4.0.9",
|
|
174
|
-
"@types/node": "^25.5.
|
|
175
|
+
"@types/node": "^25.5.2",
|
|
175
176
|
"@types/papaparse": "^5.5.2",
|
|
176
177
|
"@types/sanitize-html": "^2.16.1",
|
|
177
178
|
"@types/validator": "^13.15.10",
|
|
@@ -198,7 +199,7 @@
|
|
|
198
199
|
"typedoc": "^0.28.18",
|
|
199
200
|
"typescript": "^6.0.2",
|
|
200
201
|
"unpdf": "^1.4.0",
|
|
201
|
-
"validator": "^13.15.
|
|
202
|
+
"validator": "^13.15.35",
|
|
202
203
|
"vite": "8.0.3",
|
|
203
204
|
"vitest": "^4.1.2"
|
|
204
205
|
},
|
|
@@ -253,10 +254,10 @@
|
|
|
253
254
|
"dependencies": {
|
|
254
255
|
"@hono/mcp": "^0.2.5",
|
|
255
256
|
"@hono/node-server": "^1.19.12",
|
|
256
|
-
"@modelcontextprotocol/ext-apps": "^1.
|
|
257
|
+
"@modelcontextprotocol/ext-apps": "^1.5.0",
|
|
257
258
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
258
|
-
"dotenv": "^17.
|
|
259
|
-
"hono": "^4.12.
|
|
259
|
+
"dotenv": "^17.4.0",
|
|
260
|
+
"hono": "^4.12.10",
|
|
260
261
|
"jose": "^6.2.2",
|
|
261
262
|
"pino": "^10.3.1",
|
|
262
263
|
"zod": "^4.3.6"
|
|
@@ -41,6 +41,7 @@ import { resource, z } from '@cyanheads/mcp-ts-core';
|
|
|
41
41
|
export const {{RESOURCE_EXPORT}} = resource('{{scheme}}://{{{paramName}}}/data', {
|
|
42
42
|
description: '{{RESOURCE_DESCRIPTION}}',
|
|
43
43
|
mimeType: 'application/json',
|
|
44
|
+
// size: 1024, // optional: content size in bytes, if known
|
|
44
45
|
params: z.object({
|
|
45
46
|
{{paramName}}: z.string().describe('{{PARAM_DESCRIPTION}}'),
|
|
46
47
|
}),
|
package/skills/add-tool/SKILL.md
CHANGED
|
@@ -222,6 +222,37 @@ return {
|
|
|
222
222
|
};
|
|
223
223
|
```
|
|
224
224
|
|
|
225
|
+
### Defend against empty values from form-based clients
|
|
226
|
+
|
|
227
|
+
LLM clients (Claude, Cursor, etc.) only send populated fields. **Form-based clients** (MCP Inspector, web UIs) submit the full schema shape — optional object fields arrive with empty-string inner values instead of `undefined`. Zod's `.optional()` only rejects `undefined`, so `{ minDate: "", maxDate: "" }` passes validation and reaches the handler.
|
|
228
|
+
|
|
229
|
+
**Don't reject empty strings on optional fields** — that punishes form clients for valid MCP behavior. Instead, guard for meaningful values in the handler:
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
// Schema: keep permissive — accepts empty strings from form clients
|
|
233
|
+
input: z.object({
|
|
234
|
+
query: z.string().describe('Search terms'),
|
|
235
|
+
dateRange: z.object({
|
|
236
|
+
minDate: z.string().describe('Start date (YYYY-MM-DD)'),
|
|
237
|
+
maxDate: z.string().describe('End date (YYYY-MM-DD)'),
|
|
238
|
+
}).optional().describe('Restrict results to a date range.'),
|
|
239
|
+
}),
|
|
240
|
+
|
|
241
|
+
// Handler: check for meaningful values, not just object presence
|
|
242
|
+
async handler(input, ctx) {
|
|
243
|
+
const params: Record<string, string> = { query: input.query };
|
|
244
|
+
if (input.dateRange?.minDate && input.dateRange?.maxDate) {
|
|
245
|
+
params.minDate = input.dateRange.minDate;
|
|
246
|
+
params.maxDate = input.dateRange.maxDate;
|
|
247
|
+
}
|
|
248
|
+
// ...
|
|
249
|
+
},
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
The same applies to optional arrays — use `?.length` guards so empty arrays are skipped, not passed through.
|
|
253
|
+
|
|
254
|
+
**Required fields are different.** If a string field is required and must be non-empty to be meaningful, `.min(1)` is correct — the client shouldn't have submitted the form without filling it in.
|
|
255
|
+
|
|
225
256
|
### Match response density to context budget
|
|
226
257
|
|
|
227
258
|
Large payloads burn the agent's context window. Default to curated summaries; offer full data via opt-in parameters.
|
|
@@ -236,6 +267,7 @@ Large payloads burn the agent's context window. Default to curated summaries; of
|
|
|
236
267
|
- [ ] All Zod schema fields have `.describe()` annotations
|
|
237
268
|
- [ ] Schemas use only JSON-Schema-serializable types (no `z.custom()`, `z.date()`, `z.transform()`, `z.bigint()`, `z.symbol()`, `z.void()`, `z.map()`, `z.set()`)
|
|
238
269
|
- [ ] JSDoc `@fileoverview` and `@module` header present
|
|
270
|
+
- [ ] Optional nested objects guarded for empty inner values from form-based clients (check `?.field` truthiness, not just object presence)
|
|
239
271
|
- [ ] `handler(input, ctx)` is pure — throws on failure, no try/catch
|
|
240
272
|
- [ ] `format()` renders all data the LLM needs (not just a count or title) — `content[]` is the only field most clients forward to the model
|
|
241
273
|
- [ ] `auth` scopes declared if the tool needs authorization
|
|
@@ -168,6 +168,41 @@ it('handles missing elicitation gracefully', async () => {
|
|
|
168
168
|
|
|
169
169
|
---
|
|
170
170
|
|
|
171
|
+
## Testing with form-based client payloads
|
|
172
|
+
|
|
173
|
+
LLM clients only send populated fields. **Form-based clients** (MCP Inspector, web UIs) submit the full schema shape — optional object fields arrive with empty-string inner values instead of `undefined`. Both are valid MCP usage. Test that handlers handle both gracefully.
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
describe('form-client payloads', () => {
|
|
177
|
+
it('skips optional object when inner fields are empty strings', async () => {
|
|
178
|
+
const ctx = createMockContext();
|
|
179
|
+
// Form client sends the object with empty values instead of omitting it
|
|
180
|
+
const input = myTool.input.parse({
|
|
181
|
+
query: 'test',
|
|
182
|
+
dateRange: { minDate: '', maxDate: '' },
|
|
183
|
+
});
|
|
184
|
+
const result = await myTool.handler(input, ctx);
|
|
185
|
+
// Should succeed — empty dateRange is ignored, not passed downstream
|
|
186
|
+
expect(result.items).toBeDefined();
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('uses optional object when inner fields have real values', async () => {
|
|
190
|
+
const ctx = createMockContext();
|
|
191
|
+
const input = myTool.input.parse({
|
|
192
|
+
query: 'test',
|
|
193
|
+
dateRange: { minDate: '2025-01-01', maxDate: '2025-12-31' },
|
|
194
|
+
});
|
|
195
|
+
const result = await myTool.handler(input, ctx);
|
|
196
|
+
// Should apply the date filter
|
|
197
|
+
expect(result.items).toBeDefined();
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
The pattern: parse through the schema (confirms Zod accepts the payload), call the handler, assert the empty-value case produces correct results — no errors, no corrupted downstream queries. Same applies to optional arrays: test with `[]` to verify the handler skips rather than passes through.
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
171
206
|
## Vitest config
|
|
172
207
|
|
|
173
208
|
Extend the framework's base config using `mergeConfig`. The base provides `globals: true`, `pool: 'forks'`, `isolate: true`, `tsconfigPaths`, and a Zod SSR compatibility fix. Add only the `@/` alias for your server's source:
|
|
@@ -46,6 +46,7 @@ export default createWorkerHandler({
|
|
|
46
46
|
| `tools` | `AnyToolDefinition[]` | Tool definitions to register |
|
|
47
47
|
| `resources` | `AnyResourceDefinition[]` | Resource definitions to register |
|
|
48
48
|
| `prompts` | `PromptDefinition[]` | Prompt definitions to register |
|
|
49
|
+
| `extensions` | `Record<string, object>` | SEP-2133 extensions to advertise in server capabilities |
|
|
49
50
|
| `setup` | `(core: CoreServices) => void \| Promise<void>` | Runs after core services are ready, during the first request (lazy init inside the fetch handler) |
|
|
50
51
|
| `extraEnvBindings` | `[bindingKey: string, processEnvKey: string][]` | Maps CF string bindings to `process.env` keys |
|
|
51
52
|
| `extraObjectBindings` | `[bindingKey: string, globalKey: string][]` | Maps CF object bindings (KV, R2, D1, AI) to `globalThis` keys |
|
package/templates/CLAUDE.md
CHANGED
|
@@ -281,6 +281,7 @@ import { getMyService } from '@/services/my-domain/my-service.js';
|
|
|
281
281
|
## Checklist
|
|
282
282
|
|
|
283
283
|
- [ ] Zod schemas: all fields have `.describe()`, only JSON-Schema-serializable types (no `z.custom()`, `z.date()`, `z.transform()`, etc.)
|
|
284
|
+
- [ ] Optional nested objects: handler guards for empty inner values from form-based clients (`if (input.obj?.field && ...)`, not just `if (input.obj)`)
|
|
284
285
|
- [ ] JSDoc `@fileoverview` + `@module` on every file
|
|
285
286
|
- [ ] `ctx.log` for logging, `ctx.state` for storage
|
|
286
287
|
- [ ] Handlers throw on failure — error factories or plain `Error`, no try/catch
|