@frontmcp/skills 1.1.2 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/catalog/TEMPLATE.md +16 -11
- package/catalog/frontmcp-authorities/SKILL.md +116 -11
- package/catalog/frontmcp-authorities/references/authority-profiles.md +39 -36
- package/catalog/frontmcp-authorities/references/claims-mapping.md +7 -0
- package/catalog/frontmcp-authorities/references/custom-evaluators.md +63 -14
- package/catalog/frontmcp-channels/SKILL.md +36 -0
- package/catalog/frontmcp-channels/examples/channel-sources/file-watcher.md +8 -2
- package/catalog/frontmcp-channels/examples/channel-sources/replay-buffer.md +111 -30
- package/catalog/frontmcp-channels/examples/channel-two-way/whatsapp-bridge.md +45 -3
- package/catalog/frontmcp-channels/references/channel-sources.md +11 -3
- package/catalog/frontmcp-channels/references/channel-two-way.md +60 -89
- package/catalog/frontmcp-config/SKILL.md +111 -8
- package/catalog/frontmcp-config/examples/configure-auth-modes/local-self-signed-tokens.md +4 -4
- package/catalog/frontmcp-config/examples/configure-auth-modes/remote-enterprise-oauth.md +7 -1
- package/catalog/frontmcp-config/examples/configure-deployment-targets/distributed-ha-config.md +1 -1
- package/catalog/frontmcp-config/examples/configure-deployment-targets/json-schema-ide-support.md +1 -1
- package/catalog/frontmcp-config/examples/configure-deployment-targets/multi-target-with-security.md +12 -9
- package/catalog/frontmcp-config/examples/configure-http/cors-restricted-origins.md +2 -2
- package/catalog/frontmcp-config/examples/configure-http/entry-path-reverse-proxy.md +1 -1
- package/catalog/frontmcp-config/examples/configure-security-headers/csp-report-only.md +1 -1
- package/catalog/frontmcp-config/examples/configure-security-headers/full-production-headers.md +1 -1
- package/catalog/frontmcp-config/examples/configure-skills-http/audit-log-basic.md +76 -0
- package/catalog/frontmcp-config/examples/configure-skills-http/audit-log-redis.md +116 -0
- package/catalog/frontmcp-config/examples/configure-skills-http/inject-instructions.md +59 -0
- package/catalog/frontmcp-config/references/configure-auth-modes.md +5 -5
- package/catalog/frontmcp-config/references/configure-deployment-targets.md +27 -24
- package/catalog/frontmcp-config/references/configure-http.md +14 -10
- package/catalog/frontmcp-config/references/configure-security-headers.md +2 -2
- package/catalog/frontmcp-config/references/configure-session.md +25 -25
- package/catalog/frontmcp-config/references/configure-skills-http.md +157 -0
- package/catalog/frontmcp-config/references/configure-throttle.md +1 -1
- package/catalog/frontmcp-config/references/configure-transport.md +2 -2
- package/catalog/frontmcp-deployment/SKILL.md +112 -9
- package/catalog/frontmcp-deployment/examples/build-for-browser/browser-build-with-custom-entry.md +23 -11
- package/catalog/frontmcp-deployment/examples/build-for-browser/browser-crypto-and-storage.md +44 -17
- package/catalog/frontmcp-deployment/examples/build-for-browser/react-provider-setup.md +53 -21
- package/catalog/frontmcp-deployment/examples/build-for-cli/cli-binary-build.md +1 -1
- package/catalog/frontmcp-deployment/examples/build-for-cli/unix-socket-daemon.md +1 -1
- package/catalog/frontmcp-deployment/examples/build-for-mcpb/mcpb-bundle-build.md +1 -1
- package/catalog/frontmcp-deployment/examples/build-for-sdk/connect-openai.md +1 -1
- package/catalog/frontmcp-deployment/examples/build-for-sdk/multi-platform-connect.md +1 -1
- package/catalog/frontmcp-deployment/examples/deploy-to-cloudflare/basic-worker-deploy.md +7 -8
- package/catalog/frontmcp-deployment/examples/deploy-to-cloudflare/worker-custom-domain.md +8 -6
- package/catalog/frontmcp-deployment/examples/deploy-to-cloudflare/worker-with-kv-storage.md +5 -4
- package/catalog/frontmcp-deployment/examples/deploy-to-lambda/cdk-deployment.md +8 -5
- package/catalog/frontmcp-deployment/examples/deploy-to-lambda/lambda-handler-with-cors.md +20 -18
- package/catalog/frontmcp-deployment/examples/deploy-to-lambda/sam-template-basic.md +8 -5
- package/catalog/frontmcp-deployment/examples/deploy-to-node/docker-compose-with-redis.md +3 -3
- package/catalog/frontmcp-deployment/examples/deploy-to-node/pm2-with-nginx.md +1 -1
- package/catalog/frontmcp-deployment/examples/deploy-to-node/resource-limits.md +2 -2
- package/catalog/frontmcp-deployment/examples/deploy-to-node-dockerfile/basic-multistage-dockerfile.md +2 -2
- package/catalog/frontmcp-deployment/examples/deploy-to-node-dockerfile/secure-nonroot-dockerfile.md +1 -1
- package/catalog/frontmcp-deployment/examples/deploy-to-vercel/vercel-mcp-endpoint-test.md +23 -21
- package/catalog/frontmcp-deployment/examples/deploy-to-vercel/vercel-with-kv.md +25 -22
- package/catalog/frontmcp-deployment/examples/deploy-to-vercel/vercel-with-skills-cache.md +23 -30
- package/catalog/frontmcp-deployment/examples/deploy-to-vercel-config/minimal-vercel-config.md +52 -28
- package/catalog/frontmcp-deployment/examples/deploy-to-vercel-config/vercel-config-with-security-headers.md +32 -55
- package/catalog/frontmcp-deployment/examples/mcp-client-integration/http-remote.md +9 -0
- package/catalog/frontmcp-deployment/references/build-for-browser.md +40 -17
- package/catalog/frontmcp-deployment/references/build-for-cli.md +8 -8
- package/catalog/frontmcp-deployment/references/deploy-to-cloudflare.md +43 -24
- package/catalog/frontmcp-deployment/references/deploy-to-lambda.md +36 -25
- package/catalog/frontmcp-deployment/references/deploy-to-node-dockerfile.md +56 -14
- package/catalog/frontmcp-deployment/references/deploy-to-node.md +9 -6
- package/catalog/frontmcp-deployment/references/deploy-to-vercel-config.md +57 -58
- package/catalog/frontmcp-deployment/references/deploy-to-vercel.md +49 -59
- package/catalog/frontmcp-deployment/references/mcp-client-integration.md +2 -0
- package/catalog/frontmcp-development/SKILL.md +186 -11
- package/catalog/frontmcp-development/examples/create-agent/custom-multi-pass-agent.md +1 -1
- package/catalog/frontmcp-development/examples/create-agent/nested-agents-with-swarm.md +30 -27
- package/catalog/frontmcp-development/examples/create-job/job-with-permissions.md +13 -8
- package/catalog/frontmcp-development/examples/create-provider/basic-database-provider.md +33 -23
- package/catalog/frontmcp-development/examples/create-provider/config-and-api-providers.md +19 -10
- package/catalog/frontmcp-development/examples/create-tool/tool-with-rate-limiting-and-progress.md +3 -3
- package/catalog/frontmcp-development/examples/create-workflow/webhook-triggered-workflow.md +6 -4
- package/catalog/frontmcp-development/examples/decorators-guide/agent-skill-job-workflow.md +1 -1
- package/catalog/frontmcp-development/examples/decorators-guide/basic-server-with-app-and-tools.md +13 -8
- package/catalog/frontmcp-development/examples/decorators-guide/multi-app-with-plugins-and-providers.md +50 -23
- package/catalog/frontmcp-development/references/create-agent.md +47 -30
- package/catalog/frontmcp-development/references/create-job.md +69 -54
- package/catalog/frontmcp-development/references/create-plugin-hooks.md +45 -28
- package/catalog/frontmcp-development/references/create-plugin.md +10 -8
- package/catalog/frontmcp-development/references/create-prompt.md +3 -3
- package/catalog/frontmcp-development/references/create-provider.md +91 -51
- package/catalog/frontmcp-development/references/create-resource.md +3 -3
- package/catalog/frontmcp-development/references/create-skill.md +2 -2
- package/catalog/frontmcp-development/references/create-tool.md +7 -7
- package/catalog/frontmcp-development/references/create-workflow.md +8 -10
- package/catalog/frontmcp-development/references/decorators-guide.md +92 -56
- package/catalog/frontmcp-development/references/official-plugins.md +4 -3
- package/catalog/frontmcp-development/references/openapi-adapter.md +1 -1
- package/catalog/frontmcp-extensibility/SKILL.md +70 -10
- package/catalog/frontmcp-extensibility/examples/skill-audit-log/custom-store.md +197 -0
- package/catalog/frontmcp-extensibility/examples/skill-audit-log/verify-chain.md +68 -0
- package/catalog/frontmcp-extensibility/examples/vectoriadb/product-catalog-search.md +3 -5
- package/catalog/frontmcp-extensibility/examples/vectoriadb/semantic-search-with-persistence.md +4 -11
- package/catalog/frontmcp-extensibility/examples/vectoriadb/tfidf-keyword-search.md +41 -30
- package/catalog/frontmcp-extensibility/references/skill-audit-log.md +233 -0
- package/catalog/frontmcp-extensibility/references/vectoriadb.md +73 -63
- package/catalog/frontmcp-guides/SKILL.md +84 -27
- package/catalog/frontmcp-guides/examples/example-knowledge-base/agent-and-plugin.md +72 -62
- package/catalog/frontmcp-guides/examples/example-knowledge-base/vector-search-and-resources.md +32 -43
- package/catalog/frontmcp-guides/examples/example-task-manager/auth-and-crud-tools.md +24 -17
- package/catalog/frontmcp-guides/examples/example-task-manager/authenticated-e2e-tests.md +23 -21
- package/catalog/frontmcp-guides/examples/example-task-manager/redis-provider-with-di.md +47 -39
- package/catalog/frontmcp-guides/examples/example-weather-api/server-and-app-setup.md +16 -6
- package/catalog/frontmcp-guides/examples/example-weather-api/unit-and-e2e-tests.md +9 -8
- package/catalog/frontmcp-guides/references/example-knowledge-base.md +192 -265
- package/catalog/frontmcp-guides/references/example-task-manager.md +60 -54
- package/catalog/frontmcp-guides/references/example-weather-api.md +22 -24
- package/catalog/frontmcp-observability/SKILL.md +66 -2
- package/catalog/frontmcp-observability/examples/telemetry-api/skill-counters.md +100 -0
- package/catalog/frontmcp-observability/examples/tracing-setup/production-tracing.md +7 -2
- package/catalog/frontmcp-observability/examples/vendor-integrations/coralogix-setup.md +6 -2
- package/catalog/frontmcp-observability/references/telemetry-api.md +72 -8
- package/catalog/frontmcp-observability/references/testing-observability.md +33 -49
- package/catalog/frontmcp-observability/references/tracing-setup.md +12 -5
- package/catalog/frontmcp-observability/references/vendor-integrations.md +46 -1
- package/catalog/frontmcp-production-readiness/SKILL.md +134 -3
- package/catalog/frontmcp-production-readiness/examples/common-checklist/caching-and-performance.md +57 -36
- package/catalog/frontmcp-production-readiness/examples/common-checklist/observability-setup.md +1 -1
- package/catalog/frontmcp-production-readiness/examples/common-checklist/security-hardening.md +102 -6
- package/catalog/frontmcp-production-readiness/examples/production-cli-daemon/daemon-socket-config.md +2 -1
- package/catalog/frontmcp-production-readiness/examples/production-cli-daemon/graceful-shutdown-cleanup.md +66 -58
- package/catalog/frontmcp-production-readiness/examples/production-cli-daemon/security-and-permissions.md +5 -3
- package/catalog/frontmcp-production-readiness/examples/production-cloudflare/durable-objects-state.md +2 -1
- package/catalog/frontmcp-production-readiness/examples/production-cloudflare/wrangler-config.md +55 -76
- package/catalog/frontmcp-production-readiness/examples/production-lambda/cold-start-connection-reuse.md +43 -40
- package/catalog/frontmcp-production-readiness/examples/production-lambda/sam-template.md +63 -94
- package/catalog/frontmcp-production-readiness/examples/production-lambda/scaling-and-monitoring.md +28 -18
- package/catalog/frontmcp-production-readiness/examples/production-node-sdk/multi-instance-cleanup.md +29 -14
- package/catalog/frontmcp-production-readiness/examples/production-node-server/graceful-shutdown.md +58 -42
- package/catalog/frontmcp-production-readiness/examples/production-node-server/redis-session-scaling.md +5 -2
- package/catalog/frontmcp-production-readiness/examples/production-vercel/cold-start-optimization.md +41 -24
- package/catalog/frontmcp-production-readiness/examples/production-vercel/vercel-edge-config.md +56 -65
- package/catalog/frontmcp-production-readiness/references/common-checklist.md +17 -5
- package/catalog/frontmcp-production-readiness/references/production-cli-daemon.md +5 -5
- package/catalog/frontmcp-production-readiness/references/production-cloudflare.md +5 -5
- package/catalog/frontmcp-production-readiness/references/production-lambda.md +5 -5
- package/catalog/frontmcp-production-readiness/references/production-node-sdk.md +5 -5
- package/catalog/frontmcp-production-readiness/references/production-node-server.md +1 -1
- package/catalog/frontmcp-production-readiness/references/production-vercel.md +5 -5
- package/catalog/frontmcp-setup/SKILL.md +88 -0
- package/catalog/frontmcp-setup/examples/project-structure-nx/nx-workspace-with-apps.md +10 -4
- package/catalog/frontmcp-setup/examples/project-structure-standalone/dev-workflow-commands.md +21 -8
- package/catalog/frontmcp-setup/examples/readme-guide/node-server-readme.md +3 -3
- package/catalog/frontmcp-setup/references/multi-app-composition.md +4 -3
- package/catalog/frontmcp-setup/references/project-structure-nx.md +15 -6
- package/catalog/frontmcp-setup/references/project-structure-standalone.md +18 -15
- package/catalog/frontmcp-setup/references/readme-guide.md +1 -1
- package/catalog/frontmcp-setup/references/setup-project.md +19 -5
- package/catalog/frontmcp-setup/references/setup-redis.md +27 -39
- package/catalog/frontmcp-setup/references/setup-sqlite.md +25 -18
- package/catalog/frontmcp-testing/SKILL.md +102 -15
- package/catalog/frontmcp-testing/examples/setup-testing/unit-test-tool-resource-prompt.md +3 -3
- package/catalog/frontmcp-testing/examples/test-auth/oauth-flow-test.md +50 -39
- package/catalog/frontmcp-testing/examples/test-auth/role-based-access-test.md +52 -29
- package/catalog/frontmcp-testing/examples/test-auth/token-factory-test.md +37 -20
- package/catalog/frontmcp-testing/examples/test-direct-client/basic-create-test.md +25 -15
- package/catalog/frontmcp-testing/examples/test-direct-client/openai-claude-format-test.md +27 -21
- package/catalog/frontmcp-testing/examples/test-e2e-handler/basic-e2e-test.md +29 -20
- package/catalog/frontmcp-testing/examples/test-e2e-handler/manual-client-with-transport.md +5 -3
- package/catalog/frontmcp-testing/examples/test-e2e-handler/tool-call-and-error-e2e.md +35 -26
- package/catalog/frontmcp-testing/examples/test-tool-unit/basic-tool-test.md +8 -3
- package/catalog/frontmcp-testing/examples/test-tool-unit/schema-validation-test.md +4 -1
- package/catalog/frontmcp-testing/examples/test-tool-unit/tool-error-handling-test.md +6 -3
- package/catalog/frontmcp-testing/references/setup-testing.md +35 -39
- package/catalog/frontmcp-testing/references/test-auth.md +86 -43
- package/catalog/frontmcp-testing/references/test-browser-build.md +1 -1
- package/catalog/frontmcp-testing/references/test-direct-client.md +29 -19
- package/catalog/frontmcp-testing/references/test-e2e-handler.md +31 -19
- package/catalog/frontmcp-testing/references/test-tool-unit.md +6 -2
- package/catalog/skills-manifest.json +428 -339
- package/package.json +1 -1
- package/src/manifest.d.ts +13 -0
- 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
|
|
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
|
|
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: '
|
|
55
|
-
class
|
|
56
|
-
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
|
71
|
-
//
|
|
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: [
|
|
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: [
|
|
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
|
-
|
|
171
|
-
private
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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
|
-
|
|
210
|
-
|
|
211
|
-
|
|
|
212
|
-
|
|
|
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
|
-
|
|
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
|
|
235
|
-
| ------------------ | ---------------------------------------------------------------------- |
|
|
236
|
-
| Token definition | `const DB: Token<DbService> = Symbol('DbService')` (typed Symbol) | `const DB = 'database'` (string literal)
|
|
237
|
-
| DI resolution | `this.get(TOKEN)` with error handling | `this.tryGet(TOKEN)!` with non-null assertion
|
|
238
|
-
| Lifecycle |
|
|
239
|
-
| Registration scope | Register at `@App` level for app-scoped, `@FrontMcp` for server-scoped | Registering same provider in multiple apps
|
|
240
|
-
| Config provider | `readonly` properties from `process.env` | Mutable properties that change at runtime
|
|
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
|
-
- [ ]
|
|
250
|
-
- [ ] `
|
|
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
|
-
- [ ]
|
|
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
|
|
263
|
-
|
|
|
264
|
-
| `DependencyNotFoundError` at runtime
|
|
265
|
-
| Provider
|
|
266
|
-
|
|
|
267
|
-
|
|
|
268
|
-
|
|
|
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
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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
|
|
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.
|
|
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** --
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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`, `
|
|
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` | `
|
|
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
|
-
|
|
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',
|