@frontmcp/skills 1.5.7 → 1.6.1

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/README.md CHANGED
@@ -76,10 +76,12 @@ scoped [Providers / DI][docs-providers].
76
76
  stateful / stateless [sessions][docs-server] (JWT or UUID transport IDs).
77
77
 
78
78
  **Connect & operate** — [Streamable HTTP + SSE transport][docs-transport],
79
- capability [discovery][docs-discovery], [elicitation][docs-elicitation],
80
- [hooks][docs-hooks], HTTP-discoverable [skills][docs-skills],
81
- [external MCP sub-apps][docs-ext-apps], an in-process [Direct Client][docs-direct]
82
- (`connectOpenAI` / `connectClaude`), and first-class [deployment][docs-deploy].
79
+ every [MCP protocol revision][docs-protocol] from `2024-11-05` through
80
+ `2026-07-28` on one endpoint, capability [discovery][docs-discovery],
81
+ [elicitation][docs-elicitation], [hooks][docs-hooks], HTTP-discoverable
82
+ [skills][docs-skills], [tool UI / MCP Apps][docs-ext-apps], an in-process
83
+ [Direct Client][docs-direct] (`connectOpenAI` / `connectClaude`), and
84
+ first-class [deployment][docs-deploy].
83
85
 
84
86
  **Extend & tooling** — official [plugins][docs-plugins] (Cache, Remember, CodeCall,
85
87
  Dashboard), the [OpenAPI adapter][docs-adapters], a [UI library][docs-ui] (HTML/React
@@ -90,18 +92,66 @@ widgets, SSR, MCP Bridge), an [E2E testing framework][docs-testing], and a
90
92
 
91
93
  ## Packages
92
94
 
93
- | Package | Description |
94
- | ------------------------------------- | ------------------------------------------------------ |
95
- | [`@frontmcp/sdk`](libs/sdk) | Core framework — decorators, DI, flows, transport |
96
- | [`@frontmcp/cli`](libs/cli) | CLI tooling (`frontmcp create`, `dev`, `build`) |
97
- | [`@frontmcp/auth`](libs/auth) | Authentication, OAuth, JWKS, credential vault |
98
- | [`@frontmcp/adapters`](libs/adapters) | OpenAPI adapter for auto-generating tools |
99
- | [`@frontmcp/plugins`](libs/plugins) | Official plugins: Cache, Remember, CodeCall, Dashboard |
100
- | [`@frontmcp/testing`](libs/testing) | E2E test framework with fixtures and matchers |
101
- | [`@frontmcp/ui`](libs/ui) | React components, hooks, SSR renderers |
102
- | [`@frontmcp/uipack`](libs/uipack) | React-free themes, build tools, platform adapters |
103
- | [`@frontmcp/di`](libs/di) | Dependency injection container (internal) |
104
- | [`@frontmcp/utils`](libs/utils) | Shared utilities — naming, URI, crypto, FS (internal) |
95
+ You install `frontmcp` (the CLI) and `@frontmcp/sdk`. Everything else is either
96
+ pulled in for you or opt-in.
97
+
98
+ ### Core
99
+
100
+ | Package | Description |
101
+ | ----------------------------------- | --------------------------------------------------------------- |
102
+ | [`frontmcp`](libs/cli) | The CLI — `create`, `init`, `dev`, `build`, `inspect`, `doctor` |
103
+ | [`@frontmcp/sdk`](libs/sdk) | Core framework — decorators, DI, flows, transport, MCP protocol |
104
+ | [`@frontmcp/auth`](libs/auth) | Authentication, OAuth, JWKS, DCR/CIMD, credential vault |
105
+ | [`@frontmcp/testing`](libs/testing) | E2E test framework with fixtures and matchers |
106
+
107
+ ### Extend
108
+
109
+ | Package | Description |
110
+ | ----------------------------------------------- | ------------------------------------------------------------- |
111
+ | [`@frontmcp/plugins`](libs/plugins) | Plugin authoring toolkit + official plugin re-exports |
112
+ | [`@frontmcp/adapters`](libs/adapters) | OpenAPI adapter — generate tools from an OpenAPI spec |
113
+ | [`@frontmcp/skills`](libs/skills) | Curated SKILL.md catalog for scaffolding and `skills install` |
114
+ | [`@frontmcp/guard`](libs/guard) | Policy/guard rules for tool inputs and outputs |
115
+ | [`@frontmcp/observability`](libs/observability) | Structured logging, metrics, and tracing helpers |
116
+
117
+ ### UI
118
+
119
+ | Package | Description |
120
+ | --------------------------------- | ----------------------------------------------------- |
121
+ | [`@frontmcp/react`](libs/react) | React hooks + client for talking to a FrontMCP server |
122
+ | [`@frontmcp/ui`](libs/ui) | React components, SSR renderers, MCP Bridge |
123
+ | [`@frontmcp/uipack`](libs/uipack) | React-free themes, build tools, platform adapters |
124
+
125
+ ### Runtime & storage
126
+
127
+ | Package | Description |
128
+ | ------------------------------------------------- | -------------------------------------------------------------- |
129
+ | [`@frontmcp/edge`](libs/edge) | Run a server on Cloudflare Workers / V8 isolates from a config |
130
+ | [`@frontmcp/storage-sqlite`](libs/storage-sqlite) | SQLite-backed session, task, and elicitation stores |
131
+ | [`@frontmcp/nx`](libs/nx-plugin) | Nx generators and executors for FrontMCP workspaces |
132
+
133
+ ### Internal
134
+
135
+ Published so the packages above resolve, but not intended for direct use:
136
+
137
+ | Package | Description |
138
+ | ------------------------------------- | ------------------------------------------------------------ |
139
+ | [`@frontmcp/protocol`](libs/protocol) | The single boundary to the upstream MCP SDK — protocol types |
140
+ | [`@frontmcp/di`](libs/di) | Dependency injection container |
141
+ | [`@frontmcp/utils`](libs/utils) | Shared utilities — naming, URI, crypto, FS |
142
+ | [`@frontmcp/lazy-zod`](libs/lazy-zod) | Lazily-loaded Zod wrapper that keeps cold starts small |
143
+
144
+ ### Official plugins
145
+
146
+ | Package | Description |
147
+ | -------------------------------------------------------------------- | -------------------------------------------- |
148
+ | [`@frontmcp/plugin-cache`](plugins/plugin-cache) | Cache tool results with a TTL |
149
+ | [`@frontmcp/plugin-remember`](plugins/plugin-remember) | Per-session memory (`this.remember`) |
150
+ | [`@frontmcp/plugin-approval`](plugins/plugin-approval) | Human approval gates before a tool runs |
151
+ | [`@frontmcp/plugin-codecall`](plugins/plugin-codecall) | Let the model compose tool calls as code |
152
+ | [`@frontmcp/plugin-dashboard`](plugins/plugin-dashboard) | Built-in web dashboard |
153
+ | [`@frontmcp/plugin-feature-flags`](plugins/plugin-feature-flags) | Toggle tools and apps at runtime |
154
+ | [`@frontmcp/plugin-skilled-openapi`](plugins/plugin-skilled-openapi) | OpenAPI → skills + meta-tools for large APIs |
105
155
 
106
156
  ## Version Alignment
107
157
 
@@ -120,7 +170,7 @@ PRs welcome! See [CONTRIBUTING.md](./CONTRIBUTING.md) for workflow, coding stand
120
170
  [docs-home]: https://docs.agentfront.dev/frontmcp 'FrontMCP Docs'
121
171
  [docs-install]: https://docs.agentfront.dev/frontmcp/getting-started/installation 'Installation'
122
172
  [docs-quickstart]: https://docs.agentfront.dev/frontmcp/getting-started/quickstart 'Quickstart'
123
- [docs-sdk-ref]: https://docs.agentfront.dev/frontmcp/sdk-reference/overview 'SDK Reference'
173
+ [docs-sdk-ref]: https://docs.agentfront.dev/frontmcp/sdk-reference/decorators/overview 'SDK Reference'
124
174
  [docs-server]: https://docs.agentfront.dev/frontmcp/servers/server 'The FrontMCP Server'
125
175
  [docs-apps]: https://docs.agentfront.dev/frontmcp/servers/apps 'Apps'
126
176
  [docs-tools]: https://docs.agentfront.dev/frontmcp/servers/tools 'Tools'
@@ -130,15 +180,16 @@ PRs welcome! See [CONTRIBUTING.md](./CONTRIBUTING.md) for workflow, coding stand
130
180
  [docs-elicitation]: https://docs.agentfront.dev/frontmcp/servers/elicitation 'Elicitation'
131
181
  [docs-skills]: https://docs.agentfront.dev/frontmcp/servers/skills 'Skills'
132
182
  [docs-discovery]: https://docs.agentfront.dev/frontmcp/servers/discovery 'Discovery'
183
+ [docs-protocol]: https://docs.agentfront.dev/frontmcp/fundamentals/protocol-versions 'Protocol Versions'
133
184
  [docs-auth]: https://docs.agentfront.dev/frontmcp/authentication/overview 'Authentication'
134
185
  [docs-direct]: https://docs.agentfront.dev/frontmcp/deployment/direct-client 'Direct Client'
135
- [docs-transport]: https://docs.agentfront.dev/frontmcp/deployment/transport 'Transport'
136
- [docs-ext-apps]: https://docs.agentfront.dev/frontmcp/servers/ext-apps 'Ext-Apps'
137
- [docs-hooks]: https://docs.agentfront.dev/frontmcp/extensibility/hooks 'Hooks'
186
+ [docs-transport]: https://docs.agentfront.dev/frontmcp/deployment/transport-security 'Transport'
187
+ [docs-ext-apps]: https://docs.agentfront.dev/frontmcp/guides/building-tool-ui 'Tool UI / MCP Apps'
188
+ [docs-hooks]: https://docs.agentfront.dev/frontmcp/sdk-reference/decorators/hooks 'Hooks'
138
189
  [docs-providers]: https://docs.agentfront.dev/frontmcp/extensibility/providers 'Providers'
139
190
  [docs-plugins]: https://docs.agentfront.dev/frontmcp/plugins/overview 'Plugins'
140
191
  [docs-adapters]: https://docs.agentfront.dev/frontmcp/adapters/overview 'Adapters'
141
192
  [docs-testing]: https://docs.agentfront.dev/frontmcp/testing/overview 'Testing'
142
- [docs-ui]: https://docs.agentfront.dev/frontmcp/ui/overview 'UI Library'
193
+ [docs-ui]: https://docs.agentfront.dev/frontmcp/react/overview 'React SDK'
143
194
  [docs-deploy]: https://docs.agentfront.dev/frontmcp/deployment/local-dev-server 'Deployment'
