@cyanheads/mcp-ts-core 0.8.1 → 0.8.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.
Files changed (50) hide show
  1. package/CLAUDE.md +8 -2
  2. package/README.md +1 -1
  3. package/changelog/0.8.x/0.8.2.md +18 -0
  4. package/changelog/0.8.x/0.8.3.md +43 -0
  5. package/dist/logs/combined.log +12 -4
  6. package/dist/logs/error.log +12 -4
  7. package/dist/mcp-server/resources/resource-registration.d.ts.map +1 -1
  8. package/dist/mcp-server/resources/resource-registration.js +2 -3
  9. package/dist/mcp-server/resources/resource-registration.js.map +1 -1
  10. package/dist/mcp-server/resources/utils/resourceDefinition.d.ts +3 -3
  11. package/dist/mcp-server/tools/tool-registration.d.ts.map +1 -1
  12. package/dist/mcp-server/tools/tool-registration.js +8 -12
  13. package/dist/mcp-server/tools/tool-registration.js.map +1 -1
  14. package/dist/mcp-server/tools/utils/toolDefinition.d.ts +2 -3
  15. package/dist/mcp-server/tools/utils/toolDefinition.d.ts.map +1 -1
  16. package/dist/mcp-server/tools/utils/toolDefinition.js.map +1 -1
  17. package/dist/mcp-server/tools/utils/toolHandlerFactory.d.ts +28 -0
  18. package/dist/mcp-server/tools/utils/toolHandlerFactory.d.ts.map +1 -1
  19. package/dist/mcp-server/tools/utils/toolHandlerFactory.js +64 -23
  20. package/dist/mcp-server/tools/utils/toolHandlerFactory.js.map +1 -1
  21. package/dist/mcp-server/transports/http/landing-page/assets/copy-script.d.ts +13 -4
  22. package/dist/mcp-server/transports/http/landing-page/assets/copy-script.d.ts.map +1 -1
  23. package/dist/mcp-server/transports/http/landing-page/assets/copy-script.js +99 -25
  24. package/dist/mcp-server/transports/http/landing-page/assets/copy-script.js.map +1 -1
  25. package/dist/mcp-server/transports/http/landing-page/assets/styles.d.ts.map +1 -1
  26. package/dist/mcp-server/transports/http/landing-page/assets/styles.js +318 -8
  27. package/dist/mcp-server/transports/http/landing-page/assets/styles.js.map +1 -1
  28. package/dist/mcp-server/transports/http/landing-page/sections/status-strip.d.ts.map +1 -1
  29. package/dist/mcp-server/transports/http/landing-page/sections/status-strip.js +20 -1
  30. package/dist/mcp-server/transports/http/landing-page/sections/status-strip.js.map +1 -1
  31. package/dist/mcp-server/transports/http/landing-page/sections/tools.d.ts +6 -5
  32. package/dist/mcp-server/transports/http/landing-page/sections/tools.d.ts.map +1 -1
  33. package/dist/mcp-server/transports/http/landing-page/sections/tools.js +114 -69
  34. package/dist/mcp-server/transports/http/landing-page/sections/tools.js.map +1 -1
  35. package/dist/types-global/errors.d.ts +3 -22
  36. package/dist/types-global/errors.d.ts.map +1 -1
  37. package/dist/types-global/errors.js +0 -19
  38. package/dist/types-global/errors.js.map +1 -1
  39. package/package.json +1 -1
  40. package/skills/add-app-tool/SKILL.md +24 -8
  41. package/skills/add-resource/SKILL.md +1 -1
  42. package/skills/add-tool/SKILL.md +87 -20
  43. package/skills/api-errors/SKILL.md +21 -7
  44. package/skills/api-linter/SKILL.md +1 -1
  45. package/skills/design-mcp-server/SKILL.md +1 -1
  46. package/skills/field-test/SKILL.md +15 -6
  47. package/skills/maintenance/SKILL.md +19 -7
  48. package/templates/AGENTS.md +3 -2
  49. package/templates/CLAUDE.md +3 -2
  50. package/templates/src/mcp-server/tools/definitions/echo.tool.ts +18 -1
