@frontmcp/skills 1.1.2 → 1.2.0

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 (176) hide show
  1. package/catalog/TEMPLATE.md +16 -11
  2. package/catalog/frontmcp-authorities/SKILL.md +116 -11
  3. package/catalog/frontmcp-authorities/references/authority-profiles.md +39 -36
  4. package/catalog/frontmcp-authorities/references/claims-mapping.md +7 -0
  5. package/catalog/frontmcp-authorities/references/custom-evaluators.md +63 -14
  6. package/catalog/frontmcp-channels/SKILL.md +36 -0
  7. package/catalog/frontmcp-channels/examples/channel-sources/file-watcher.md +8 -2
  8. package/catalog/frontmcp-channels/examples/channel-sources/replay-buffer.md +111 -30
  9. package/catalog/frontmcp-channels/examples/channel-two-way/whatsapp-bridge.md +45 -3
  10. package/catalog/frontmcp-channels/references/channel-sources.md +11 -3
  11. package/catalog/frontmcp-channels/references/channel-two-way.md +60 -89
  12. package/catalog/frontmcp-config/SKILL.md +111 -8
  13. package/catalog/frontmcp-config/examples/configure-auth-modes/local-self-signed-tokens.md +4 -4
  14. package/catalog/frontmcp-config/examples/configure-auth-modes/remote-enterprise-oauth.md +7 -1
  15. package/catalog/frontmcp-config/examples/configure-deployment-targets/distributed-ha-config.md +1 -1
  16. package/catalog/frontmcp-config/examples/configure-deployment-targets/json-schema-ide-support.md +1 -1
  17. package/catalog/frontmcp-config/examples/configure-deployment-targets/multi-target-with-security.md +12 -9
  18. package/catalog/frontmcp-config/examples/configure-http/cors-restricted-origins.md +2 -2
  19. package/catalog/frontmcp-config/examples/configure-http/entry-path-reverse-proxy.md +1 -1
  20. package/catalog/frontmcp-config/examples/configure-security-headers/csp-report-only.md +1 -1
  21. package/catalog/frontmcp-config/examples/configure-security-headers/full-production-headers.md +1 -1
  22. package/catalog/frontmcp-config/examples/configure-skills-http/audit-log-basic.md +76 -0
  23. package/catalog/frontmcp-config/examples/configure-skills-http/audit-log-redis.md +116 -0
  24. package/catalog/frontmcp-config/examples/configure-skills-http/inject-instructions.md +59 -0
  25. package/catalog/frontmcp-config/references/configure-auth-modes.md +5 -5
  26. package/catalog/frontmcp-config/references/configure-deployment-targets.md +27 -24
  27. package/catalog/frontmcp-config/references/configure-http.md +14 -10
  28. package/catalog/frontmcp-config/references/configure-security-headers.md +2 -2
  29. package/catalog/frontmcp-config/references/configure-session.md +25 -25
  30. package/catalog/frontmcp-config/references/configure-skills-http.md +157 -0
  31. package/catalog/frontmcp-config/references/configure-throttle.md +1 -1
  32. package/catalog/frontmcp-config/references/configure-transport.md +2 -2
  33. package/catalog/frontmcp-deployment/SKILL.md +112 -9
  34. package/catalog/frontmcp-deployment/examples/build-for-browser/browser-build-with-custom-entry.md +23 -11
  35. package/catalog/frontmcp-deployment/examples/build-for-browser/browser-crypto-and-storage.md +44 -17
  36. package/catalog/frontmcp-deployment/examples/build-for-browser/react-provider-setup.md +53 -21
  37. package/catalog/frontmcp-deployment/examples/build-for-cli/cli-binary-build.md +1 -1
  38. package/catalog/frontmcp-deployment/examples/build-for-cli/unix-socket-daemon.md +1 -1
  39. package/catalog/frontmcp-deployment/examples/build-for-mcpb/mcpb-bundle-build.md +1 -1
  40. package/catalog/frontmcp-deployment/examples/build-for-sdk/connect-openai.md +1 -1
  41. package/catalog/frontmcp-deployment/examples/build-for-sdk/multi-platform-connect.md +1 -1
  42. package/catalog/frontmcp-deployment/examples/deploy-to-cloudflare/basic-worker-deploy.md +7 -8
  43. package/catalog/frontmcp-deployment/examples/deploy-to-cloudflare/worker-custom-domain.md +8 -6
  44. package/catalog/frontmcp-deployment/examples/deploy-to-cloudflare/worker-with-kv-storage.md +5 -4
  45. package/catalog/frontmcp-deployment/examples/deploy-to-lambda/cdk-deployment.md +8 -5
  46. package/catalog/frontmcp-deployment/examples/deploy-to-lambda/lambda-handler-with-cors.md +20 -18
  47. package/catalog/frontmcp-deployment/examples/deploy-to-lambda/sam-template-basic.md +8 -5
  48. package/catalog/frontmcp-deployment/examples/deploy-to-node/docker-compose-with-redis.md +3 -3
  49. package/catalog/frontmcp-deployment/examples/deploy-to-node/pm2-with-nginx.md +1 -1
  50. package/catalog/frontmcp-deployment/examples/deploy-to-node/resource-limits.md +2 -2
  51. package/catalog/frontmcp-deployment/examples/deploy-to-node-dockerfile/basic-multistage-dockerfile.md +2 -2
  52. package/catalog/frontmcp-deployment/examples/deploy-to-node-dockerfile/secure-nonroot-dockerfile.md +1 -1
  53. package/catalog/frontmcp-deployment/examples/deploy-to-vercel/vercel-mcp-endpoint-test.md +23 -21
  54. package/catalog/frontmcp-deployment/examples/deploy-to-vercel/vercel-with-kv.md +25 -22
  55. package/catalog/frontmcp-deployment/examples/deploy-to-vercel/vercel-with-skills-cache.md +23 -30
  56. package/catalog/frontmcp-deployment/examples/deploy-to-vercel-config/minimal-vercel-config.md +52 -28
  57. package/catalog/frontmcp-deployment/examples/deploy-to-vercel-config/vercel-config-with-security-headers.md +32 -55
  58. package/catalog/frontmcp-deployment/examples/mcp-client-integration/http-remote.md +9 -0
  59. package/catalog/frontmcp-deployment/references/build-for-browser.md +40 -17
  60. package/catalog/frontmcp-deployment/references/build-for-cli.md +8 -8
  61. package/catalog/frontmcp-deployment/references/deploy-to-cloudflare.md +43 -24
  62. package/catalog/frontmcp-deployment/references/deploy-to-lambda.md +36 -25
  63. package/catalog/frontmcp-deployment/references/deploy-to-node-dockerfile.md +56 -14
  64. package/catalog/frontmcp-deployment/references/deploy-to-node.md +9 -6
  65. package/catalog/frontmcp-deployment/references/deploy-to-vercel-config.md +57 -58
  66. package/catalog/frontmcp-deployment/references/deploy-to-vercel.md +49 -59
  67. package/catalog/frontmcp-deployment/references/mcp-client-integration.md +2 -0
  68. package/catalog/frontmcp-development/SKILL.md +186 -11
  69. package/catalog/frontmcp-development/examples/create-agent/custom-multi-pass-agent.md +1 -1
  70. package/catalog/frontmcp-development/examples/create-agent/nested-agents-with-swarm.md +30 -27
  71. package/catalog/frontmcp-development/examples/create-job/job-with-permissions.md +13 -8
  72. package/catalog/frontmcp-development/examples/create-provider/basic-database-provider.md +33 -23
  73. package/catalog/frontmcp-development/examples/create-provider/config-and-api-providers.md +19 -10
  74. package/catalog/frontmcp-development/examples/create-tool/tool-with-rate-limiting-and-progress.md +3 -3
  75. package/catalog/frontmcp-development/examples/create-workflow/webhook-triggered-workflow.md +6 -4
  76. package/catalog/frontmcp-development/examples/decorators-guide/agent-skill-job-workflow.md +1 -1
  77. package/catalog/frontmcp-development/examples/decorators-guide/basic-server-with-app-and-tools.md +13 -8
  78. package/catalog/frontmcp-development/examples/decorators-guide/multi-app-with-plugins-and-providers.md +50 -23
  79. package/catalog/frontmcp-development/references/create-agent.md +47 -30
  80. package/catalog/frontmcp-development/references/create-job.md +69 -54
  81. package/catalog/frontmcp-development/references/create-plugin-hooks.md +45 -28
  82. package/catalog/frontmcp-development/references/create-plugin.md +10 -8
  83. package/catalog/frontmcp-development/references/create-prompt.md +3 -3
  84. package/catalog/frontmcp-development/references/create-provider.md +91 -51
  85. package/catalog/frontmcp-development/references/create-resource.md +3 -3
  86. package/catalog/frontmcp-development/references/create-skill.md +2 -2
  87. package/catalog/frontmcp-development/references/create-tool.md +7 -7
  88. package/catalog/frontmcp-development/references/create-workflow.md +8 -10
  89. package/catalog/frontmcp-development/references/decorators-guide.md +92 -56
  90. package/catalog/frontmcp-development/references/official-plugins.md +4 -3
  91. package/catalog/frontmcp-development/references/openapi-adapter.md +1 -1
  92. package/catalog/frontmcp-extensibility/SKILL.md +70 -10
  93. package/catalog/frontmcp-extensibility/examples/skill-audit-log/custom-store.md +197 -0
  94. package/catalog/frontmcp-extensibility/examples/skill-audit-log/verify-chain.md +68 -0
  95. package/catalog/frontmcp-extensibility/examples/vectoriadb/product-catalog-search.md +3 -5
  96. package/catalog/frontmcp-extensibility/examples/vectoriadb/semantic-search-with-persistence.md +4 -11
  97. package/catalog/frontmcp-extensibility/examples/vectoriadb/tfidf-keyword-search.md +41 -30
  98. package/catalog/frontmcp-extensibility/references/skill-audit-log.md +233 -0
  99. package/catalog/frontmcp-extensibility/references/vectoriadb.md +73 -63
  100. package/catalog/frontmcp-guides/SKILL.md +84 -27
  101. package/catalog/frontmcp-guides/examples/example-knowledge-base/agent-and-plugin.md +72 -62
  102. package/catalog/frontmcp-guides/examples/example-knowledge-base/vector-search-and-resources.md +32 -43
  103. package/catalog/frontmcp-guides/examples/example-task-manager/auth-and-crud-tools.md +24 -17
  104. package/catalog/frontmcp-guides/examples/example-task-manager/authenticated-e2e-tests.md +23 -21
  105. package/catalog/frontmcp-guides/examples/example-task-manager/redis-provider-with-di.md +47 -39
  106. package/catalog/frontmcp-guides/examples/example-weather-api/server-and-app-setup.md +16 -6
  107. package/catalog/frontmcp-guides/examples/example-weather-api/unit-and-e2e-tests.md +9 -8
  108. package/catalog/frontmcp-guides/references/example-knowledge-base.md +192 -265
  109. package/catalog/frontmcp-guides/references/example-task-manager.md +60 -54
  110. package/catalog/frontmcp-guides/references/example-weather-api.md +22 -24
  111. package/catalog/frontmcp-observability/SKILL.md +66 -2
  112. package/catalog/frontmcp-observability/examples/telemetry-api/skill-counters.md +100 -0
  113. package/catalog/frontmcp-observability/examples/tracing-setup/production-tracing.md +7 -2
  114. package/catalog/frontmcp-observability/examples/vendor-integrations/coralogix-setup.md +6 -2
  115. package/catalog/frontmcp-observability/references/telemetry-api.md +72 -8
  116. package/catalog/frontmcp-observability/references/testing-observability.md +33 -49
  117. package/catalog/frontmcp-observability/references/tracing-setup.md +12 -5
  118. package/catalog/frontmcp-observability/references/vendor-integrations.md +46 -1
  119. package/catalog/frontmcp-production-readiness/SKILL.md +134 -3
  120. package/catalog/frontmcp-production-readiness/examples/common-checklist/caching-and-performance.md +57 -36
  121. package/catalog/frontmcp-production-readiness/examples/common-checklist/observability-setup.md +1 -1
  122. package/catalog/frontmcp-production-readiness/examples/common-checklist/security-hardening.md +102 -6
  123. package/catalog/frontmcp-production-readiness/examples/production-cli-daemon/daemon-socket-config.md +2 -1
  124. package/catalog/frontmcp-production-readiness/examples/production-cli-daemon/graceful-shutdown-cleanup.md +66 -58
  125. package/catalog/frontmcp-production-readiness/examples/production-cli-daemon/security-and-permissions.md +5 -3
  126. package/catalog/frontmcp-production-readiness/examples/production-cloudflare/durable-objects-state.md +2 -1
  127. package/catalog/frontmcp-production-readiness/examples/production-cloudflare/wrangler-config.md +55 -76
  128. package/catalog/frontmcp-production-readiness/examples/production-lambda/cold-start-connection-reuse.md +43 -40
  129. package/catalog/frontmcp-production-readiness/examples/production-lambda/sam-template.md +63 -94
  130. package/catalog/frontmcp-production-readiness/examples/production-lambda/scaling-and-monitoring.md +28 -18
  131. package/catalog/frontmcp-production-readiness/examples/production-node-sdk/multi-instance-cleanup.md +29 -14
  132. package/catalog/frontmcp-production-readiness/examples/production-node-server/graceful-shutdown.md +58 -42
  133. package/catalog/frontmcp-production-readiness/examples/production-node-server/redis-session-scaling.md +5 -2
  134. package/catalog/frontmcp-production-readiness/examples/production-vercel/cold-start-optimization.md +41 -24
  135. package/catalog/frontmcp-production-readiness/examples/production-vercel/vercel-edge-config.md +56 -65
  136. package/catalog/frontmcp-production-readiness/references/common-checklist.md +17 -5
  137. package/catalog/frontmcp-production-readiness/references/production-cli-daemon.md +5 -5
  138. package/catalog/frontmcp-production-readiness/references/production-cloudflare.md +5 -5
  139. package/catalog/frontmcp-production-readiness/references/production-lambda.md +5 -5
  140. package/catalog/frontmcp-production-readiness/references/production-node-sdk.md +5 -5
  141. package/catalog/frontmcp-production-readiness/references/production-node-server.md +1 -1
  142. package/catalog/frontmcp-production-readiness/references/production-vercel.md +5 -5
  143. package/catalog/frontmcp-setup/SKILL.md +88 -0
  144. package/catalog/frontmcp-setup/examples/project-structure-nx/nx-workspace-with-apps.md +10 -4
  145. package/catalog/frontmcp-setup/examples/project-structure-standalone/dev-workflow-commands.md +21 -8
  146. package/catalog/frontmcp-setup/examples/readme-guide/node-server-readme.md +3 -3
  147. package/catalog/frontmcp-setup/references/multi-app-composition.md +4 -3
  148. package/catalog/frontmcp-setup/references/project-structure-nx.md +15 -6
  149. package/catalog/frontmcp-setup/references/project-structure-standalone.md +18 -15
  150. package/catalog/frontmcp-setup/references/readme-guide.md +1 -1
  151. package/catalog/frontmcp-setup/references/setup-project.md +19 -5
  152. package/catalog/frontmcp-setup/references/setup-redis.md +27 -39
  153. package/catalog/frontmcp-setup/references/setup-sqlite.md +25 -18
  154. package/catalog/frontmcp-testing/SKILL.md +102 -15
  155. package/catalog/frontmcp-testing/examples/setup-testing/unit-test-tool-resource-prompt.md +3 -3
  156. package/catalog/frontmcp-testing/examples/test-auth/oauth-flow-test.md +50 -39
  157. package/catalog/frontmcp-testing/examples/test-auth/role-based-access-test.md +52 -29
  158. package/catalog/frontmcp-testing/examples/test-auth/token-factory-test.md +37 -20
  159. package/catalog/frontmcp-testing/examples/test-direct-client/basic-create-test.md +25 -15
  160. package/catalog/frontmcp-testing/examples/test-direct-client/openai-claude-format-test.md +27 -21
  161. package/catalog/frontmcp-testing/examples/test-e2e-handler/basic-e2e-test.md +29 -20
  162. package/catalog/frontmcp-testing/examples/test-e2e-handler/manual-client-with-transport.md +5 -3
  163. package/catalog/frontmcp-testing/examples/test-e2e-handler/tool-call-and-error-e2e.md +35 -26
  164. package/catalog/frontmcp-testing/examples/test-tool-unit/basic-tool-test.md +8 -3
  165. package/catalog/frontmcp-testing/examples/test-tool-unit/schema-validation-test.md +4 -1
  166. package/catalog/frontmcp-testing/examples/test-tool-unit/tool-error-handling-test.md +6 -3
  167. package/catalog/frontmcp-testing/references/setup-testing.md +35 -39
  168. package/catalog/frontmcp-testing/references/test-auth.md +86 -43
  169. package/catalog/frontmcp-testing/references/test-browser-build.md +1 -1
  170. package/catalog/frontmcp-testing/references/test-direct-client.md +29 -19
  171. package/catalog/frontmcp-testing/references/test-e2e-handler.md +31 -19
  172. package/catalog/frontmcp-testing/references/test-tool-unit.md +6 -2
  173. package/catalog/skills-manifest.json +428 -339
  174. package/package.json +1 -1
  175. package/src/manifest.d.ts +13 -0
  176. package/src/manifest.js.map +1 -1
