@frontmcp/skills 1.8.5 → 1.8.7
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/catalog/create-tool/SKILL.md +24 -24
- package/catalog/create-tool/examples/22-tool-with-ui-html-template.md +0 -1
- package/catalog/create-tool/examples/23-tool-with-ui-filesource-tsx.md +7 -6
- package/catalog/create-tool/examples/24-tool-with-ui-csp-and-bridge.md +4 -6
- package/catalog/create-tool/examples/27-tool-with-examples-metadata.md +3 -2
- package/catalog/create-tool/references/decorator-options.md +1 -1
- package/catalog/create-tool/references/elicitation.md +1 -0
- package/catalog/create-tool/references/file-layout.md +2 -0
- package/catalog/create-tool/references/ui-widgets.md +96 -40
- package/catalog/create-tool/rules/widget-paths-anchor-with-import-meta-url.md +10 -3
- package/catalog/frontmcp-config/examples/configure-throttle/distributed-redis-throttle.md +8 -0
- package/catalog/frontmcp-config/references/configure-auth.md +1 -0
- package/catalog/frontmcp-config/references/configure-deployment-targets.md +19 -1
- package/catalog/frontmcp-config/references/configure-http.md +6 -4
- package/catalog/frontmcp-config/references/configure-security-headers.md +18 -13
- package/catalog/frontmcp-config/references/configure-throttle-guard-config.md +19 -4
- package/catalog/frontmcp-config/references/configure-throttle.md +25 -7
- package/catalog/frontmcp-deployment/SKILL.md +19 -19
- package/catalog/frontmcp-deployment/examples/build-for-browser/react-provider-setup.md +5 -3
- package/catalog/frontmcp-deployment/examples/deploy-to-vercel/vercel-mcp-endpoint-test.md +1 -1
- package/catalog/frontmcp-deployment/examples/deploy-to-vercel/vercel-with-kv.md +3 -1
- package/catalog/frontmcp-deployment/examples/deploy-to-vercel/vercel-with-skills-cache.md +1 -1
- package/catalog/frontmcp-deployment/examples/deploy-to-vercel-config/minimal-vercel-config.md +7 -3
- package/catalog/frontmcp-deployment/examples/deploy-to-vercel-config/vercel-config-with-security-headers.md +4 -3
- package/catalog/frontmcp-deployment/references/build-for-browser.md +8 -0
- package/catalog/frontmcp-deployment/references/build-for-mcpb.md +9 -8
- package/catalog/frontmcp-deployment/references/build-for-sdk.md +9 -9
- package/catalog/frontmcp-deployment/references/deploy-to-cloudflare.md +3 -1
- package/catalog/frontmcp-deployment/references/deploy-to-lambda.md +9 -8
- package/catalog/frontmcp-deployment/references/deploy-to-vercel-config.md +15 -3
- package/catalog/frontmcp-deployment/references/deploy-to-vercel.md +16 -8
- package/catalog/frontmcp-deployment/references/protocol-versions.md +9 -0
- package/catalog/frontmcp-development/examples/official-plugins/cache-and-feature-flags.md +5 -0
- package/catalog/frontmcp-development/examples/official-plugins/remember-plugin-session-memory.md +7 -5
- package/catalog/frontmcp-development/references/create-agent.md +8 -7
- package/catalog/frontmcp-development/references/create-plugin.md +17 -0
- package/catalog/frontmcp-development/references/official-plugins.md +66 -8
- package/catalog/frontmcp-guides/references/example-task-manager.md +2 -2
- package/catalog/frontmcp-guides/references/example-weather-api.md +2 -2
- package/catalog/frontmcp-production-readiness/examples/distributed-ha/ha-kubernetes-3-replicas.md +1 -0
- package/catalog/frontmcp-production-readiness/examples/production-node-sdk/package-json-config.md +2 -2
- package/catalog/frontmcp-production-readiness/examples/production-vercel/vercel-edge-config.md +1 -0
- package/catalog/frontmcp-production-readiness/references/common-checklist.md +4 -0
- package/catalog/frontmcp-production-readiness/references/distributed-ha.md +17 -7
- package/catalog/frontmcp-production-readiness/references/health-readiness-endpoints.md +3 -1
- package/catalog/frontmcp-setup/examples/project-structure-nx/nx-generator-scaffolding.md +1 -1
- package/catalog/frontmcp-setup/references/nx-workflow.md +25 -17
- package/catalog/frontmcp-setup/references/setup-redis.md +37 -7
- package/catalog/frontmcp-setup/references/setup-sqlite.md +9 -6
- package/catalog/frontmcp-testing/SKILL.md +24 -23
- package/catalog/frontmcp-testing/references/setup-testing.md +28 -3
- package/catalog/frontmcp-testing/references/test-auth.md +8 -0
- package/catalog/frontmcp-testing/references/test-e2e-handler.md +1 -0
- package/catalog/skills-manifest.json +9 -6
- package/package.json +1 -1
|
@@ -127,12 +127,13 @@ export default class Server {}
|
|
|
127
127
|
|
|
128
128
|
Configuration reference:
|
|
129
129
|
|
|
130
|
-
| Option | Type | Default | Description
|
|
131
|
-
| ---------------------- | -------------------- | ----------- |
|
|
132
|
-
| `path` | `string` | (optional) | Absolute or `~`-prefixed path to the `.sqlite` file. Auto-resolved when omitted — see the default-path policy below.
|
|
133
|
-
| `walMode` | `boolean` | `true` | Enable WAL mode for better read concurrency
|
|
134
|
-
| `
|
|
135
|
-
| `
|
|
130
|
+
| Option | Type | Default | Description |
|
|
131
|
+
| ---------------------- | -------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
132
|
+
| `path` | `string` | (optional) | Absolute or `~`-prefixed path to the `.sqlite` file. Auto-resolved when omitted — see the default-path policy below. |
|
|
133
|
+
| `walMode` | `boolean` | `true` | Enable WAL mode for better read concurrency |
|
|
134
|
+
| `busyTimeoutMs` | `number` | `5000` | How long a connection waits on a lock held by another process before `SQLITE_BUSY`. Set before WAL and table creation, so two processes starting on one file wait for each other |
|
|
135
|
+
| `encryption` | `{ secret: string }` | `undefined` | AES-256-GCM encryption for values at rest |
|
|
136
|
+
| `ttlCleanupIntervalMs` | `number` | `60000` | Interval for purging expired keys (milliseconds) |
|
|
136
137
|
|
|
137
138
|
### With at-rest encryption
|
|
138
139
|
|
|
@@ -155,6 +156,8 @@ If the database stores sensitive session data (tokens, credentials), enable encr
|
|
|
155
156
|
export default class Server {}
|
|
156
157
|
```
|
|
157
158
|
|
|
159
|
+
Reading a value written under a different secret throws `SqliteDecryptionError` (code `SQLITE_DECRYPTION_FAILED`) whose message names the secret as the likely cause; restore the original secret or delete the database file.
|
|
160
|
+
|
|
158
161
|
The encryption uses HKDF-SHA256 for key derivation and AES-256-GCM for value encryption. The secret should be at least 32 characters. Store it in environment variables, never in source code.
|
|
159
162
|
|
|
160
163
|
### For a unix-socket daemon
|
|
@@ -95,18 +95,18 @@ This is a router skill. Follow this order to pick a testing approach, then move
|
|
|
95
95
|
|
|
96
96
|
## Cross-Cutting Testing Patterns
|
|
97
97
|
|
|
98
|
-
| Pattern | Rule
|
|
99
|
-
| ------------------ |
|
|
100
|
-
| File naming | Always `.spec.ts` (not `.test.ts`); E2E uses `.e2e.spec.ts`
|
|
101
|
-
| File organization | Split E2E tests by app/feature: `e2e/calc.e2e.spec.ts`, `e2e/ecommerce.e2e.spec.ts`. Never put all tests in a single `server.e2e.spec.ts`
|
|
102
|
-
| Environment | `frontmcp test` loads `.env` / `.env.local` into the Jest child, same precedence as `dev` (real environment wins over the files, config `env.shared` + `env.test` underneath). `--no-env` skips it
|
|
103
|
-
| Test runner | Standalone projects: use `frontmcp test` (auto-generates Jest/SWC config; discovers `src/**/*.spec.ts(x)`, `__tests__/**/*.spec.ts(x)`, and `e2e/**/*.e2e.spec.ts(x)`; transforms both `.ts` and `.tsx` with the automatic JSX runtime; transpiles ESM-only deps such as `jose` under npm, yarn AND pnpm's `node_modules/.pnpm/` store — add your own via `test.esmPackages` in `frontmcp.config.ts`; delegates to a user-provided `jest.config.{ts,js,mjs,cjs,json}` if present, which drops the injected ESM transforms). Nx monorepos: use `nx test <lib>` (resolves the project's `jest.config.ts`). Never invoke `jest --config ...` directly |
|
|
104
|
-
| Coverage threshold | 95%+ across statements, branches, functions, lines
|
|
105
|
-
| Test descriptions | Plain English, no prefixes like "PT-001"; describe behavior not implementation
|
|
106
|
-
| Mocking | Mock providers via DI token replacement, never mock the framework
|
|
107
|
-
| httpMock scope | `httpMock` intercepts HTTP in the **test process** only, NOT in the MCP server subprocess. Do not use httpMock to intercept server-to-API calls — those happen in the child process. Use httpMock for verifying client-to-server request shapes or mocking external APIs called from the test itself
|
|
108
|
-
| Error testing | Assert `instanceof` specific error class AND MCP error code
|
|
109
|
-
| Async | Always `await` async operations; use `expect(...).rejects.toThrow()` for async errors
|
|
98
|
+
| Pattern | Rule |
|
|
99
|
+
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
100
|
+
| File naming | Always `.spec.ts` (not `.test.ts`); E2E uses `.e2e.spec.ts` |
|
|
101
|
+
| File organization | Split E2E tests by app/feature: `e2e/calc.e2e.spec.ts`, `e2e/ecommerce.e2e.spec.ts`. Never put all tests in a single `server.e2e.spec.ts` |
|
|
102
|
+
| Environment | `frontmcp test` loads `.env` / `.env.local` into the Jest child, same precedence as `dev` (real environment wins over the files, config `env.shared` + `env.test` underneath). `--no-env` skips it |
|
|
103
|
+
| Test runner | Standalone projects: use `frontmcp test` (auto-generates Jest/SWC config; discovers `src/**/*.spec.ts(x)`, `__tests__/**/*.spec.ts(x)`, and `e2e/**/*.e2e.spec.ts(x)`; transforms both `.ts` and `.tsx` with the automatic JSX runtime; transpiles ESM-only deps such as `jose`, `@noble/hashes` and `@noble/ciphers` (CodeCall) under npm, yarn AND pnpm's `node_modules/.pnpm/` store — add your own via `test.esmPackages` in `frontmcp.config.ts`; does not force `NODE_OPTIONS=--experimental-vm-modules` (it would bypass the ESM transforms; scaffolded projects use Jest 30); delegates to a user-provided `jest.config.{ts,js,mjs,cjs,json}` if present, which drops the injected ESM transforms). Nx monorepos: use `nx test <lib>` (resolves the project's `jest.config.ts`). Never invoke `jest --config ...` directly |
|
|
104
|
+
| Coverage threshold | 95%+ across statements, branches, functions, lines |
|
|
105
|
+
| Test descriptions | Plain English, no prefixes like "PT-001"; describe behavior not implementation |
|
|
106
|
+
| Mocking | Mock providers via DI token replacement, never mock the framework |
|
|
107
|
+
| httpMock scope | `httpMock` intercepts HTTP in the **test process** only, NOT in the MCP server subprocess. Do not use httpMock to intercept server-to-API calls — those happen in the child process. Use httpMock for verifying client-to-server request shapes or mocking external APIs called from the test itself |
|
|
108
|
+
| Error testing | Assert `instanceof` specific error class AND MCP error code |
|
|
109
|
+
| Async | Always `await` async operations; use `expect(...).rejects.toThrow()` for async errors |
|
|
110
110
|
|
|
111
111
|
## Common Patterns
|
|
112
112
|
|
|
@@ -146,17 +146,18 @@ This is a router skill. Follow this order to pick a testing approach, then move
|
|
|
146
146
|
|
|
147
147
|
## Troubleshooting
|
|
148
148
|
|
|
149
|
-
| Problem
|
|
150
|
-
|
|
|
151
|
-
| Jest not finding test files
|
|
152
|
-
| `SyntaxError: Unexpected token 'export'`
|
|
153
|
-
| Coverage below 95%
|
|
154
|
-
| E2E test timeout
|
|
155
|
-
| DI resolution fails in tests
|
|
156
|
-
| Istanbul shows 0% on async methods
|
|
157
|
-
| Specs see no `.env` values
|
|
158
|
-
| `Invalid first argument, true` at collection time
|
|
159
|
-
|
|
|
149
|
+
| Problem | Cause | Solution |
|
|
150
|
+
| --------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
151
|
+
| Jest not finding test files | Wrong file extension (`.test.ts` instead of `.spec.ts`) | Rename to `.spec.ts`; check `testMatch` in jest.config |
|
|
152
|
+
| `SyntaxError: Unexpected token 'export'` | An ESM-only dependency is being ignored instead of transpiled | Add it to `test.esmPackages` in `frontmcp.config.ts`. With a hand-written `jest.config.ts`, use the pnpm-safe `transformIgnorePatterns` in [`setup-testing`](./references/setup-testing.md#jest-configuration) AND make sure `transform` matches `.js` (`^.+\.[tj]sx?$` + `allowJs`) — un-ignoring a file does nothing if no transform matches it |
|
|
153
|
+
| Coverage below 95% | Untested error paths or conditional branches | Run `frontmcp test --coverage` and inspect uncovered lines in the report |
|
|
154
|
+
| E2E test timeout | Server startup too slow or port conflict | Increase Jest timeout; use random port allocation |
|
|
155
|
+
| DI resolution fails in tests | Provider not registered in test scope | Register mock providers before creating the test context |
|
|
156
|
+
| Istanbul shows 0% on async methods | TypeScript source-map mismatch with Istanbul | Known issue with some TS compilation settings; verify coverage with actual test output |
|
|
157
|
+
| Specs see no `.env` values | An older CLI did not load `.env` for `frontmcp test`, only for `dev` | Upgrade the CLI — `frontmcp test` now loads `.env` / `.env.local` with the same precedence as `dev` (real environment wins, so CI secrets still override). Pass `--no-env` for a hermetic run |
|
|
158
|
+
| `Invalid first argument, true` at collection time | `test.skip(condition, reason)` reached Jest's `skip(name, fn)` | Upgrade the CLI — the Playwright signature is supported: `test.skip(!hasCredentials, 'credentials not set')` skips every test registered after it in the enclosing block |
|
|
159
|
+
| `test.use()` in one `describe` leaks into another, or two files fight over a port | Older `@frontmcp/testing` kept one global config and per-process ports | Upgrade — `test.use()` is scoped per `describe` and ports are locked across Jest workers; use `port: 0` |
|
|
160
|
+
| Every spec fails with `HTTP 404` after setting `http.entryPath` | The test client always connected to the server root | Upgrade the CLI — the client now follows the `entryPaths` a 404 reports, and `test.use({ entryPath: '/mcp' })` sets it explicitly |
|
|
160
161
|
|
|
161
162
|
## Examples
|
|
162
163
|
|
|
@@ -275,6 +275,7 @@ test.use({
|
|
|
275
275
|
});
|
|
276
276
|
|
|
277
277
|
test('server exposes expected tools', async ({ mcp }) => {
|
|
278
|
+
// Every page: `list()` follows `nextCursor`, so this holds past 40 tools too.
|
|
278
279
|
const tools = await mcp.tools.list();
|
|
279
280
|
expect(tools).toContainTool('create_record');
|
|
280
281
|
expect(tools).toContainTool('delete_record');
|
|
@@ -395,6 +396,27 @@ You usually do not need to set this: when the client's first request 404s and th
|
|
|
395
396
|
|
|
396
397
|
`baseUrl` may also be supplied alongside `server` to override the booted server's own URL (for a proxy, or a different host than it binds).
|
|
397
398
|
|
|
399
|
+
### Scoping config, parameterised tests, ports and restarts
|
|
400
|
+
|
|
401
|
+
- `test.use()` is scoped to the `describe` block it is called in. Nested blocks merge over outer ones (`env` key by key); each distinct configuration gets its own server, stopped by the block that configured it. At file level it applies to the whole file.
|
|
402
|
+
- `port: 0` (or omitting `port`) picks any free port. Ports are reserved with a cross-process lock, so parallel Jest workers do not collide.
|
|
403
|
+
- `auth: { mode, type }` reaches the server process as `FRONTMCP_TEST_AUTH_MODE` / `FRONTMCP_TEST_AUTH_TYPE`; `mode: 'public'` also keeps the `mcp` client anonymous.
|
|
404
|
+
- `test.each` / `test.describe.each` pass the row values to the callback (fixtures first for `test.each`):
|
|
405
|
+
|
|
406
|
+
```typescript
|
|
407
|
+
test.each([
|
|
408
|
+
['read', 1],
|
|
409
|
+
['write', 2],
|
|
410
|
+
])('scope %s', async ({ mcp }, scope, level) => {
|
|
411
|
+
expect(mcp.isConnected()).toBe(true);
|
|
412
|
+
});
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
- `server.info.pid` is the pid of the process that listens on the port. `server.restart()` reconnects `mcp` and every client made with `server.createClient()`.
|
|
416
|
+
- `mcp.logs` holds the log notifications the client received; `server.getLogs()` holds the server process output. They are different sources.
|
|
417
|
+
- `mcp.intercept.failMethod(method, message)` makes matching calls reject with `message`; the returned function removes it.
|
|
418
|
+
- `httpMock` patches `fetch` in the test process only (see above) and `interceptor.restore()` puts the original `fetch` back.
|
|
419
|
+
|
|
398
420
|
### Gating a block on credentials
|
|
399
421
|
|
|
400
422
|
`test.skip(condition, reason)` is the Playwright signature and skips every test registered after it in the enclosing block:
|
|
@@ -493,7 +515,10 @@ matches at the first `node_modules/`, and the run fails with
|
|
|
493
515
|
`SyntaxError: Unexpected token 'export'`.
|
|
494
516
|
|
|
495
517
|
In standalone projects driven by `frontmcp test`, prefer `test.esmPackages` in
|
|
496
|
-
`frontmcp.config.ts` — the injected config already carries the pattern above
|
|
518
|
+
`frontmcp.config.ts` — the injected config already carries the pattern above,
|
|
519
|
+
and already transpiles `jose`, `@noble/hashes` and `@noble/ciphers` (CodeCall).
|
|
520
|
+
`frontmcp test` does not set `NODE_OPTIONS=--experimental-vm-modules` (it would make Jest
|
|
521
|
+
load ESM natively and bypass these transforms); use Jest 30 (what `frontmcp create` scaffolds):
|
|
497
522
|
|
|
498
523
|
```typescript
|
|
499
524
|
// frontmcp.config.ts
|
|
@@ -586,7 +611,7 @@ node scripts/fix-unused-imports.mjs feature/my-branch
|
|
|
586
611
|
### E2E Tests
|
|
587
612
|
|
|
588
613
|
- [ ] Fixture-based tests use `test.use({ server, port })` for server lifecycle
|
|
589
|
-
- [ ] Tools appear in `tools/list` response via `toContainTool()` matcher
|
|
614
|
+
- [ ] Tools appear in `tools/list` response via `toContainTool()` matcher (`mcp.tools.list()` and the other `list()` calls return every page, so no cursor handling is needed)
|
|
590
615
|
- [ ] Tool calls return expected results via `toBeSuccessful()` matcher
|
|
591
616
|
- [ ] Authenticated tests use `TestTokenFactory` and verify rejection without token
|
|
592
617
|
|
|
@@ -606,7 +631,7 @@ node scripts/fix-unused-imports.mjs feature/my-branch
|
|
|
606
631
|
| `toContainTool` matcher not found | Using `expect` from Jest instead of `@frontmcp/testing` | Import `expect` from `@frontmcp/testing` to get MCP-specific matchers |
|
|
607
632
|
| `McpTestClient.create()` connection refused | Test server not running or wrong `baseUrl` | Ensure `TestServer.start()` completes before creating client; verify port matches |
|
|
608
633
|
| Istanbul shows 0% coverage for async methods | TypeScript compilation source-map mismatch | Known issue with `ts-jest` and certain async patterns; check `tsconfig.spec.json` source-map settings |
|
|
609
|
-
| Auth E2E test returns 401 unexpectedly | Token not set or expired | Call `mcp.
|
|
634
|
+
| Auth E2E test returns 401 unexpectedly | Token not set or expired | Call `await mcp.authenticate(token)` before the tool call; use `auth.createToken()` with valid claims |
|
|
610
635
|
|
|
611
636
|
## Examples
|
|
612
637
|
|
|
@@ -94,6 +94,14 @@ describe('Authenticated Server', () => {
|
|
|
94
94
|
});
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
+
## Token semantics
|
|
98
|
+
|
|
99
|
+
- Default issuer `https://test.frontmcp.local`, default audience `frontmcp-test` (override with `new TestTokenFactory({ issuer, audience })`).
|
|
100
|
+
- `expiresIn` is counted from now and rounded up to whole seconds, so `expiresIn: 1` is valid for at least one second. `createAnonymousToken(expiresIn?)` takes a lifetime too.
|
|
101
|
+
- `await mcp.authenticate(token)` opens a new session for the token and **rejects** if the server refuses it (expired, bad signature); the client then keeps its previous identity. On an unconnected client it only stores the token. 401/403 are never retried.
|
|
102
|
+
- Tools read token scopes through `this.auth` (e.g. `this.auth.scopes`).
|
|
103
|
+
- Access tokens from `MockOAuthServer` carry the granted `scope` claim and `exp = accessTokenTtlSeconds`, also after a refresh.
|
|
104
|
+
|
|
97
105
|
## Mock OAuth / OIDC server
|
|
98
106
|
|
|
99
107
|
`MockOAuthServer` serves JWKS, OAuth metadata, authorization, token, and userinfo endpoints. Construct it with a `TestTokenFactory`, call `.start()` to bind a port, and configure your MCP server to point at the returned `info.issuer` / `info.jwksUrl`.
|
|
@@ -12,6 +12,7 @@ Real API references:
|
|
|
12
12
|
- `TestServer.start({ command, port })` returns a `TestServer` instance with `info.baseUrl` and `stop()` — `libs/testing/src/server/test-server.ts:101`. There is no `TestServer.create(ServerClass)`.
|
|
13
13
|
- Build a client with `await McpTestClient.create({ baseUrl }).withTransport('streamable-http').buildAndConnect()` — `libs/testing/src/client/mcp-test-client.builder.ts`.
|
|
14
14
|
- The public client API is namespaced: `client.tools.list()`, `client.tools.call(name, args)`, `client.resources.list()`, `client.resources.read(uri)`, `client.prompts.list()`, `client.prompts.get(name, args)`, `client.disconnect()` — `libs/testing/src/client/mcp-test-client.ts:306-402`.
|
|
15
|
+
- `tools.list()`, `resources.list()`, `resources.listTemplates()` and `prompts.list()` return **every page**: they follow `nextCursor` until the server stops returning one (a FrontMCP server pages at 40 by default), and throw if a cursor repeats or paging passes 1000 pages. Assert on the full list; there is no cursor to pass.
|
|
15
16
|
|
|
16
17
|
```typescript
|
|
17
18
|
// server.e2e.spec.ts
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
},
|
|
75
75
|
{
|
|
76
76
|
"name": "ui-widgets",
|
|
77
|
-
"description": "@Tool({ ui }) \u2014 template formats, trusted markup (html / escapeStringResults), servingMode, host-detect resourceMode, CSP,
|
|
77
|
+
"description": "@Tool({ ui }) \u2014 template formats, trusted markup (html / escapeStringResults), servingMode, host-detect resourceMode, CSP, ignored options, MCP Apps spec."
|
|
78
78
|
},
|
|
79
79
|
{
|
|
80
80
|
"name": "annotations",
|
|
@@ -362,10 +362,10 @@
|
|
|
362
362
|
"name": "24-tool-with-ui-csp-and-bridge",
|
|
363
363
|
"level": "advanced",
|
|
364
364
|
"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.",
|
|
365
|
-
"tags": ["ui", "csp", "
|
|
365
|
+
"tags": ["ui", "csp", "callTool", "FrontMcpBridge", "interactive-widget"],
|
|
366
366
|
"features": [
|
|
367
367
|
"Restricting the widget's outbound `fetch` via `ui.csp.connectDomains` (emitted on the resource per #455)",
|
|
368
|
-
"
|
|
368
|
+
"Calling other tools from the widget with `window.FrontMcpBridge.callTool(name, args)` instead of host-specific APIs",
|
|
369
369
|
"Building the markup with `ctx.helpers.html` and embedding initial data into the inline `<script>` via `trustedHtml(jsonEmbed(...))` (`jsonEmbed` escapes `<`, `>` and `&`)",
|
|
370
370
|
"Surfacing in-flight status via `invocationStatus.invoking` / `invoked` so the host UI shows feedback"
|
|
371
371
|
]
|
|
@@ -943,7 +943,8 @@
|
|
|
943
943
|
"Configuring `storage: { type: 'redis' }` so rate limit counters are shared across instances",
|
|
944
944
|
"Using `keyPrefix` to namespace guard keys in a shared Redis instance",
|
|
945
945
|
"Combining `partitionBy: 'ip'` for global limits with `partitionBy: 'session'` per tool",
|
|
946
|
-
"In-memory counters are per-process and would allow N times the intended rate with N instances"
|
|
946
|
+
"In-memory counters are per-process and would allow N times the intended rate with N instances",
|
|
947
|
+
"Startup fails closed, and a limited call is refused, with `GuardStorageUnavailableError` when Redis is down, unless `fallback: 'memory'`"
|
|
947
948
|
]
|
|
948
949
|
},
|
|
949
950
|
{
|
|
@@ -1412,6 +1413,7 @@
|
|
|
1412
1413
|
"tags": ["deployment", "vercel", "serverless", "config", "minimal"],
|
|
1413
1414
|
"features": [
|
|
1414
1415
|
"The exact shape of the auto-generated `vercel.json` \u2014 three keys, nothing else",
|
|
1416
|
+
"That `buildCommand` builds the vercel target (`<exec> frontmcp build --target vercel`), not the `build` script",
|
|
1415
1417
|
"That routing and function configuration live in `.vercel/output/`, not `vercel.json`",
|
|
1416
1418
|
"That hand-authoring `api/frontmcp.ts` references in `vercel.json` is unnecessary and breaks deploys"
|
|
1417
1419
|
]
|
|
@@ -2071,6 +2073,7 @@
|
|
|
2071
2073
|
"Using `toolPatterns` glob patterns to cache groups of tools without per-tool configuration",
|
|
2072
2074
|
"Per-tool `cache` metadata with custom `ttl` (seconds) and `slideWindow` for TTL refresh on hits",
|
|
2073
2075
|
"Using `cache: true` for simple default-TTL caching",
|
|
2076
|
+
"A cache hit returns the same `content`/`structuredContent` as the miss, marked by `_meta.cache: 'hit'` on the result",
|
|
2074
2077
|
"Gating a tool with `featureFlag: 'beta-search'` -- the tool is hidden from `list_tools` when the flag is off",
|
|
2075
2078
|
"Accessing `this.featureFlags.isEnabled()` inside a tool for runtime flag checks"
|
|
2076
2079
|
]
|
|
@@ -2099,8 +2102,8 @@
|
|
|
2099
2102
|
"tags": ["development", "session", "plugins", "remember", "plugin", "memory"],
|
|
2100
2103
|
"features": [
|
|
2101
2104
|
"Installing `RememberPlugin` with `type: 'memory'` for development",
|
|
2102
|
-
"Enabling `tools: { enabled: true }` to expose LLM-callable memory tools (`remember_this`, `recall`, etc.)",
|
|
2103
|
-
"Using `this.remember.set()` with default `session` scope and explicit `user` scope",
|
|
2105
|
+
"Enabling `tools: { enabled: true }` to expose LLM-callable memory tools (`remember_this`, `recall`, etc.), whose `scope` defaults to `session`",
|
|
2106
|
+
"Using `this.remember.set()` with default `session` scope and explicit `user` scope (refused for an anonymous caller)",
|
|
2104
2107
|
"Using `this.remember.get()` with a `defaultValue` fallback",
|
|
2105
2108
|
"Using `this.remember.knows()` to check key existence without retrieving the value"
|
|
2106
2109
|
]
|