144
195
  [docs-production]: https://docs.agentfront.dev/frontmcp/deployment/production-build 'Production Build'
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: frontmcp-deployment
3
- description: 'Use when deploying, building for production, packaging, or shipping a FrontMCP server. Covers build targets (node, cli SEA binary, browser, embeddable SDK, mcpb archive for Claude Desktop, serverless) and deploying to Vercel (with Vercel KV), AWS Lambda (API Gateway, SAM, CDK), Cloudflare Workers (KV, D1, Durable Objects, v1.3 skills-only), and Node (multi-stage Docker, docker-compose, PM2, nginx). Also the frontmcp.deploy.yaml manifest plus GitHub Action push-resync, and MCP client integration / .mcp.json for Claude Desktop, Claude Code, Cursor, and VS Code over stdio or HTTP. Triggers: deploy, build for production, dockerize, containerize, serverless, edge runtime, go live, ship it.'
3
+ description: 'Use when deploying, building for production, packaging, or shipping a FrontMCP server. Covers build targets (node, cli SEA binary, browser, embeddable SDK, mcpb archive for Claude Desktop, serverless) and deploying to Vercel (with Vercel KV), AWS Lambda (API Gateway, SAM, CDK), Cloudflare Workers (KV, D1, Durable Objects, v1.3 skills-only), and Node (multi-stage Docker, docker-compose, PM2, nginx). Also the frontmcp.deploy.yaml manifest plus GitHub Action push-resync, MCP client integration / .mcp.json for Claude Desktop, Claude Code, Cursor, and VS Code over stdio or HTTP, and MCP protocol revisions (serving 2026-07-28 alongside 2024-11-05 through 2025-11-25). Triggers: deploy, build for production, dockerize, containerize, serverless, edge runtime, go live, ship it.'
4
4
  tags: [router, deployment, node, vercel, lambda, cloudflare, cli, browser, sdk, guide]
5
5
  category: deployment
6
6
  targets: [all]
@@ -67,6 +67,7 @@ Entry point for deploying and building FrontMCP servers. This skill helps you ch
67
67
  | Write a Dockerfile for Node.js deployment | `deploy-to-node-dockerfile` | Dockerfile configuration for Node.js deployment |
68
68
  | Configure Vercel-specific settings (vercel.json) | `deploy-to-vercel-config` | Vercel-specific configuration (vercel.json) |
69
69
  | Connect MCP clients (Claude, Cursor, VS Code) | `mcp-client-integration` | Configure .mcp.json for stdio, HTTP, or Unix socket transport |
70
+ | Serve or consume MCP protocol `2026-07-28` | `protocol-versions` | Stateless requests, `server/discover`, mirrored headers, MRTR, tasks extension, and the `McpStatelessClient` |
70
71
 
71
72
  ### CLI Commands for Deployment and Operations
72
73
 