@@ -13,7 +13,7 @@ Providers are singleton services — database pools, API clients, config objects
13
13
 
14
14
  - Multiple tools, resources, or agents need a shared database connection pool
15
15
  - API clients or external service connections must be singleton (not recreated per request)
16
- - You need lifecycle management with `onInit()` at startup and `onDestroy()` at shutdown
16
+ - You need async one-time setup before any tool runs (use `AsyncProvider({ useFactory })`)
17
17
 
18
18
  ### Recommended
19
19
 
@@ -27,7 +27,7 @@ Providers are singleton services — database pools, API clients, config objects
27
27
  - You need to build an executable action for AI clients (see `create-tool`)
28
28
  - You need autonomous LLM-driven orchestration (see `create-agent`)
29
29
 
30
- > **Decision:** Use this skill when you need a shared, singleton service with lifecycle management that tools, resources, and agents access via `this.get(token)`.
30
+ > **Decision:** Use this skill when you need a shared, singleton service that tools, resources, and agents access via `this.get(token)`. `@Provider` does **not** support `onInit`/`onDestroy` lifecycle hooks — use the constructor for sync setup, `AsyncProvider({ useFactory })` for async setup, and an explicit method (e.g., `close()`) plus the framework's shutdown path for cleanup.
31
31
 
