@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.
Files changed (55) hide show
  1. package/catalog/create-tool/SKILL.md +24 -24
  2. package/catalog/create-tool/examples/22-tool-with-ui-html-template.md +0 -1
  3. package/catalog/create-tool/examples/23-tool-with-ui-filesource-tsx.md +7 -6
  4. package/catalog/create-tool/examples/24-tool-with-ui-csp-and-bridge.md +4 -6
  5. package/catalog/create-tool/examples/27-tool-with-examples-metadata.md +3 -2
  6. package/catalog/create-tool/references/decorator-options.md +1 -1
  7. package/catalog/create-tool/references/elicitation.md +1 -0
  8. package/catalog/create-tool/references/file-layout.md +2 -0
  9. package/catalog/create-tool/references/ui-widgets.md +96 -40
  10. package/catalog/create-tool/rules/widget-paths-anchor-with-import-meta-url.md +10 -3
  11. package/catalog/frontmcp-config/examples/configure-throttle/distributed-redis-throttle.md +8 -0
  12. package/catalog/frontmcp-config/references/configure-auth.md +1 -0
  13. package/catalog/frontmcp-config/references/configure-deployment-targets.md +19 -1
  14. package/catalog/frontmcp-config/references/configure-http.md +6 -4
  15. package/catalog/frontmcp-config/references/configure-security-headers.md +18 -13
  16. package/catalog/frontmcp-config/references/configure-throttle-guard-config.md +19 -4
  17. package/catalog/frontmcp-config/references/configure-throttle.md +25 -7
  18. package/catalog/frontmcp-deployment/SKILL.md +19 -19
  19. package/catalog/frontmcp-deployment/examples/build-for-browser/react-provider-setup.md +5 -3
  20. package/catalog/frontmcp-deployment/examples/deploy-to-vercel/vercel-mcp-endpoint-test.md +1 -1
  21. package/catalog/frontmcp-deployment/examples/deploy-to-vercel/vercel-with-kv.md +3 -1
  22. package/catalog/frontmcp-deployment/examples/deploy-to-vercel/vercel-with-skills-cache.md +1 -1
  23. package/catalog/frontmcp-deployment/examples/deploy-to-vercel-config/minimal-vercel-config.md +7 -3
  24. package/catalog/frontmcp-deployment/examples/deploy-to-vercel-config/vercel-config-with-security-headers.md +4 -3
  25. package/catalog/frontmcp-deployment/references/build-for-browser.md +8 -0
  26. package/catalog/frontmcp-deployment/references/build-for-mcpb.md +9 -8
  27. package/catalog/frontmcp-deployment/references/build-for-sdk.md +9 -9
  28. package/catalog/frontmcp-deployment/references/deploy-to-cloudflare.md +3 -1
  29. package/catalog/frontmcp-deployment/references/deploy-to-lambda.md +9 -8
  30. package/catalog/frontmcp-deployment/references/deploy-to-vercel-config.md +15 -3
  31. package/catalog/frontmcp-deployment/references/deploy-to-vercel.md +16 -8
  32. package/catalog/frontmcp-deployment/references/protocol-versions.md +9 -0
  33. package/catalog/frontmcp-development/examples/official-plugins/cache-and-feature-flags.md +5 -0
  34. package/catalog/frontmcp-development/examples/official-plugins/remember-plugin-session-memory.md +7 -5
  35. package/catalog/frontmcp-development/references/create-agent.md +8 -7
  36. package/catalog/frontmcp-development/references/create-plugin.md +17 -0
  37. package/catalog/frontmcp-development/references/official-plugins.md +66 -8
  38. package/catalog/frontmcp-guides/references/example-task-manager.md +2 -2
  39. package/catalog/frontmcp-guides/references/example-weather-api.md +2 -2
  40. package/catalog/frontmcp-production-readiness/examples/distributed-ha/ha-kubernetes-3-replicas.md +1 -0
  41. package/catalog/frontmcp-production-readiness/examples/production-node-sdk/package-json-config.md +2 -2
  42. package/catalog/frontmcp-production-readiness/examples/production-vercel/vercel-edge-config.md +1 -0
  43. package/catalog/frontmcp-production-readiness/references/common-checklist.md +4 -0
  44. package/catalog/frontmcp-production-readiness/references/distributed-ha.md +17 -7
  45. package/catalog/frontmcp-production-readiness/references/health-readiness-endpoints.md +3 -1
  46. package/catalog/frontmcp-setup/examples/project-structure-nx/nx-generator-scaffolding.md +1 -1
  47. package/catalog/frontmcp-setup/references/nx-workflow.md +25 -17
  48. package/catalog/frontmcp-setup/references/setup-redis.md +37 -7
  49. package/catalog/frontmcp-setup/references/setup-sqlite.md +9 -6
  50. package/catalog/frontmcp-testing/SKILL.md +24 -23
  51. package/catalog/frontmcp-testing/references/setup-testing.md +28 -3
  52. package/catalog/frontmcp-testing/references/test-auth.md +8 -0
  53. package/catalog/frontmcp-testing/references/test-e2e-handler.md +1 -0
  54. package/catalog/skills-manifest.json +9 -6
  55. 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
- | `encryption` | `{ secret: string }` | `undefined` | AES-256-GCM encryption for values at rest |
135
- | `ttlCleanupIntervalMs` | `number` | `60000` | Interval for purging expired keys (milliseconds) |
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 | 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
- | 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 |
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.setAuthToken(token)` before the tool call; use `auth.createToken()` with valid claims |
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, widgetAccessible, MCP Apps spec."
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", "widgetAccessible", "FrontMcpBridge", "interactive-widget"],
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
- "Opting the widget into cross-tool calls with `widgetAccessible: true` and using `window.FrontMcpBridge.callTool(name, args)` instead of host-specific APIs",
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
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontmcp/skills",
3
- "version": "1.8.5",
3
+ "version": "1.8.7",
4
4
  "description": "Curated skills catalog for FrontMCP projects",
5
5
  "author": "AgentFront <info@agentfront.dev>",
6
6
  "homepage": "https://docs.agentfront.dev",