@frontmcp/skills 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +135 -0
  3. package/catalog/TEMPLATE.md +49 -0
  4. package/catalog/adapters/create-adapter/SKILL.md +127 -0
  5. package/catalog/adapters/official-adapters/SKILL.md +136 -0
  6. package/catalog/auth/configure-auth/SKILL.md +250 -0
  7. package/catalog/auth/configure-auth/references/auth-modes.md +77 -0
  8. package/catalog/auth/configure-session/SKILL.md +201 -0
  9. package/catalog/config/configure-elicitation/SKILL.md +136 -0
  10. package/catalog/config/configure-http/SKILL.md +167 -0
  11. package/catalog/config/configure-throttle/SKILL.md +189 -0
  12. package/catalog/config/configure-throttle/references/guard-config.md +68 -0
  13. package/catalog/config/configure-transport/SKILL.md +151 -0
  14. package/catalog/config/configure-transport/references/protocol-presets.md +57 -0
  15. package/catalog/deployment/build-for-browser/SKILL.md +95 -0
  16. package/catalog/deployment/build-for-cli/SKILL.md +100 -0
  17. package/catalog/deployment/build-for-sdk/SKILL.md +218 -0
  18. package/catalog/deployment/deploy-to-cloudflare/SKILL.md +192 -0
  19. package/catalog/deployment/deploy-to-lambda/SKILL.md +304 -0
  20. package/catalog/deployment/deploy-to-node/SKILL.md +229 -0
  21. package/catalog/deployment/deploy-to-node/references/Dockerfile.example +45 -0
  22. package/catalog/deployment/deploy-to-vercel/SKILL.md +196 -0
  23. package/catalog/deployment/deploy-to-vercel/references/vercel.json.example +60 -0
  24. package/catalog/development/create-agent/SKILL.md +563 -0
  25. package/catalog/development/create-agent/references/llm-config.md +46 -0
  26. package/catalog/development/create-job/SKILL.md +566 -0
  27. package/catalog/development/create-prompt/SKILL.md +400 -0
  28. package/catalog/development/create-provider/SKILL.md +233 -0
  29. package/catalog/development/create-resource/SKILL.md +437 -0
  30. package/catalog/development/create-skill/SKILL.md +526 -0
  31. package/catalog/development/create-skill-with-tools/SKILL.md +579 -0
  32. package/catalog/development/create-tool/SKILL.md +418 -0
  33. package/catalog/development/create-tool/references/output-schema-types.md +56 -0
  34. package/catalog/development/create-tool/references/tool-annotations.md +34 -0
  35. package/catalog/development/create-workflow/SKILL.md +709 -0
  36. package/catalog/development/decorators-guide/SKILL.md +598 -0
  37. package/catalog/plugins/create-plugin/SKILL.md +336 -0
  38. package/catalog/plugins/create-plugin-hooks/SKILL.md +282 -0
  39. package/catalog/plugins/official-plugins/SKILL.md +667 -0
  40. package/catalog/setup/frontmcp-skills-usage/SKILL.md +200 -0
  41. package/catalog/setup/multi-app-composition/SKILL.md +358 -0
  42. package/catalog/setup/nx-workflow/SKILL.md +357 -0
  43. package/catalog/setup/project-structure-nx/SKILL.md +186 -0
  44. package/catalog/setup/project-structure-standalone/SKILL.md +153 -0
  45. package/catalog/setup/setup-project/SKILL.md +493 -0
  46. package/catalog/setup/setup-redis/SKILL.md +385 -0
  47. package/catalog/setup/setup-sqlite/SKILL.md +359 -0
  48. package/catalog/skills-manifest.json +414 -0
  49. package/catalog/testing/setup-testing/SKILL.md +539 -0
  50. package/catalog/testing/setup-testing/references/test-auth.md +88 -0
  51. package/catalog/testing/setup-testing/references/test-browser-build.md +57 -0
  52. package/catalog/testing/setup-testing/references/test-cli-binary.md +48 -0
  53. package/catalog/testing/setup-testing/references/test-direct-client.md +62 -0
  54. package/catalog/testing/setup-testing/references/test-e2e-handler.md +51 -0
  55. package/catalog/testing/setup-testing/references/test-tool-unit.md +41 -0
  56. package/package.json +34 -0
  57. package/src/index.d.ts +3 -0
  58. package/src/index.js +16 -0
  59. package/src/index.js.map +1 -0
  60. package/src/loader.d.ts +46 -0
  61. package/src/loader.js +75 -0
  62. package/src/loader.js.map +1 -0
  63. package/src/manifest.d.ts +81 -0
  64. package/src/manifest.js +26 -0
  65. package/src/manifest.js.map +1 -0