32
32
  ## Step 1: Define a Token
33
33
 
@@ -47,31 +47,61 @@ const DB_TOKEN: Token<DatabaseService> = Symbol('DatabaseService');
47
47
 
48
48
  ## Step 2: Create the Provider
49
49
 
50
+ `@Provider` is a class decorator. There are two patterns depending on whether
51
+ your provider needs async setup:
52
+
53
+ **Pattern A — sync setup (no async I/O at boot):** decorate the class, do the
54
+ work in the constructor.
55
+
50
56
  ```typescript
51
57
  import { Provider } from '@frontmcp/sdk';
52
- import { createPool, Pool } from 'your-db-driver';
53
58
 
54
- @Provider({ name: 'DatabaseProvider' })
55
- class DatabaseProvider implements DatabaseService {
56
- private pool!: Pool;
59
+ @Provider({ name: 'ConfigProvider' })
60
+ class ConfigProvider {
61
+ // Constructor runs synchronously the first time the class is resolved;
62
+ // a thrown error here aborts startup (fail-fast).
63
+ readonly apiBaseUrl = process.env.API_BASE_URL ?? 'https://api.example.com';
64
+ readonly maxRetries = Number(process.env.MAX_RETRIES ?? 3);
65
+ }
66
+ ```
57
67
 