@@ -0,0 +1,221 @@
1
+ ---
2
+ name: protocol-versions
3
+ description: Serve MCP protocol revision 2026-07-28 alongside every earlier revision, and connect to a 2026 server as a client
4
+ ---
5
+
6
+ # MCP Protocol Versions
7
+
8
+ FrontMCP serves **every MCP revision from `2024-11-05` through `2026-07-28`** on
9
+ the same endpoint. The revision is selected per request — there is no
10
+ configuration switch and no server-side flag to flip.
11
+
12
+ ## When to Use This Skill
13
+
14
+ ### Must Use
15
+
16
+ - A client reports `-32020`, `-32021`, or `-32022` against a FrontMCP server
17
+ - Building a tool that needs elicitation, sampling, or roots on a 2026 client
18
+ - Connecting FrontMCP to a remote MCP server that speaks `2026-07-28`
19
+ - Returning long-running work as a task handle under the tasks extension
20
+
21
+ ### Recommended
22
+
23
+ - Auditing which revision a deployed server is actually serving to a client
24
+ - Adding `x-mcp-header` annotations so intermediaries can route on tool arguments
25
+ - Wiring OpenTelemetry trace context through MCP requests
26
+
27
+ ### Skip When
28
+
29
+ - The client speaks `2025-11-25` or earlier — nothing changes for it
30
+ - You are configuring transports/ports (see `deploy-to-node`)
31
+
32
+ ## How a revision is selected
33
+
34
+ A request is served as `2026-07-28` when ANY of these is true:
35
+
36
+ - `params._meta` carries `io.modelcontextprotocol/protocolVersion` (a key that
37
+ exists only in this revision)
38
+ - the `MCP-Protocol-Version` header names a version the session pipeline does not
39
+ know (an unknown/future version then gets `-32022`, not a session error)
40
+ - the method is `server/discover` or `subscriptions/listen`
41
+
42
+ Everything else — including every `initialize` and every request carrying
43
+ `Mcp-Session-Id` — takes the session pipeline unchanged.
44
+
45
+ ## Default for unversioned requests
46
+
47
+ A bare JSON-RPC call naming no revision (no `initialize`, no `Mcp-Session-Id`,
48
+ no `MCP-Protocol-Version`) falls back to:
49
+
50
+ | Runtime | Default |
51
+ | -------------------------------------- | -------------- |
52
+ | Cloudflare Workers / other V8 isolates | `'2026-07-28'` |
53
+ | Node and everything else | `'legacy'` |
54
+
55
+ Override per server:
56
+
57
+ ```ts
58
+ @FrontMcp({
59
+ transport: { defaultProtocolVersion: '2026-07-28' }, // or 'legacy'
60
+ })
61
+ ```
62
+
63
+ The Worker default is stateless on purpose: no session means no Durable Object
64
+ binding is needed to serve MCP.
65
+
66
+ When the SERVER defaults a request to 2026-07-28, the mirrored-header rules are
67
+ NOT enforced — the client never opted into SEP-2243. Headers that ARE present
68
+ are still validated. A client that declares the revision itself gets the full
69
+ contract.
70
+
71
+ ## What 2026-07-28 changed
72
+
73
+ | Area | Before | 2026-07-28 |
74
+ | ------------- | ------------------------------------------ | ---------------------------------------------------- |
75
+ | Handshake | `initialize` + `notifications/initialized` | none; `_meta` on every request |
76
+ | Sessions | `Mcp-Session-Id` | removed (`GET`/`DELETE` → `405`) |
77
+ | Discovery | `initialize` result | `server/discover` |
78
+ | Notifications | standalone GET stream | `subscriptions/listen` (opt-in filter) |
79
+ | Server→client | `elicitation/create` etc. as requests | MRTR `InputRequiredResult` |
80
+ | Log level | `logging/setLevel` | per-request `_meta` `logLevel` |
81
+ | Results | bare result | `resultType` + `serverInfo` (+ `ttlMs`/`cacheScope`) |
82
+ | Tasks | core protocol | `io.modelcontextprotocol/tasks` extension |
83
+ | Not found | `-32002` | `-32602` |
84
+
85
+ ## Mirrored request headers
86
+
87
+ The server validates that headers agree with the body and rejects a mismatch
88
+ with `400` + `-32020`. Annotate a tool argument to have it mirrored:
89
+
90
+ ```ts
91
+ const inputSchema = {
92
+ region: z.string().describe('Region to query').meta({ 'x-mcp-header': 'Region' }),
93
+ query: z.string(),
94
+ };
95
+ ```
96
+
97
+ A conforming client then sends `Mcp-Param-Region: us-west1` alongside
98
+ `MCP-Protocol-Version`, `Mcp-Method`, and `Mcp-Name`. Non-ASCII values travel as
99
+ `=?base64?…?=`.
100
+
101
+ ## Multi Round-Trip Requests (MRTR)
102
+
103
+ `this.elicit()`, `this.sample()`, and `this.listRoots()` no longer round-trip
104
+ inline. The server answers the ORIGINAL request with:
105
+
106
+ ```json
107
+ {
108
+ "resultType": "input_required",
109
+ "inputRequests": { "elicitation-1": { "method": "elicitation/create", "params": { "message": "Proceed?" } } },
110
+ "requestState": "<opaque, signed>"
111
+ }
112
+ ```
113
+
114
+ The client gathers the input and re-issues the same request with a NEW id plus
115
+ `inputResponses` + the echoed `requestState`.
116
+
117
+ **Write tools to be replay-safe.** The tool runs again from the top on the
118
+ retry; recorded answers resolve inline. Do not perform irreversible side effects
119
+ before the first `elicit()`/`sample()`/`listRoots()` call.
120
+
121
+ `requestState` is HMAC-signed and bound to the caller, the originating request,
122
+ and a 10-minute expiry — a tampered or replayed blob is discarded and the
123
+ exchange restarts.
124
+
125
+ The client MUST declare the matching capability, or the server answers `-32021`:
126
+
127
+ ```json
128
+ "io.modelcontextprotocol/clientCapabilities": { "elicitation": { "form": {} } }
129
+ ```
130
+
131
+ ## Request-scoped logging and progress
132
+
133
+ A client opts in per request:
134
+
135
+ ```json
136
+ "_meta": { "io.modelcontextprotocol/logLevel": "info", "progressToken": "tok-1" }
137
+ ```
138
+
139
+ `this.notify()` and `this.progress()` then stream on that request's own SSE
140
+ response, terminated by the final result. Omit `logLevel` and the server emits
141
+ no `notifications/message` at all.
142
+
143
+ ## Tasks extension
144
+
145
+ ```json
146
+ "io.modelcontextprotocol/clientCapabilities": {
147
+ "extensions": { "io.modelcontextprotocol/tasks": {} }
148
+ }
149
+ ```
150
+
151
+ A tool with `execution: { taskSupport: 'optional' }` then returns
152
+ `{ "resultType": "task", "task": { "taskId", "status", "ttlMs", "pollIntervalMs" } }`.
153
+ Poll `tasks/get`; answer `input_required` with `tasks/update`; `tasks/cancel`
154
+ still works. `tasks/list` and `tasks/result` were removed.
155
+
156
+ Tasks require an **authenticated** caller — without protocol sessions an
157
+ anonymous task cannot be scoped to its creator, so a public server refuses.
158
+
159
+ ## Connecting as a client
160
+
161
+ The upstream `@modelcontextprotocol/sdk` client cannot speak this revision:
162
+
163
+ ```ts
164
+ import { McpStatelessClient } from '@frontmcp/sdk';
165
+
166
+ const client = new McpStatelessClient({
167
+ url: 'https://example.com/mcp',
168
+ capabilities: { elicitation: { form: {} } },
169
+ handlers: { onElicit: async () => ({ action: 'accept', content: { confirmed: true } }) },
170
+ });
171
+
172
+ await client.listTools();
173
+ await client.callTool('confirm', { action: 'deploy' });
174
+ ```
175
+
176
+ The MRTR retry loop and task polling are handled internally, so `callTool`
177
+ resolves with the final result either way.
178
+
179
+ For a remote app, negotiate per remote:
180
+
181
+ ```ts
182
+ transportOptions: {
183
+ protocolVersion: 'auto';
184
+ } // 'legacy' (default) | '2026-07-28' | 'auto'
185
+ ```
186
+
187
+ ## Deprecated in this revision
188
+
189
+ Still functional; do not adopt in new servers:
190
+
191
+ - **Roots** → pass directories via tool parameters or server config
192
+ - **Sampling** → integrate an LLM provider API directly
193
+ - **Logging** → `stderr` or OpenTelemetry
194
+ - **HTTP+SSE transport** → Streamable HTTP
195
+ - **DCR** → Client ID Metadata Documents
196
+
197
+ ## Cloudflare Workers
198
+
199
+ A Worker serves 2026-07-28 natively and defaults to it. `server/discover`,
200
+ stateless `tools/call`, `subscriptions/listen`, and the mirrored-header rules
201
+ all work through the same `fetch` handler; `initialize` clients keep working on
202
+ the same endpoint.
203
+
204
+ Skills over MCP (`skill://` resources plus `skills/search` / `skills/load` /
205
+ `skills/list`) share the same handler set, so they are available under
206
+ 2026-07-28 with no extra configuration.
207
+
208
+ ## Common Mistakes
209
+
210
+ ❌ Reusing the JSON-RPC id on an MRTR retry — it MUST be a new id
211
+ ❌ Inspecting or rewriting `requestState` — it is opaque and integrity-protected
212
+ ❌ Performing side effects before the first `elicit()` — the tool is replayed
213
+ ❌ Expecting `Mcp-Session-Id` to be echoed — sessions are gone
214
+ ❌ Calling `tasks/list` or `tasks/result` — both removed (`404` + `-32601`)
215
+ ❌ Omitting `Mcp-Method`/`Mcp-Name` headers once you declare 2026 — `-32020`
216
+ ❌ Assuming a Worker still mints `Mcp-Session-Id` — it defaults to stateless
217
+
218
+ ## Related
219
+
220
+ - Docs: https://docs.agentfront.dev/frontmcp/fundamentals/protocol-versions
221
+ - Spec: https://modelcontextprotocol.io/specification/2026-07-28/changelog
@@ -4,7 +4,7 @@
4
4
  {
5
5
  "name": "create-tool",
6
6
  "category": "development/create",
7
- "description": "ALWAYS use this skill when the user asks to build, modify, or audit a FrontMCP tool. Covers @Tool({...}) end-to-end: class and function-style tools, Zod input/output schemas with derived execute() types, dependency injection, error handling, throttling (rate-limit / concurrency / timeout), auth providers, availability constraints, elicitation, interactive UI widgets (MCP Apps / SEP-1865 — including .tsx FileSource, CSP, window.FrontMcpBridge, host-detect resourceMode), annotations, examples metadata, registration in @App, and per-tool unit testing.",
7
+ "description": "ALWAYS use this skill when the user asks to build, modify, or audit a FrontMCP tool. Covers @Tool({...}) end-to-end: class and function-style tools, Zod input/output schemas with derived execute() types, dependency injection, error handling, throttling (rate-limit / concurrency / timeout), auth providers, availability constraints, elicitation, interactive UI widgets (MCP Apps / SEP-1865 \u2014 including .tsx FileSource, CSP, window.FrontMcpBridge, host-detect resourceMode), annotations, examples metadata, registration in @App, and per-tool unit testing.",
8
8
  "path": "create-tool",
9
9
  "targets": ["all"],
10
10
  "hasResources": true,
@@ -30,19 +30,19 @@
30
30
  "references": [
31
31
  {
32
32
  "name": "quick-start",
33
- "description": "60-second tour — minimal tool, schemas, registration, calling it."
33
+ "description": "60-second tour \u2014 minimal tool, schemas, registration, calling it."
34
34
  },
35
35
  {
36
36
  "name": "decorator-options",
37
- "description": "Every field on `@Tool({...})` — what it does, default, when to set it."
37
+ "description": "Every field on `@Tool({...})` \u2014 what it does, default, when to set it."
38
38
  },
39
39
  {
40
40
  "name": "input-schema",
41
- "description": "Define the tool's input contract — raw Zod shapes, refinements, defaults, optional fields."
41
+ "description": "Define the tool's input contract \u2014 raw Zod shapes, refinements, defaults, optional fields."
42
42
  },
43
43
  {
44
44
  "name": "output-schema",
45
- "description": "Define the tool's output contract — Zod shape, primitives, media, multi-content arrays."
45
+ "description": "Define the tool's output contract \u2014 Zod shape, primitives, media, multi-content arrays."
46
46
  },
47
47
  {
48
48
  "name": "derived-types",
@@ -50,15 +50,15 @@
50
50
  },
51
51
  {
52
52
  "name": "execution-context",
53
- "description": "What ToolContext provides at runtime — this.get, this.fetch, this.notify, this.context."
53
+ "description": "What ToolContext provides at runtime \u2014 this.get, this.fetch, this.notify, this.context."
54
54
  },
55
55
  {
56
56
  "name": "error-handling",
57
- "description": "this.fail, MCP error classes, error flow — when to throw vs fail."
57
+ "description": "this.fail, MCP error classes, error flow \u2014 when to throw vs fail."
58
58
  },
59
59
  {
60
60
  "name": "throttling",
61
- "description": "rateLimit, concurrency, timeout — semantics, interaction, defaults."
61
+ "description": "rateLimit, concurrency, timeout \u2014 semantics, interaction, defaults."
62
62
  },
63
63
  {
64
64
  "name": "auth-providers",
@@ -70,23 +70,23 @@
70
70
  },
71
71
  {
72
72
  "name": "elicitation",
73
- "description": "this.elicit — request interactive input mid-execution. Server enable + accept/decline/cancel flow."
73
+ "description": "this.elicit \u2014 request interactive input mid-execution. Server enable + accept/decline/cancel flow."
74
74
  },
75
75
  {
76
76
  "name": "ui-widgets",
77
- "description": "@Tool({ ui }) — template formats, servingMode, host-detect resourceMode, CSP, widgetAccessible, MCP Apps spec."
77
+ "description": "@Tool({ ui }) \u2014 template formats, servingMode, host-detect resourceMode, CSP, widgetAccessible, MCP Apps spec."
78
78
  },
79
79
  {
80
80
  "name": "annotations",
81
- "description": "readOnlyHint, destructiveHint, idempotentHint, openWorldHint, title — behavioral hints for clients."
81
+ "description": "readOnlyHint, destructiveHint, idempotentHint, openWorldHint, title \u2014 behavioral hints for clients."
82
82
  },
83
83
  {
84
84
  "name": "function-style-builder",
85
- "description": "tool({...})(handler) — when to pick over a class, register, ctx parameter."
85
+ "description": "tool({...})(handler) \u2014 when to pick over a class, register, ctx parameter."
86
86
  },
87
87
  {
88
88
  "name": "remote-and-esm",
89
- "description": "Tool.esm / Tool.remote — load tools from ESM URLs or remote MCP servers."
89
+ "description": "Tool.esm / Tool.remote \u2014 load tools from ESM URLs or remote MCP servers."
90
90
  },
91
91
  {
92
92
  "name": "registration",
@@ -98,7 +98,7 @@
98
98
  },
99
99
  {
100
100
  "name": "testing",
101
- "description": "Per-tool unit tests — @frontmcp/testing, mocking DI, asserting output validation."
101
+ "description": "Per-tool unit tests \u2014 @frontmcp/testing, mocking DI, asserting output validation."
102
102
  }
103
103
  ],
104
104
  "examples": [
@@ -119,7 +119,7 @@
119
119
  {
120
120
  "name": "02-basic-function-tool",
121
121
  "level": "basic",
122
- "description": "Function-style `tool({...})(handler)` for a tiny pure-input tool — pick this over a class only when the tool needs no DI / lifecycle / UI.",
122
+ "description": "Function-style `tool({...})(handler)` for a tiny pure-input tool \u2014 pick this over a class only when the tool needs no DI / lifecycle / UI.",
123
123
  "tags": ["foundation", "function-tool", "tool-builder"],
124
124
  "features": [
125
125
  "Using the `tool({...})(handler)` builder for a one-liner",
@@ -131,10 +131,10 @@
131
131
  {
132
132
  "name": "03-tool-with-zod-shape-output",
133
133
  "level": "basic",
134
- "description": "Tool returning structured JSON declared via a Zod raw shape outputSchema — the recommended pattern for any complex output.",
134
+ "description": "Tool returning structured JSON declared via a Zod raw shape outputSchema \u2014 the recommended pattern for any complex output.",
135
135
  "tags": ["output-schema", "zod-shape", "structured-output"],
136
136
  "features": [
137
- "Declaring `outputSchema` as a Zod raw shape `{ field: z.string(), … }`",
137
+ "Declaring `outputSchema` as a Zod raw shape `{ field: z.string(), \u2026 }`",
138
138
  "Constraining values with `.int().min(0)` so invalid output is rejected at the boundary",
139
139
  "Letting unrelated fields returned by the implementation (e.g. an upstream API's extras) be stripped silently",
140
140
  "Deriving `OrderSummaryOutput` once so the type and runtime contract can't drift"
@@ -143,7 +143,7 @@
143
143
  {
144
144
  "name": "04-tool-with-zod-schema-output",
145
145
  "level": "advanced",
146
- "description": "Tool returning a discriminated union via a full `z.discriminatedUnion(...)` outputSchema — for outputs that branch on a kind field.",
146
+ "description": "Tool returning a discriminated union via a full `z.discriminatedUnion(...)` outputSchema \u2014 for outputs that branch on a kind field.",
147
147
  "tags": ["output-schema", "zod-schema", "discriminated-union"],
148
148
  "features": [
149
149
  "Using a full Zod schema (`z.discriminatedUnion(...)`) as `outputSchema` instead of a raw shape",
@@ -155,7 +155,7 @@
155
155
  {
156
156
  "name": "05-tool-with-primitive-output",
157
157
  "level": "basic",
158
- "description": "Tool returning a single primitive — `outputSchema: 'string' | 'number' | 'boolean' | 'date'` for single-value outputs.",
158
+ "description": "Tool returning a single primitive \u2014 `outputSchema: 'string' | 'number' | 'boolean' | 'date'` for single-value outputs.",
159
159
  "tags": ["output-schema", "primitive-output"],
160
160
  "features": [
161
161
  "Using a primitive literal (`'string'`, `'number'`, `'boolean'`, `'date'`) for `outputSchema`",
@@ -167,19 +167,19 @@
167
167
  {
168
168
  "name": "06-tool-with-media-output",
169
169
  "level": "intermediate",
170
- "description": "Tool returning binary content (image / audio) or a multi-content array of `[text, image]` — for outputs that aren't plain JSON.",
170
+ "description": "Tool returning binary content (image / audio) or a multi-content array of `[text, image]` \u2014 for outputs that aren't plain JSON.",
171
171
  "tags": ["output-schema", "media-output", "image", "multi-content"],
172
172
  "features": [
173
173
  "Returning a base64-encoded image with `outputSchema: 'image'` and `{ type: 'image', data, mimeType }`",
174
174
  "Returning audio with `outputSchema: 'audio'` (same `{ type: 'audio', data, mimeType }` shape, audio MIME types)",
175
- "Returning multi-content via `outputSchema: ['string', 'image']` — text summary + annotated image in one response",
175
+ "Returning multi-content via `outputSchema: ['string', 'image']` \u2014 text summary + annotated image in one response",
176
176
  "When to pick a media literal vs `'resource_link'` (host-fetched URI)"
177
177
  ]
178
178
  },
179
179
  {
180
180
  "name": "08-tool-with-provider-injection",
181
181
  "level": "intermediate",
182
- "description": "Tool that resolves a DI-registered service via `this.get(TOKEN)` and uses it to power `execute()` — the standard pattern for tools that talk to a database or external API.",
182
+ "description": "Tool that resolves a DI-registered service via `this.get(TOKEN)` and uses it to power `execute()` \u2014 the standard pattern for tools that talk to a database or external API.",
183
183
  "tags": ["di", "provider", "this.get", "error-handling"],
184
184
  "features": [
185
185
  "Defining a typed DI token with `Symbol('UserService')` and `Token<UserService>`",
@@ -191,11 +191,11 @@
191
191
  {
192
192
  "name": "09-tool-with-multiple-providers",
193
193
  "level": "intermediate",
194
- "description": "Tool composing three DI services — config (env-only), cache (optional, `tryGet`), and database (required) — the realistic shape for a production tool.",
194
+ "description": "Tool composing three DI services \u2014 config (env-only), cache (optional, `tryGet`), and database (required) \u2014 the realistic shape for a production tool.",
195
195
  "tags": ["di", "multiple-providers", "cache-aside", "tryGet"],
196
196
  "features": [
197
197
  "Resolving multiple providers via `this.get(TOKEN)` and `this.tryGet(TOKEN)`",
198
- "Cache-aside pattern — check `tryGet(CACHE)` first, fall back to the database",
198
+ "Cache-aside pattern \u2014 check `tryGet(CACHE)` first, fall back to the database",
199
199
  "Reading typed config from a `CONFIG` token vs `process.env` directly",
200
200
  "Letting the tool work in production (with cache) AND in test (without it)"
201
201
  ]
@@ -203,12 +203,12 @@
203
203
  {
204
204
  "name": "11-tool-with-fetch",
205
205
  "level": "intermediate",
206
- "description": "Tool calling an external HTTP API with `this.fetch` — context propagation, status-code handling, and bounding the call with a tool `timeout`.",
206
+ "description": "Tool calling an external HTTP API with `this.fetch` \u2014 context propagation, status-code handling, and bounding the call with a tool `timeout`.",
207
207
  "tags": ["fetch", "http", "external-api", "error-handling"],
208
208
  "features": [
209
209
  "Using `this.fetch(url, init?)` so trace context propagates to the upstream service",
210
210
  "Translating non-2xx HTTP responses into `PublicMcpError` so the MCP client gets a clean error",
211
- "Bounding the call with a tool `timeout` (and `this.fetch`'s built-in per-request timeout) — without relying on a non-existent context abort signal",
211
+ "Bounding the call with a tool `timeout` (and `this.fetch`'s built-in per-request timeout) \u2014 without relying on a non-existent context abort signal",
212
212
  "Letting genuine network errors (DNS failure, ECONNREFUSED) propagate to the framework's error flow"
213
213
  ]
214
214
  },
@@ -227,36 +227,36 @@
227
227
  {
228
228
  "name": "13-tool-with-single-auth-provider",
229
229
  "level": "intermediate",
230
- "description": "Tool requiring a single OAuth provider via the `authProviders: ['github']` string shorthand — credentials loaded before `execute()` runs.",
230
+ "description": "Tool requiring a single OAuth provider via the `authProviders: ['github']` string shorthand \u2014 credentials loaded before `execute()` runs.",
231
231
  "tags": ["auth-providers", "oauth", "github", "this.authProviders"],
232
232
  "features": [
233
233
  "Declaring a single required OAuth provider with the `authProviders: ['github']` shorthand",
234
234
  "Reading pre-formatted credentials via `await this.authProviders.headers('github')`",
235
- "Letting the framework reject calls whose required credential is missing **before** `execute()` runs — a JSON-RPC `-32001` (MCP `UNAUTHORIZED`) error whose `data` carries `{ tool, providers: ['github'], authUrl }` (no auth-check boilerplate)",
235
+ "Letting the framework reject calls whose required credential is missing **before** `execute()` runs \u2014 a JSON-RPC `-32001` (MCP `UNAUTHORIZED`) error whose `data` carries `{ tool, providers: ['github'], authUrl }` (no auth-check boilerplate)",
236
236
  "Trusting the framework to handle token refresh, expiration, and the connect/authorize URL"
237
237
  ]
238
238
  },
239
239
  {
240
240
  "name": "14-tool-with-multiple-auth-providers",
241
241
  "level": "advanced",
242
- "description": "Tool with the full `authProviders` mapping form — one required provider with explicit scopes, one optional provider with an alias, and graceful degradation when the optional creds are missing.",
242
+ "description": "Tool with the full `authProviders` mapping form \u2014 one required provider with explicit scopes, one optional provider with an alias, and graceful degradation when the optional creds are missing.",
243
243
  "tags": ["auth-providers", "oauth", "scopes", "optional-auth", "this.authProviders.headers"],
244
244
  "features": [
245
245
  "Using the object form of `authProviders` to set `required`, `scopes`, and `alias`",
246
246
  "Declaring required OAuth scopes that the server advertises in its Protected Resource Metadata (`scopes_supported`) so clients request them",
247
247
  "Resolving an optional provider via `await this.authProviders.headers('cloud')` (returns an empty object `{}` when absent)",
248
- "Branching the tool's behavior — full deploy when both providers are present; preview-only when the cloud provider is missing",
248
+ "Branching the tool's behavior \u2014 full deploy when both providers are present; preview-only when the cloud provider is missing",
249
249
  "The required `github` provider gating the call: when its credential is missing the framework aborts before `execute()` with `-32001` and `data: { tool, providers: ['github'], authUrl }`; the optional `aws`/`cloud` provider never gates"
250
250
  ]
251
251
  },
252
252
  {
253
253
  "name": "15-tool-with-credential-vault",
254
254
  "level": "advanced",
255
- "description": "Tool that reads a user-supplied static credential (a Slack webhook URL) from the per-session encrypted credential vault — the pattern for credentials that aren't OAuth.",
255
+ "description": "Tool that reads a user-supplied static credential (a Slack webhook URL) from the per-session encrypted credential vault \u2014 the pattern for credentials that aren't OAuth.",
256
256
  "tags": ["auth-providers", "credential-vault", "slack-webhook", "encryption-at-rest"],
257
257
  "features": [
258
258
  "Declaring a vault-backed auth provider with `authProviders: ['slack-webhook']`",
259
- "Reading the user's pasted-in credential via `await this.authProviders.headers('slack-webhook')` — same API as OAuth",
259
+ "Reading the user's pasted-in credential via `await this.authProviders.headers('slack-webhook')` \u2014 same API as OAuth",
260
260
  "Letting the framework handle per-session AES-256-GCM encryption at rest (Redis or memory store)",
261
261
  "Knowing when to pick the vault (static secrets the user knows) vs OAuth (delegated identity)"
262
262
  ]
@@ -264,19 +264,19 @@
264
264
  {
265
265
  "name": "16-tool-with-rate-limit",
266
266
  "level": "intermediate",
267
- "description": "Tool with `rateLimit: { maxRequests, windowMs }` capping invocations per session per minute — the protection for expensive / external-API-billed operations.",
267
+ "description": "Tool with `rateLimit: { maxRequests, windowMs }` capping invocations per session per minute \u2014 the protection for expensive / external-API-billed operations.",
268
268
  "tags": ["throttling", "rate-limit", "abuse-protection"],
269
269
  "features": [
270
270
  "Capping the tool to N invocations per windowMs, partitioned per session via `partitionBy: 'session'`",
271
271
  "Letting the framework reject over-limit calls with `RateLimitError` (code `'RATE_LIMIT_EXCEEDED'`, HTTP status 429) carrying a retry-after hint in its message that clients can back off against",
272
272
  "Combining `rateLimit` with `annotations.openWorldHint: true` so clients know the tool talks to billed external services",
273
- "Sizing the limit against upstream quota / billing — not just \"what feels reasonable\""
273
+ "Sizing the limit against upstream quota / billing \u2014 not just \"what feels reasonable\""
274
274
  ]
275
275
  },
276
276
  {
277
277
  "name": "17-tool-with-concurrency-and-timeout",
278
278
  "level": "advanced",
279
- "description": "Tool with `concurrency` + `timeout` for a real bottleneck (PDF rendering) — caps simultaneous in-flight work AND hard-caps per-call duration.",
279
+ "description": "Tool with `concurrency` + `timeout` for a real bottleneck (PDF rendering) \u2014 caps simultaneous in-flight work AND hard-caps per-call duration.",
280
280
  "tags": ["throttling", "concurrency", "timeout"],
281
281
  "features": [
282
282
  "Capping simultaneous in-flight executions with `concurrency: { maxConcurrent }` (server-wide by default)",
@@ -288,7 +288,7 @@
288
288
  {
289
289
  "name": "18-tool-with-progress-and-notify",
290
290
  "level": "intermediate",
291
- "description": "Long-running tool emitting progress updates (`this.progress`), log notifications (`this.notify`), and stage markers (`this.mark`) — the standard pattern for jobs you don't want to feel hung.",
291
+ "description": "Long-running tool emitting progress updates (`this.progress`), log notifications (`this.notify`), and stage markers (`this.mark`) \u2014 the standard pattern for jobs you don't want to feel hung.",
292
292
  "tags": ["progress", "notifications", "mark", "long-running"],
293
293
  "features": [
294
294
  "Emitting per-item progress with `await this.progress(current, total, message)`",
@@ -300,19 +300,19 @@
300
300
  {
301
301
  "name": "19-tool-with-elicitation",
302
302
  "level": "advanced",
303
- "description": "Tool that pauses mid-execution to ask the user for confirmation + extra input via `this.elicit(...)` — the safe pattern for destructive or expensive actions.",
303
+ "description": "Tool that pauses mid-execution to ask the user for confirmation + extra input via `this.elicit(...)` \u2014 the safe pattern for destructive or expensive actions.",
304
304
  "tags": ["elicitation", "this.elicit", "destructive-action", "confirmation"],
305
305
  "features": [
306
306
  "Calling `this.elicit(message, z.object({ ... }))` to request interactive input mid-`execute()`",
307
- "Branching on `result.status` — `accept` / `decline` / `cancel` — and matching the early returns against `outputSchema`",
307
+ "Branching on `result.status` \u2014 `accept` / `decline` / `cancel` \u2014 and matching the early returns against `outputSchema`",
308
308
  "Pairing elicitation with `annotations.destructiveHint: true` so clients know to render the confirmation prominently",
309
- "Requiring `elicitation: { enabled: true }` at the `@FrontMcp({...})` server level — and what fails when it isn't"
309
+ "Requiring `elicitation: { enabled: true }` at the `@FrontMcp({...})` server level \u2014 and what fails when it isn't"
310
310
  ]
311
311
  },
312
312
  {
313
313
  "name": "20-tool-with-annotations",
314
314
  "level": "basic",
315
- "description": "Four tools showing the standard annotation combinations — read-only query, destructive delete, send-email side-effecting, external-API search — and the client behavior each combination opts into.",
315
+ "description": "Four tools showing the standard annotation combinations \u2014 read-only query, destructive delete, send-email side-effecting, external-API search \u2014 and the client behavior each combination opts into.",
316
316
  "tags": ["annotations", "readOnlyHint", "destructiveHint", "idempotentHint", "openWorldHint"],
317
317
  "features": [
318
318
  "Setting `readOnlyHint` / `destructiveHint` / `idempotentHint` / `openWorldHint` to opt into specific client behaviors (auto-retry, confirmation gating, parallelization)",
@@ -324,43 +324,43 @@
324
324
  {
325
325
  "name": "21-tool-with-availability-constraints",
326
326
  "level": "advanced",
327
- "description": "Three tools showing the `availableWhen` axes — macOS-only OS gate, production+Node runtime gate, and a `surface` gate that allows agent + job invocation but blocks direct MCP-client calls.",
327
+ "description": "Three tools showing the `availableWhen` axes \u2014 macOS-only OS gate, production+Node runtime gate, and a `surface` gate that allows agent + job invocation but blocks direct MCP-client calls.",
328
328
  "tags": ["availableWhen", "os", "runtime", "surface", "EntryUnavailableError"],
329
329
  "features": [
330
330
  "Restricting a tool to macOS with `availableWhen: { os: ['darwin'] }`",
331
- "Composing constraints — `runtime: ['node']` AND `env: ['production']` — both must match for the tool to be available",
331
+ "Composing constraints \u2014 `runtime: ['node']` AND `env: ['production']` \u2014 both must match for the tool to be available",
332
332
  "Using the `surface` axis to expose an internal tool to agents and jobs while hiding it from direct user invocation",
333
- "Knowing what happens on mismatch — `EntryUnavailableError` (`-32003` FORBIDDEN) with `data.missingAxes` so clients show the right \"not available here\" reason"
333
+ "Knowing what happens on mismatch \u2014 `EntryUnavailableError` (`-32003` FORBIDDEN) with `data.missingAxes` so clients show the right \"not available here\" reason"
334
334
  ]
335
335
  },
336
336
  {
337
337
  "name": "22-tool-with-ui-html-template",
338
338
  "level": "intermediate",
339
- "description": "Tool with an inline HTML function template — `ui: { template: (ctx) => '<div>…</div>' }` — for a quick widget that doesn't need a separate `.tsx` file.",
339
+ "description": "Tool with an inline HTML function template \u2014 `ui: { template: (ctx) => '<div>\u2026</div>' }` \u2014 for a quick widget that doesn't need a separate `.tsx` file.",
340
340
  "tags": ["ui", "ui-widgets", "html-template", "escapeHtml", "TemplateContext"],
341
341
  "features": [
342
342
  "Adding a `ui:` block with a function template `(ctx: TemplateContext<In, Out>) => string`",
343
343
  "Annotating `ctx` explicitly to dodge the TS7006 inference gap on the union `ui.template` type",
344
344
  "Always escaping user-controlled output with `ctx.helpers.escapeHtml(...)` so the widget can't XSS itself",
345
- "Reading from `ctx.output` and `ctx.helpers` — the typed runtime context the template renderer hands you"
345
+ "Reading from `ctx.output` and `ctx.helpers` \u2014 the typed runtime context the template renderer hands you"
346
346
  ]
347
347
  },
348
348
  {
349
349
  "name": "23-tool-with-ui-filesource-tsx",
350
350
  "level": "advanced",
351
- "description": "Tool with a `.tsx` widget in a separate file via the `FileSource` form — the recommended pattern for any React widget. Path anchored with `import.meta.url` so it survives any cwd.",
351
+ "description": "Tool with a `.tsx` widget in a separate file via the `FileSource` form \u2014 the recommended pattern for any React widget. Path anchored with `import.meta.url` so it survives any cwd.",
352
352
  "tags": ["ui", "ui-widgets", "FileSource", "tsx", "import.meta.url", "host-detect"],
353
353
  "features": [
354
354
  "Pointing `template` at a sibling `.tsx` file via the `FileSource` form `{ file: ... }`",
355
355
  "Anchoring the path to the tool source with `fileURLToPath(new URL('./...widget.tsx', import.meta.url))` so `process.cwd()` doesn't matter",
356
- "Leaving `resourceMode` unset — the framework host-detects (`'inline'` for Claude, `'cdn'` for others)",
356
+ "Leaving `resourceMode` unset \u2014 the framework host-detects (`'inline'` for Claude, `'cdn'` for others)",
357
357
  "Naming the widget `*.widget.tsx` so the scaffolded `tsconfig.json`'s `exclude` keeps it out of the server typecheck"
358
358
  ]
359
359
  },
360
360
  {
361
361
  "name": "24-tool-with-ui-csp-and-bridge",
362
362
  "level": "advanced",
363
- "description": "Interactive tool widget that fetches from an allow-listed CSP origin and invokes another tool via `window.FrontMcpBridge.callTool` — the full pattern for live-data widgets that need cross-tool composition.",
363
+ "description": "Interactive tool widget that fetches from an allow-listed CSP origin and invokes another tool via `window.FrontMcpBridge.callTool` \u2014 the full pattern for live-data widgets that need cross-tool composition.",
364
364
  "tags": ["ui", "csp", "widgetAccessible", "FrontMcpBridge", "interactive-widget"],
365
365
  "features": [
366
366
  "Restricting the widget's outbound `fetch` via `ui.csp.connectDomains` (emitted on the resource per #455)",
@@ -372,7 +372,7 @@
372
372
  {
373
373
  "name": "25-tool-handing-off-to-job",
374
374
  "level": "advanced",
375
- "description": "Thin tool that validates input and enqueues a `@Job` to do the heavy lifting — the right pattern for any operation that takes more than a few seconds.",
375
+ "description": "Thin tool that validates input and enqueues a `@Job` to do the heavy lifting \u2014 the right pattern for any operation that takes more than a few seconds.",
376
376
  "tags": ["composition", "jobs", "job-handoff", "hideFromDiscovery"],
377
377
  "features": [
378
378
  "Splitting a long-running operation into a thin tool (validates, enqueues, returns a tracking handle) plus a `@Job` (does the work)",
@@ -384,10 +384,10 @@
384
384
  {
385
385
  "name": "26-tool-with-resource-link-output",
386
386
  "level": "advanced",
387
- "description": "Tool returning `outputSchema: 'resource_link'` — the URI is sent to the client; the client fetches the body via `resources/read`. The right pattern for large or cacheable payloads.",
387
+ "description": "Tool returning `outputSchema: 'resource_link'` \u2014 the URI is sent to the client; the client fetches the body via `resources/read`. The right pattern for large or cacheable payloads.",
388
388
  "tags": ["output-schema", "resource_link", "large-payload", "caching"],
389
389
  "features": [
390
- "Returning `outputSchema: 'resource_link'` from a tool — `{ type: 'resource_link', uri }`, body fetched separately",
390
+ "Returning `outputSchema: 'resource_link'` from a tool \u2014 `{ type: 'resource_link', uri }`, body fetched separately",
391
391
  "Pairing the tool with a matching `@Resource({ uri: 'export://{exportId}.csv' })` URI template that resolves to the actual body",
392
392
  "When `'resource_link'` beats `'image'` / `'audio'` / a raw byte response (large payloads, cacheable URIs, deferred fetch)",
393
393
  "Cross-linking to the `create-resource` skill for the URI-template resource on the other end"
@@ -396,13 +396,13 @@
396
396
  {
397
397
  "name": "27-tool-with-examples-metadata",
398
398
  "level": "basic",
399
- "description": "Tool with the `examples: [...]` field on `@Tool({...})` — concrete input (and optional expected output) examples consumed by the CodeCall `codecall:describe` tool to give agents accurate usage examples.",
399
+ "description": "Tool with the `examples: [...]` field on `@Tool({...})` \u2014 concrete input (and optional expected output) examples consumed by the CodeCall `codecall:describe` tool to give agents accurate usage examples.",
400
400
  "tags": ["examples-metadata", "codecall", "describe"],
401
401
  "features": [
402
402
  "Adding `examples: [{ description, input, output? }]` to `@Tool({...})` so `codecall:describe` surfaces canned invocations",
403
403
  "Writing realistic example inputs so the generated describe output is concrete, not abstract",
404
404
  "Including `output?` for examples where showing the expected result helps an agent understand the tool",
405
- "Why `examples` are advisory metadata — not emitted in `tools/list`, only consumed by `codecall:describe`"
405
+ "Why `examples` are advisory metadata \u2014 not emitted in `tools/list`, only consumed by `codecall:describe`"
406
406
  ]
407
407
  }
408
408
  ],
@@ -414,7 +414,7 @@
414
414
  },
415
415
  {
416
416
  "name": "derive-execute-types",
417
- "constraint": "`execute()` parameter and return types come from `ToolInputOf<>` / `ToolOutputOf<>` — never duplicated inline.",
417
+ "constraint": "`execute()` parameter and return types come from `ToolInputOf<>` / `ToolOutputOf<>` \u2014 never duplicated inline.",
418
418
  "severity": "required"
419
419
  },
420
420
  {
@@ -424,7 +424,7 @@
424
424
  },
425
425
  {
426
426
  "name": "no-toolcontext-generics",
427
- "constraint": "`class MyTool extends ToolContext` — never `extends ToolContext<typeof inputSchema>`.",
427
+ "constraint": "`class MyTool extends ToolContext` \u2014 never `extends ToolContext<typeof inputSchema>`.",
428
428
  "severity": "required"
429
429
  },
430
430
  {
@@ -444,7 +444,7 @@
444
444
  },
445
445
  {
446
446
  "name": "use-this-fail-for-business-errors",
447
- "constraint": "`this.fail(new SomeMcpError(...))` for business-logic errors — never raw `throw new Error(...)`.",
447
+ "constraint": "`this.fail(new SomeMcpError(...))` for business-logic errors \u2014 never raw `throw new Error(...)`.",
448
448
  "severity": "required"
449
449
  },
450
450
  {
@@ -454,7 +454,7 @@
454
454
  },
455
455
  {
456
456
  "name": "widget-resource-mode-host-detect",
457
- "constraint": "Leave `ui.resourceMode` unset — the framework host-detects (`inline` for Claude, `cdn` for others).",
457
+ "constraint": "Leave `ui.resourceMode` unset \u2014 the framework host-detects (`inline` for Claude, `cdn` for others).",
458
458
  "severity": "recommended"
459
459
  }
460
460
  ]
@@ -471,7 +471,7 @@
471
471
  "references": [
472
472
  {
473
473
  "name": "custom-auth-ui",
474
- "description": "Replace FrontMCP's built-in OAuth pages with custom React components using the auth.ui slot→file map and auth.extras name→handler map (no decorator, no class) plus the @frontmcp/ui/auth hooks.",
474
+ "description": "Replace FrontMCP's built-in OAuth pages with custom React components using the auth.ui slot\u2192file map and auth.extras name\u2192handler map (no decorator, no class) plus the @frontmcp/ui/auth hooks.",
475
475
  "examples": [
476
476
  {
477
477
  "name": "login-slot",
@@ -480,7 +480,7 @@
480
480
  "tags": ["auth", "auth-ui", "login", "custom-ui", "react", "client-rendered"],
481
481
  "features": [
482
482
  "Mapping a slot to a `.tsx` file with `auth.ui: { login: './login.tsx' }` (the supported render path)",
483
- "Using a RELATIVE path auto-anchored to the config file — no `fileURLToPath`, no decorator, no class",
483
+ "Using a RELATIVE path auto-anchored to the config file \u2014 no `fileURLToPath`, no decorator, no class",
484
484
  "Reading the injected `AuthFlowState` via `useAuthFlow()` and submitting with `<form onSubmit={submitFinish}>`",
485
485
  "Letting `<AuthPageWrapper>` render the enclosing finish `<form>` with the `pending_auth_id` + `csrf` hidden fields",
486
486
  "The SDK transpiling the `.tsx` server-side and inlining it as an ES module (deps from esm.sh via an import-map) + appending the `mountAuthPage` call automatically"
@@ -488,7 +488,7 @@
488
488
  },
489
489
  {
490
490
  "name": "multi-step-auth-extra",
491
- "description": "Add a server-validated multi-step field to a custom login page with auth.extras: { 'envs:add': fn }, useExtraField, and useAddedItems — accepted rows accumulate server-side and reflect back without a reload.",
491
+ "description": "Add a server-validated multi-step field to a custom login page with auth.extras: { 'envs:add': fn }, useExtraField, and useAddedItems \u2014 accepted rows accumulate server-side and reflect back without a reload.",
492
492
  "level": "advanced",
493
493
  "tags": ["auth", "auth-ui", "auth-extras", "useExtraField", "useAddedItems", "multi-step", "react"],
494
494
  "features": [
@@ -693,7 +693,7 @@
693
693
  "features": [
694
694
  "Selecting the secure-store backing via `auth.secureStore` (memory / sqlite / redis / custom backend) plus a namespace `scope`",
695
695
  "Reading/writing arbitrary user-typed secrets from a tool via `this.secureStore.set/get/list/delete` (JSON-serialized, scoped to the session/subject)",
696
- "Backing the store with an OS keychain by supplying a `SecureStoreBackend` — no native dependency is bundled by the framework",
696
+ "Backing the store with an OS keychain by supplying a `SecureStoreBackend` \u2014 no native dependency is bundled by the framework",
697
697
  "Understanding scope: `user` (keyed by sub, default), `session` (keyed by sessionId), `global` (server-wide)"
698
698
  ]
699
699
  }
@@ -793,7 +793,7 @@
793
793
  "level": "intermediate",
794
794
  "tags": ["config", "http", "routes", "custom", "webhook", "download", "auth"],
795
795
  "features": [
796
- "Registering custom HTTP endpoints with `http.routes` — no tool/resource/prompt needed",
796
+ "Registering custom HTTP endpoints with `http.routes` \u2014 no tool/resource/prompt needed",
797
797
  "A POST endpoint that validates a user-entered secret server-side (the `/connect-env` pattern)",
798
798
  "Overriding the default `application/json` Content-Type for binary/HTML delivery",
799
799
  "Gating a route behind the MCP `session:verify` flow with `auth: true`",
@@ -1058,7 +1058,7 @@
1058
1058
  },
1059
1059
  {
1060
1060
  "name": "configure-skills-http",
1061
- "description": "Full reference for skillsConfig — HTTP catalog endpoints, auth, caching, instructions injection, and tamper-evident audit log.",
1061
+ "description": "Full reference for skillsConfig \u2014 HTTP catalog endpoints, auth, caching, instructions injection, and tamper-evident audit log.",
1062
1062
  "examples": [
1063
1063
  {
1064
1064
  "name": "inject-instructions",
@@ -1079,7 +1079,7 @@
1079
1079
  "tags": ["config", "skills", "audit", "hs256", "development"],
1080
1080
  "features": [
1081
1081
  "Bootstraps the audit subsystem via setSkillAuditFactory(...) before FrontMcp registers",
1082
- "MemoryAuditStore keeps records in-process — perfect for tests, lost on restart",
1082
+ "MemoryAuditStore keeps records in-process \u2014 perfect for tests, lost on restart",
1083
1083
  "Hs256AuditSigner refuses to start when NODE_ENV === production with a random key",
1084
1084
  "subjectMode: 'hash' redacts user identifiers while keeping them correlatable"
1085
1085
  ]
@@ -1103,11 +1103,24 @@
1103
1103
  {
1104
1104
  "name": "frontmcp-deployment",
1105
1105
  "category": "deployment",
1106
- "description": "Use when deploying, building for production, packaging, or shipping a FrontMCP server. Covers build targets (node, cli SEA binary, browser, embeddable SDK, mcpb archive for Claude Desktop, serverless) and deploying to Vercel (with Vercel KV), AWS Lambda (API Gateway, SAM, CDK), Cloudflare Workers (KV, D1, Durable Objects, v1.3 skills-only), and Node (multi-stage Docker, docker-compose, PM2, nginx). Also the frontmcp.deploy.yaml manifest plus GitHub Action push-resync, and MCP client integration / .mcp.json for Claude Desktop, Claude Code, Cursor, and VS Code over stdio or HTTP. Triggers: deploy, build for production, dockerize, containerize, serverless, edge runtime, go live, ship it.",
1106
+ "description": "Use when deploying, building for production, packaging, or shipping a FrontMCP server. Covers build targets (node, cli SEA binary, browser, embeddable SDK, mcpb archive for Claude Desktop, serverless) and deploying to Vercel (with Vercel KV), AWS Lambda (API Gateway, SAM, CDK), Cloudflare Workers (KV, D1, Durable Objects, v1.3 skills-only), and Node (multi-stage Docker, docker-compose, PM2, nginx). Also the frontmcp.deploy.yaml manifest plus GitHub Action push-resync, MCP client integration / .mcp.json for Claude Desktop, Claude Code, Cursor, and VS Code over stdio or HTTP, and MCP protocol revisions (serving 2026-07-28 alongside 2024-11-05 through 2025-11-25). Triggers: deploy, build for production, dockerize, containerize, serverless, edge runtime, go live, ship it.",
1107
1107
  "path": "frontmcp-deployment",
1108
1108
  "targets": ["all"],
1109
1109
  "hasResources": true,
1110
- "tags": ["router", "deployment", "node", "vercel", "lambda", "cloudflare", "cli", "browser", "sdk", "guide"],
1110
+ "tags": [
1111
+ "router",
1112
+ "deployment",
1113
+ "node",
1114
+ "vercel",
1115
+ "lambda",
1116
+ "cloudflare",
1117
+ "cli",
1118
+ "browser",
1119
+ "sdk",
1120
+ "guide",
1121
+ "protocol",
1122
+ "mcp-20260728"
1123
+ ],
1111
1124
  "bundle": ["recommended", "minimal", "full"],
1112
1125
  "references": [
1113
1126
  {
@@ -1116,7 +1129,7 @@
1116
1129
  "examples": [
1117
1130
  {
1118
1131
  "name": "browser-build-with-custom-entry",
1119
- "description": "Build a browser bundle using a dedicated client entry file that avoids Node.js-only imports. Re-export the real `@frontmcp/react` symbols (`useListTools`, `useListResources`, `useCallTool`) — `useTools`/`useResources` do not exist.",
1132
+ "description": "Build a browser bundle using a dedicated client entry file that avoids Node.js-only imports. Re-export the real `@frontmcp/react` symbols (`useListTools`, `useListResources`, `useCallTool`) \u2014 `useTools`/`useResources` do not exist.",
1120
1133
  "level": "intermediate",
1121
1134
  "tags": ["deployment", "browser", "custom", "entry"],
1122
1135
  "features": [
@@ -1138,7 +1151,7 @@
1138
1151
  },
1139
1152
  {
1140
1153
  "name": "react-provider-setup",
1141
- "description": "Connect a React application to a FrontMCP server using `@frontmcp/react`. `FrontMcpProvider` takes a `DirectMcpServer` instance via the `server` prop — there is no `serverUrl` option.",
1154
+ "description": "Connect a React application to a FrontMCP server using `@frontmcp/react`. `FrontMcpProvider` takes a `DirectMcpServer` instance via the `server` prop \u2014 there is no `serverUrl` option.",
1142
1155
  "level": "basic",
1143
1156
  "tags": ["deployment", "react", "browser", "provider", "setup"],
1144
1157
  "features": [
@@ -1235,11 +1248,11 @@
1235
1248
  },
1236
1249
  {
1237
1250
  "name": "deploy-to-cloudflare-skills-only",
1238
- "description": "Deploy a FrontMCP server to Cloudflare Workers using the v1.3 skills-only model — OpenAPI as capability inventory, AgentScript with namespaced bindings, four meta-tools, hot-reload via GitHub Action and a signed-bundle webhook."
1251
+ "description": "Deploy a FrontMCP server to Cloudflare Workers using the v1.3 skills-only model \u2014 OpenAPI as capability inventory, AgentScript with namespaced bindings, four meta-tools, hot-reload via GitHub Action and a signed-bundle webhook."
1239
1252
  },
1240
1253
  {
1241
1254
  "name": "deploy-manifest-yaml",
1242
- "description": "The frontmcp.deploy.yaml v1 schema — declarative manifest the GitHub Action consumes on every push to build, sign, and hot-reload the Cloudflare Worker."
1255
+ "description": "The frontmcp.deploy.yaml v1 schema \u2014 declarative manifest the GitHub Action consumes on every push to build, sign, and hot-reload the Cloudflare Worker."
1243
1256
  },
1244
1257
  {
1245
1258
  "name": "deploy-to-cloudflare",
@@ -1297,7 +1310,7 @@
1297
1310
  },
1298
1311
  {
1299
1312
  "name": "lambda-handler-with-cors",
1300
- "description": "CORS for a FrontMCP Lambda is configured at the API Gateway HTTP API level, not in the handler. `frontmcp build --target lambda` writes `dist/lambda/handler.cjs` — your `@FrontMcp` server is wrapped automatically with `@codegenie/serverless-express`, so CORS belongs on the gateway.",
1313
+ "description": "CORS for a FrontMCP Lambda is configured at the API Gateway HTTP API level, not in the handler. `frontmcp build --target lambda` writes `dist/lambda/handler.cjs` \u2014 your `@FrontMcp` server is wrapped automatically with `@codegenie/serverless-express`, so CORS belongs on the gateway.",
1301
1314
  "level": "intermediate",
1302
1315
  "tags": ["deployment", "lambda", "handler", "cors"],
1303
1316
  "features": [
@@ -1396,14 +1409,14 @@
1396
1409
  "level": "basic",
1397
1410
  "tags": ["deployment", "vercel", "serverless", "config", "minimal"],
1398
1411
  "features": [
1399
- "The exact shape of the auto-generated `vercel.json` — three keys, nothing else",
1412
+ "The exact shape of the auto-generated `vercel.json` \u2014 three keys, nothing else",
1400
1413
  "That routing and function configuration live in `.vercel/output/`, not `vercel.json`",
1401
1414
  "That hand-authoring `api/frontmcp.ts` references in `vercel.json` is unnecessary and breaks deploys"
1402
1415
  ]
1403
1416
  },
1404
1417
  {
1405
1418
  "name": "vercel-config-with-security-headers",
1406
- "description": "The Vercel adapter emits a minimal `vercel.json` (version + buildCommand + installCommand). You can layer extra Vercel-supported keys on top after the build — but never add `functions: { 'api/frontmcp.ts': ... }` or `rewrites` to `/api/frontmcp` (the build does not produce an `api/` directory).",
1419
+ "description": "The Vercel adapter emits a minimal `vercel.json` (version + buildCommand + installCommand). You can layer extra Vercel-supported keys on top after the build \u2014 but never add `functions: { 'api/frontmcp.ts': ... }` or `rewrites` to `/api/frontmcp` (the build does not produce an `api/` directory).",
1407
1420
  "level": "intermediate",
1408
1421
  "tags": ["deployment", "vercel", "security", "config", "headers"],
1409
1422
  "features": [
@@ -1420,18 +1433,18 @@
1420
1433
  "examples": [
1421
1434
  {
1422
1435
  "name": "vercel-mcp-endpoint-test",
1423
- "description": "Verify a Vercel-deployed FrontMCP server by testing health, tool listing, and tool invocation. The CLI emits the Build Output API v3 structure — there is no `api/frontmcp.ts` to test against; the function lives at `.vercel/output/functions/index.func/handler.cjs` and is routed via `.vercel/output/config.json`.",
1436
+ "description": "Verify a Vercel-deployed FrontMCP server by testing health, tool listing, and tool invocation. The CLI emits the Build Output API v3 structure \u2014 there is no `api/frontmcp.ts` to test against; the function lives at `.vercel/output/functions/index.func/handler.cjs` and is routed via `.vercel/output/config.json`.",
1424
1437
  "level": "advanced",
1425
1438
  "tags": ["deployment", "json-rpc", "vercel", "mcp", "endpoint"],
1426
1439
  "features": [
1427
1440
  "Testing the health endpoint (`/healthz`) and MCP JSON-RPC API of a deployed Vercel function",
1428
1441
  "Using preview deployments to validate changes before promoting to production",
1429
- "Vercel plan limits for `maxDuration` (Hobby: 10s, Pro: 60s, Enterprise: 900s) — configure these in the Vercel dashboard, not via `functions: { 'api/frontmcp.ts': ... }`"
1442
+ "Vercel plan limits for `maxDuration` (Hobby: 10s, Pro: 60s, Enterprise: 900s) \u2014 configure these in the Vercel dashboard, not via `functions: { 'api/frontmcp.ts': ... }`"
1430
1443
  ]
1431
1444
  },
1432
1445
  {
1433
1446
  "name": "vercel-with-kv",
1434
- "description": "Deploy a FrontMCP server to Vercel serverless functions with Vercel KV for session persistence. The CLI emits the full Build Output API v3 structure for you — you do **not** author `api/frontmcp.ts` and you do **not** add a `rewrites` block.",
1447
+ "description": "Deploy a FrontMCP server to Vercel serverless functions with Vercel KV for session persistence. The CLI emits the full Build Output API v3 structure for you \u2014 you do **not** author `api/frontmcp.ts` and you do **not** add a `rewrites` block.",
1435
1448
  "level": "basic",
1436
1449
  "tags": ["deployment", "vercel-kv", "vercel", "session", "performance", "serverless"],
1437
1450
  "features": [
@@ -1442,7 +1455,7 @@
1442
1455
  },
1443
1456
  {
1444
1457
  "name": "vercel-with-skills-cache",
1445
- "description": "Deploy a FrontMCP server to Vercel with skills enabled and KV-backed skill caching. The CLI handles the Build Output API v3 emission for you — your job is to configure the server and provision Vercel KV.",
1458
+ "description": "Deploy a FrontMCP server to Vercel with skills enabled and KV-backed skill caching. The CLI handles the Build Output API v3 emission for you \u2014 your job is to configure the server and provision Vercel KV.",
1446
1459
  "level": "intermediate",
1447
1460
  "tags": ["deployment", "vercel-kv", "vercel", "cache", "skills"],
1448
1461
  "features": [
@@ -1494,6 +1507,10 @@
1494
1507
  ]
1495
1508
  }
1496
1509
  ]
1510
+ },
1511
+ {
1512
+ "name": "protocol-versions",
1513
+ "description": "Serve MCP protocol revision 2026-07-28 alongside every earlier revision, and connect to a 2026 server as a client"
1497
1514
  }
1498
1515
  ]
1499
1516
  },
@@ -1803,7 +1820,7 @@
1803
1820
  "tags": ["development", "provider", "config", "api", "providers"],
1804
1821
  "features": [
1805
1822
  "A configuration provider using `readonly` properties from environment variables (sync construction)",
1806
- "An API client provider that reads credentials in the constructor (no `onInit` — `@Provider` has no lifecycle hooks)",
1823
+ "An API client provider that reads credentials in the constructor (no `onInit` \u2014 `@Provider` has no lifecycle hooks)",
1807
1824
  "Folder-per-provider layout (`src/apps/main/providers/<slug>/`) with a barrel `index.ts` and a co-located `.provider.spec.ts`",
1808
1825
  "Top-level `src/apps/main/providers/index.ts` barrel re-exporting each provider folder",
1809
1826
  "Registering providers at `@FrontMcp` level for server-wide sharing across all apps",
@@ -2024,7 +2041,7 @@
2024
2041
  "tags": ["development", "database", "multi-app", "decorators", "multi", "app"],
2025
2042
  "features": [
2026
2043
  "Organizing a server into multiple `@App` modules (`analytics` and `admin`)",
2027
- "Decorating a service class with `@Provider({ name, scope })` so it acts as its own DI token (the strict schema rejects `useFactory`/`useClass`/`provide` — use `AsyncProvider` for those)",
2044
+ "Decorating a service class with `@Provider({ name, scope })` so it acts as its own DI token (the strict schema rejects `useFactory`/`useClass`/`provide` \u2014 use `AsyncProvider` for those)",
2028
2045
  "Accessing injected dependencies via `this.get(DatabaseClient)` in tools and resources",
2029
2046
  "Using `@ResourceTemplate` with URI parameters (`{dashboardId}`) for dynamic resources",
2030
2047
  "Registering a `@Plugin` at the server level so it applies across all apps",
@@ -2148,7 +2165,7 @@
2148
2165
  "level": "intermediate",
2149
2166
  "tags": ["development", "openapi", "adapters", "security", "ssrf", "filtering"],
2150
2167
  "features": [
2151
- "Secure defaults: external `$ref` resolution off, spec-URL redirects not followed, internal/private targets blocked (DNS-resolved) — on `mcp-from-openapi` >= 2.5.0",
2168
+ "Secure defaults: external `$ref` resolution off, spec-URL redirects not followed, internal/private targets blocked (DNS-resolved) \u2014 on `mcp-from-openapi` >= 2.5.0",
2152
2169
  "Opting back into external refs with `allowedProtocols`, and restricting the spec URL + `$ref`s with `allowedHosts`",
2153
2170
  "Using `allowInternalIPs` for trusted internal/local targets (governs the spec URL and `$ref`s)",
2154
2171
  "Filtering operations with `includeOperations`, `excludeOperations`, and `filterFn`",
@@ -2218,7 +2235,7 @@
2218
2235
  },
2219
2236
  {
2220
2237
  "name": "skill-audit-log",
2221
- "description": "Tamper-evident, hash-chained audit log for skill action executions — pluggable signer, pluggable store, offline verification.",
2238
+ "description": "Tamper-evident, hash-chained audit log for skill action executions \u2014 pluggable signer, pluggable store, offline verification.",
2222
2239
  "examples": [
2223
2240
  {
2224
2241
  "name": "verify-chain",
@@ -2228,7 +2245,7 @@
2228
2245
  "features": [
2229
2246
  "verifyChain returns { ok, breakAt?, reason? } and exits with the first detected break",
2230
2247
  "defaultAuditSignatureVerifier dispatches on record.signatureAlg (HS256 or RS256)",
2231
- "Trusted-keys registry maps signatureKeyId → public key PEM",
2248
+ "Trusted-keys registry maps signatureKeyId \u2192 public key PEM",
2232
2249
  "iterate() reads the chain in order from any SkillAuditStore implementation"
2233
2250
  ]
2234
2251
  },
@@ -2341,7 +2358,7 @@
2341
2358
  "features": [
2342
2359
  "Class-as-token DI: `@Provider({ name, scope })` and inject via `this.get(TaskStoreProvider)`",
2343
2360
  "Building the singleton with `AsyncProvider({ provide, name, scope, useFactory })` for async setup",
2344
- "Cleanup: explicit `disconnect()` method (called from the host before `server.dispose()`) — `@Provider` has no `onDestroy` hook",
2361
+ "Cleanup: explicit `disconnect()` method (called from the host before `server.dispose()`) \u2014 `@Provider` has no `onDestroy` hook",
2345
2362
  "Using `@frontmcp/utils` for `randomUUID()` instead of `node:crypto`",
2346
2363
  "Per-user data isolation using Redis hash keys (`tasks:${userId}`)"
2347
2364
  ]
@@ -2418,7 +2435,7 @@
2418
2435
  "Setting per-tool TTL via `@Tool({ cache: { ttl } })` metadata in seconds",
2419
2436
  "Using Redis-backed cache for multi-instance consistency",
2420
2437
  "Configuring connection pool limits and timeouts to prevent resource exhaustion",
2421
- "Providers do not implement `onInit` / `onDestroy` — initialize in the constructor and let framework shutdown handle cleanup"
2438
+ "Providers do not implement `onInit` / `onDestroy` \u2014 initialize in the constructor and let framework shutdown handle cleanup"
2422
2439
  ]
2423
2440
  },
2424
2441
  {
@@ -2597,12 +2614,12 @@
2597
2614
  "level": "intermediate",
2598
2615
  "tags": ["production", "unix-socket", "cli", "database", "daemon", "graceful"],
2599
2616
  "features": [
2600
- "The framework already wires SIGTERM/SIGINT — daemon cleanup attaches _additional_ listeners and does not call `process.exit()`",
2617
+ "The framework already wires SIGTERM/SIGINT \u2014 daemon cleanup attaches _additional_ listeners and does not call `process.exit()`",
2601
2618
  "Using `server.dispose()` (the only real method) instead of fictional `server.close()`",
2602
2619
  "Removing the Unix socket file to prevent stale `.sock` files on restart",
2603
2620
  "Cleaning up the PID file on shutdown",
2604
2621
  "Using `@frontmcp/utils` (`unlink`, `fileExists`, `ensureDir`) for file operations",
2605
- "Providers initialize in the constructor — there is no `onInit` / `onDestroy`"
2622
+ "Providers initialize in the constructor \u2014 there is no `onInit` / `onDestroy`"
2606
2623
  ]
2607
2624
  },
2608
2625
  {
@@ -2651,14 +2668,14 @@
2651
2668
  },
2652
2669
  {
2653
2670
  "name": "wrangler-config",
2654
- "description": "Checklist for verifying the `wrangler.toml` produced by `frontmcp build --target cloudflare` is production-ready. **Note:** configuration authoring lives in `frontmcp-deployment → references/deploy-to-cloudflare.md`; this file is checklist-only.",
2671
+ "description": "Checklist for verifying the `wrangler.toml` produced by `frontmcp build --target cloudflare` is production-ready. **Note:** configuration authoring lives in `frontmcp-deployment \u2192 references/deploy-to-cloudflare.md`; this file is checklist-only.",
2655
2672
  "level": "basic",
2656
2673
  "tags": ["production", "cloudflare", "cache", "session", "wrangler", "checklist"],
2657
2674
  "features": [
2658
- "Verify `main = \"dist/cloudflare/index.js\"` (the build adapter writes this — never override)",
2675
+ "Verify `main = \"dist/cloudflare/index.js\"` (the build adapter writes this \u2014 never override)",
2659
2676
  "Verify KV bindings for sessions and cache exist",
2660
2677
  "Verify staging / production environment configs are separated",
2661
- "Verify secrets are NOT in `wrangler.toml` — use `wrangler secret put`"
2678
+ "Verify secrets are NOT in `wrangler.toml` \u2014 use `wrangler secret put`"
2662
2679
  ]
2663
2680
  }
2664
2681
  ]
@@ -2675,13 +2692,13 @@
2675
2692
  "features": [
2676
2693
  "Connection reuse pattern: caching the connection promise in module scope so it survives Lambda freeze/thaw",
2677
2694
  "Lazy-loading heavy dependencies (`pg`) via dynamic `import()` on first use, not at module load",
2678
- "Not closing connections on shutdown for Lambda (they survive freeze/thaw — and providers have no `onDestroy` hook anyway)",
2695
+ "Not closing connections on shutdown for Lambda (they survive freeze/thaw \u2014 and providers have no `onDestroy` hook anyway)",
2679
2696
  "Keeping module scope lightweight with no heavy initialization"
2680
2697
  ]
2681
2698
  },
2682
2699
  {
2683
2700
  "name": "sam-template",
2684
- "description": "Checklist for verifying the SAM template pairs correctly with the bundle produced by `frontmcp build --target lambda`. **Note:** configuration authoring lives in `frontmcp-deployment → references/deploy-to-lambda.md`; this file is checklist-only.",
2701
+ "description": "Checklist for verifying the SAM template pairs correctly with the bundle produced by `frontmcp build --target lambda`. **Note:** configuration authoring lives in `frontmcp-deployment \u2192 references/deploy-to-lambda.md`; this file is checklist-only.",
2685
2702
  "level": "basic",
2686
2703
  "tags": ["production", "lambda", "session", "sam", "checklist"],
2687
2704
  "features": [
@@ -2725,7 +2742,7 @@
2725
2742
  },
2726
2743
  {
2727
2744
  "name": "multi-instance-cleanup",
2728
- "description": "Shows how multiple SDK instances can coexist without conflicts, and how to clean up timers and listeners — given that `@Provider` classes have **no** `onInit` / `onDestroy` lifecycle hooks. The pattern is: initialize in the constructor, expose an explicit `stop()` method, and have the host app call it before `server.dispose()`.",
2745
+ "description": "Shows how multiple SDK instances can coexist without conflicts, and how to clean up timers and listeners \u2014 given that `@Provider` classes have **no** `onInit` / `onDestroy` lifecycle hooks. The pattern is: initialize in the constructor, expose an explicit `stop()` method, and have the host app call it before `server.dispose()`.",
2729
2746
  "level": "advanced",
2730
2747
  "tags": ["production", "sdk", "node", "multi", "instance", "cleanup"],
2731
2748
  "features": [
@@ -2773,7 +2790,7 @@
2773
2790
  "level": "intermediate",
2774
2791
  "tags": ["production", "redis", "database", "node", "graceful", "shutdown"],
2775
2792
  "features": [
2776
- "The framework already handles SIGTERM/SIGINT — never call `server.close()` (no such method) or `process.exit()` on top of it",
2793
+ "The framework already handles SIGTERM/SIGINT \u2014 never call `server.close()` (no such method) or `process.exit()` on top of it",
2777
2794
  "Use `server.dispose()` if you need explicit cleanup in non-server (SDK) contexts",
2778
2795
  "Add a _drain probe_ on `/healthz` so load balancers stop sending traffic during the framework's drain window",
2779
2796
  "Avoid handler conflicts: registering a second SIGTERM that calls `process.exit(0)` races the framework's own exit path"
@@ -2824,12 +2841,12 @@
2824
2841
  },
2825
2842
  {
2826
2843
  "name": "vercel-edge-config",
2827
- "description": "Checklist for verifying the Vercel Build Output API v3 artifact and edge config produced by `frontmcp build --target vercel`. **Note:** configuration authoring lives in `frontmcp-deployment → references/deploy-to-vercel.md`; this file is checklist-only.",
2844
+ "description": "Checklist for verifying the Vercel Build Output API v3 artifact and edge config produced by `frontmcp build --target vercel`. **Note:** configuration authoring lives in `frontmcp-deployment \u2192 references/deploy-to-vercel.md`; this file is checklist-only.",
2828
2845
  "level": "basic",
2829
2846
  "tags": ["production", "vercel-kv", "vercel", "session", "serverless", "checklist"],
2830
2847
  "features": [
2831
2848
  "Verify `frontmcp build --target vercel` produced `.vercel/output/functions/index.func/handler.cjs`",
2832
- "No hand-written `vercel.json` `builds`/`routes` — the build adapter uses Build Output API v3",
2849
+ "No hand-written `vercel.json` `builds`/`routes` \u2014 the build adapter uses Build Output API v3",
2833
2850
  "Verify Vercel KV (`provider: 'vercel-kv'`) is configured for session/cache state",
2834
2851
  "Verify CORS origins include `VERCEL_URL` and any custom production domain"
2835
2852
  ]
@@ -3517,7 +3534,7 @@
3517
3534
  },
3518
3535
  {
3519
3536
  "name": "production-tracing",
3520
- "description": "Full production observability — traces to OTLP, structured logs to stdout, per-request log collection.",
3537
+ "description": "Full production observability \u2014 traces to OTLP, structured logs to stdout, per-request log collection.",
3521
3538
  "level": "intermediate",
3522
3539
  "tags": ["tracing", "production", "otlp", "logging", "request-logs"],
3523
3540
  "features": [
@@ -3541,7 +3558,7 @@
3541
3558
  "features": [
3542
3559
  "NDJSON format for stdout (Docker/K8s log collection)",
3543
3560
  "Automatic trace context enrichment (trace_id, span_id)",
3544
- "Sensitive field redaction (token → [REDACTED])"
3561
+ "Sensitive field redaction (token \u2192 [REDACTED])"
3545
3562
  ]
3546
3563
  },
3547
3564
  {
@@ -3638,7 +3655,7 @@
3638
3655
  "tags": ["coralogix", "otlp", "vendor", "integration", "production"],
3639
3656
  "features": [
3640
3657
  "Traces and logs both sent to Coralogix via OTLP",
3641
- "Automatic trace_id correlation — click a trace, see its logs",
3658
+ "Automatic trace_id correlation \u2014 click a trace, see its logs",
3642
3659
  "Environment variable configuration for production"
3643
3660
  ]
3644
3661
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontmcp/skills",
3
- "version": "1.5.7",
3
+ "version": "1.6.1",
4
4
  "description": "Curated skills catalog for FrontMCP projects",
5
5
  "author": "AgentFront <info@agentfront.dev>",
6
6
  "homepage": "https://docs.agentfront.dev",