@@ -1,40 +1,73 @@
1
1
  /**
2
- * @fileoverview Tools section — responsive 2-column card grid, optionally
3
- * prefix-grouped when ≥2 tools share a common `snake_case` prefix. Each card
4
- * carries annotation pills (read-only / destructive / open-world / task /
5
- * app), auth scope chips, a JSON-RPC invocation snippet, and a collapsible
6
- * input-schema preview.
2
+ * @fileoverview Tools section — responsive card grid grouped by safety
3
+ * mutability (read / write / destructive). Each card carries annotation
4
+ * pills, a scope chip, a JSON-RPC invocation snippet, and a collapsible
5
+ * input-schema preview. A filter bar above the grid wires chip + search
6
+ * filtering through `data-mutability` / `data-name` attributes consumed
7
+ * by the inline filter script.
7
8
  *
8
9
  * @module src/mcp-server/transports/http/landing-page/sections/tools
9
10
  */
10
11
  import { html } from '../../../../../utils/formatting/html.js';
11
12
  import { renderPill, renderSectionHeading, renderSnippet } from '../primitives.js';
13
+ /**
14
+ * Mutability bucket order — safe defaults first, deliberate engagement last.
15
+ * Filter chips render in this order too.
16
+ */
17
+ const MUTABILITY_ORDER = ['read', 'write', 'destructive'];
12
18
  export function renderToolsSection(tools) {
13
19
  if (tools.length === 0)
14
20
  return html ``;
15
- const groups = groupToolsByPrefix(tools);
16
- // A single group whether labeled or not — would render as redundant with
17
- // the section header. Skip the sub-heading; render a flat grid.
18
- const showHeadings = groups.length > 1;
19
- const body = groups.map((group) => {
20
- const heading = showHeadings && group.label ? html `<h4 class="group-heading">${group.label}</h4>` : html ``;
21
- return html `${heading}<div class="card-grid">${group.tools.map(renderToolCard)}</div>`;
21
+ const buckets = bucketByMutability(tools);
22
+ const populatedBuckets = MUTABILITY_ORDER.filter((m) => buckets[m].length > 0);
23
+ // A single bucket is redundant with the section header skip per-group
24
+ // labels in that case but keep `data-mutability` on cards so the filter
25
+ // chips still work.
26
+ const showHeadings = populatedBuckets.length > 1;
27
+ const groups = populatedBuckets.map((mutability) => {
28
+ const bucketTools = buckets[mutability];
29
+ const heading = showHeadings
30
+ ? html `<h4 class="group-heading" data-group="${mutability}">${mutability} <span class="group-count">${String(bucketTools.length)}</span></h4>`
31
+ : html ``;
32
+ return html `${heading}<div class="card-grid" data-grid="${mutability}">${bucketTools.map((t) => renderToolCard(t, mutability))}</div>`;
22
33
  });
23
34
  return html `
24
- <section aria-labelledby="section-tools">
35
+ <section aria-labelledby="section-tools" data-tools-section>
25
36
  ${renderSectionHeading('section-tools', 'Tools', tools.length)}
26
- ${body}
37
+ ${renderToolFilterBar(populatedBuckets)}
38
+ <div class="tools-body">${groups}</div>
39
+ <p class="tools-empty" hidden>No tools match the current filter.</p>
27
40
  </section>
28
41
  `;
29
42
  }
30
- function renderToolCard(tool) {
43
+ function renderToolFilterBar(populatedBuckets) {
44
+ const chips = [
45
+ html `<button type="button" class="tool-chip" data-filter-mutability="all" aria-pressed="true">all</button>`,
46
+ ];
47
+ for (const m of populatedBuckets) {
48
+ chips.push(html `<button type="button" class="tool-chip tool-chip--${m}" data-filter-mutability="${m}" aria-pressed="false">${m}</button>`);
49
+ }
50
+ return html `
51
+ <div class="tool-filter-bar" role="search" aria-label="Filter tools">
52
+ <div class="tool-chips" role="group" aria-label="Filter by mutability">${chips}</div>
53
+ <label class="tool-search">
54
+ <span class="visually-hidden">Search tools</span>
55
+ <input
56
+ type="search"
57
+ data-tool-search
58
+ placeholder="Search tools…"
59
+ autocomplete="off"
60
+ spellcheck="false"
61
+ />
62
+ </label>
63
+ </div>
64
+ `;
65
+ }
66
+ function renderToolCard(tool, mutability) {
31
67
  const anchor = `tool-${tool.name}`;
32
68
  const annotations = tool.annotations;
33
- const pills = [];
34
- if (annotations?.readOnlyHint)
35
- pills.push(renderPill('read-only', 'readonly'));
36
- if (annotations?.destructiveHint === true)
37
- pills.push(renderPill('destructive', 'destructive'));
69
+ // Mutability badge first — the safety signal readers track at a glance.
70
+ const pills = [renderPill(mutability, mutability)];
38
71
  if (annotations?.openWorldHint)
39
72
  pills.push(renderPill('open-world', 'openworld'));
40
73
  if (tool.isTask)
@@ -42,75 +75,87 @@ function renderToolCard(tool) {
42
75
  if (tool.isApp)
43
76
  pills.push(renderPill('app', 'app'));
44
77
  const source = tool.sourceUrl
45
- ? html `<a class="source-link" href="${tool.sourceUrl}" rel="noopener">view source ↗</a>`
78
+ ? html `<a class="source-link" href="${tool.sourceUrl}" rel="noopener" aria-label="View source for ${tool.name}">view source ↗</a>`
79
+ : html ``;
80
+ const scopeChips = tool.auth && tool.auth.length > 0
81
+ ? html `<span class="card-scope" title="${tool.auth.join(', ')}"><span class="card-meta-label">scope</span>${tool.auth.map((scope) => html ` <code class="scope-chip">${scopeAccessLevel(scope)}</code>`)}</span>`
46
82
  : html ``;
47
83
  const schemaPreview = tool.inputSchema
48
84
  ? html `
49
- <details>
50
- <summary>Input schema</summary>
85
+ <details class="card-detail">
86
+ <summary>schema</summary>
51
87
  <pre><code>${JSON.stringify(tool.inputSchema, null, 2)}</code></pre>
52
88
  </details>
53
89
  `
54
90
  : html ``;
55
91
  const invocation = html `
56
- <details>
57
- <summary>Invocation</summary>
92
+ <details class="card-detail">
93
+ <summary>invocation</summary>
58
94
  ${renderSnippet(`tool-${tool.name}`, buildInvocationSnippet(tool))}
59
95
  </details>
60
96
  `;
61
- const authBadges = tool.auth && tool.auth.length > 0
62
- ? html `<div class="card-meta"><span class="card-meta-label">scopes</span>${tool.auth.map((scope) => html ` <span class="pill pill-auth">${scope}</span>`)}</div>`
63
- : html ``;
97
+ // Search target: name + description as a single lowercase string. Hidden
98
+ // attribute (not visible) so the filter script can match without parsing
99
+ // DOM text repeatedly. Description gets normalized whitespace so multi-line
100
+ // entries don't waste haystack length.
101
+ const searchTarget = `${tool.name} ${tool.description}`.replace(/\s+/g, ' ').toLowerCase();
64
102
  return html `
65
- <article class="card" id="${anchor}">
66
- <div class="card-head">
103
+ <article
104
+ class="card tool-card"
105
+ id="${anchor}"
106
+ data-tool-card
107
+ data-mutability="${mutability}"
108
+ data-name="${tool.name}"
109
+ data-search="${searchTarget}"
110
+ >
111
+ <header class="card-head">
67
112
  <h3 class="card-title"><a href="#${anchor}">${tool.name}</a></h3>
68
113
  <div class="pill-row" role="list">${pills}</div>
69
114
  ${source}
70
- </div>
115
+ </header>
71
116
  <p class="card-desc">${tool.description}</p>
72
- ${authBadges}
73
- ${invocation}
74
- ${schemaPreview}
117
+ <footer class="card-foot">
118
+ ${scopeChips}
119
+ <div class="card-actions">
120
+ ${invocation}
121
+ ${schemaPreview}
122
+ </div>
123
+ </footer>
75
124
  </article>
76
125
  `;
77
126
  }
78
- function groupToolsByPrefix(tools) {
79
- if (tools.length < 3)
80
- return [{ label: null, tools }];
81
- const prefixCounts = new Map();
82
- for (const tool of tools) {
83
- const prefix = tool.name.split('_', 1)[0];
84
- if (!prefix)
85
- continue;
86
- prefixCounts.set(prefix, (prefixCounts.get(prefix) ?? 0) + 1);
87
- }
88
- const groupablePrefixes = new Set([...prefixCounts.entries()].filter(([, count]) => count >= 2).map(([p]) => p));
89
- if (groupablePrefixes.size === 0)
90
- return [{ label: null, tools }];
91
- const groups = new Map();
92
- const other = [];
93
- for (const tool of tools) {
94
- const prefix = tool.name.split('_', 1)[0];
95
- if (prefix && groupablePrefixes.has(prefix)) {
96
- const list = groups.get(prefix) ?? [];
97
- list.push(tool);
98
- groups.set(prefix, list);
99
- }
100
- else {
101
- other.push(tool);
102
- }
103
- }
104
- const out = [];
105
- for (const [prefix, list] of groups) {
106
- out.push({ label: titleCase(prefix), tools: list });
107
- }
108
- if (other.length > 0)
109
- out.push({ label: 'Other', tools: other });
110
- return out;
127
+ /**
128
+ * Map a tool to a mutability bucket using its annotations. The MCP spec
129
+ * defaults `destructiveHint` to `true`, but treating annotation-less tools
130
+ * as "destructive" surprises readers — bucket as `write` unless the
131
+ * destructive hint is explicitly set. Mirrors how the annotation pills
132
+ * render today (`pill-destructive` requires `=== true`).
133
+ */
134
+ function classifyMutability(tool) {
135
+ const a = tool.annotations;
136
+ if (a?.readOnlyHint === true)
137
+ return 'read';
138
+ if (a?.destructiveHint === true)
139
+ return 'destructive';
140
+ return 'write';
141
+ }
142
+ function bucketByMutability(tools) {
143
+ const buckets = { read: [], write: [], destructive: [] };
144
+ for (const tool of tools)
145
+ buckets[classifyMutability(tool)].push(tool);
146
+ return buckets;
111
147
  }
112
- function titleCase(s) {
113
- return s.charAt(0).toUpperCase() + s.slice(1);
148
+ /**
149
+ * Reduce a colon-delimited scope (`tool:foo:read`) to its trailing access
150
+ * level (`read`). Scopes that don't match the convention render verbatim —
151
+ * the linter doesn't enforce shape, so falling back is friendlier than
152
+ * eating the value.
153
+ */
154
+ function scopeAccessLevel(scope) {
155
+ const idx = scope.lastIndexOf(':');
156
+ if (idx < 0 || idx === scope.length - 1)
157
+ return scope;
158
+ return scope.slice(idx + 1);
114
159
  }
115
160
  function buildInvocationSnippet(tool) {
116
161
  const args = {};
@@ -1 +1 @@
1
- {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../../../../../src/mcp-server/transports/http/landing-page/sections/tools.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../../../../../src/mcp-server/transports/http/landing-page/sections/tools.ts"],"names":[],"mappings":"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"}
@@ -116,13 +116,9 @@ export type ErrorResponse = z.infer<typeof ErrorSchema>;
116
116
  * Lets a definition advertise what it can fail with — the JSON-RPC code, a
117
117
  * stable machine-readable `reason`, and a human-readable `when` description.
118
118
  *
119
- * **Where it shows up:**
120
- * - Surfaced in `tools/list` / `resources/list` under
121
- * `_meta['mcp-ts-core/errors']`, so MCP clients and agents can preview failure
122
- * modes alongside the input/output schema.
123
- * - Validated by the startup linter — invalid codes, duplicate `reason` strings
124
- * within a single definition, and (with the conformance check enabled)
125
- * handler bodies that throw codes not in the contract are flagged.
119
+ * **Validation.** Checked by the startup linter — invalid codes, duplicate
120
+ * `reason` strings within a single definition, and (with the conformance check
121
+ * enabled) handler bodies that throw codes not in the contract are flagged.
126
122
  *
127
123
  * **Authoring guidance:**
128
124
  * - Keep `reason` short, snake_case, stable. Treat it like a CSS class name
@@ -171,19 +167,4 @@ export interface ErrorContract {
171
167
  */
172
168
  when: string;
173
169
  }
174
- /**
175
- * The MCP `_meta` namespace key under which `errors[]` is published in
176
- * `tools/list` and `resources/list`. Namespaced to avoid collisions with
177
- * other framework or vendor extensions.
178
- */
179
- export declare const ERROR_CONTRACT_META_KEY = "mcp-ts-core/errors";
180
- /**
181
- * Merges a tool/resource's `errors[]` contract into its `_meta` object under
182
- * {@link ERROR_CONTRACT_META_KEY}. Returns `undefined` when both sides are
183
- * absent so callers can spread conditionally without producing an empty
184
- * `_meta` field. Used by the tool and resource registries.
185
- *
186
- * @internal
187
- */
188
- export declare function buildMetaWithErrorContract(baseMeta: Record<string, unknown> | undefined, errors: readonly unknown[] | undefined): Record<string, unknown> | undefined;
189
170
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/types-global/errors.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/types-global/errors.ts"],"names":[],"mappings":"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"}
@@ -138,23 +138,4 @@ export const ErrorSchema = z
138
138
  .describe('Optional structured data providing more context about the error'),
139
139
  })
140
140
  .describe('Schema for validating structured error objects, ensuring consistency in error reporting.');
141
- /**
142
- * The MCP `_meta` namespace key under which `errors[]` is published in
143
- * `tools/list` and `resources/list`. Namespaced to avoid collisions with
144
- * other framework or vendor extensions.
145
- */
146
- export const ERROR_CONTRACT_META_KEY = 'mcp-ts-core/errors';
147
- /**
148
- * Merges a tool/resource's `errors[]` contract into its `_meta` object under
149
- * {@link ERROR_CONTRACT_META_KEY}. Returns `undefined` when both sides are
150
- * absent so callers can spread conditionally without producing an empty
151
- * `_meta` field. Used by the tool and resource registries.
152
- *
153
- * @internal
154
- */
155
- export function buildMetaWithErrorContract(baseMeta, errors) {
156
- if (!errors || errors.length === 0)
157
- return baseMeta;
158
- return { ...(baseMeta ?? {}), [ERROR_CONTRACT_META_KEY]: errors };
159
- }
160
141
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/types-global/errors.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/types-global/errors.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.8.1",
3
+ "version": "0.8.3",
4
4
  "mcpName": "io.github.cyanheads/mcp-ts-core",
5
5
  "description": "Agent-native TypeScript framework for building MCP servers. Declarative definitions with auth, multi-backend storage, OpenTelemetry, and first-class support for Bun/Node/Cloudflare Workers.",
6
6
  "main": "dist/core/index.js",
@@ -108,8 +108,10 @@ const APP_HTML = `<!DOCTYPE html>
108
108
  <!-- your UI markup -->
109
109
 
110
110
  <script type="module">
111
- // Prefer a bundled or inlined SDK for the final shipped HTML. Leaving a live
112
- // CDN import in the served ui:// resource is not the recommended default.
111
+ // PROTOTYPING ONLY replace before shipping. Bundle via Vite +
112
+ // vite-plugin-singlefile or inline the SDK. Live CDN imports require
113
+ // CSP whitelisting, add supply-chain risk, and break offline use.
114
+ // See UI Notes below.
113
115
  import {
114
116
  App,
115
117
  applyDocumentTheme,
@@ -186,13 +188,27 @@ export const {{RESOURCE_EXPORT}} = appResource('ui://{{tool-name}}/app.html', {
186
188
  });
187
189
  ```
188
190
 
189
- ## UI Design Notes
191
+ ## UI Notes
190
192
 
191
- - **Bundling:** Prefer Vite + `vite-plugin-singlefile` for any UI that uses `@modelcontextprotocol/ext-apps`. The served `ui://` HTML should ideally be self-contained. The inline template literal pattern is fine for zero-dependency UIs or when you inline the SDK yourself.
192
- - **Client-side SDK:** Author against `@modelcontextprotocol/ext-apps`, but ship a bundled or inlined artifact when possible. Avoid relying on a live CDN import as the default final pattern for portable host compatibility.
193
- - **CSP:** MCP Apps iframes run under deny-by-default CSP. With `appResource()`, put `_meta.ui.csp.resourceDomains` on the definition and the builder will mirror it into returned `resources/read` content items. With plain `resource()`, you still need to attach `_meta.ui` yourself in `format()`.
194
- - **App resource `format()`:** `appResource()` already preserves raw HTML for the default app MIME type and mirrors definition `_meta.ui` into content items. Add a custom `format()` only when you need extra per-read metadata or non-default content shaping.
195
- - **format() for app tools:** The first `text` content block is typically JSON that the UI parses via `ontoolresult`. Additional blocks provide a human-readable fallback that non-app hosts and LLMs consume. Do not rely on the JSON block alone for model-visible detail; the fallback blocks still need to render the fields the LLM must reason about.
193
+ - **Ship self-contained HTML.** Author with Vite + `vite-plugin-singlefile` or inline the SDK. Live CDN imports in a `ui://` resource are a CSP footgun (every domain has to be whitelisted on `_meta.ui.csp.resourceDomains`), a supply-chain footgun (third-party JS executes inside the host's iframe), and a runtime footgun (every render needs network). The `unpkg` line in the template is for prototyping only.
194
+ - **CSP.** MCP Apps iframes run under deny-by-default CSP. With `appResource()`, put `_meta.ui.csp.resourceDomains` on the definition; the builder mirrors it into returned `resources/read` content items. With plain `resource()`, attach `_meta.ui` yourself in `format()`.
195
+ - **Adopt the host's visual identity, don't impose your own.** App UIs render inside the host's iframe alongside its native UI. Three host hooks layer on top of your CSS:
196
+ - `applyDocumentTheme(hostContext.theme)` sets `color-scheme` and a `data-theme` attribute on `<html>`
197
+ - `applyHostStyleVariables(hostContext.styles.variables)` installs host CSS custom properties on `:root` (host decides the names, e.g. `--mcp-color-bg-primary`)
198
+ - `applyHostFonts(hostContext.styles.css.fonts)` — installs `@font-face` rules for the host's font stack
199
+
200
+ Author CSS to *consume* these via `var(--mcp-color-bg-primary, /* fallback */ #fff)`. Don't hardcode brand colors that fight the host.
201
+ - **Pre-connect baseline.** `app.connect()` is async — host context arrives a frame or two after first paint. Without a baseline, the UI flashes unstyled or wrong-themed on light hosts. Ship a `prefers-color-scheme`-aware default so the first frame is sensible:
202
+
203
+ ```css
204
+ :root { color-scheme: light dark; --bg: #fff; --fg: #111; }
205
+ @media (prefers-color-scheme: dark) { :root { --bg: #0c0d12; --fg: #ededef; } }
206
+ body { background: var(--bg); color: var(--fg); }
207
+ ```
208
+
209
+ Host vars override these once `onhostcontextchanged` fires.
210
+ - **`format()` for app tools.** The first `text` content block is typically JSON that the UI parses via `ontoolresult`. Additional blocks are the human-readable fallback that non-app hosts and LLMs consume — they must render every field the LLM needs to reason about. JSON-only payloads leave model-visible context blind.
211
+ - **App resource `format()`.** `appResource()` already preserves raw HTML for the default app MIME type and mirrors definition `_meta.ui` into content items. Add a custom `format()` only when you need extra per-read metadata or non-default content shaping.
196
212
 
197
213
  ## Registration
198
214
 
@@ -109,7 +109,7 @@ If the repo already uses `src/mcp-server/resources/definitions/index.ts`, update
109
109
 
110
110
  ### Optional: declarative `errors[]` contract
111
111
 
112
- Resources can opt into the same typed error contract as tools — surfaced in `resources/list` under `_meta['mcp-ts-core/errors']` and bound to a typed `ctx.fail(reason, …)` keyed by the declared reason union:
112
+ Resources can opt into the same typed error contract as tools — bound to a typed `ctx.fail(reason, …)` keyed by the declared reason union:
113
113
 
114
114
  ```typescript
115
115
  import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
@@ -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.9"
7
+ version: "2.0"
8
8
  audience: external
9
9
  type: reference
10
10
  ---
@@ -44,6 +44,7 @@ For shape selection (Workflow or Instruction variants — standard single-action
44
44
  */
45
45
 
46
46
  import { tool, z } from '@cyanheads/mcp-ts-core';
47
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
47
48
 
48
49
  export const {{TOOL_EXPORT}} = tool('{{tool_name}}', {
49
50
  title: '{{TOOL_TITLE}}',
@@ -58,17 +59,25 @@ export const {{TOOL_EXPORT}} = tool('{{tool_name}}', {
58
59
  // All fields need .describe(). Only JSON-Schema-serializable Zod types allowed.
59
60
  }),
60
61
  // auth: ['tool:{{tool_name}}:read'],
61
- // errors: [
62
- // { reason: 'no_match', code: JsonRpcErrorCode.NotFound, when: 'No items matched the query.' },
63
- // { reason: 'queue_full', code: JsonRpcErrorCode.RateLimited, when: 'Local queue at capacity.', retryable: true },
64
- // ],
62
+
63
+ // Each entry declares a domain-specific failure mode and types
64
+ // `ctx.fail(reason, …)` against the declared union. Baseline codes
65
+ // (InternalError, ServiceUnavailable, Timeout, ValidationError,
66
+ // SerializationError) bubble freely — only declare domain-specific reasons.
67
+ // Delete this block if no domain failures apply.
68
+ errors: [
69
+ { reason: 'no_match', code: JsonRpcErrorCode.NotFound, when: 'No items matched the query.' },
70
+ { reason: 'queue_full', code: JsonRpcErrorCode.RateLimited, when: 'Local queue at capacity.', retryable: true },
71
+ ],
65
72
 
66
73
  async handler(input, ctx) {
67
74
  ctx.log.info('Processing', { /* relevant input fields */ });
68
75
  // Pure logic — throw on failure, no try/catch.
69
76
  // With an `errors[]` contract: `throw ctx.fail('reason_id', message?, data?)`.
70
77
  // Without: throw via factories (`notFound`, `validationError`, …) or plain `Error`.
71
- return { /* output */ };
78
+ const items = await search(input);
79
+ if (items.length === 0) throw ctx.fail('no_match', `No items matched "${input.query}"`);
80
+ return { items };
72
81
  },
73
82
 
74
83
  // format() populates MCP content[] — the markdown twin of structuredContent.
@@ -186,18 +195,38 @@ Single-item tools don't need this — they either succeed or throw. The partial
186
195
 
187
196
  ### Empty results need context
188
197
 
189
- An empty array with no explanation is a dead end. Echo back the criteria that produced zero results and, where possible, suggest how to broaden the search.
198
+ An empty array with no explanation is a dead end. Echo back the criteria that produced zero results and, where possible, suggest how to broaden the search. The recovery hint needs three pieces working together — schema entry, handler return, and `format()` rendering — or the `format-parity` lint will flag the missing field.
190
199
 
191
200
  ```typescript
192
- // In handlerafter getting zero results:
193
- if (results.length === 0) {
194
- return {
195
- items: [],
196
- totalCount: 0,
197
- message: `No items matched status="${input.status}" in project "${input.project}". `
198
- + `Try a broader status filter or verify the project name.`,
199
- };
200
- }
201
+ // 1. Output schema declare the recovery field so the linter sees it
202
+ output: z.object({
203
+ items: z.array(ItemSchema).describe('Matching items.'),
204
+ totalCount: z.number().describe('Total matches before pagination.'),
205
+ message: z.string().optional()
206
+ .describe('Recovery hint when results are empty — echoes filters and suggests how to broaden. Absent on successful result pages.'),
207
+ }),
208
+
209
+ // 2. Handler — populate `message` when the result is empty
210
+ async handler(input, ctx) {
211
+ const results = await search(input);
212
+ if (results.length === 0) {
213
+ return {
214
+ items: [],
215
+ totalCount: 0,
216
+ message: `No items matched status="${input.status}" in project "${input.project}". `
217
+ + `Try a broader status filter or verify the project name.`,
218
+ };
219
+ }
220
+ return { items: results, totalCount: results.length };
221
+ },
222
+
223
+ // 3. format() — render the recovery hint so content[]-only clients see it too
224
+ format: (result) => {
225
+ const lines = [`**Total:** ${result.totalCount}`];
226
+ if (result.message) lines.push(`\n> ${result.message}`);
227
+ for (const item of result.items) lines.push(`- ${item.name}`);
228
+ return [{ type: 'text', text: lines.join('\n') }];
229
+ },
201
230
  ```
202
231
 
203
232
  ### Sparse upstream data must stay honest
@@ -265,13 +294,51 @@ export const fetchArticles = tool('fetch_articles', {
265
294
  });
266
295
  ```
267
296
 
268
- **Baseline codes** (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`) bubble freely and don't need declaring. Omit the contract only for throwaway prototypes — declare it everywhere else. Wire-level behavior is identical when omitted, but you lose the type-checked `ctx.fail`, the `tools/list` advertisement, and conformance lint coverage.
297
+ **Baseline codes** (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`) bubble freely and don't need declaring. Wire-level behavior is identical when the contract is omitted, but you lose the type-checked `ctx.fail`, the `tools/list` advertisement, and conformance lint coverage — declare a contract whenever the tool has a domain-specific failure mode.
269
298
 
270
299
  `ctx.fail` accepts an optional 4th `options` argument for ES2022 cause chaining: `throw ctx.fail('upstream_error', 'Upstream returned 500', { url }, { cause: e })`.
271
300
 
272
- **Service-thrown contract reasons.** When the throw happens in a called service rather than the handler itself, `ctx.fail` isn't reachable — services don't have `ctx`. Pass `data: { reason: 'X' }` to the factory in the service; the framework's auto-classifier preserves `data` on the wire, so the contract reason rides through unchanged. The handler bubbles the error without catching. See `add-service` for the pattern.
301
+ #### Service-layer throws
302
+
303
+ API-wrapping tools usually delegate to a service: `const data = await ncbi.fetch(input)`. The throw lives in the service, not the handler — and services don't receive `ctx`, so `ctx.fail` is unreachable from there. The fix is to pass `data: { reason: 'X' }` to the factory in the service. The framework's auto-classifier preserves `data` on the wire, so clients see the same `error.data.reason` they would have seen from `ctx.fail`. The handler doesn't catch — it just bubbles.
304
+
305
+ The contract entry on the tool and the `data: { reason }` on the service throw need to use the **same reason string** so the two sides line up.
306
+
307
+ ```typescript
308
+ // service — passes data.reason to match the consuming tool's contract
309
+ import { serviceUnavailable } from '@cyanheads/mcp-ts-core/errors';
310
+
311
+ export class NcbiService {
312
+ async fetch(pmids: string[]) {
313
+ const response = await fetchWithRetry(...);
314
+ if (!response.ok) {
315
+ throw serviceUnavailable(
316
+ `NCBI returned HTTP ${response.status}`,
317
+ { reason: 'ncbi_unreachable', status: response.status }, // ← matches contract entry
318
+ { cause: undefined },
319
+ );
320
+ }
321
+ return response.json();
322
+ }
323
+ }
324
+
325
+ // tool — declares the matching contract entry, calls the service, doesn't catch
326
+ export const fetchArticles = tool('fetch_articles', {
327
+ errors: [
328
+ { reason: 'ncbi_unreachable', code: JsonRpcErrorCode.ServiceUnavailable,
329
+ when: 'NCBI E-utilities is unreachable.', retryable: true },
330
+ ],
331
+ async handler(input, ctx) {
332
+ return { articles: await ncbi.fetch(input.pmids) }; // throws bubble unchanged
333
+ },
334
+ });
335
+ ```
336
+
337
+ See `add-service` for the full pattern.
338
+
339
+ #### Ad-hoc factory throws (fallback)
273
340
 
274
- **Fallback: error factories.** Use when no contract entry fits — ad-hoc throws, prototype tools, or service-layer code. The framework also auto-classifies plain `throw new Error()` from message patterns as a last resort.
341
+ When no contract entry fits — prototype code, one-off throws, or service-layer fallbacks use error factories or plain `throw new Error()`. The framework auto-classifies plain `Error` from message patterns as a last resort.
275
342
 
276
343
  ```typescript
277
344
  // Client input error — agent can fix and retry
@@ -365,7 +432,7 @@ Large payloads burn the agent's context window. Default to curated summaries; of
365
432
  - [ ] `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
366
433
  - [ ] If wrapping external API: output schema and `format()` preserve uncertainty from sparse upstream payloads instead of inventing concrete values
367
434
  - [ ] `auth` scopes declared if the tool needs authorization
368
- - [ ] `errors: [...]` contract declared for known domain failure modes (recommended; omit only for throwaway prototypes)
435
+ - [ ] `errors: [...]` contract declared for the tool's domain-specific failure modes or block deleted if no domain failures apply (baseline codes bubble freely)
369
436
  - [ ] `task: true` added if the tool is long-running
370
437
  - [ ] Registered in the project's existing `createApp()` tool list (directly or via barrel)
371
438
  - [ ] `bun run devcheck` passes