58
- async onInit() {
59
- // Called once when server starts
60
- this.pool = await createPool({
61
- connectionString: process.env.DATABASE_URL,
62
- max: 20,
63
- });
64
- }
68
+ **Pattern B — async setup (e.g., open a connection pool):** use `AsyncProvider`
69
+ factory. The framework `await`s `useFactory` before any tool can resolve the
70
+ token, so the pool is guaranteed to be open by the time `this.get(...)` returns.
71
+
72
+ ```typescript
73
+ import { createPool, type Pool } from 'your-db-driver';
74
+
75
+ import { AsyncProvider, ProviderScope } from '@frontmcp/sdk';
76
+
77
+ class DatabasePool implements DatabaseService {
78
+ constructor(private readonly pool: Pool) {}
65
79
 
66
80
  async query(sql: string, params?: unknown[]) {
67
81
  return this.pool.query(sql, params);
68
82
  }
69
83
 
70
- async onDestroy() {
71
- // Called when server shuts down
84
+ async close() {
85
+ // `@Provider` has no `onDestroy` hook. Expose explicit cleanup as a
86
+ // method and call it from the host (e.g., before `server.dispose()`)
87
+ // when the provider owns network/file handles that need to drain.
72
88
  await this.pool.end();
73
89
  }
74
90
  }
91
+
92
+ export const databaseProvider = AsyncProvider({
93
+ provide: DB_TOKEN,
94
+ name: 'DatabaseProvider',
95
+ scope: ProviderScope.GLOBAL,
96
+ inject: () => [] as const,
97
+ useFactory: async (): Promise<DatabaseService> => {
98
+ const pool = await createPool({
99
+ connectionString: process.env.DATABASE_URL,
100
+ max: 20,
101
+ });
102
+ return new DatabasePool(pool);
103
+ },
104
+ });
75
105
  ```
