@frontmcp/skills 1.2.1 → 1.4.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.
- package/README.md +38 -29
- package/catalog/TEMPLATE.md +26 -0
- package/catalog/create-tool/SKILL.md +318 -0
- package/catalog/create-tool/examples/01-basic-class-tool.md +112 -0
- package/catalog/create-tool/examples/02-basic-function-tool.md +80 -0
- package/catalog/create-tool/examples/03-tool-with-zod-shape-output.md +78 -0
- package/catalog/create-tool/examples/04-tool-with-zod-schema-output.md +97 -0
- package/catalog/create-tool/examples/05-tool-with-primitive-output.md +93 -0
- package/catalog/create-tool/examples/06-tool-with-media-output.md +109 -0
- package/catalog/create-tool/examples/08-tool-with-provider-injection.md +110 -0
- package/catalog/create-tool/examples/09-tool-with-multiple-providers.md +107 -0
- package/catalog/create-tool/examples/11-tool-with-fetch.md +94 -0
- package/catalog/create-tool/examples/12-tool-with-fetch-and-retries.md +115 -0
- package/catalog/create-tool/examples/13-tool-with-single-auth-provider.md +85 -0
- package/catalog/create-tool/examples/14-tool-with-multiple-auth-providers.md +105 -0
- package/catalog/create-tool/examples/15-tool-with-credential-vault.md +115 -0
- package/catalog/create-tool/examples/16-tool-with-rate-limit.md +71 -0
- package/catalog/create-tool/examples/17-tool-with-concurrency-and-timeout.md +101 -0
- package/catalog/create-tool/examples/18-tool-with-progress-and-notify.md +96 -0
- package/catalog/create-tool/examples/19-tool-with-elicitation.md +102 -0
- package/catalog/create-tool/examples/20-tool-with-annotations.md +125 -0
- package/catalog/create-tool/examples/21-tool-with-availability-constraints.md +107 -0
- package/catalog/create-tool/examples/22-tool-with-ui-html-template.md +93 -0
- package/catalog/create-tool/examples/23-tool-with-ui-filesource-tsx.md +112 -0
- package/catalog/create-tool/examples/24-tool-with-ui-csp-and-bridge.md +127 -0
- package/catalog/create-tool/examples/25-tool-handing-off-to-job.md +143 -0
- package/catalog/create-tool/examples/26-tool-with-resource-link-output.md +94 -0
- package/catalog/create-tool/examples/27-tool-with-examples-metadata.md +90 -0
- package/catalog/create-tool/references/annotations.md +96 -0
- package/catalog/create-tool/references/auth-providers.md +167 -0
- package/catalog/create-tool/references/availability.md +106 -0
- package/catalog/create-tool/references/decorator-options.md +95 -0
- package/catalog/create-tool/references/derived-types.md +102 -0
- package/catalog/create-tool/references/elicitation.md +128 -0
- package/catalog/create-tool/references/error-handling.md +128 -0
- package/catalog/create-tool/references/execution-context.md +158 -0
- package/catalog/create-tool/references/file-layout.md +96 -0
- package/catalog/create-tool/references/function-style-builder.md +118 -0
- package/catalog/create-tool/references/input-schema.md +141 -0
- package/catalog/create-tool/references/output-schema.md +175 -0
- package/catalog/create-tool/references/quick-start.md +124 -0
- package/catalog/create-tool/references/registration.md +132 -0
- package/catalog/create-tool/references/remote-and-esm.md +68 -0
- package/catalog/create-tool/references/testing.md +59 -0
- package/catalog/create-tool/references/throttling.md +109 -0
- package/catalog/create-tool/references/ui-widgets.md +198 -0
- package/catalog/create-tool/rules/always-define-output-schema.md +77 -0
- package/catalog/create-tool/rules/derive-execute-types.md +57 -0
- package/catalog/create-tool/rules/input-schema-is-raw-shape.md +76 -0
- package/catalog/create-tool/rules/no-toolcontext-generics.md +50 -0
- package/catalog/create-tool/rules/no-try-catch-around-execute.md +79 -0
- package/catalog/create-tool/rules/register-in-app.md +76 -0
- package/catalog/create-tool/rules/snake-case-tool-names.md +45 -0
- package/catalog/create-tool/rules/use-this-fail-for-business-errors.md +75 -0
- package/catalog/create-tool/rules/widget-paths-anchor-with-import-meta-url.md +76 -0
- package/catalog/create-tool/rules/widget-resource-mode-host-detect.md +61 -0
- package/catalog/frontmcp-auth-ui/SKILL.md +146 -0
- package/catalog/frontmcp-auth-ui/examples/custom-auth-ui/login-slot.md +97 -0
- package/catalog/frontmcp-auth-ui/examples/custom-auth-ui/multi-step-auth-extra.md +133 -0
- package/catalog/frontmcp-auth-ui/references/custom-auth-ui.md +162 -0
- package/catalog/frontmcp-authorities/SKILL.md +55 -18
- package/catalog/frontmcp-authorities/references/authority-profiles.md +25 -1
- package/catalog/frontmcp-authorities/references/custom-evaluators.md +1 -1
- package/catalog/frontmcp-authorities/references/rbac-abac-rebac.md +9 -0
- package/catalog/frontmcp-channels/SKILL.md +7 -1
- package/catalog/frontmcp-config/SKILL.md +14 -7
- package/catalog/frontmcp-config/examples/configure-auth/local-credential-vault.md +94 -0
- package/catalog/frontmcp-config/examples/configure-auth/local-secure-store.md +138 -0
- package/catalog/frontmcp-config/examples/configure-auth/remote-oauth-with-vault.md +45 -23
- package/catalog/frontmcp-config/examples/configure-auth-modes/local-behind-tunnel.md +73 -0
- package/catalog/frontmcp-config/examples/configure-auth-modes/local-consent-enforcement.md +87 -0
- package/catalog/frontmcp-config/examples/configure-auth-modes/local-dcr-control.md +67 -0
- package/catalog/frontmcp-config/examples/configure-auth-modes/local-minimal.md +62 -0
- package/catalog/frontmcp-config/examples/configure-auth-modes/local-multi-provider-orchestration.md +93 -0
- package/catalog/frontmcp-config/examples/configure-auth-modes/local-self-signed-tokens.md +18 -20
- package/catalog/frontmcp-config/examples/configure-auth-modes/local-single-operator.md +66 -0
- package/catalog/frontmcp-config/examples/configure-auth-modes/remote-enterprise-oauth.md +37 -23
- package/catalog/frontmcp-config/examples/configure-http/custom-http-routes.md +98 -0
- package/catalog/frontmcp-config/examples/configure-skills-http/audit-log-redis.md +17 -9
- package/catalog/frontmcp-config/references/configure-auth-modes.md +86 -23
- package/catalog/frontmcp-config/references/configure-auth.md +296 -50
- package/catalog/frontmcp-config/references/configure-deployment-targets.md +84 -1
- package/catalog/frontmcp-config/references/configure-http.md +203 -14
- package/catalog/frontmcp-config/references/configure-session.md +14 -7
- package/catalog/frontmcp-deployment/SKILL.md +17 -15
- package/catalog/frontmcp-deployment/references/build-for-mcpb.md +1 -1
- package/catalog/frontmcp-deployment/references/deploy-manifest-yaml.md +308 -0
- package/catalog/frontmcp-deployment/references/deploy-to-cloudflare-skills-only.md +174 -0
- package/catalog/frontmcp-deployment/references/mcp-client-integration.md +145 -2
- package/catalog/frontmcp-development/SKILL.md +36 -50
- package/catalog/frontmcp-development/examples/create-provider/basic-database-provider.md +14 -0
- package/catalog/frontmcp-development/examples/create-provider/config-and-api-providers.md +85 -9
- package/catalog/frontmcp-development/references/create-job.md +45 -11
- package/catalog/frontmcp-development/references/create-provider.md +80 -8
- package/catalog/frontmcp-development/references/create-skill-with-tools.md +31 -0
- package/catalog/frontmcp-development/references/create-skill.md +45 -0
- package/catalog/frontmcp-development/references/decorators-guide.md +15 -15
- package/catalog/frontmcp-extensibility/SKILL.md +1 -1
- package/catalog/frontmcp-extensibility/examples/skill-audit-log/verify-chain.md +8 -6
- package/catalog/frontmcp-extensibility/references/skill-audit-log.md +7 -2
- package/catalog/frontmcp-guides/SKILL.md +8 -8
- package/catalog/frontmcp-observability/SKILL.md +16 -8
- package/catalog/frontmcp-observability/examples/metrics-endpoint/enable-metrics-endpoint.md +77 -0
- package/catalog/frontmcp-observability/references/metrics-endpoint.md +161 -0
- package/catalog/frontmcp-production-readiness/SKILL.md +1 -1
- package/catalog/frontmcp-production-readiness/examples/common-checklist/security-hardening.md +3 -2
- package/catalog/frontmcp-setup/SKILL.md +12 -12
- package/catalog/frontmcp-setup/examples/frontmcp-skills-usage/install-and-search-skills.md +19 -1
- package/catalog/frontmcp-setup/examples/multi-app-composition/per-app-auth-and-isolation.md +7 -4
- package/catalog/frontmcp-setup/references/frontmcp-skills-usage.md +260 -19
- package/catalog/frontmcp-setup/references/multi-app-composition.md +6 -5
- package/catalog/frontmcp-setup/references/setup-project.md +29 -0
- package/catalog/frontmcp-setup/references/setup-sqlite.md +68 -9
- package/catalog/frontmcp-testing/SKILL.md +26 -18
- package/catalog/frontmcp-testing/references/test-auth.md +24 -0
- package/catalog/skills-manifest.json +676 -146
- package/package.json +1 -1
- package/src/manifest.d.ts +72 -1
- package/src/manifest.js +4 -1
- package/src/manifest.js.map +1 -1
- package/catalog/frontmcp-development/examples/create-tool/basic-class-tool.md +0 -61
- package/catalog/frontmcp-development/examples/create-tool/tool-with-di-and-errors.md +0 -84
- package/catalog/frontmcp-development/examples/create-tool/tool-with-rate-limiting-and-progress.md +0 -92
- package/catalog/frontmcp-development/examples/create-tool-annotations/destructive-delete-tool.md +0 -92
- package/catalog/frontmcp-development/examples/create-tool-annotations/readonly-query-tool.md +0 -59
- package/catalog/frontmcp-development/examples/create-tool-output-schema-types/primitive-and-media-outputs.md +0 -101
- package/catalog/frontmcp-development/examples/create-tool-output-schema-types/zod-raw-shape-output.md +0 -62
- package/catalog/frontmcp-development/examples/create-tool-output-schema-types/zod-schema-advanced-output.md +0 -101
- package/catalog/frontmcp-development/references/create-tool-annotations.md +0 -48
- package/catalog/frontmcp-development/references/create-tool-output-schema-types.md +0 -71
- package/catalog/frontmcp-development/references/create-tool.md +0 -728
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: frontmcp-development
|
|
3
|
-
description: 'Use when
|
|
3
|
+
description: 'Use when building any FrontMCP server component other than a tool (for tools, use create-tool). Covers @Resource static resources and parameterized URI templates; @Prompt reusable prompts (RAG, multi-turn); @Provider singleton dependency-injection providers (database pools, API clients); @Agent autonomous LLM agents (Anthropic, OpenAI) and swarms; @Job background jobs (retry, progress, permissions) and @Workflow DAG pipelines; framework adapters and the OpenAPI adapter (turn OpenAPI 3.x specs into MCP tools with auth, polling, transforms); plugins, plugin lifecycle hooks (before / after / around / stage), and the official plugins; instruction-only skills and skills that reference tools; and the hierarchical decorator system from @FrontMcp down to @App. Triggers: create a resource, build a prompt, write a provider, add an agent, job, workflow, plugin, adapter, or OpenAPI integration.'
|
|
4
|
+
when_to_use: |
|
|
5
|
+
Trigger when creating or editing a non-tool FrontMCP component: a
|
|
6
|
+
*.resource.ts, *.prompt.ts, *.provider.ts, *.agent.ts, *.job.ts,
|
|
7
|
+
*.workflow.ts, *.plugin.ts, or *.skill.ts file, or adding @Resource, @Prompt,
|
|
8
|
+
@Provider, @Agent, @Job, @Workflow, a plugin, an adapter, or an OpenAPI
|
|
9
|
+
integration. For tools (*.tool.ts) use create-tool instead.
|
|
10
|
+
paths: '**/*.resource.ts, **/*.prompt.ts, **/*.provider.ts, **/*.agent.ts, **/*.job.ts, **/*.workflow.ts, **/*.plugin.ts, **/*.skill.ts'
|
|
4
11
|
tags: [router, development, tools, resources, prompts, agents, skills, guide]
|
|
5
12
|
category: development
|
|
6
13
|
targets: [all]
|
|
@@ -14,7 +21,7 @@ metadata:
|
|
|
14
21
|
|
|
15
22
|
# FrontMCP Development Router
|
|
16
23
|
|
|
17
|
-
Entry point for building MCP server components. This skill helps you find the right development
|
|
24
|
+
Entry point for building MCP server components. This skill helps you find the right development reference based on what you want to build. It does not teach implementation details itself — it routes you to the specific reference (under `references/`) that does.
|
|
18
25
|
|
|
19
26
|
## When to Use This Skill
|
|
20
27
|
|
|
@@ -26,7 +33,7 @@ Entry point for building MCP server components. This skill helps you find the ri
|
|
|
26
33
|
|
|
27
34
|
### Recommended
|
|
28
35
|
|
|
29
|
-
- Looking up the canonical name of a development
|
|
36
|
+
- Looking up the canonical name of a development reference to install or search
|
|
30
37
|
- Comparing component types to decide which fits your use case
|
|
31
38
|
- Understanding how tools, resources, prompts, agents, and skills relate to each other
|
|
32
39
|
|
|
@@ -36,7 +43,7 @@ Entry point for building MCP server components. This skill helps you find the ri
|
|
|
36
43
|
- You need to configure server settings, not build components (see `frontmcp-config`)
|
|
37
44
|
- You need to deploy or build, not develop (see `frontmcp-deployment`)
|
|
38
45
|
|
|
39
|
-
> **Decision:** Use this skill when you need to figure out WHAT to build.
|
|
46
|
+
> **Decision:** Use this skill when you need to figure out WHAT to build. Open the matching reference under `references/` directly when you already know.
|
|
40
47
|
|
|
41
48
|
## Prerequisites
|
|
42
49
|
|
|
@@ -46,40 +53,38 @@ Entry point for building MCP server components. This skill helps you find the ri
|
|
|
46
53
|
|
|
47
54
|
## Steps
|
|
48
55
|
|
|
49
|
-
This is a router skill. The "steps" here are how to choose the right
|
|
56
|
+
This is a router skill. The "steps" here are how to choose the right reference (a markdown file under `references/`), not how to implement a component.
|
|
50
57
|
|
|
51
58
|
1. **Identify the component type** using the Scenario Routing Table below.
|
|
52
|
-
2. **Open the matching
|
|
53
|
-
3. **Compose**, if needed: most non-trivial features need two or more components (e.g. tool + provider, resource + adapter). Read each
|
|
59
|
+
2. **Open the matching reference** (e.g. `references/create-tool.md`, `references/create-resource.md`) and follow its Steps section.
|
|
60
|
+
3. **Compose**, if needed: most non-trivial features need two or more components (e.g. tool + provider, resource + adapter). Read each reference independently before wiring them together.
|
|
54
61
|
4. **Test before integration** (`frontmcp-testing`) — every component type has a unit-test recipe.
|
|
55
62
|
|
|
56
63
|
## Scenario Routing Table
|
|
57
64
|
|
|
58
|
-
| Scenario
|
|
59
|
-
|
|
|
60
|
-
| Expose an executable action that AI clients can call
|
|
61
|
-
| Expose read-only data via a URI
|
|
62
|
-
| Create a reusable conversation template or system prompt
|
|
63
|
-
| Build an autonomous AI loop that orchestrates tools
|
|
64
|
-
| Register shared services or configuration via DI
|
|
65
|
-
| Run a background task with progress and retries
|
|
66
|
-
| Chain multiple jobs into a sequential pipeline
|
|
67
|
-
| Write instruction-only AI guidance (no code execution)
|
|
68
|
-
| Write AI guidance that also orchestrates tools
|
|
69
|
-
| Look up any decorator signature or option
|
|
70
|
-
| Overview of all official adapters
|
|
71
|
-
| Integrate an external API via OpenAPI spec
|
|
72
|
-
| Use official plugins (caching, remember, feature flags)
|
|
73
|
-
| Connect to an external data source via a custom adapter
|
|
74
|
-
| Configure LLM settings for an agent component
|
|
75
|
-
| Add will/did/around lifecycle hooks to a plugin
|
|
76
|
-
| Annotate tools with client hints for AI clients | `create-tool-annotations` | Add MCP tool annotations for client hints |
|
|
77
|
-
| Define typed output schemas for tool responses | `create-tool-output-schema-types` | Define typed output schemas for tools |
|
|
65
|
+
| Scenario | Reference | Description |
|
|
66
|
+
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
67
|
+
| Expose an executable action that AI clients can call (full surface: schemas, DI, errors, throttling, auth, availability, elicitation, UI widgets, annotations, examples metadata, registration) | **[`create-tool` (top-level skill)](../create-tool/SKILL.md)** | Single source of truth for everything inside `@Tool({...})`. Subsumes the former `create-tool`, `create-tool-annotations`, `create-tool-output-schema-types`, and `create-tool-ui` references. |
|
|
68
|
+
| Expose read-only data via a URI | `create-resource` | Static resources or URI template resources for dynamic data |
|
|
69
|
+
| Create a reusable conversation template or system prompt | `create-prompt` | Prompt entries with arguments and multi-turn message sequences |
|
|
70
|
+
| Build an autonomous AI loop that orchestrates tools | `create-agent` | Agent entries with LLM config, inner tools, and swarm handoff |
|
|
71
|
+
| Register shared services or configuration via DI | `create-provider` | Dependency injection tokens, lifecycle hooks, factory providers |
|
|
72
|
+
| Run a background task with progress and retries | `create-job` | Job entries with attempt tracking, retry config, and progress |
|
|
73
|
+
| Chain multiple jobs into a sequential pipeline | `create-workflow` | Workflow entries that compose jobs with data passing |
|
|
74
|
+
| Write instruction-only AI guidance (no code execution) | `create-skill` | Skill entries with markdown instructions from files, strings, or URLs |
|
|
75
|
+
| Write AI guidance that also orchestrates tools | `create-skill-with-tools` | Skill entries that combine instructions with registered tools |
|
|
76
|
+
| Look up any decorator signature or option | `decorators-guide` | Complete reference for @Tool, @Resource, @Prompt, @Agent, @App, @FrontMcp, and more |
|
|
77
|
+
| Overview of all official adapters | `official-adapters` | Router to all adapter types; adapter vs plugin comparison |
|
|
78
|
+
| Integrate an external API via OpenAPI spec | `openapi-adapter` | OpenapiAdapter with auth, polling, filtering, transforms, format resolution, $ref security |
|
|
79
|
+
| Use official plugins (caching, remember, feature flags) | `official-plugins` | Built-in plugins for caching, session memory, approval, and feature flags (dashboard is beta) |
|
|
80
|
+
| Connect to an external data source via a custom adapter | `create-adapter` | Create custom adapters for external data sources |
|
|
81
|
+
| Configure LLM settings for an agent component | `create-agent-llm-config` | Configure LLM settings for agent components |
|
|
82
|
+
| Add will/did/around lifecycle hooks to a plugin | `create-plugin-hooks` | Add lifecycle hooks to plugins (will/did/around) |
|
|
78
83
|
|
|
79
84
|
## Recommended Reading Order
|
|
80
85
|
|
|
81
86
|
1. **`decorators-guide`** — Start here to understand the full decorator landscape
|
|
82
|
-
2.
|
|
87
|
+
2. **[`create-tool`](../create-tool/SKILL.md)** — The most common building block (top-level skill — covers schemas, DI, errors, throttling, auth, UI widgets, annotations); learn tools first
|
|
83
88
|
3. **`create-resource`** — Expose data alongside tools
|
|
84
89
|
4. **`create-prompt`** — Add reusable conversation templates
|
|
85
90
|
5. **`create-provider`** — Share services across tools and resources via DI
|
|
@@ -225,28 +230,9 @@ Each reference has matching examples under [`examples/<reference>/`](./examples/
|
|
|
225
230
|
| [`directory-based-skill`](./examples/create-skill/directory-based-skill.md) | Advanced | A skill loaded from a directory structure with SKILL.md frontmatter, plus file-based and URL-based instruction sources. |
|
|
226
231
|
| [`parameterized-skill`](./examples/create-skill/parameterized-skill.md) | Intermediate | A skill with customizable parameters, usage examples for AI guidance, and controlled visibility. |
|
|
227
232
|
|
|
228
|
-
### `create-tool-
|
|
233
|
+
### `create-tool` (migrated to top-level skill)
|
|
229
234
|
|
|
230
|
-
|
|
231
|
-
| ------------------------------------------------------------------------------------------ | ------------ | ------------------------------------------------------------------------------------------------------------------------------- |
|
|
232
|
-
| [`destructive-delete-tool`](./examples/create-tool-annotations/destructive-delete-tool.md) | Intermediate | Demonstrates annotating a tool that deletes data, enabling MCP clients to warn users before execution. |
|
|
233
|
-
| [`readonly-query-tool`](./examples/create-tool-annotations/readonly-query-tool.md) | Basic | Demonstrates annotating a tool that only reads data, signaling to MCP clients that it has no side effects and is safe to retry. |
|
|
234
|
-
|
|
235
|
-
### `create-tool-output-schema-types`
|
|
236
|
-
|
|
237
|
-
| Example | Level | Description |
|
|
238
|
-
| ---------------------------------------------------------------------------------------------------------- | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
239
|
-
| [`primitive-and-media-outputs`](./examples/create-tool-output-schema-types/primitive-and-media-outputs.md) | Intermediate | Demonstrates using primitive string literals and media types as `outputSchema` for tools that return plain text, images, or multi-content arrays. |
|
|
240
|
-
| [`zod-raw-shape-output`](./examples/create-tool-output-schema-types/zod-raw-shape-output.md) | Basic | Demonstrates the recommended approach of using a Zod raw shape as `outputSchema` for structured, validated JSON output. |
|
|
241
|
-
| [`zod-schema-advanced-output`](./examples/create-tool-output-schema-types/zod-schema-advanced-output.md) | Advanced | Demonstrates using full Zod schema objects (not raw shapes) as `outputSchema`, including `z.object()`, `z.array()`, `z.union()`, and `z.discriminatedUnion()`. |
|
|
242
|
-
|
|
243
|
-
### `create-tool`
|
|
244
|
-
|
|
245
|
-
| Example | Level | Description |
|
|
246
|
-
| -------------------------------------------------------------------------------------------------------- | ------------ | -------------------------------------------------------------------------------------------------------------- |
|
|
247
|
-
| [`basic-class-tool`](./examples/create-tool/basic-class-tool.md) | Basic | A minimal tool using the class-based pattern with Zod input validation and output schema. |
|
|
248
|
-
| [`tool-with-di-and-errors`](./examples/create-tool/tool-with-di-and-errors.md) | Intermediate | A tool that resolves a database service via DI and uses `this.fail()` for business-logic errors. |
|
|
249
|
-
| [`tool-with-rate-limiting-and-progress`](./examples/create-tool/tool-with-rate-limiting-and-progress.md) | Advanced | A batch processing tool that uses rate limiting, concurrency control, progress notifications, and annotations. |
|
|
235
|
+
The full `@Tool({...})` surface — including the former `create-tool-annotations`, `create-tool-output-schema-types`, and `create-tool-ui` references — now lives in the top-level [`create-tool`](../create-tool/SKILL.md) skill. See its [`examples/`](../create-tool/examples/) directory for 25 combination examples covering schemas, DI, errors, throttling, auth, availability, elicitation, UI widgets, annotations, examples metadata, and job hand-off.
|
|
250
236
|
|
|
251
237
|
### `create-workflow`
|
|
252
238
|
|
|
@@ -299,4 +285,4 @@ when a server has been configured to host this skill.
|
|
|
299
285
|
## Reference
|
|
300
286
|
|
|
301
287
|
- [FrontMCP Overview](https://docs.agentfront.dev/frontmcp/fundamentals/overview)
|
|
302
|
-
- Related skills: `create-tool
|
|
288
|
+
- Related skills: [`create-tool`](../create-tool/SKILL.md) (top-level), `create-resource`, `create-prompt`, `create-agent`, `create-provider`, `create-job`, `create-workflow`, `create-skill`, `create-skill-with-tools`, `decorators-guide`, `official-adapters`, `openapi-adapter`, `official-plugins`
|
|
@@ -118,6 +118,20 @@ class MainApp {}
|
|
|
118
118
|
- Consuming the provider in a tool via `this.get(DB_TOKEN)` with full type safety
|
|
119
119
|
- Registering the factory in the `providers` array so tools can resolve it
|
|
120
120
|
|
|
121
|
+
## When to promote this to a folder
|
|
122
|
+
|
|
123
|
+
The flat `src/apps/main/providers/database.provider.ts` layout above is fine while the provider is a single class. The moment you add a `database.provider.spec.ts`, a `connection.ts` helper, or a config-loading module, promote it to its own folder:
|
|
124
|
+
|
|
125
|
+
```text
|
|
126
|
+
src/apps/main/providers/database/
|
|
127
|
+
├── index.ts # barrel: re-exports the factory + DatabasePool class
|
|
128
|
+
├── database.provider.ts # AsyncProvider factory + DatabasePool class
|
|
129
|
+
├── database.provider.spec.ts # tests
|
|
130
|
+
└── connection.ts # (optional) connection-setup helper
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
See [`create-provider` → File Layout](../../references/create-provider.md#file-layout) for the full convention.
|
|
134
|
+
|
|
121
135
|
## Related
|
|
122
136
|
|
|
123
137
|
- See `create-provider` for configuration providers, HTTP API clients, and cache providers
|
|
@@ -2,18 +2,40 @@
|
|
|
2
2
|
name: config-and-api-providers
|
|
3
3
|
reference: create-provider
|
|
4
4
|
level: intermediate
|
|
5
|
-
description: 'A configuration provider
|
|
5
|
+
description: 'A configuration provider and an HTTP API client provider, organized as one folder per provider with co-located specs and barrels.'
|
|
6
6
|
tags: [development, provider, config, api, providers]
|
|
7
7
|
features:
|
|
8
8
|
- 'A configuration provider using `readonly` properties from environment variables (sync construction)'
|
|
9
9
|
- 'An API client provider that reads credentials in the constructor (no `onInit` — `@Provider` has no lifecycle hooks)'
|
|
10
|
+
- 'Folder-per-provider layout (`src/apps/main/providers/<slug>/`) with a barrel `index.ts` and a co-located `.provider.spec.ts`'
|
|
11
|
+
- 'Top-level `src/apps/main/providers/index.ts` barrel re-exporting each provider folder'
|
|
10
12
|
- 'Registering providers at `@FrontMcp` level for server-wide sharing across all apps'
|
|
11
13
|
- 'Separating token definitions from provider implementations for clean dependency boundaries'
|
|
12
14
|
---
|
|
13
15
|
|
|
14
16
|
# Configuration and API Client Providers
|
|
15
17
|
|
|
16
|
-
A configuration provider
|
|
18
|
+
A configuration provider and an HTTP API client provider, organized as one folder per provider with co-located specs and barrels.
|
|
19
|
+
|
|
20
|
+
## File layout
|
|
21
|
+
|
|
22
|
+
```text
|
|
23
|
+
src/apps/main/
|
|
24
|
+
├── tokens.ts # shared token + interface definitions
|
|
25
|
+
├── index.ts # @App / @FrontMcp registration
|
|
26
|
+
└── providers/
|
|
27
|
+
├── index.ts # top-level barrel
|
|
28
|
+
├── config/
|
|
29
|
+
│ ├── index.ts # barrel: ConfigProvider
|
|
30
|
+
│ ├── config.provider.ts # @Provider class
|
|
31
|
+
│ └── config.provider.spec.ts # tests
|
|
32
|
+
└── api-client/
|
|
33
|
+
├── index.ts # barrel: ApiClientProvider
|
|
34
|
+
├── api-client.provider.ts # @Provider class
|
|
35
|
+
└── api-client.provider.spec.ts # tests
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Each provider lives in its own subfolder with a barrel — cross-provider imports go through the barrel (`from '../config'`), never reaching into another provider's implementation file.
|
|
17
39
|
|
|
18
40
|
## Code
|
|
19
41
|
|
|
@@ -38,13 +60,13 @@ export const API_TOKEN: Token<ApiClient> = Symbol('ApiClient');
|
|
|
38
60
|
```
|
|
39
61
|
|
|
40
62
|
```typescript
|
|
41
|
-
// src/apps/main/providers/config.provider.ts
|
|
63
|
+
// src/apps/main/providers/config/config.provider.ts
|
|
42
64
|
import { Provider } from '@frontmcp/sdk';
|
|
43
65
|
|
|
44
|
-
import type { AppConfig } from '
|
|
66
|
+
import type { AppConfig } from '../../tokens';
|
|
45
67
|
|
|
46
68
|
@Provider({ name: 'ConfigProvider' })
|
|
47
|
-
class ConfigProvider implements AppConfig {
|
|
69
|
+
export class ConfigProvider implements AppConfig {
|
|
48
70
|
readonly apiBaseUrl = process.env.API_BASE_URL ?? 'https://api.example.com';
|
|
49
71
|
readonly maxRetries = Number(process.env.MAX_RETRIES ?? 3);
|
|
50
72
|
readonly debug = process.env.DEBUG === 'true';
|
|
@@ -52,13 +74,31 @@ class ConfigProvider implements AppConfig {
|
|
|
52
74
|
```
|
|
53
75
|
|
|
54
76
|
```typescript
|
|
55
|
-
// src/apps/main/providers/
|
|
77
|
+
// src/apps/main/providers/config/index.ts
|
|
78
|
+
export { ConfigProvider } from './config.provider';
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
// src/apps/main/providers/config/config.provider.spec.ts
|
|
83
|
+
import { ConfigProvider } from './config.provider';
|
|
84
|
+
|
|
85
|
+
describe('ConfigProvider', () => {
|
|
86
|
+
it('reads apiBaseUrl from env with a default fallback', () => {
|
|
87
|
+
const provider = new ConfigProvider();
|
|
88
|
+
expect(provider.apiBaseUrl).toBeDefined();
|
|
89
|
+
expect(typeof provider.apiBaseUrl).toBe('string');
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
// src/apps/main/providers/api-client/api-client.provider.ts
|
|
56
96
|
import { Provider } from '@frontmcp/sdk';
|
|
57
97
|
|
|
58
|
-
import type { ApiClient } from '
|
|
98
|
+
import type { ApiClient } from '../../tokens';
|
|
59
99
|
|
|
60
100
|
@Provider({ name: 'ApiClientProvider' })
|
|
61
|
-
class ApiClientProvider implements ApiClient {
|
|
101
|
+
export class ApiClientProvider implements ApiClient {
|
|
62
102
|
// `@Provider` has no `onInit` lifecycle hook — read env in the constructor.
|
|
63
103
|
// First instantiation throws synchronously on missing config (fail fast).
|
|
64
104
|
private readonly baseUrl: string;
|
|
@@ -92,10 +132,44 @@ class ApiClientProvider implements ApiClient {
|
|
|
92
132
|
}
|
|
93
133
|
```
|
|
94
134
|
|
|
135
|
+
```typescript
|
|
136
|
+
// src/apps/main/providers/api-client/index.ts
|
|
137
|
+
export { ApiClientProvider } from './api-client.provider';
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
// src/apps/main/providers/api-client/api-client.provider.spec.ts
|
|
142
|
+
import { ApiClientProvider } from './api-client.provider';
|
|
143
|
+
|
|
144
|
+
describe('ApiClientProvider', () => {
|
|
145
|
+
const origEnv = { ...process.env };
|
|
146
|
+
afterEach(() => {
|
|
147
|
+
process.env = { ...origEnv };
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('throws fast when API_URL or API_KEY is missing', () => {
|
|
151
|
+
delete process.env.API_URL;
|
|
152
|
+
delete process.env.API_KEY;
|
|
153
|
+
expect(() => new ApiClientProvider()).toThrow(/API_URL and API_KEY/);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
// src/apps/main/providers/index.ts
|
|
160
|
+
// Top-level barrel — re-exports each provider folder so importers can do
|
|
161
|
+
// `import { ConfigProvider, ApiClientProvider } from './providers'`.
|
|
162
|
+
export * from './config';
|
|
163
|
+
export * from './api-client';
|
|
164
|
+
```
|
|
165
|
+
|
|
95
166
|
```typescript
|
|
96
167
|
// src/index.ts
|
|
97
168
|
import { FrontMcp } from '@frontmcp/sdk';
|
|
98
169
|
|
|
170
|
+
import { MainApp } from './apps/main';
|
|
171
|
+
import { ApiClientProvider, ConfigProvider } from './apps/main/providers';
|
|
172
|
+
|
|
99
173
|
@FrontMcp({
|
|
100
174
|
info: { name: 'my-server', version: '1.0.0' },
|
|
101
175
|
apps: [MainApp],
|
|
@@ -108,9 +182,11 @@ class MyServer {}
|
|
|
108
182
|
|
|
109
183
|
- A configuration provider using `readonly` properties from environment variables (sync construction)
|
|
110
184
|
- An API client provider that reads credentials in the constructor (no `onInit` — `@Provider` has no lifecycle hooks)
|
|
185
|
+
- Folder-per-provider layout (`src/apps/main/providers/<slug>/`) with a barrel `index.ts` and a co-located `.provider.spec.ts`
|
|
186
|
+
- Top-level `src/apps/main/providers/index.ts` barrel re-exporting each provider folder
|
|
111
187
|
- Registering providers at `@FrontMcp` level for server-wide sharing across all apps
|
|
112
188
|
- Separating token definitions from provider implementations for clean dependency boundaries
|
|
113
189
|
|
|
114
190
|
## Related
|
|
115
191
|
|
|
116
|
-
- See `create-provider` for cache providers, lifecycle details, and the `tryGet()` safe access pattern
|
|
192
|
+
- See `create-provider` for the [File Layout](../../references/create-provider.md#file-layout) section, cache providers, lifecycle details, and the `tryGet()` safe access pattern
|
|
@@ -418,7 +418,9 @@ class DataApp {}
|
|
|
418
418
|
|
|
419
419
|
### Enabling the Jobs System
|
|
420
420
|
|
|
421
|
-
|
|
421
|
+
**Auto-enable (issue #408):** declaring any `@App({ jobs: [...] })` (or `workflows: [...]`) is enough — the jobs subsystem comes up with in-memory stores by default and the management tools (`execute_job`, `list_jobs`, `get_job_status`, `register_job`, `remove_job`) are registered automatically so agents can invoke them. No `@FrontMcp({ jobs: { enabled: true } })` is required for the happy path.
|
|
422
|
+
|
|
423
|
+
**When to configure `@FrontMcp({ jobs })` explicitly:** override the in-memory default with persistent storage (Redis recommended for multi-replica HA) so job state, progress, logs, and outputs survive retries and server restarts.
|
|
422
424
|
|
|
423
425
|
```typescript
|
|
424
426
|
import { FrontMcp } from '@frontmcp/sdk';
|
|
@@ -426,8 +428,9 @@ import { FrontMcp } from '@frontmcp/sdk';
|
|
|
426
428
|
@FrontMcp({
|
|
427
429
|
info: { name: 'my-server', version: '1.0.0' },
|
|
428
430
|
apps: [DataApp],
|
|
431
|
+
// `enabled: true` is implied by `@App({ jobs })`. Set explicitly only to
|
|
432
|
+
// configure store, or set to `false` to opt out and suppress the tools.
|
|
429
433
|
jobs: {
|
|
430
|
-
enabled: true,
|
|
431
434
|
store: {
|
|
432
435
|
redis: {
|
|
433
436
|
provider: 'redis',
|
|
@@ -441,7 +444,36 @@ import { FrontMcp } from '@frontmcp/sdk';
|
|
|
441
444
|
class MyServer {}
|
|
442
445
|
```
|
|
443
446
|
|
|
444
|
-
|
|
447
|
+
Setting `jobs: { enabled: false }` is an explicit opt-out — declared jobs will NOT be activated and the framework logs a warning so the configuration mismatch is loud.
|
|
448
|
+
|
|
449
|
+
### Calling Jobs from an Agent
|
|
450
|
+
|
|
451
|
+
Once jobs are registered, the SDK exposes five MCP tools (snake_case per ecosystem convention; hyphen aliases like `execute-job` keep working with a deprecation log line for one release):
|
|
452
|
+
|
|
453
|
+
| Tool | Purpose |
|
|
454
|
+
| ---------------- | ------------------------------------------------------------------------ |
|
|
455
|
+
| `list_jobs` | List registered jobs with optional `tags` / `labels` / `query` filters |
|
|
456
|
+
| `execute_job` | Execute a registered job by name (`{ name, input?, background? }`) |
|
|
457
|
+
| `get_job_status` | Get the run state for a `runId` returned by `execute_job` |
|
|
458
|
+
| `register_job` | Register a dynamic job at runtime (sandboxed; `hideFromDiscovery: true`) |
|
|
459
|
+
| `remove_job` | Remove a dynamic job by name (`hideFromDiscovery: true`) |
|
|
460
|
+
|
|
461
|
+
Workflows expose a parallel set: `list_workflows`, `execute_workflow`, `get_workflow_status`, `register_workflow`, `remove_workflow`.
|
|
462
|
+
|
|
463
|
+
For finer-grained control (e.g. omit `register_job` / `remove_job` in production), opt out of auto-registration by importing the tool classes manually:
|
|
464
|
+
|
|
465
|
+
```typescript
|
|
466
|
+
import { App, ExecuteJobTool, GetJobStatusTool, ListJobsTool } from '@frontmcp/sdk';
|
|
467
|
+
|
|
468
|
+
@App({
|
|
469
|
+
name: 'data-app',
|
|
470
|
+
jobs: [GenerateReportJob],
|
|
471
|
+
tools: [ExecuteJobTool, ListJobsTool, GetJobStatusTool], // omit register/remove
|
|
472
|
+
})
|
|
473
|
+
class DataApp {}
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
The same classes are also reachable via the subpath `@frontmcp/sdk/job/tools` and `@frontmcp/sdk/workflow/tools` for bundlers that prefer narrower imports.
|
|
445
477
|
|
|
446
478
|
## Nx Generator
|
|
447
479
|
|
|
@@ -603,7 +635,9 @@ class DataServer {}
|
|
|
603
635
|
|
|
604
636
|
### Runtime
|
|
605
637
|
|
|
606
|
-
- [ ]
|
|
638
|
+
- [ ] Jobs subsystem is active — either implicitly via `@App({ jobs: [...] })`
|
|
639
|
+
(auto-enable, issue #408) or explicitly via `@FrontMcp({ jobs: { store: { ... } } })`
|
|
640
|
+
when overriding the in-memory default
|
|
607
641
|
- [ ] Job executes and returns output matching `outputSchema`
|
|
608
642
|
- [ ] Progress is reported and queryable during execution
|
|
609
643
|
- [ ] Retry fires with correct backoff delays on transient failures
|
|
@@ -611,13 +645,13 @@ class DataServer {}
|
|
|
611
645
|
|
|
612
646
|
## Troubleshooting
|
|
613
647
|
|
|
614
|
-
| Problem | Cause
|
|
615
|
-
| -------------------------- |
|
|
616
|
-
| Job not activated | `jobs
|
|
617
|
-
| Job fails without retrying | No `retry` policy configured
|
|
618
|
-
| Progress not visible | Not calling `this.progress()` during execution
|
|
619
|
-
| Job times out unexpectedly | Default 5-minute timeout too short
|
|
620
|
-
| Permission denied error | User lacks required roles or scopes
|
|
648
|
+
| Problem | Cause | Solution |
|
|
649
|
+
| -------------------------- | ------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
|
|
650
|
+
| Job not activated | `@App` doesn't declare `jobs: [...]` AND `@FrontMcp({ jobs: { enabled: true } })` isn't set | Add the job class to `@App({ jobs: [...] })` (auto-enables) OR set `@FrontMcp({ jobs: { enabled: true, store: { ... } } })` |
|
|
651
|
+
| Job fails without retrying | No `retry` policy configured | Add `retry: { maxAttempts: 3, backoffMs: 2000 }` to `@Job` options |
|
|
652
|
+
| Progress not visible | Not calling `this.progress()` during execution | Add `this.progress(pct, total, message)` calls at each stage |
|
|
653
|
+
| Job times out unexpectedly | Default 5-minute timeout too short | Set `timeout` in `@Job` to a higher value (e.g., `600000` for 10 minutes) |
|
|
654
|
+
| Permission denied error | User lacks required roles or scopes | Verify user has one of the `roles` and all `scopes` defined in `permissions` |
|
|
621
655
|
|
|
622
656
|
## Examples
|
|
623
657
|
|
|
@@ -164,6 +164,73 @@ if (!db) {
|
|
|
164
164
|
}
|
|
165
165
|
```
|
|
166
166
|
|
|
167
|
+
## File Layout
|
|
168
|
+
|
|
169
|
+
Once a provider grows past a single class, a flat `src/providers/<slug>.provider.ts` becomes ambiguous: helpers, internal types, schema fragments, and the spec file all need somewhere to go. The recommended convention is **one folder per provider**, co-locating the class, the spec, an optional barrel, and any helpers:
|
|
170
|
+
|
|
171
|
+
```text
|
|
172
|
+
src/providers/<provider-slug>/
|
|
173
|
+
├── index.ts # barrel: re-exports class, factory, public types
|
|
174
|
+
├── <provider-slug>.provider.ts # @Provider class and/or AsyncProvider factory
|
|
175
|
+
├── <provider-slug>.provider.spec.ts # unit tests
|
|
176
|
+
├── types.ts # (optional) internal types / token interfaces
|
|
177
|
+
└── <helper>.ts (+ .spec.ts) # (optional) per-provider helpers
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Plus a top-level `src/providers/index.ts` barrel re-exporting each subfolder:
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
// src/providers/index.ts
|
|
184
|
+
export * from './task-store';
|
|
185
|
+
export * from './config';
|
|
186
|
+
export * from './redis';
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Naming rules
|
|
190
|
+
|
|
191
|
+
- **Folder slug**: `kebab-case`, matches the provider's primary purpose (`task-store`, `redis`, `api-client`).
|
|
192
|
+
- **Class file**: `<slug>.provider.ts` — matches the in-tree demo-app convention (`apps/demo/src/apps/expenses/providers/redis.provider.ts`) and what the Nx generator emits.
|
|
193
|
+
- **Spec file**: `<slug>.provider.spec.ts` — co-located with source per the repo's `.spec.ts` convention (CLAUDE.md).
|
|
194
|
+
- **Barrel**: `index.ts`, re-exporting the class, the `AsyncProvider` factory (if any), and any public types/tokens.
|
|
195
|
+
|
|
196
|
+
### Single-file vs folder — when to fold
|
|
197
|
+
|
|
198
|
+
A trivial provider (e.g. a `Map`-based cache, a pure DTO with no helpers) does NOT need its own folder; promote to a folder as soon as the provider grows. Use this rubric:
|
|
199
|
+
|
|
200
|
+
| Provider shape | Layout | Why |
|
|
201
|
+
| ------------------------------------------------------ | ------------------------------------------------------- | ------------------------------------------------------------------------------ |
|
|
202
|
+
| Pure DTO (e.g. `extends Map`, no methods, no helpers) | Single file `<slug>.provider.ts` under `src/providers/` | A folder for a 5-line class is over-architected |
|
|
203
|
+
| Provider with a spec file | Folder | Keeps source and spec adjacent; matches CLAUDE.md `.spec.ts` rule |
|
|
204
|
+
| Provider with helpers, types, or schema fragments | Folder | Helpers/types are private to the provider; folder boundary makes that explicit |
|
|
205
|
+
| `AsyncProvider({ useFactory })` with non-trivial setup | Folder | Factory + class + setup helpers cluster naturally |
|
|
206
|
+
| Multiple related providers sharing helpers | Folder per provider + sibling `_shared/` folder | Avoids leaking helpers into the top-level `providers/` namespace |
|
|
207
|
+
|
|
208
|
+
### Cross-provider imports
|
|
209
|
+
|
|
210
|
+
Cross-provider imports go through the **subfolder barrel**, not into another provider's internals:
|
|
211
|
+
|
|
212
|
+
<!-- prettier-ignore -->
|
|
213
|
+
```typescript
|
|
214
|
+
// ✅ Good — imports through the subfolder barrel
|
|
215
|
+
import { TaskStoreProvider } from '../task-store';
|
|
216
|
+
|
|
217
|
+
// ❌ Bad — top-level barrel for sibling imports causes circular-init churn
|
|
218
|
+
import { TaskStoreProvider } from '..';
|
|
219
|
+
// ❌ Bad — reaches into another provider's implementation file
|
|
220
|
+
import { TaskStoreProvider } from '../task-store/task-store.provider';
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Tool → provider imports follow the same rule:
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
// ✅ Good — tool imports the provider's public surface from its barrel
|
|
227
|
+
import { TaskStoreProvider } from '../../providers/task-store';
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Same convention for tools and resources
|
|
231
|
+
|
|
232
|
+
The folder layout applies to `create-tool` and `create-resource` too. Once a tool grows a `<slug>.schema.ts` or a resource grows a content helper, promote it to `src/tools/<slug>/` or `src/resources/<slug>/` with the same barrel + spec layout. (Tracked separately in issue #405 for `create-tool`.)
|
|
233
|
+
|
|
167
234
|
## Common Provider Patterns
|
|
168
235
|
|
|
169
236
|
### Configuration Provider
|
|
@@ -258,6 +325,8 @@ class CacheProvider extends Map<string, unknown> {
|
|
|
258
325
|
nx generate @frontmcp/nx:provider my-provider --project=my-app
|
|
259
326
|
```
|
|
260
327
|
|
|
328
|
+
The generator currently writes a single `<slug>.provider.ts` directly into `src/providers/`. Promote it to the folder layout above as soon as you add a spec file or helpers — see [File Layout](#file-layout).
|
|
329
|
+
|
|
261
330
|
## Verification
|
|
262
331
|
|
|
263
332
|
```bash
|
|
@@ -270,13 +339,15 @@ frontmcp dev
|
|
|
270
339
|
|
|
271
340
|
## Common Patterns
|
|
272
341
|
|
|
273
|
-
| Pattern
|
|
274
|
-
|
|
|
275
|
-
| Token definition
|
|
276
|
-
| DI resolution
|
|
277
|
-
| Lifecycle
|
|
278
|
-
| Registration scope
|
|
279
|
-
| Config provider
|
|
342
|
+
| Pattern | Correct | Incorrect | Why |
|
|
343
|
+
| --------------------- | ------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
|
|
344
|
+
| 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()` |
|
|
345
|
+
| 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 |
|
|
346
|
+
| 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 |
|
|
347
|
+
| 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 |
|
|
348
|
+
| Config provider | `readonly` properties from `process.env` | Mutable properties that change at runtime | Providers are singletons; mutable state can cause race conditions |
|
|
349
|
+
| File layout | `src/providers/<slug>/` folder with `index.ts` + `<slug>.provider.ts` + `<slug>.provider.spec.ts` | Flat `src/providers/<slug>.provider.ts` once helpers or a spec exist | Co-locates source, tests, helpers; barrel hides internals — see [File Layout](#file-layout) |
|
|
350
|
+
| Cross-provider import | `import { TaskStoreProvider } from '../task-store'` (subfolder barrel) | `import { TaskStoreProvider } from '../task-store/task-store.provider'` | Subfolder barrel hides internals; reaching past it couples consumers to implementation files |
|
|
280
351
|
|
|
281
352
|
## Verification Checklist
|
|
282
353
|
|
|
@@ -287,6 +358,7 @@ frontmcp dev
|
|
|
287
358
|
- [ ] Provider (class or `AsyncProvider` factory) is registered in `providers` array of `@App` or `@FrontMcp`
|
|
288
359
|
- [ ] Sync setup happens in the constructor (throws fast on missing config)
|
|
289
360
|
- [ ] Async setup uses `AsyncProvider({ useFactory })`; the framework awaits it before resolution
|
|
361
|
+
- [ ] Each provider lives in its own `src/providers/<slug>/` folder once it has a spec, helpers, or internal types (single-file is fine for trivial providers — see the [File Layout](#file-layout) rubric)
|
|
290
362
|
|
|
291
363
|
### Runtime
|
|
292
364
|
|
|
@@ -312,7 +384,7 @@ frontmcp dev
|
|
|
312
384
|
| Example | Level | Description |
|
|
313
385
|
| ------------------------------------------------------------------------------------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
314
386
|
| [`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
|
|
387
|
+
| [`config-and-api-providers`](../examples/create-provider/config-and-api-providers.md) | Intermediate | A configuration provider and an HTTP API client provider, organized as one folder per provider with co-located specs and barrels. |
|
|
316
388
|
|
|
317
389
|
> See all examples in [`examples/create-provider/`](../examples/create-provider/)
|
|
318
390
|
|
|
@@ -462,6 +462,37 @@ nx generate @frontmcp/nx:skill-dir
|
|
|
462
462
|
|
|
463
463
|
The class generator creates the skill file, spec file, and updates barrel exports. The directory generator creates the full directory structure ready for `skillDir()`.
|
|
464
464
|
|
|
465
|
+
## Installing on a User's Machine
|
|
466
|
+
|
|
467
|
+
Tool-enabled skills install the same way as instruction-only skills —
|
|
468
|
+
the tools they reference are exposed through the same MCP server, so
|
|
469
|
+
copying the `SKILL.md` (with the decorator metadata in its frontmatter)
|
|
470
|
+
under `.claude/skills/<name>/` is all Claude Code needs to load it.
|
|
471
|
+
|
|
472
|
+
```bash
|
|
473
|
+
# Install one named skill from a local project entry
|
|
474
|
+
frontmcp skills install deploy-service --from-entry src/main.ts -p claude
|
|
475
|
+
|
|
476
|
+
# Install every @Skill the project exposes
|
|
477
|
+
frontmcp skills install --from-entry src/main.ts --all -p claude
|
|
478
|
+
|
|
479
|
+
# Install from a published package (resolves the package main entry)
|
|
480
|
+
frontmcp skills install --from-package my-devops-server --all -p claude
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
The CLI bundles the entry, enumerates `@Skill` entries via the SDK's
|
|
484
|
+
in-memory client, and copies each skill's `SKILL.md` and resource
|
|
485
|
+
directories. When a skill declares `allowedTools` in its decorator, that
|
|
486
|
+
list ends up in the synthesized SKILL.md frontmatter so Claude Code
|
|
487
|
+
pre-approves those tools during the skill session. See
|
|
488
|
+
`frontmcp-skills-usage` for the full selector matrix, and `create-skill`
|
|
489
|
+
for the analogous note on instruction-only skills.
|
|
490
|
+
|
|
491
|
+
> Shipping slash commands alongside the skills? Use the full per-bin
|
|
492
|
+
> install instead: `my-devops-server install -p claude` writes the
|
|
493
|
+
> plugin manifest, `commands/` directory, and `skills/` directory in a
|
|
494
|
+
> single pass.
|
|
495
|
+
|
|
465
496
|
## HTTP Endpoints for Skill Discovery
|
|
466
497
|
|
|
467
498
|
When skills have `visibility` set to `'http'` or `'both'`, they are discoverable via HTTP endpoints:
|