@@ -0,0 +1,437 @@
1
+ ---
2
+ name: create-resource
3
+ description: Create MCP resources and resource templates with URI-based access. Use when exposing data via URIs, creating resource templates, or serving dynamic content.
4
+ tags: [resources, mcp, uri, templates, decorator]
5
+ tools:
6
+ - name: create_resource
7
+ purpose: Scaffold a new resource or resource template class
8
+ parameters:
9
+ - name: name
10
+ description: Resource name in kebab-case
11
+ type: string
12
+ required: true
13
+ - name: type
14
+ description: Whether to create a static resource or resource template
15
+ type: string
16
+ required: false
17
+ examples:
18
+ - scenario: Create a static configuration resource
19
+ expected-outcome: Resource registered and readable via MCP at a fixed URI
20
+ - scenario: Create a resource template for user profiles
21
+ expected-outcome: Resource template with parameterized URI pattern
22
+ priority: 10
23
+ visibility: both
24
+ license: Apache-2.0
25
+ metadata:
26
+ docs: https://docs.agentfront.dev/frontmcp/servers/resources
27
+ ---
28
+
29
+ # Creating MCP Resources
30
+
31
+ Resources expose data to AI clients through URI-based access following the MCP protocol. FrontMCP supports two kinds: **static resources** with fixed URIs (`@Resource`) and **resource templates** with parameterized URI patterns (`@ResourceTemplate`).
32
+
33
+ ## When to Use @Resource vs @ResourceTemplate
34
+
35
+ Use `@Resource` when the data lives at a single, known URI (e.g., `config://app/settings`, `status://server`). Use `@ResourceTemplate` when you need a family of related resources identified by parameters in the URI (e.g., `users://{userId}/profile`, `repo://{owner}/{repo}/files/{path}`).
36
+
37
+ ## Static Resources with @Resource
38
+
39
+ ### Decorator Options
40
+
41
+ The `@Resource` decorator accepts:
42
+
43
+ - `name` (required) -- unique resource name
44
+ - `uri` (required) -- static URI with a valid scheme per RFC 3986
45
+ - `description` (optional) -- human-readable description
46
+ - `mimeType` (optional) -- MIME type of the resource content
47
+
48
+ ### Class-Based Pattern
49
+
50
+ Create a class extending `ResourceContext` and implement `execute(uri, params)`. It must return a `ReadResourceResult`.
51
+
52
+ ```typescript
53
+ import { Resource, ResourceContext } from '@frontmcp/sdk';
54
+ import { ReadResourceResult } from '@frontmcp/protocol';
55
+
56
+ @Resource({
57
+ name: 'app-config',
58
+ uri: 'config://app/settings',
59
+ description: 'Current application configuration',
60
+ mimeType: 'application/json',
61
+ })
62
+ class AppConfigResource extends ResourceContext {
63
+ async execute(uri: string, params: Record<string, string>): Promise<ReadResourceResult> {
64
+ const config = {
65
+ version: '2.1.0',
66
+ environment: 'production',
67
+ features: { darkMode: true, notifications: true },
68
+ };
69
+
70
+ return {
71
+ contents: [
72
+ {
73
+ uri,
74
+ mimeType: 'application/json',
75
+ text: JSON.stringify(config, null, 2),
76
+ },
77
+ ],
78
+ };
79
+ }
80
+ }
81
+ ```
82
+
83
+ ### ReadResourceResult Structure
84
+
85
+ The `ReadResourceResult` returned by `execute()` has this shape:
86
+
87
+ ```typescript
88
+ interface ReadResourceResult {
89
+ contents: Array<{
90
+ uri: string;
91
+ mimeType?: string;
92
+ text?: string; // string content
93
+ blob?: string; // base64-encoded binary content
94
+ }>;
95
+ }
96
+ ```
97
+
98
+ Each content item has a `uri`, optional `mimeType`, and either `text` (string data) or `blob` (base64 binary data).
99
+
100
+ ### Available Context Methods and Properties
101
+
102
+ `ResourceContext` extends `ExecutionContextBase`, providing:
103
+
104
+ **Methods:**
105
+
106
+ - `execute(uri, params)` -- the main method you implement
107
+ - `this.get(token)` -- resolve a dependency from DI (throws if not found)
108
+ - `this.tryGet(token)` -- resolve a dependency from DI (returns `undefined` if not found)
109
+ - `this.fail(err)` -- abort execution, triggers error flow (never returns)
110
+ - `this.mark(stage)` -- set active execution stage for debugging/tracking
111
+ - `this.fetch(input, init?)` -- HTTP fetch with context propagation
112
+
113
+ **Properties:**
114
+
115
+ - `this.metadata` -- resource metadata from the decorator
116
+ - `this.scope` -- the current scope instance
117
+ - `this.context` -- the execution context
118
+
119
+ ### Simplified Return Values
120
+
121
+ FrontMCP automatically normalizes common return shapes into valid `ReadResourceResult` format:
122
+
123
+ ```typescript
124
+ @Resource({
125
+ name: 'server-status',
126
+ uri: 'status://server',
127
+ mimeType: 'application/json',
128
+ })
129
+ class ServerStatusResource extends ResourceContext {
130
+ async execute(uri: string, params: Record<string, string>) {
131
+ // Return a plain object -- FrontMCP wraps it in { contents: [{ uri, text: JSON.stringify(...) }] }
132
+ return { status: 'healthy', uptime: process.uptime() };
133
+ }
134
+ }
135
+ ```
136
+
137
+ Supported return shapes:
138
+
139
+ - **Full `ReadResourceResult`**: `{ contents: [...] }` -- passed through as-is
140
+ - **Array of content items**: each item with `text` or `blob` is treated as a content entry
141
+ - **Plain string**: wrapped into a single text content block
142
+ - **Plain object**: serialized with `JSON.stringify` into a single text content block
143
+
144
+ ## Resource Templates with @ResourceTemplate
145
+
146
+ ### Decorator Options
147
+
148
+ The `@ResourceTemplate` decorator accepts:
149
+
150
+ - `name` (required) -- unique resource template name
151
+ - `uriTemplate` (required) -- URI pattern with `{paramName}` placeholders (RFC 6570 style)
152
+ - `description` (optional) -- human-readable description
153
+ - `mimeType` (optional) -- MIME type of the resource content
154
+
155
+ ### Class-Based Pattern
156
+
157
+ Use `@ResourceTemplate` with `uriTemplate` instead of `uri`. Type the `ResourceContext` generic parameter to get typed `params`.
158
+
159
+ ```typescript
160
+ import { ResourceTemplate, ResourceContext } from '@frontmcp/sdk';
161
+ import { ReadResourceResult } from '@frontmcp/protocol';
162
+
163
+ @ResourceTemplate({
164
+ name: 'user-profile',
165
+ uriTemplate: 'users://{userId}/profile',
166
+ description: 'User profile by ID',
167
+ mimeType: 'application/json',
168
+ })
169
+ class UserProfileResource extends ResourceContext<{ userId: string }> {
170
+ async execute(uri: string, params: { userId: string }): Promise<ReadResourceResult> {
171
+ const user = await this.fetchUser(params.userId);
172
+
173
+ return {
174
+ contents: [
175
+ {
176
+ uri,
177
+ mimeType: 'application/json',
178
+ text: JSON.stringify(user),
179
+ },
180
+ ],
181
+ };
182
+ }
183
+
184
+ private async fetchUser(userId: string) {
185
+ return { id: userId, name: 'Alice', email: 'alice@example.com' };
186
+ }
187
+ }
188
+ ```
189
+
190
+ When a client reads `users://u-123/profile`, the framework matches the template and passes `{ userId: 'u-123' }` as `params`.
191
+
192
+ ### Templates with Multiple Parameters
193
+
194
+ ```typescript
195
+ @ResourceTemplate({
196
+ name: 'repo-file',
197
+ uriTemplate: 'repo://{owner}/{repo}/files/{path}',
198
+ description: 'File content from a repository',
199
+ mimeType: 'text/plain',
200
+ })
201
+ class RepoFileResource extends ResourceContext<{ owner: string; repo: string; path: string }> {
202
+ async execute(uri: string, params: { owner: string; repo: string; path: string }): Promise<ReadResourceResult> {
203
+ const content = await this.fetchFileContent(params.owner, params.repo, params.path);
204
+
205
+ return {
206
+ contents: [
207
+ {
208
+ uri,
209
+ mimeType: this.metadata.mimeType ?? 'text/plain',
210
+ text: content,
211
+ },
212
+ ],
213
+ };
214
+ }
215
+
216
+ private async fetchFileContent(owner: string, repo: string, path: string): Promise<string> {
217
+ const response = await this.fetch(`https://api.github.com/repos/${owner}/${repo}/contents/${path}`);
218
+ const data = await response.json();
219
+ return Buffer.from(data.content, 'base64').toString('utf-8');
220
+ }
221
+ }
222
+ ```
223
+
224
+ ## Function-Style Builders
225
+
226
+ For simple cases, use `resource()` and `resourceTemplate()` function builders.
227
+
228
+ **Static resource:**
229
+
230
+ ```typescript
231
+ import { resource } from '@frontmcp/sdk';
232
+
233
+ const SystemInfo = resource({
234
+ name: 'system-info',
235
+ uri: 'system://info',
236
+ mimeType: 'application/json',
237
+ })((uri) => ({
238
+ contents: [
239
+ {
240
+ uri,
241
+ text: JSON.stringify({
242
+ platform: process.platform,
243
+ nodeVersion: process.version,
244
+ memoryUsage: process.memoryUsage(),
245
+ }),
246
+ },
247
+ ],
248
+ }));
249
+ ```
250
+
251
+ **Resource template:**
252
+
253
+ ```typescript
254
+ import { resourceTemplate } from '@frontmcp/sdk';
255
+
256
+ const LogFile = resourceTemplate({
257
+ name: 'log-file',
258
+ uriTemplate: 'logs://{date}/{level}',
259
+ mimeType: 'text/plain',
260
+ })((uri, params) => ({
261
+ contents: [
262
+ {
263
+ uri,
264
+ text: `Logs for ${params.date} at level ${params.level}`,
265
+ },
266
+ ],
267
+ }));
268
+ ```
269
+
270
+ Register them the same way as class resources: `resources: [SystemInfo, LogFile]`.
271
+
272
+ ## Remote and ESM Loading
273
+
274
+ Load resources from external modules or remote URLs.
275
+
276
+ **ESM loading:**
277
+
278
+ ```typescript
279
+ const ExternalResource = Resource.esm('@my-org/resources@^1.0.0', 'ExternalResource', {
280
+ description: 'A resource loaded from an ES module',
281
+ });
282
+ ```
283
+
284
+ **Remote loading:**
285
+
286
+ ```typescript
287
+ const CloudResource = Resource.remote('https://example.com/resources/data', 'CloudResource', {
288
+ description: 'A resource loaded from a remote server',
289
+ });
290
+ ```
291
+
292
+ Both return values that can be registered in `resources: [ExternalResource, CloudResource]`.
293
+
294
+ ## Binary Content with Blob
295
+
296
+ Return binary data as base64-encoded blobs:
297
+
298
+ ```typescript
299
+ @Resource({
300
+ name: 'app-logo',
301
+ uri: 'assets://logo.png',
302
+ description: 'Application logo image',
303
+ mimeType: 'image/png',
304
+ })
305
+ class AppLogoResource extends ResourceContext {
306
+ async execute(uri: string, params: Record<string, string>): Promise<ReadResourceResult> {
307
+ const { readFileBuffer } = await import('@frontmcp/utils');
308
+ const buffer = await readFileBuffer('/assets/logo.png');
309
+
310
+ return {
311
+ contents: [
312
+ {
313
+ uri,
314
+ mimeType: 'image/png',
315
+ blob: buffer.toString('base64'),
316
+ },
317
+ ],
318
+ };
319
+ }
320
+ }
321
+ ```
322
+
323
+ ## Multiple Content Items
324
+
325
+ A single resource can return multiple content entries:
326
+
327
+ ```typescript
328
+ @Resource({
329
+ name: 'dashboard-data',
330
+ uri: 'dashboard://overview',
331
+ description: 'Dashboard overview with metrics and chart data',
332
+ mimeType: 'application/json',
333
+ })
334
+ class DashboardResource extends ResourceContext {
335
+ async execute(uri: string, params: Record<string, string>): Promise<ReadResourceResult> {
336
+ const metrics = await this.loadMetrics();
337
+ const chartData = await this.loadChartData();
338
+
339
+ return {
340
+ contents: [
341
+ {
342
+ uri: `${uri}#metrics`,
343
+ mimeType: 'application/json',
344
+ text: JSON.stringify(metrics),
345
+ },
346
+ {
347
+ uri: `${uri}#charts`,
348
+ mimeType: 'application/json',
349
+ text: JSON.stringify(chartData),
350
+ },
351
+ ],
352
+ };
353
+ }
354
+
355
+ private async loadMetrics() {
356
+ return { users: 1500, revenue: 42000 };
357
+ }
358
+ private async loadChartData() {
359
+ return { labels: ['Jan', 'Feb'], values: [100, 200] };
360
+ }
361
+ }
362
+ ```
363
+
364
+ ## Dependency Injection
365
+
366
+ Resources have access to the same DI utilities as tools:
367
+
368
+ ```typescript
369
+ import type { Token } from '@frontmcp/di';
370
+
371
+ interface CacheService {
372
+ get(key: string): Promise<string | null>;
373
+ set(key: string, value: string, ttlMs: number): Promise<void>;
374
+ }
375
+ const CACHE: Token<CacheService> = Symbol('cache');
376
+
377
+ @ResourceTemplate({
378
+ name: 'cached-data',
379
+ uriTemplate: 'cache://{key}',
380
+ description: 'Cached data by key',
381
+ mimeType: 'application/json',
382
+ })
383
+ class CachedDataResource extends ResourceContext<{ key: string }> {
384
+ async execute(uri: string, params: { key: string }): Promise<ReadResourceResult> {
385
+ const cache = this.get(CACHE);
386
+ const value = await cache.get(params.key);
387
+
388
+ if (!value) {
389
+ this.fail(new Error(`Cache key not found: ${params.key}`));
390
+ }
391
+
392
+ return {
393
+ contents: [{ uri, mimeType: 'application/json', text: value }],
394
+ };
395
+ }
396
+ }
397
+ ```
398
+
399
+ ## Registration
400
+
401
+ Add resource classes (or function-style resources) to the `resources` array in `@FrontMcp` or `@App`.
402
+
403
+ ```typescript
404
+ import { FrontMcp, App } from '@frontmcp/sdk';
405
+
406
+ @App({
407
+ name: 'my-app',
408
+ resources: [AppConfigResource, UserProfileResource, SystemInfo, LogFile],
409
+ })
410
+ class MyApp {}
411
+
412
+ @FrontMcp({
413
+ info: { name: 'my-server', version: '1.0.0' },
414
+ apps: [MyApp],
415
+ resources: [DashboardResource], // can also register resources directly on the server
416
+ })
417
+ class MyServer {}
418
+ ```
419
+
420
+ ## URI Validation Rules
421
+
422
+ All resource URIs are validated per RFC 3986 at metadata level:
423
+
424
+ - Must have a valid scheme (e.g., `file://`, `https://`, `config://`, `custom://`).
425
+ - Scheme-less URIs like `my-resource` will be rejected at registration time.
426
+ - Template URIs must also have a valid scheme: `users://{id}` is valid, `{id}/profile` is not.
427
+ - URI validation happens at decorator parse time, so errors surface immediately during server startup.
428
+
429
+ ## Nx Generator
430
+
431
+ Scaffold a new resource using the Nx generator:
432
+
433
+ ```bash
434
+ nx generate @frontmcp/nx:resource
435
+ ```
436
+
437
+ This creates the resource file, spec file, and updates barrel exports.