76
106
 
77
107
  ## Step 3: Register in @App or @FrontMcp
@@ -79,7 +109,7 @@ class DatabaseProvider implements DatabaseService {
79
109
  ```typescript
80
110
  @App({
81
111
  name: 'MyApp',
82
- providers: [DatabaseProvider], // App-scoped provider
112
+ providers: [databaseProvider], // App-scoped provider (factory)
83
113
  tools: [QueryTool, InsertTool],
84
114
  })
85
115
  class MyApp {}
@@ -88,7 +118,7 @@ class MyApp {}
88
118
  @FrontMcp({
89
119
  info: { name: 'my-server', version: '1.0.0' },
90
120
  apps: [MyApp],
91
- providers: [DatabaseProvider], // Server-scoped provider
121
+ providers: [databaseProvider], // Server-scoped provider
92
122
  })
93
123
  class Server {}
94
124
  ```
@@ -167,12 +197,18 @@ const API_TOKEN: Token<ApiClient> = Symbol('ApiClient');
167
197
 
168
198
  @Provider({ name: 'ApiClientProvider' })
169
199
  class ApiClientProvider implements ApiClient {
170
- private baseUrl!: string;
171
- private apiKey!: string;
172
-
173
- async onInit() {
174
- this.baseUrl = process.env.API_URL!;
175
- this.apiKey = process.env.API_KEY!;
200
+ // No `onInit` hook — read env in the constructor and fail fast on missing values.
201
+ private readonly baseUrl: string;
202
+ private readonly apiKey: string;
203
+
204
+ constructor() {
205
+ const baseUrl = process.env.API_URL;
206
+ const apiKey = process.env.API_KEY;
207
+ if (!baseUrl || !apiKey) {
208
+ throw new Error('ApiClientProvider: API_URL and API_KEY must be set');
209
+ }
210
+ this.baseUrl = baseUrl;
211
+ this.apiKey = apiKey;
176
212
  }
177
213
 
178
214
  async get(path: string) {
@@ -206,12 +242,15 @@ class CacheProvider extends Map<string, unknown> {
206
242
 
207
243
  ## Provider Lifecycle
208
244
 
209
- | Method | When Called | Use For |
210
- | ------------- | ----------------------- | -------------------------------- |
211
- | `onInit()` | Server startup (async) | Open connections, load config |
212
- | `onDestroy()` | Server shutdown (async) | Close connections, flush buffers |
245
+ `@Provider` classes have **no** `onInit` / `onDestroy` lifecycle hooks. Choose the right setup pattern for your provider:
246
+
247
+ | Setup need | Pattern | Cleanup |
248
+ | ------------------------------------------ | --------------------------------------------------------------------- | ------------------------------------------------------- |
249
+ | Sync — read env, build a Map, etc. | `@Provider({ name })` + constructor (throw on missing config) | None / GC (or expose a `close()` and call from host) |
250
+ | Async — open a pool, fetch a remote schema | `AsyncProvider({ provide, name, scope, useFactory })` factory binding | Expose `close()`/`stop()`; framework dispose runs first |
251
+ | Singleton with no setup (e.g., a `Map`) | `@Provider({ name })` on the class | None |
213
252
 
214
- Providers are initialized in dependency order if Provider A depends on Provider B, B initializes first.
253
+ `AsyncProvider` factories are awaited in dependency order before any tool can resolve the bound token, so async setup completes before user code runs.
215
254
 
216
255
  ## Nx Generator
217
256
 
@@ -231,48 +270,49 @@ frontmcp dev
231
270
 
232
271
  ## Common Patterns
233
272
 
234
- | Pattern | Correct | Incorrect | Why |
235
- | ------------------ | ---------------------------------------------------------------------- | --------------------------------------------- | --------------------------------------------------------------------------------- |
236
- | Token definition | `const DB: Token<DbService> = Symbol('DbService')` (typed Symbol) | `const DB = 'database'` (string literal) | Typed `Token<T>` enables compile-time type checking on `this.get()` |
237
- | DI resolution | `this.get(TOKEN)` with error handling | `this.tryGet(TOKEN)!` with non-null assertion | `get` throws a clear `DependencyNotFoundError`; non-null assertions hide failures |
238
- | Lifecycle | Use `onInit()` for async setup, `onDestroy()` for cleanup | Initializing connections in the constructor | Constructor runs synchronously; `onInit()` supports async operations |
239
- | Registration scope | Register at `@App` level for app-scoped, `@FrontMcp` for server-scoped | Registering same provider in multiple apps | Server-scoped providers are shared; duplicating causes multiple instances |
240
- | Config provider | `readonly` properties from `process.env` | Mutable properties that change at runtime | Providers are singletons; mutable state can cause race conditions |
273
+ | Pattern | Correct | Incorrect | Why |
274
+ | ------------------ | ---------------------------------------------------------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------- |
275
+ | Token definition | `const DB: Token<DbService> = Symbol('DbService')` (typed Symbol) | `const DB = 'database'` (string literal) | Typed `Token<T>` enables compile-time type checking on `this.get()` |
276
+ | DI resolution | `this.get(TOKEN)` with error handling | `this.tryGet(TOKEN)!` with non-null assertion | `get` throws a clear `DependencyNotFoundError`; non-null assertions hide failures |
277
+ | Lifecycle | `AsyncProvider({ useFactory })` for async setup; constructor for sync | Using `onInit()` / `onDestroy()` lifecycle hooks | `@Provider` has no lifecycle hooks; `AsyncProvider` factories are awaited before resolution |
278
+ | Registration scope | Register at `@App` level for app-scoped, `@FrontMcp` for server-scoped | Registering same provider in multiple apps | Server-scoped providers are shared; duplicating causes multiple instances |
279
+ | Config provider | `readonly` properties from `process.env` | Mutable properties that change at runtime | Providers are singletons; mutable state can cause race conditions |
241
280
 
242
281
  ## Verification Checklist
243
282
 
244
283
  ### Configuration
245
284
 
246
- - [ ] Provider class has `@Provider` decorator with `name`
285
+ - [ ] Provider class has `@Provider` decorator with `name` (or factory uses `AsyncProvider`)
247
286
  - [ ] Token is defined with `Token<T>` using a `Symbol` and typed interface
248
- - [ ] Provider is registered in `providers` array of `@App` or `@FrontMcp`
249
- - [ ] `onInit()` handles async setup (DB connections, API clients)
250
- - [ ] `onDestroy()` cleans up resources (close connections, flush buffers)
287
+ - [ ] Provider (class or `AsyncProvider` factory) is registered in `providers` array of `@App` or `@FrontMcp`
288
+ - [ ] Sync setup happens in the constructor (throws fast on missing config)
289
+ - [ ] Async setup uses `AsyncProvider({ useFactory })`; the framework awaits it before resolution
251
290
 
252
291
  ### Runtime
253
292
 
254
293
  - [ ] Server starts without provider initialization errors
255
294
  - [ ] `this.get(TOKEN)` resolves the provider in tools, resources, and agents
256
295
  - [ ] Provider is a singleton (same instance across all contexts)
257
- - [ ] Server shutdown calls `onDestroy()` and cleans up resources
296
+ - [ ] Resource-owning providers expose an explicit `close()` / `stop()` method that the host calls before `server.dispose()`
258
297
  - [ ] Missing provider throws `DependencyNotFoundError` with a clear message
259
298
 
260
299
  ## Troubleshooting
261
300
 
262
- | Problem | Cause | Solution |
263
- | ------------------------------------ | --------------------------------------------------- | ---------------------------------------------------------------------- |
264
- | `DependencyNotFoundError` at runtime | Provider not registered in scope | Add provider to `providers` array in `@App` or `@FrontMcp` |
265
- | Provider `onInit()` fails at startup | Missing environment variable or unreachable service | Check environment variables and service connectivity before starting |
266
- | Multiple instances of same provider | Registered in multiple apps instead of server level | Move to `@FrontMcp` `providers` for shared, server-scoped access |
267
- | Type mismatch on `this.get(TOKEN)` | Token typed with wrong interface | Ensure `Token<T>` generic matches the provider's implemented interface |
268
- | Provider not destroyed on shutdown | Missing `onDestroy()` method | Implement `onDestroy()` to close connections and release resources |
301
+ | Problem | Cause | Solution |
302
+ | -------------------------------------- | ------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
303
+ | `DependencyNotFoundError` at runtime | Provider not registered in scope | Add provider (class or `AsyncProvider` factory) to `providers` array in `@App` or `@FrontMcp` |
304
+ | Provider constructor throws at startup | Missing environment variable or unreachable service | Validate env in the constructor; restart with the missing config supplied |
305
+ | `AsyncProvider` factory rejects | Async setup error (DB unreachable, schema fetch failed) | The factory error aborts boot fix the dependency or wrap with retry inside `useFactory` |
306
+ | Multiple instances of same provider | Registered in multiple apps instead of server level | Move to `@FrontMcp` `providers` for shared, server-scoped access |
307
+ | Type mismatch on `this.get(TOKEN)` | Token typed with wrong interface | Ensure `Token<T>` generic matches the provider's implemented interface |
308
+ | Resources leak on shutdown | No explicit cleanup method exposed | Add a `close()` / `stop()` method and call it from the host before `server.dispose()` |
269
309
 
270
310
  ## Examples
271
311
 
272
- | Example | Level | Description |
273
- | ------------------------------------------------------------------------------------- | ------------ | ----------------------------------------------------------------------------------------------------- |
274
- | [`basic-database-provider`](../examples/create-provider/basic-database-provider.md) | Basic | A provider that manages a database connection pool with `onInit()` and `onDestroy()` lifecycle hooks. |
275
- | [`config-and-api-providers`](../examples/create-provider/config-and-api-providers.md) | Intermediate | A configuration provider with readonly environment settings and an HTTP API client provider. |
312
+ | Example | Level | Description |
313
+ | ------------------------------------------------------------------------------------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------- |
314
+ | [`basic-database-provider`](../examples/create-provider/basic-database-provider.md) | Basic | A provider that manages a database connection pool, bound through `AsyncProvider({ useFactory })` so the pool is opened before any tool runs. |
315
+ | [`config-and-api-providers`](../examples/create-provider/config-and-api-providers.md) | Intermediate | A configuration provider with readonly environment settings and an HTTP API client provider. |
276
316
 
277
317
  > See all examples in [`examples/create-provider/`](../examples/create-provider/)
278
318
 
@@ -47,8 +47,8 @@ The `@Resource` decorator accepts:
47
47
  Create a class extending `ResourceContext` and implement `execute(uri, params)`. It must return a `ReadResourceResult`.
48
48
 
49
49
  ```typescript
50
- import { Resource, ResourceContext } from '@frontmcp/sdk';
51
50
  import { ReadResourceResult } from '@frontmcp/protocol';
51
+ import { Resource, ResourceContext } from '@frontmcp/sdk';
52
52
 
53
53
  @Resource({
54
54
  name: 'app-config',
@@ -156,8 +156,8 @@ The `@ResourceTemplate` decorator accepts:
156
156
  Use `@ResourceTemplate` with `uriTemplate` instead of `uri`. Type the `ResourceContext` generic parameter to get typed `params`.
157
157
 
158
158
  ```typescript
159
- import { ResourceTemplate, ResourceContext } from '@frontmcp/sdk';
160
159
  import { ReadResourceResult } from '@frontmcp/protocol';
160
+ import { ResourceContext, ResourceTemplate } from '@frontmcp/sdk';
161
161
 
162
162
  @ResourceTemplate({
163
163
  name: 'user-profile',
@@ -400,7 +400,7 @@ class CachedDataResource extends ResourceContext<{ key: string }> {
400
400
  Add resource classes (or function-style resources) to the `resources` array in `@FrontMcp` or `@App`.
401
401
 
402
402
  ```typescript
403
- import { FrontMcp, App } from '@frontmcp/sdk';
403
+ import { App, FrontMcp } from '@frontmcp/sdk';
404
404
 
405
405
  @App({
406
406
  name: 'my-app',
@@ -380,7 +380,7 @@ class AdminProceduresSkill extends SkillContext {}
380
380
  Add skill classes (or function-style skills) to the `skills` array in `@FrontMcp` or `@App`.
381
381
 
382
382
  ```typescript
383
- import { FrontMcp, App } from '@frontmcp/sdk';
383
+ import { App, FrontMcp } from '@frontmcp/sdk';
384
384
 
385
385
  @App({
386
386
  name: 'standards-app',
@@ -472,7 +472,7 @@ The class generator creates the skill file, spec file, and updates barrel export
472
472
  ## Complete Example: Project Onboarding Skill
473
473
 
474
474
  ```typescript
475
- import { Skill, SkillContext, FrontMcp, App, skill, skillDir } from '@frontmcp/sdk';
475
+ import { App, FrontMcp, Skill, skill, SkillContext, skillDir } from '@frontmcp/sdk';
476
476
 
477
477
  // Class-based instruction-only skill
478
478
  @Skill({
@@ -31,7 +31,7 @@ Tools are the primary way to expose executable actions to AI clients in the MCP
31
31
 
32
32
  ## Class-Based Pattern
33
33
 
34
- Create a class extending `ToolContext<In, Out>` and implement the `execute(input: In): Promise<Out>` method. The `@Tool` decorator requires at minimum a `name` and an `inputSchema`.
34
+ Create a class extending `ToolContext` and implement the `execute(input)` method. The `@Tool` decorator requires at minimum a `name` and an `inputSchema`. Do **not** parameterize `ToolContext` with explicit generics — the input/output types are inferred automatically from the `@Tool` decorator.
35
35
 
36
36
  ```typescript
37
37
  import { Tool, ToolContext, z } from '@frontmcp/sdk';
@@ -63,7 +63,7 @@ class GreetUserTool extends ToolContext {
63
63
  - `this.mark(stage)` -- set the active execution stage for debugging/tracking
64
64
  - `this.fetch(input, init?)` -- HTTP fetch with context propagation
65
65
  - `this.notify(message, level?)` -- send a log-level notification to the client
66
- - `this.respondProgress(value, total?)` -- send a progress notification to the client
66
+ - `this.progress(progress, total?, message?)` -- send a progress notification to the client (returns `Promise<boolean>`)
67
67
 
68
68
  **Properties:**
69
69
 
@@ -116,7 +116,7 @@ The `execute()` parameter type must match the inferred output of `z.object(input
116
116
 
117
117
  1. **Output validation** -- Prevents data leaks by ensuring your tool only returns fields you explicitly declare. Without `outputSchema`, any data in the return value passes through unvalidated, risking accidental exposure of sensitive fields (internal IDs, tokens, PII).
118
118
  2. **CodeCall plugin compatibility** -- The CodeCall plugin uses `outputSchema` to understand what a tool returns, enabling correct VM-based orchestration and pass-by-reference. Tools without `outputSchema` degrade CodeCall's ability to chain results.
119
- 3. **Type safety** -- The `Out` generic on `ToolContext<In, Out>` is inferred from `outputSchema`, giving you compile-time guarantees that `execute()` returns the correct shape.
119
+ 3. **Type safety** -- `ToolContext` infers the output type from `outputSchema` automatically (no explicit generics needed), giving you compile-time guarantees that `execute()` returns the correct shape.
120
120
 
121
121
  ```typescript
122
122
  @Tool({
@@ -159,7 +159,7 @@ class GetWeatherTool extends ToolContext {
159
159
 
160
160
  ### Typed Output Patterns
161
161
 
162
- The `Out` generic on `ToolContext<InSchema, OutSchema, In, Out>` is inferred from `outputSchema`. You can wire the generics explicitly for full type safety no `as any` casts needed:
162
+ `ToolContext` infers both input and output types from the `@Tool` decorator's `inputSchema` / `outputSchema`. Do not pass explicit generics the inference is automatic and gives you full type safety with no `as any` casts:
163
163
 
164
164
  ```typescript
165
165
  const inputSchema = {
@@ -328,7 +328,7 @@ this.fail(new ResourceNotFoundError(`Record ${input.id}`));
328
328
 
329
329
  ## Progress and Notifications
330
330
 
331
- Use `this.notify(message, level?)` to send log-level notifications and `this.respondProgress(value, total?)` to send progress updates to the client.
331
+ Use `this.notify(message, level?)` to send log-level notifications and `this.progress(progress, total?, message?)` to send progress updates to the client. `this.progress()` returns a `Promise<boolean>` indicating whether the notification was sent (`false` if no progress token was provided in the request).
332
332
 
333
333
  ```typescript
334
334
  @Tool({
@@ -346,7 +346,7 @@ class BatchProcessTool extends ToolContext {
346
346
  this.mark('processing');
347
347
  const results: string[] = [];
348
348
  for (let i = 0; i < input.items.length; i++) {
349
- await this.respondProgress(i + 1, input.items.length);
349
+ await this.progress(i + 1, input.items.length, `Processing item ${i + 1}`);
350
350
  const result = await this.processItem(input.items[i]);
351
351
  results.push(result);
352
352
  }
@@ -421,7 +421,7 @@ const AddNumbers = tool({
421
421
  });
422
422
  ```
423
423
 
424
- The callback receives `(input, ctx)` where `ctx` provides access to the same context methods (`get`, `tryGet`, `fail`, `mark`, `fetch`, `notify`, `respondProgress`).
424
+ The callback receives `(input, ctx)` where `ctx` provides access to the same context methods (`get`, `tryGet`, `fail`, `mark`, `fetch`, `notify`, `progress`).
425
425
 
426
426
  Register it the same way as a class tool: `tools: [AddNumbers]`.
427
427
 
@@ -44,7 +44,7 @@ Create a class decorated with `@Workflow`. The decorator requires `name` and `st
44
44
  | `webhook` | `WebhookConfig` | No | -- | Webhook configuration (when trigger is `'webhook'`) |
45
45
  | `timeout` | `number` | No | `600000` (10 min) | Maximum total workflow execution time in milliseconds |
46
46
  | `maxConcurrency` | `number` | No | `5` | Maximum number of steps running in parallel |
47
- | `permissions` | `WorkflowPermissions` | No | -- | Access control configuration |
47
+ | `permissions` | `WorkflowPermission[]` | No | -- | Array of permission rules (one per action) |
48
48
 
49
49
  ### WorkflowStep Fields
50
50
 
@@ -562,11 +562,7 @@ class BuildArtifactJob extends JobContext {
562
562
  url: z.string().url(),
563
563
  },
564
564
  retry: { maxAttempts: 3, backoffMs: 5000, backoffMultiplier: 2, maxBackoffMs: 30000 },
565
- permissions: {
566
- actions: ['execute'],
567
- roles: ['admin', 'deployer'],
568
- scopes: ['deploy:write'],
569
- },
565
+ permissions: [{ action: 'execute', roles: ['admin', 'deployer'], scopes: ['deploy:write'] }],
570
566
  })
571
567
  class DeployArtifactJob extends JobContext {
572
568
  async execute(input: { artifactUrl: string; environment: string }) {
@@ -609,10 +605,12 @@ class NotifyTeamJob extends JobContext {
609
605
  },
610
606
  timeout: 900000, // 15 minutes
611
607
  maxConcurrency: 3,
612
- permissions: {
613
- actions: ['create', 'read', 'execute', 'list'],
614
- roles: ['admin', 'ci-bot'],
615
- },
608
+ permissions: [
609
+ { action: 'execute', roles: ['admin', 'ci-bot'] },
610
+ { action: 'create', roles: ['admin', 'ci-bot'] },
611
+ { action: 'read', roles: ['admin', 'ci-bot'] },
612
+ { action: 'list', roles: ['admin', 'ci-bot'] },
613
+ ],
616
614
  steps: [
617
615
  {
618
616
  id: 'checkout',