@frontmcp/skills 0.0.1 → 1.0.0-beta.11
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 +2 -2
- package/catalog/TEMPLATE.md +58 -13
- package/catalog/frontmcp-config/SKILL.md +156 -0
- package/catalog/{auth/configure-auth/references/auth-modes.md → frontmcp-config/references/configure-auth-modes.md} +5 -0
- package/catalog/frontmcp-config/references/configure-auth.md +243 -0
- package/catalog/frontmcp-config/references/configure-elicitation.md +183 -0
- package/catalog/frontmcp-config/references/configure-http.md +210 -0
- package/catalog/frontmcp-config/references/configure-session.md +210 -0
- package/catalog/{config/configure-throttle/references/guard-config.md → frontmcp-config/references/configure-throttle-guard-config.md} +5 -0
- package/catalog/frontmcp-config/references/configure-throttle.md +234 -0
- package/catalog/{config/configure-transport/references/protocol-presets.md → frontmcp-config/references/configure-transport-protocol-presets.md} +5 -0
- package/catalog/frontmcp-config/references/configure-transport.md +200 -0
- package/catalog/frontmcp-config/references/setup-redis.md +9 -0
- package/catalog/frontmcp-config/references/setup-sqlite.md +9 -0
- package/catalog/frontmcp-deployment/SKILL.md +152 -0
- package/catalog/frontmcp-deployment/references/build-for-browser.md +143 -0
- package/catalog/frontmcp-deployment/references/build-for-cli.md +191 -0
- package/catalog/{deployment/build-for-sdk/SKILL.md → frontmcp-deployment/references/build-for-sdk.md} +66 -20
- package/catalog/frontmcp-deployment/references/deploy-to-cloudflare.md +218 -0
- package/catalog/{deployment/deploy-to-lambda/SKILL.md → frontmcp-deployment/references/deploy-to-lambda.md} +77 -59
- package/catalog/{deployment/deploy-to-node/references/Dockerfile.example → frontmcp-deployment/references/deploy-to-node-dockerfile.md} +18 -4
- package/catalog/{deployment/deploy-to-node/SKILL.md → frontmcp-deployment/references/deploy-to-node.md} +69 -36
- package/catalog/frontmcp-deployment/references/deploy-to-vercel-config.md +65 -0
- package/catalog/frontmcp-deployment/references/deploy-to-vercel.md +229 -0
- package/catalog/frontmcp-development/SKILL.md +126 -0
- package/catalog/frontmcp-development/references/create-adapter.md +170 -0
- package/catalog/{development/create-agent/references/llm-config.md → frontmcp-development/references/create-agent-llm-config.md} +10 -5
- package/catalog/{development/create-agent/SKILL.md → frontmcp-development/references/create-agent.md} +83 -40
- package/catalog/{development/create-job/SKILL.md → frontmcp-development/references/create-job.md} +62 -15
- package/catalog/{plugins/create-plugin-hooks/SKILL.md → frontmcp-development/references/create-plugin-hooks.md} +100 -7
- package/catalog/frontmcp-development/references/create-plugin.md +506 -0
- package/catalog/{development/create-prompt/SKILL.md → frontmcp-development/references/create-prompt.md} +65 -22
- package/catalog/{development/create-provider/SKILL.md → frontmcp-development/references/create-provider.md} +63 -23
- package/catalog/{development/create-resource/SKILL.md → frontmcp-development/references/create-resource.md} +148 -26
- package/catalog/{development/create-skill-with-tools/SKILL.md → frontmcp-development/references/create-skill-with-tools.md} +174 -20
- package/catalog/{development/create-skill/SKILL.md → frontmcp-development/references/create-skill.md} +114 -28
- package/catalog/{development/create-tool/references/tool-annotations.md → frontmcp-development/references/create-tool-annotations.md} +5 -0
- package/catalog/{development/create-tool/references/output-schema-types.md → frontmcp-development/references/create-tool-output-schema-types.md} +5 -0
- package/catalog/{development/create-tool/SKILL.md → frontmcp-development/references/create-tool.md} +172 -23
- package/catalog/{development/create-workflow/SKILL.md → frontmcp-development/references/create-workflow.md} +61 -14
- package/catalog/frontmcp-development/references/decorators-guide.md +754 -0
- package/catalog/frontmcp-development/references/official-adapters.md +199 -0
- package/catalog/{plugins/official-plugins/SKILL.md → frontmcp-development/references/official-plugins.md} +97 -27
- package/catalog/frontmcp-extensibility/SKILL.md +103 -0
- package/catalog/frontmcp-extensibility/references/vectoriadb.md +289 -0
- package/catalog/frontmcp-guides/SKILL.md +420 -0
- package/catalog/frontmcp-guides/references/example-knowledge-base.md +641 -0
- package/catalog/frontmcp-guides/references/example-task-manager.md +517 -0
- package/catalog/frontmcp-guides/references/example-weather-api.md +297 -0
- package/catalog/frontmcp-production-readiness/SKILL.md +98 -0
- package/catalog/frontmcp-production-readiness/references/common-checklist.md +156 -0
- package/catalog/frontmcp-production-readiness/references/production-browser.md +46 -0
- package/catalog/frontmcp-production-readiness/references/production-cli-binary.md +62 -0
- package/catalog/frontmcp-production-readiness/references/production-cli-daemon.md +61 -0
- package/catalog/frontmcp-production-readiness/references/production-cloudflare.md +52 -0
- package/catalog/frontmcp-production-readiness/references/production-lambda.md +53 -0
- package/catalog/frontmcp-production-readiness/references/production-node-sdk.md +66 -0
- package/catalog/frontmcp-production-readiness/references/production-node-server.md +61 -0
- package/catalog/frontmcp-production-readiness/references/production-vercel.md +52 -0
- package/catalog/frontmcp-setup/SKILL.md +132 -0
- package/catalog/frontmcp-setup/references/frontmcp-skills-usage.md +280 -0
- package/catalog/{setup/multi-app-composition/SKILL.md → frontmcp-setup/references/multi-app-composition.md} +66 -19
- package/catalog/{setup/nx-workflow/SKILL.md → frontmcp-setup/references/nx-workflow.md} +79 -17
- package/catalog/frontmcp-setup/references/project-structure-nx.md +251 -0
- package/catalog/frontmcp-setup/references/project-structure-standalone.md +217 -0
- package/catalog/frontmcp-setup/references/readme-guide.md +226 -0
- package/catalog/{setup/setup-project/SKILL.md → frontmcp-setup/references/setup-project.md} +63 -58
- package/catalog/{setup/setup-redis/SKILL.md → frontmcp-setup/references/setup-redis.md} +60 -82
- package/catalog/{setup/setup-sqlite/SKILL.md → frontmcp-setup/references/setup-sqlite.md} +65 -72
- package/catalog/frontmcp-testing/SKILL.md +135 -0
- package/catalog/{testing/setup-testing/SKILL.md → frontmcp-testing/references/setup-testing.md} +79 -63
- package/catalog/{testing/setup-testing → frontmcp-testing}/references/test-auth.md +5 -0
- package/catalog/{testing/setup-testing → frontmcp-testing}/references/test-browser-build.md +5 -0
- package/catalog/{testing/setup-testing → frontmcp-testing}/references/test-cli-binary.md +5 -0
- package/catalog/{testing/setup-testing → frontmcp-testing}/references/test-direct-client.md +5 -0
- package/catalog/{testing/setup-testing → frontmcp-testing}/references/test-e2e-handler.md +5 -0
- package/catalog/{testing/setup-testing → frontmcp-testing}/references/test-tool-unit.md +6 -0
- package/catalog/skills-manifest.json +337 -382
- package/package.json +2 -2
- package/src/index.d.ts +1 -1
- package/src/index.js.map +1 -1
- package/src/loader.js +0 -1
- package/src/loader.js.map +1 -1
- package/src/manifest.d.ts +15 -3
- package/src/manifest.js +3 -3
- package/src/manifest.js.map +1 -1
- package/catalog/adapters/create-adapter/SKILL.md +0 -127
- package/catalog/adapters/official-adapters/SKILL.md +0 -136
- package/catalog/auth/configure-auth/SKILL.md +0 -250
- package/catalog/auth/configure-session/SKILL.md +0 -201
- package/catalog/config/configure-elicitation/SKILL.md +0 -136
- package/catalog/config/configure-http/SKILL.md +0 -167
- package/catalog/config/configure-throttle/SKILL.md +0 -189
- package/catalog/config/configure-transport/SKILL.md +0 -151
- package/catalog/deployment/build-for-browser/SKILL.md +0 -95
- package/catalog/deployment/build-for-cli/SKILL.md +0 -100
- package/catalog/deployment/deploy-to-cloudflare/SKILL.md +0 -192
- package/catalog/deployment/deploy-to-vercel/SKILL.md +0 -196
- package/catalog/deployment/deploy-to-vercel/references/vercel.json.example +0 -60
- package/catalog/development/decorators-guide/SKILL.md +0 -598
- package/catalog/plugins/create-plugin/SKILL.md +0 -336
- package/catalog/setup/frontmcp-skills-usage/SKILL.md +0 -200
- package/catalog/setup/project-structure-nx/SKILL.md +0 -186
- package/catalog/setup/project-structure-standalone/SKILL.md +0 -153
|
@@ -0,0 +1,754 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: decorators-guide
|
|
3
|
+
description: Complete reference for the hierarchical decorator system from @FrontMcp to @Tool
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# FrontMCP Decorators - Complete Reference
|
|
7
|
+
|
|
8
|
+
## Architecture Overview
|
|
9
|
+
|
|
10
|
+
FrontMCP uses a hierarchical decorator system. The nesting order is:
|
|
11
|
+
|
|
12
|
+
```text
|
|
13
|
+
@FrontMcp (server root)
|
|
14
|
+
+-- @App (application module)
|
|
15
|
+
+-- @Tool (MCP tool)
|
|
16
|
+
+-- @Resource (static MCP resource)
|
|
17
|
+
+-- @ResourceTemplate (parameterized resource)
|
|
18
|
+
+-- @Prompt (MCP prompt)
|
|
19
|
+
+-- @Agent (autonomous AI agent)
|
|
20
|
+
+-- @Skill (knowledge/workflow package)
|
|
21
|
+
+-- @Plugin (lifecycle plugin)
|
|
22
|
+
+-- @Provider (DI provider)
|
|
23
|
+
+-- @Adapter (external source adapter)
|
|
24
|
+
+-- @Job (long-running job)
|
|
25
|
+
+-- @Workflow (multi-step workflow)
|
|
26
|
+
+-- @Flow (custom flow)
|
|
27
|
+
+-- @Hook (@Will, @Did, @Stage, @Around)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## When to Use This Skill
|
|
33
|
+
|
|
34
|
+
### Must Use
|
|
35
|
+
|
|
36
|
+
- You are building a new FrontMCP server and need to choose the correct decorator for each component
|
|
37
|
+
- You are reviewing or debugging decorator configuration and need to verify field names, types, or nesting hierarchy
|
|
38
|
+
- You are onboarding to the FrontMCP codebase and need a single reference for the full decorator architecture
|
|
39
|
+
|
|
40
|
+
### Recommended
|
|
41
|
+
|
|
42
|
+
- You are adding a new capability (tool, resource, prompt, agent, skill) to an existing server and want to confirm the correct decorator signature
|
|
43
|
+
- You are designing a plugin or adapter and need to understand how it integrates with the decorator hierarchy
|
|
44
|
+
- You are refactoring an app's module structure and need to verify which decorators belong in `@App` vs `@FrontMcp`
|
|
45
|
+
|
|
46
|
+
### Skip When
|
|
47
|
+
|
|
48
|
+
- You only need to write business logic inside an existing tool or resource (see `create-tool` reference)
|
|
49
|
+
- You are configuring authentication or session management without changing decorators (see `configure-auth` reference)
|
|
50
|
+
- You are working on CI/CD, deployment, or infrastructure that does not involve decorator choices
|
|
51
|
+
|
|
52
|
+
> **Decision:** Use this skill whenever you need to look up, choose, or validate a FrontMCP decorator -- skip it when the decorator is already chosen and you are only implementing internal logic.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## 1. @FrontMcp
|
|
57
|
+
|
|
58
|
+
**Purpose:** Declares the root MCP server and its global configuration.
|
|
59
|
+
|
|
60
|
+
**When to use:** Once per server, on the top-level bootstrap class.
|
|
61
|
+
|
|
62
|
+
**Key fields:**
|
|
63
|
+
|
|
64
|
+
| Field | Description |
|
|
65
|
+
| --------------- | -------------------------------------------------------------------------------- |
|
|
66
|
+
| `info` | Server name, version, and description |
|
|
67
|
+
| `apps` | Array of `@App` classes to mount |
|
|
68
|
+
| `serve?` | Auto-start HTTP server (default: `true`). Set `false` for programmatic usage |
|
|
69
|
+
| `splitByApp?` | If `true`, each app gets its own scope and basePath. Default: `false` |
|
|
70
|
+
| `redis?` | Redis / Vercel KV connection for sessions, transport persistence, auth tokens |
|
|
71
|
+
| `plugins?` | Global plugins (instantiated per scope) |
|
|
72
|
+
| `providers?` | Global DI providers available to all apps |
|
|
73
|
+
| `tools?` | Standalone tools (outside apps, merged with app tools) |
|
|
74
|
+
| `resources?` | Standalone resources (merged with app resources) |
|
|
75
|
+
| `skills?` | Standalone skills (merged with app skills) |
|
|
76
|
+
| `skillsConfig?` | Skills HTTP endpoints (`/llm.txt`, `/skills`) and MCP tool config |
|
|
77
|
+
| `transport?` | Transport preset (`'modern'`, `'legacy'`, `'stateless-api'`, `'full'`) or object |
|
|
78
|
+
| `auth?` | Authentication mode: `'public'`, `'transparent'`, `'local'`, `'remote'` |
|
|
79
|
+
| `http?` | HTTP server options (port, host, cors, socketPath) |
|
|
80
|
+
| `logging?` | Logging configuration (transports and levels) |
|
|
81
|
+
| `elicitation?` | Enable interactive user input during tool execution |
|
|
82
|
+
| `sqlite?` | SQLite storage for local deployments (sessions, events) |
|
|
83
|
+
| `pubsub?` | Redis pub/sub for resource subscriptions (falls back to `redis` config) |
|
|
84
|
+
| `jobs?` | Background jobs/workflows system (`{ enabled, store? }`) |
|
|
85
|
+
| `throttle?` | Server-level guard config (see note below) |
|
|
86
|
+
| `pagination?` | List operation pagination (`tools/list` endpoint) |
|
|
87
|
+
| `ui?` | UI rendering config (CDN overrides for widget imports) |
|
|
88
|
+
| `extApps?` | Widget-to-host MCP Apps communication (host capabilities, session validation) |
|
|
89
|
+
| `loader?` | Default npm/ESM package loader for `App.esm()` / `App.remote()` apps |
|
|
90
|
+
|
|
91
|
+
> **Throttle vs per-tool guards:** Server-level `throttle` is a `GuardConfig` object with `global`, `defaultRateLimit`, `defaultConcurrency`, `defaultTimeout` sub-fields that set server-wide defaults. Tool-level `rateLimit`, `concurrency`, `timeout` fields (on `@Tool`) override these defaults per tool.
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
import { FrontMcp } from '@frontmcp/sdk';
|
|
95
|
+
|
|
96
|
+
@FrontMcp({
|
|
97
|
+
info: { name: 'my-server', version: '1.0.0' },
|
|
98
|
+
apps: [MainApp],
|
|
99
|
+
transport: 'modern', // Valid presets: 'modern', 'legacy', 'stateless-api', 'full'
|
|
100
|
+
http: { port: 3000 },
|
|
101
|
+
plugins: [RememberPlugin],
|
|
102
|
+
skillsConfig: { enabled: true },
|
|
103
|
+
})
|
|
104
|
+
class MyServer {}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## 2. @App
|
|
110
|
+
|
|
111
|
+
**Purpose:** Groups related tools, resources, prompts, agents, and skills into an application module.
|
|
112
|
+
|
|
113
|
+
**When to use:** To organize your server into logical modules. Every server has at least one app.
|
|
114
|
+
|
|
115
|
+
**Key fields:**
|
|
116
|
+
|
|
117
|
+
| Field | Description |
|
|
118
|
+
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|
|
119
|
+
| `name` | Application name (unique within server) |
|
|
120
|
+
| `description?` | Human-readable description for docs and UIs |
|
|
121
|
+
| `tools?` | Array of tool classes or function-built tools |
|
|
122
|
+
| `resources?` | Array of resource classes or function-built resources |
|
|
123
|
+
| `prompts?` | Array of prompt classes or function-built prompts |
|
|
124
|
+
| `agents?` | Array of agent classes (each exposed as `use-agent:<name>` tool) |
|
|
125
|
+
| `skills?` | Array of skill definitions |
|
|
126
|
+
| `plugins?` | App-scoped plugins |
|
|
127
|
+
| `providers?` | App-scoped DI providers |
|
|
128
|
+
| `authProviders?` | Named auth providers (e.g., GitHub, Google OAuth) separate from `auth` |
|
|
129
|
+
| `adapters?` | External source adapters (e.g., OpenAPI) |
|
|
130
|
+
| `auth?` | App-level auth config (overrides server default) |
|
|
131
|
+
| `standalone?` | `boolean \| 'includeInParent'` — `true`: isolated scope, excluded. `'includeInParent'`: isolated scope but tools exposed in parent |
|
|
132
|
+
| `jobs?` | Background job definitions |
|
|
133
|
+
| `workflows?` | Multi-step workflow definitions |
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
import { App } from '@frontmcp/sdk';
|
|
137
|
+
|
|
138
|
+
@App({
|
|
139
|
+
name: 'analytics',
|
|
140
|
+
tools: [QueryTool, ReportTool],
|
|
141
|
+
resources: [DashboardResource],
|
|
142
|
+
prompts: [SummaryPrompt],
|
|
143
|
+
providers: [DatabaseProvider],
|
|
144
|
+
})
|
|
145
|
+
class AnalyticsApp {}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## 3. @Tool
|
|
151
|
+
|
|
152
|
+
**Purpose:** Defines an MCP tool that an LLM can invoke to perform actions.
|
|
153
|
+
|
|
154
|
+
**When to use:** When you need the LLM to execute a function, query data, or trigger side effects.
|
|
155
|
+
|
|
156
|
+
**Key fields:**
|
|
157
|
+
|
|
158
|
+
| Field | Description |
|
|
159
|
+
| -------------------- | -------------------------------------------------------------------- |
|
|
160
|
+
| `name` | Tool name (used in MCP protocol, snake_case) |
|
|
161
|
+
| `description` | Human-readable description for the LLM |
|
|
162
|
+
| `inputSchema` | Zod raw shape defining input parameters |
|
|
163
|
+
| `outputSchema?` | Output type: Zod schema, `'string'`, `'image'`, `'audio'`, etc. |
|
|
164
|
+
| `annotations?` | MCP tool annotations (`readOnlyHint`, `destructiveHint`, etc.) |
|
|
165
|
+
| `tags?` | Categorization tags for filtering |
|
|
166
|
+
| `hideFromDiscovery?` | Hide from `tools/list` (still callable directly) |
|
|
167
|
+
| `examples?` | Usage examples: `[{ description, input, output? }]` |
|
|
168
|
+
| `authProviders?` | Per-tool auth providers: `['GitHub']` or `[{ name, scopes, alias }]` |
|
|
169
|
+
| `rateLimit?` | Rate limiting: `{ maxRequests, windowMs, partitionBy }` |
|
|
170
|
+
| `concurrency?` | Concurrency control: `{ maxConcurrent }` |
|
|
171
|
+
| `timeout?` | Execution timeout: `{ executeMs }` |
|
|
172
|
+
| `ui?` | UI widget configuration for tool rendering |
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
import { Tool, ToolContext } from '@frontmcp/sdk';
|
|
176
|
+
import { z } from 'zod';
|
|
177
|
+
|
|
178
|
+
@Tool({
|
|
179
|
+
name: 'search_users',
|
|
180
|
+
description: 'Search for users by name or email',
|
|
181
|
+
inputSchema: {
|
|
182
|
+
query: z.string().describe('Search query'),
|
|
183
|
+
limit: z.number().optional().default(10),
|
|
184
|
+
},
|
|
185
|
+
})
|
|
186
|
+
class SearchUsersTool extends ToolContext {
|
|
187
|
+
async execute(input: { query: string; limit: number }) {
|
|
188
|
+
const users = await this.get(UserService).search(input.query, input.limit);
|
|
189
|
+
return { users };
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## 4. @Prompt
|
|
197
|
+
|
|
198
|
+
**Purpose:** Defines an MCP prompt template that generates structured messages for the LLM.
|
|
199
|
+
|
|
200
|
+
**When to use:** When you want to expose reusable prompt templates with typed arguments.
|
|
201
|
+
|
|
202
|
+
**Key fields:**
|
|
203
|
+
|
|
204
|
+
| Field | Description |
|
|
205
|
+
| -------------- | ------------------------------------------------------------------- |
|
|
206
|
+
| `name` | Prompt name (used in MCP protocol) |
|
|
207
|
+
| `title?` | Human-readable display title for UIs |
|
|
208
|
+
| `description?` | What this prompt does |
|
|
209
|
+
| `arguments?` | Array of argument definitions (`{ name, description?, required? }`) |
|
|
210
|
+
| `icons?` | Array of Icon objects for UI representation (per MCP spec) |
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
import { Prompt, PromptContext } from '@frontmcp/sdk';
|
|
214
|
+
|
|
215
|
+
@Prompt({
|
|
216
|
+
name: 'code_review',
|
|
217
|
+
description: 'Generate a code review for the given code',
|
|
218
|
+
arguments: [
|
|
219
|
+
{ name: 'code', description: 'The code to review', required: true },
|
|
220
|
+
{ name: 'language', description: 'Programming language' },
|
|
221
|
+
],
|
|
222
|
+
})
|
|
223
|
+
class CodeReviewPrompt extends PromptContext {
|
|
224
|
+
async execute(args: { code: string; language?: string }) {
|
|
225
|
+
return {
|
|
226
|
+
messages: [
|
|
227
|
+
{
|
|
228
|
+
role: 'user' as const,
|
|
229
|
+
content: {
|
|
230
|
+
type: 'text' as const,
|
|
231
|
+
text: `Review this ${args.language ?? ''} code:\n\n${args.code}`,
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
],
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## 5. @Resource
|
|
243
|
+
|
|
244
|
+
**Purpose:** Exposes a static MCP resource identified by a fixed URI.
|
|
245
|
+
|
|
246
|
+
**When to use:** When you need to expose data at a known, unchanging URI (e.g., config files, system status).
|
|
247
|
+
|
|
248
|
+
**Key fields:**
|
|
249
|
+
|
|
250
|
+
| Field | Description |
|
|
251
|
+
| -------------- | -------------------------------------------- |
|
|
252
|
+
| `name` | Resource name (used in MCP protocol) |
|
|
253
|
+
| `title?` | Human-readable display title for UIs |
|
|
254
|
+
| `uri` | Fixed URI (e.g., `config://app/settings`) |
|
|
255
|
+
| `description?` | What this resource provides |
|
|
256
|
+
| `mimeType?` | Content MIME type (e.g., `application/json`) |
|
|
257
|
+
| `icons?` | Array of Icon objects for UI representation |
|
|
258
|
+
|
|
259
|
+
```typescript
|
|
260
|
+
import { Resource, ResourceContext } from '@frontmcp/sdk';
|
|
261
|
+
|
|
262
|
+
@Resource({
|
|
263
|
+
name: 'app_config',
|
|
264
|
+
uri: 'config://app/settings',
|
|
265
|
+
description: 'Current application settings',
|
|
266
|
+
mimeType: 'application/json',
|
|
267
|
+
})
|
|
268
|
+
class AppConfigResource extends ResourceContext {
|
|
269
|
+
async read() {
|
|
270
|
+
const config = await this.get(ConfigService).getAll();
|
|
271
|
+
return { contents: [{ uri: this.uri, text: JSON.stringify(config) }] };
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## 6. @ResourceTemplate
|
|
279
|
+
|
|
280
|
+
**Purpose:** Exposes a parameterized MCP resource with URI pattern matching.
|
|
281
|
+
|
|
282
|
+
**When to use:** When resources are identified by dynamic parameters (e.g., user profiles, documents by ID).
|
|
283
|
+
|
|
284
|
+
**Key fields:**
|
|
285
|
+
|
|
286
|
+
| Field | Description |
|
|
287
|
+
| -------------- | --------------------------------------------------------------- |
|
|
288
|
+
| `name` | Resource template name |
|
|
289
|
+
| `title?` | Human-readable display title for UIs |
|
|
290
|
+
| `uriTemplate` | URI template with parameters (e.g., `users://{userId}/profile`) |
|
|
291
|
+
| `description?` | What this resource provides |
|
|
292
|
+
| `mimeType?` | Content MIME type |
|
|
293
|
+
| `icons?` | Array of Icon objects for UI representation |
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
import { ResourceTemplate, ResourceContext } from '@frontmcp/sdk';
|
|
297
|
+
|
|
298
|
+
@ResourceTemplate({
|
|
299
|
+
name: 'user_profile',
|
|
300
|
+
uriTemplate: 'users://{userId}/profile',
|
|
301
|
+
description: 'User profile by ID',
|
|
302
|
+
mimeType: 'application/json',
|
|
303
|
+
})
|
|
304
|
+
class UserProfileResource extends ResourceContext {
|
|
305
|
+
async read(uri: string, params: { userId: string }) {
|
|
306
|
+
const user = await this.get(UserService).findById(params.userId);
|
|
307
|
+
return { contents: [{ uri, text: JSON.stringify(user) }] };
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## 7. @Agent
|
|
315
|
+
|
|
316
|
+
**Purpose:** Defines an autonomous AI agent that uses LLMs to accomplish tasks, optionally with tools and sub-agents.
|
|
317
|
+
|
|
318
|
+
**When to use:** When you need an autonomous entity that reasons, plans, and executes multi-step tasks using LLMs.
|
|
319
|
+
|
|
320
|
+
**Key fields:**
|
|
321
|
+
|
|
322
|
+
| Field | Description |
|
|
323
|
+
| --------------- | ------------------------------------------------------ |
|
|
324
|
+
| `name` | Agent name |
|
|
325
|
+
| `description` | What this agent does |
|
|
326
|
+
| `llm` | LLM configuration (model, provider, temperature, etc.) |
|
|
327
|
+
| `inputSchema?` | Zod raw shape for agent input |
|
|
328
|
+
| `outputSchema?` | Zod schema for structured output |
|
|
329
|
+
| `tools?` | Tools available to this agent |
|
|
330
|
+
| `agents?` | Sub-agents for delegation |
|
|
331
|
+
| `exports?` | What capabilities to expose externally |
|
|
332
|
+
| `swarm?` | Multi-agent swarm configuration |
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
import { Agent, AgentContext } from '@frontmcp/sdk';
|
|
336
|
+
import { z } from 'zod';
|
|
337
|
+
|
|
338
|
+
@Agent({
|
|
339
|
+
name: 'research_agent',
|
|
340
|
+
description: 'Researches topics and produces summaries',
|
|
341
|
+
llm: { model: 'claude-sonnet-4-20250514', provider: 'anthropic' },
|
|
342
|
+
inputSchema: {
|
|
343
|
+
topic: z.string().describe('Topic to research'),
|
|
344
|
+
},
|
|
345
|
+
tools: [WebSearchTool, SummarizeTool],
|
|
346
|
+
})
|
|
347
|
+
class ResearchAgent extends AgentContext {
|
|
348
|
+
async execute(input: { topic: string }) {
|
|
349
|
+
return this.run(`Research and summarize: ${input.topic}`);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## 8. @Skill
|
|
357
|
+
|
|
358
|
+
**Purpose:** Packages knowledge, instructions, and tools into a reusable workflow unit that LLMs can discover and follow.
|
|
359
|
+
|
|
360
|
+
**When to use:** When you want to bundle a set of instructions and tools into a cohesive capability that an LLM can activate.
|
|
361
|
+
|
|
362
|
+
**Key fields:**
|
|
363
|
+
|
|
364
|
+
| Field | Description |
|
|
365
|
+
| -------------------- | ------------------------------------------------------------------------------ |
|
|
366
|
+
| `name` | Skill name (kebab-case, max 64 chars) |
|
|
367
|
+
| `description` | What this skill enables (max 1024 chars, no HTML/XML) |
|
|
368
|
+
| `instructions` | Inline string, `{ file: '...' }`, or `{ url: '...' }` |
|
|
369
|
+
| `tools?` | Tool classes, names, or `{ tool/name, purpose?, required? }` refs |
|
|
370
|
+
| `parameters?` | Input parameters: `[{ name, description?, type?, default? }]` |
|
|
371
|
+
| `examples?` | Usage examples: `[{ scenario, parameters?, expectedOutcome? }]` |
|
|
372
|
+
| `visibility?` | Discovery scope: `'mcp'`, `'http'`, or `'both'` (default: `'both'`) |
|
|
373
|
+
| `toolValidation?` | `'strict'` \| `'warn'` \| `'ignore'` for missing tool refs (default: `'warn'`) |
|
|
374
|
+
| `priority?` | Search ranking weight (higher = earlier). Default: `0` |
|
|
375
|
+
| `hideFromDiscovery?` | Hide from search results; still loadable by ID |
|
|
376
|
+
| `tags?` | Tags for categorization and search |
|
|
377
|
+
| `license?` | License identifier (per Agent Skills spec, e.g., `'MIT'`) |
|
|
378
|
+
| `compatibility?` | Environment requirements (max 500 chars, e.g., `'Node.js 18+'`) |
|
|
379
|
+
| `specMetadata?` | Arbitrary key-value map (Agent Skills spec `metadata` field) |
|
|
380
|
+
| `allowedTools?` | Space-delimited pre-approved tool names (Agent Skills spec) |
|
|
381
|
+
| `resources?` | Bundled dirs: `{ scripts?, references?, assets? }` (Agent Skills spec) |
|
|
382
|
+
|
|
383
|
+
```typescript
|
|
384
|
+
import { Skill } from '@frontmcp/sdk';
|
|
385
|
+
|
|
386
|
+
@Skill({
|
|
387
|
+
name: 'code_migration',
|
|
388
|
+
description: 'Guides migration of code between frameworks',
|
|
389
|
+
instructions: `
|
|
390
|
+
1. Analyze the source codebase structure
|
|
391
|
+
2. Identify framework-specific patterns
|
|
392
|
+
3. Generate migration plan
|
|
393
|
+
4. Apply transformations using the provided tools
|
|
394
|
+
`,
|
|
395
|
+
tools: [AnalyzeTool, TransformTool, ValidateTool],
|
|
396
|
+
visibility: 'both',
|
|
397
|
+
})
|
|
398
|
+
class CodeMigrationSkill {}
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
## 9. @Plugin
|
|
404
|
+
|
|
405
|
+
**Purpose:** Adds lifecycle hooks, DI providers, and context extensions to the server.
|
|
406
|
+
|
|
407
|
+
**When to use:** When you need cross-cutting concerns (logging, caching, session memory) that span multiple tools.
|
|
408
|
+
|
|
409
|
+
**Key fields:**
|
|
410
|
+
|
|
411
|
+
| Field | Description |
|
|
412
|
+
| -------------------- | --------------------------------------------------------------- |
|
|
413
|
+
| `name` | Plugin name |
|
|
414
|
+
| `providers?` | DI providers this plugin registers |
|
|
415
|
+
| `contextExtensions?` | Extensions to add to execution contexts (e.g., `this.remember`) |
|
|
416
|
+
| `tools?` | Tools provided by this plugin |
|
|
417
|
+
|
|
418
|
+
```typescript
|
|
419
|
+
import { Plugin } from '@frontmcp/sdk';
|
|
420
|
+
|
|
421
|
+
@Plugin({
|
|
422
|
+
name: 'audit-log',
|
|
423
|
+
providers: [AuditLogProvider],
|
|
424
|
+
contextExtensions: [installAuditExtension],
|
|
425
|
+
})
|
|
426
|
+
class AuditPlugin {}
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
---
|
|
430
|
+
|
|
431
|
+
## 10. @Adapter
|
|
432
|
+
|
|
433
|
+
**Purpose:** Integrates an external API or data source, converting it into FrontMCP tools and resources.
|
|
434
|
+
|
|
435
|
+
**When to use:** When you want to auto-generate MCP tools/resources from an external OpenAPI spec, GraphQL schema, or other source.
|
|
436
|
+
|
|
437
|
+
**Key fields:**
|
|
438
|
+
|
|
439
|
+
| Field | Description |
|
|
440
|
+
| ------ | ------------ |
|
|
441
|
+
| `name` | Adapter name |
|
|
442
|
+
|
|
443
|
+
```typescript
|
|
444
|
+
import { Adapter } from '@frontmcp/sdk';
|
|
445
|
+
|
|
446
|
+
@Adapter({ name: 'github-api' })
|
|
447
|
+
class GitHubAdapter {
|
|
448
|
+
async connect() {
|
|
449
|
+
// Load OpenAPI spec and generate tools
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
---
|
|
455
|
+
|
|
456
|
+
## 11. @Provider
|
|
457
|
+
|
|
458
|
+
**Purpose:** Registers a dependency injection provider in the FrontMCP DI container.
|
|
459
|
+
|
|
460
|
+
**When to use:** When you need injectable services, configuration, or factories available via `this.get(Token)`.
|
|
461
|
+
|
|
462
|
+
**Key fields:**
|
|
463
|
+
|
|
464
|
+
| Field | Description |
|
|
465
|
+
| ------------ | --------------------------------------------------------------- |
|
|
466
|
+
| `name` | Provider name |
|
|
467
|
+
| `provide` | Injection token |
|
|
468
|
+
| `useClass` | Class to instantiate (pick one of useClass/useValue/useFactory) |
|
|
469
|
+
| `useValue` | Static value to inject |
|
|
470
|
+
| `useFactory` | Factory function for dynamic creation |
|
|
471
|
+
|
|
472
|
+
```typescript
|
|
473
|
+
import { Provider } from '@frontmcp/sdk';
|
|
474
|
+
|
|
475
|
+
@Provider({
|
|
476
|
+
name: 'database',
|
|
477
|
+
provide: DatabaseToken,
|
|
478
|
+
useFactory: () => new DatabaseClient(process.env.DB_URL),
|
|
479
|
+
})
|
|
480
|
+
class DatabaseProvider {}
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
---
|
|
484
|
+
|
|
485
|
+
## 12. @Flow
|
|
486
|
+
|
|
487
|
+
**Purpose:** Defines a custom request/response flow with a multi-stage processing plan.
|
|
488
|
+
|
|
489
|
+
**When to use:** When you need complex multi-step request processing beyond simple tool execution (e.g., validation, transformation, approval chains).
|
|
490
|
+
|
|
491
|
+
**Key fields:**
|
|
492
|
+
|
|
493
|
+
| Field | Description |
|
|
494
|
+
| -------------- | ----------------------------------- |
|
|
495
|
+
| `name` | Flow name |
|
|
496
|
+
| `plan` | Array of stages to execute in order |
|
|
497
|
+
| `inputSchema` | Zod schema for flow input |
|
|
498
|
+
| `outputSchema` | Zod schema for flow output |
|
|
499
|
+
| `access` | Access control configuration |
|
|
500
|
+
|
|
501
|
+
```typescript
|
|
502
|
+
import { Flow } from '@frontmcp/sdk';
|
|
503
|
+
import { z } from 'zod';
|
|
504
|
+
|
|
505
|
+
@Flow({
|
|
506
|
+
name: 'approval-flow',
|
|
507
|
+
plan: [ValidateStage, EnrichStage, ApproveStage, ExecuteStage],
|
|
508
|
+
inputSchema: z.object({ action: z.string(), target: z.string() }),
|
|
509
|
+
outputSchema: z.object({ approved: z.boolean(), result: z.unknown() }),
|
|
510
|
+
access: { roles: ['admin'] },
|
|
511
|
+
})
|
|
512
|
+
class ApprovalFlow {}
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
---
|
|
516
|
+
|
|
517
|
+
## 13. @Job
|
|
518
|
+
|
|
519
|
+
**Purpose:** Declares a long-running or scheduled background job.
|
|
520
|
+
|
|
521
|
+
**When to use:** When you need recurring tasks (cron), background processing, or deferred work.
|
|
522
|
+
|
|
523
|
+
**Key fields:**
|
|
524
|
+
|
|
525
|
+
| Field | Description |
|
|
526
|
+
| -------------------- | ------------------------------------------------------------- |
|
|
527
|
+
| `name` | Job name |
|
|
528
|
+
| `description` | What the job does |
|
|
529
|
+
| `inputSchema` | Zod schema for job input parameters |
|
|
530
|
+
| `outputSchema` | Zod schema for job output |
|
|
531
|
+
| `retry?` | `{ maxAttempts, backoffMs, backoffMultiplier, maxBackoffMs }` |
|
|
532
|
+
| `timeout?` | Execution timeout in ms |
|
|
533
|
+
| `tags?` | Categorization tags |
|
|
534
|
+
| `labels?` | Key-value labels (e.g., `{ env: 'prod' }`) |
|
|
535
|
+
| `hideFromDiscovery?` | Hide from job listing |
|
|
536
|
+
| `permissions?` | Access control: `[{ action: 'execute', roles: ['admin'] }]` |
|
|
537
|
+
|
|
538
|
+
```typescript
|
|
539
|
+
import { Job, JobContext } from '@frontmcp/sdk';
|
|
540
|
+
import { z } from 'zod';
|
|
541
|
+
|
|
542
|
+
@Job({
|
|
543
|
+
name: 'sync_data',
|
|
544
|
+
description: 'Synchronize data from external sources',
|
|
545
|
+
inputSchema: z.object({ source: z.string().describe('Data source to sync') }),
|
|
546
|
+
outputSchema: z.object({ synced: z.number() }),
|
|
547
|
+
retry: { maxAttempts: 3, backoffMs: 1000, backoffMultiplier: 2, maxBackoffMs: 60_000 },
|
|
548
|
+
timeout: 300_000,
|
|
549
|
+
})
|
|
550
|
+
class SyncDataJob extends JobContext {
|
|
551
|
+
async execute(input: { source: string }) {
|
|
552
|
+
const count = await this.get(SyncService).runFullSync(input.source);
|
|
553
|
+
return { synced: count };
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
---
|
|
559
|
+
|
|
560
|
+
## 14. @Workflow
|
|
561
|
+
|
|
562
|
+
**Purpose:** Orchestrates a multi-step workflow composed of sequential or parallel steps.
|
|
563
|
+
|
|
564
|
+
**When to use:** When you need to coordinate multiple jobs or actions in a defined order with error handling and rollback.
|
|
565
|
+
|
|
566
|
+
**Key fields:**
|
|
567
|
+
|
|
568
|
+
| Field | Description |
|
|
569
|
+
| -------------------- | ------------------------------------------------------------------ |
|
|
570
|
+
| `name` | Workflow name |
|
|
571
|
+
| `description` | What this workflow accomplishes |
|
|
572
|
+
| `steps` | Array of step definitions (see step fields below) |
|
|
573
|
+
| `trigger?` | `'manual'` \| `'webhook'` \| `'event'` |
|
|
574
|
+
| `webhook?` | `{ path, secret, methods }` — required when trigger is `'webhook'` |
|
|
575
|
+
| `timeout?` | Overall workflow timeout in ms |
|
|
576
|
+
| `maxConcurrency?` | Maximum parallel step concurrency (default: 5) |
|
|
577
|
+
| `tags?` | Categorization tags |
|
|
578
|
+
| `labels?` | Key-value labels (e.g., `{ env: 'prod' }`) |
|
|
579
|
+
| `hideFromDiscovery?` | Hide from workflow listing |
|
|
580
|
+
| `permissions?` | Access control: `[{ action: 'execute', roles: ['admin'] }]` |
|
|
581
|
+
| `inputSchema?` | Zod schema for workflow input parameters |
|
|
582
|
+
| `outputSchema?` | Zod schema for workflow output |
|
|
583
|
+
|
|
584
|
+
**Step fields:**
|
|
585
|
+
|
|
586
|
+
| Step Field | Description |
|
|
587
|
+
| ------------------ | --------------------------------------------------------------- |
|
|
588
|
+
| `id` | Unique step identifier |
|
|
589
|
+
| `jobName` | Name of the `@Job` to execute |
|
|
590
|
+
| `input?` | Static object or `(steps) => object` function for dynamic input |
|
|
591
|
+
| `dependsOn?` | Array of step IDs that must complete first |
|
|
592
|
+
| `condition?` | `(steps) => boolean` — skip step if returns false |
|
|
593
|
+
| `continueOnError?` | Continue workflow if this step fails (default: `false`) |
|
|
594
|
+
| `timeout?` | Per-step timeout in ms |
|
|
595
|
+
| `retry?` | Per-step retry config (same shape as `@Job.retry`) |
|
|
596
|
+
|
|
597
|
+
```typescript
|
|
598
|
+
import { Workflow } from '@frontmcp/sdk';
|
|
599
|
+
|
|
600
|
+
@Workflow({
|
|
601
|
+
name: 'deploy_pipeline',
|
|
602
|
+
description: 'Full deployment pipeline',
|
|
603
|
+
trigger: 'webhook',
|
|
604
|
+
webhookConfig: { path: '/hooks/deploy', secret: process.env.WEBHOOK_SECRET!, methods: ['POST'] },
|
|
605
|
+
timeout: 600_000,
|
|
606
|
+
steps: [
|
|
607
|
+
{ id: 'build', jobName: 'build_app', input: { env: 'production' } },
|
|
608
|
+
{ id: 'test', jobName: 'run_tests', dependsOn: ['build'] },
|
|
609
|
+
{ id: 'deploy', jobName: 'deploy_app', dependsOn: ['test'], condition: (steps) => steps.test.success },
|
|
610
|
+
],
|
|
611
|
+
})
|
|
612
|
+
class DeployPipeline {}
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
---
|
|
616
|
+
|
|
617
|
+
## 15. @Hook Decorators (@Will, @Did, @Stage, @Around)
|
|
618
|
+
|
|
619
|
+
**Purpose:** Attach lifecycle hooks to flows, allowing interception at different points.
|
|
620
|
+
|
|
621
|
+
**When to use:** When you need to run logic before, after, at a specific stage of, or wrapping around a flow execution.
|
|
622
|
+
|
|
623
|
+
**Variants:**
|
|
624
|
+
|
|
625
|
+
| Decorator | Timing | Description |
|
|
626
|
+
| --------- | -------- | ----------------------------------------- |
|
|
627
|
+
| `@Will` | Before | Runs before the flow executes |
|
|
628
|
+
| `@Did` | After | Runs after the flow completes |
|
|
629
|
+
| `@Stage` | During | Runs at a specific stage in the flow plan |
|
|
630
|
+
| `@Around` | Wrapping | Wraps the flow, controlling execution |
|
|
631
|
+
|
|
632
|
+
```typescript
|
|
633
|
+
import { Will, Did, Stage, Around, HookContext } from '@frontmcp/sdk';
|
|
634
|
+
|
|
635
|
+
class AuditHooks {
|
|
636
|
+
@Will('tools:call-tool')
|
|
637
|
+
async beforeToolCall(ctx: HookContext) {
|
|
638
|
+
ctx.state.set('startTime', Date.now());
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
@Did('tools:call-tool')
|
|
642
|
+
async afterToolCall(ctx: HookContext) {
|
|
643
|
+
const duration = Date.now() - ctx.state.get('startTime');
|
|
644
|
+
await this.get(AuditService).log({ tool: ctx.toolName, duration });
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
@Around('resources:read-resource')
|
|
648
|
+
async cacheResource(ctx: HookContext, next: () => Promise<void>) {
|
|
649
|
+
const cached = await this.get(CacheService).get(ctx.uri);
|
|
650
|
+
if (cached) {
|
|
651
|
+
ctx.respond(cached);
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
654
|
+
await next();
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
---
|
|
660
|
+
|
|
661
|
+
## Quick Reference Table
|
|
662
|
+
|
|
663
|
+
| Decorator | Extends | Registered In | Purpose |
|
|
664
|
+
| --------------------------- | ----------------- | ---------------- | ------------------------ |
|
|
665
|
+
| `@FrontMcp` | - | Root | Server configuration |
|
|
666
|
+
| `@App` | - | `@FrontMcp.apps` | Module grouping |
|
|
667
|
+
| `@Tool` | `ToolContext` | `@App.tools` | Executable action |
|
|
668
|
+
| `@Prompt` | `PromptContext` | `@App.prompts` | Prompt template |
|
|
669
|
+
| `@Resource` | `ResourceContext` | `@App.resources` | Static data |
|
|
670
|
+
| `@ResourceTemplate` | `ResourceContext` | `@App.resources` | Parameterized data |
|
|
671
|
+
| `@Agent` | `AgentContext` | `@App.agents` | Autonomous AI agent |
|
|
672
|
+
| `@Skill` | - | `@App.skills` | Knowledge package |
|
|
673
|
+
| `@Plugin` | - | `@App.plugins` | Cross-cutting concern |
|
|
674
|
+
| `@Adapter` | - | `@App.adapters` | External integration |
|
|
675
|
+
| `@Provider` | - | `@App.providers` | DI binding |
|
|
676
|
+
| `@Flow` | - | `@App` | Custom flow |
|
|
677
|
+
| `@Job` | `JobContext` | `@App.jobs` | Background task |
|
|
678
|
+
| `@Workflow` | - | `@App.workflows` | Multi-step orchestration |
|
|
679
|
+
| `@Will/@Did/@Stage/@Around` | - | Entry class | Lifecycle hooks |
|
|
680
|
+
|
|
681
|
+
---
|
|
682
|
+
|
|
683
|
+
## Common Patterns
|
|
684
|
+
|
|
685
|
+
| Pattern | Correct | Incorrect | Why |
|
|
686
|
+
| --------------------------- | ----------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
687
|
+
| Grouping tools into modules | Place tools inside `@App({ tools: [...] })` | Register tools directly in `@FrontMcp({ tools: [...] })` for large servers | Apps provide logical grouping, scoped providers, and isolation; standalone tools in `@FrontMcp` are only appropriate for small servers or global utilities |
|
|
688
|
+
| Exposing data to the LLM | Use `@Resource` for fixed URIs, `@ResourceTemplate` for parameterized URIs | Using `@Tool` to return static data that never changes | Resources are the MCP-standard way to expose readable data; tools are for actions with side effects or dynamic computation |
|
|
689
|
+
| Cross-cutting concerns | Create a `@Plugin` with providers and context extensions | Adding logging/caching logic directly inside every tool's `execute()` method | Plugins centralize shared behavior, reduce duplication, and can be reused across servers |
|
|
690
|
+
| Background processing | Use `@Job` with a cron schedule for recurring work | Using `setTimeout` or manual polling inside a tool | Jobs integrate with the scheduler, support persistence, and are visible in server diagnostics |
|
|
691
|
+
| Multi-step orchestration | Use `@Workflow` with ordered steps referencing `@Job` classes | Chaining multiple tool calls manually from the LLM | Workflows provide built-in ordering, error handling, and rollback semantics |
|
|
692
|
+
| Injecting services | Use `@Provider` with `useFactory`/`useClass` and access via `this.get(Token)` | Importing singletons directly or using global state | DI providers support testability, lifecycle management, and per-scope isolation |
|
|
693
|
+
|
|
694
|
+
---
|
|
695
|
+
|
|
696
|
+
## Verification Checklist
|
|
697
|
+
|
|
698
|
+
### Structure
|
|
699
|
+
|
|
700
|
+
- [ ] Server has exactly one `@FrontMcp` decorated class
|
|
701
|
+
- [ ] Every `@App` is listed in the `@FrontMcp({ apps: [...] })` array
|
|
702
|
+
- [ ] Each tool, resource, prompt, agent, and skill is registered in an `@App` (or in `@FrontMcp` for standalone use)
|
|
703
|
+
|
|
704
|
+
### Decorator Fields
|
|
705
|
+
|
|
706
|
+
- [ ] Every `@Tool` has `name`, `description`, and `inputSchema` defined
|
|
707
|
+
- [ ] Every `@Resource` has `name` and `uri` with a valid scheme (e.g., `config://`, `file://`)
|
|
708
|
+
- [ ] Every `@ResourceTemplate` has `uriTemplate` with `{param}` placeholders matching the `read()` params argument
|
|
709
|
+
- [ ] Every `@Prompt` has `name` and at least one argument when it accepts input
|
|
710
|
+
- [ ] Every `@Agent` has `name`, `description`, and `llm` configuration
|
|
711
|
+
|
|
712
|
+
### Inheritance
|
|
713
|
+
|
|
714
|
+
- [ ] Tool classes extend `ToolContext` and implement `execute()`
|
|
715
|
+
- [ ] Prompt classes extend `PromptContext` and implement `execute()`
|
|
716
|
+
- [ ] Resource classes extend `ResourceContext` and implement `read()`
|
|
717
|
+
- [ ] Agent classes extend `AgentContext` and implement `execute()`
|
|
718
|
+
- [ ] Job classes extend `JobContext` and implement `execute()`
|
|
719
|
+
|
|
720
|
+
### Hooks
|
|
721
|
+
|
|
722
|
+
- [ ] Hook flow strings match valid flows (e.g., `tools:call-tool`, `resources:read-resource`)
|
|
723
|
+
- [ ] `@Around` hooks call `await next()` to continue the chain (unless intentionally short-circuiting)
|
|
724
|
+
- [ ] Hooks do not mutate `rawInput` -- use `ctx.state.set()` for flow state
|
|
725
|
+
|
|
726
|
+
### DI and Plugins
|
|
727
|
+
|
|
728
|
+
- [ ] All `@Provider` entries specify exactly one of `useClass`, `useValue`, or `useFactory`
|
|
729
|
+
- [ ] Plugins are registered in `@App({ plugins: [...] })` or `@FrontMcp({ plugins: [...] })`
|
|
730
|
+
- [ ] Context extensions installed by plugins match the module augmentation declarations
|
|
731
|
+
|
|
732
|
+
---
|
|
733
|
+
|
|
734
|
+
## Troubleshooting
|
|
735
|
+
|
|
736
|
+
| Problem | Cause | Solution |
|
|
737
|
+
| -------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
|
|
738
|
+
| Tool does not appear in `tools/list` MCP response | Tool class is not registered in any `@App({ tools: [...] })` or `@FrontMcp({ tools: [...] })` | Add the tool class to the `tools` array of the appropriate `@App` or `@FrontMcp` decorator |
|
|
739
|
+
| `this.get(Token)` throws `DependencyNotFoundError` | The provider for that token is not registered or is registered in a different app scope | Add a `@Provider` for the token in the same `@App` or in `@FrontMcp({ providers: [...] })` for global access |
|
|
740
|
+
| Resource returns 404 / `ResourceNotFoundError` | The `uri` in `@Resource` does not match the requested URI, or `uriTemplate` parameters are misaligned | Verify the URI string exactly matches what the client requests; for templates, confirm `{param}` names match |
|
|
741
|
+
| Hook never fires | The `flow` string in `@Will`/`@Did`/`@Around`/`@Stage` does not match any registered flow | Check the flow string against valid flows (e.g., `tools:call-tool`, `resources:read-resource`, `resources:list-resources`) |
|
|
742
|
+
| Plugin context extension is `undefined` at runtime | The plugin's `installContextExtension` function was not called, or module augmentation is missing | Ensure the plugin is registered and its context extension function runs at startup; verify the `declare module` augmentation exists |
|
|
743
|
+
| Agent `execute()` returns empty result | LLM configuration is missing or invalid (wrong model name, missing API key) | Verify `llm.model` and `llm.provider` in `@Agent`, and ensure the provider API key is set in environment variables |
|
|
744
|
+
|
|
745
|
+
---
|
|
746
|
+
|
|
747
|
+
## Reference
|
|
748
|
+
|
|
749
|
+
- **Official docs:** [FrontMCP Decorators Overview](https://docs.agentfront.dev/frontmcp/sdk-reference/decorators/overview)
|
|
750
|
+
- **Related skills:**
|
|
751
|
+
- `create-tool` -- step-by-step guide for building tools with `@Tool` and `ToolContext`
|
|
752
|
+
- `create-resource` -- patterns for `@Resource` and `@ResourceTemplate` usage
|
|
753
|
+
- `create-plugin` -- creating plugins with `@Plugin`, providers, and context extensions
|
|
754
|
+
- `configure-auth` -- authentication and session configuration (not decorator-focused)
|