@frontmcp/skills 1.0.2 → 1.0.4

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.
@@ -52,7 +52,8 @@ Entry point for building MCP server components. This skill helps you find the ri
52
52
  | Write instruction-only AI guidance (no code execution) | `create-skill` | Skill entries with markdown instructions from files, strings, or URLs |
53
53
  | Write AI guidance that also orchestrates tools | `create-skill-with-tools` | Skill entries that combine instructions with registered tools |
54
54
  | Look up any decorator signature or option | `decorators-guide` | Complete reference for @Tool, @Resource, @Prompt, @Agent, @App, @FrontMcp, and more |
55
- | Integrate an external API via OpenAPI spec | `official-adapters` | OpenapiAdapter with auth, polling, inline specs, and multiple API composition |
55
+ | Overview of all official adapters | `official-adapters` | Router to all adapter types; adapter vs plugin comparison |
56
+ | Integrate an external API via OpenAPI spec | `openapi-adapter` | OpenapiAdapter with auth, polling, filtering, transforms, format resolution, $ref security |
56
57
  | Use official plugins (caching, remember, feature flags) | `official-plugins` | Built-in plugins for caching, session memory, approval, and feature flags (dashboard is beta) |
57
58
  | Connect to an external data source via a custom adapter | `create-adapter` | Create custom adapters for external data sources |
58
59
  | Configure LLM settings for an agent component | `create-agent-llm-config` | Configure LLM settings for agent components |
@@ -70,7 +71,7 @@ Entry point for building MCP server components. This skill helps you find the ri
70
71
  6. **`create-agent`** — Build autonomous AI loops (advanced)
71
72
  7. **`create-job`** / **`create-workflow`** — Background processing (advanced)
72
73
  8. **`create-skill`** / **`create-skill-with-tools`** — Author your own skills (meta)
73
- 9. **`official-adapters`** — Integrate external APIs via OpenAPI specs
74
+ 9. **`official-adapters`** / **`openapi-adapter`** — Integrate external APIs via OpenAPI specs
74
75
  10. **`official-plugins`** — Add caching, session memory, feature flags, and more
75
76
 
76
77
  ## Cross-Cutting Patterns
@@ -123,4 +124,4 @@ Entry point for building MCP server components. This skill helps you find the ri
123
124
  ## Reference
124
125
 
125
126
  - [FrontMCP Overview](https://docs.agentfront.dev/frontmcp/fundamentals/overview)
126
- - Related skills: `create-tool`, `create-resource`, `create-prompt`, `create-agent`, `create-provider`, `create-job`, `create-workflow`, `create-skill`, `create-skill-with-tools`, `decorators-guide`, `official-adapters`, `official-plugins`
127
+ - Related skills: `create-tool`, `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`
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: authenticated-adapter-with-polling
3
- reference: official-adapters
3
+ reference: openapi-adapter
4
4
  level: intermediate
5
5
  description: 'Demonstrates configuring authentication (API key and bearer token) and automatic spec polling for OpenAPI adapters.'
6
6
  tags: [development, auth, openapi, security, adapters, authenticated]
@@ -80,5 +80,5 @@ class MyServer {}
80
80
 
81
81
  ## Related
82
82
 
83
- - See `official-adapters` for inline specs, multiple adapter registration, and troubleshooting
83
+ - See `openapi-adapter` for all five auth strategies, format resolution, and $ref security
84
84
  - See `decorators-guide` for the full `@App` and `@FrontMcp` field reference
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: basic-openapi-adapter
3
- reference: official-adapters
3
+ reference: openapi-adapter
4
4
  level: basic
5
5
  description: 'Demonstrates converting an OpenAPI specification into MCP tools automatically using `OpenapiAdapter` with minimal configuration.'
6
6
  tags: [development, openapi, adapters, adapter]
@@ -51,4 +51,4 @@ class MyServer {}
51
51
 
52
52
  ## Related
53
53
 
54
- - See `official-adapters` for authentication options, spec polling, and inline specs
54
+ - See `openapi-adapter` for authentication, filtering, transforms, and security options
@@ -0,0 +1,108 @@
1
+ ---
2
+ name: format-resolution-and-custom-resolvers
3
+ reference: openapi-adapter
4
+ level: intermediate
5
+ description: 'Demonstrates using built-in and custom format resolvers to enrich tool input schemas with concrete constraints from OpenAPI format values.'
6
+ tags: [development, openapi, adapters, format, schema, validation]
7
+ features:
8
+ - 'Enabling built-in format resolvers with `resolveFormats: true` for uuid, date-time, email, int32, etc.'
9
+ - 'Adding custom format resolvers for domain-specific formats (phone, currency)'
10
+ - 'Merging custom resolvers with built-ins where custom takes precedence'
11
+ - 'Using custom-only resolvers without built-ins for full control'
12
+ ---
13
+
14
+ # Format Resolution and Custom Resolvers
15
+
16
+ Demonstrates using built-in and custom format resolvers to enrich tool input schemas with concrete constraints from OpenAPI format values.
17
+
18
+ ## Code
19
+
20
+ ```typescript
21
+ // src/server.ts
22
+ import { FrontMcp, App } from '@frontmcp/sdk';
23
+ import { OpenapiAdapter } from '@frontmcp/adapters';
24
+
25
+ @App({
26
+ name: 'format-demo',
27
+ adapters: [
28
+ // Built-in format resolvers only
29
+ // uuid fields get regex patterns, date-time gets ISO 8601 format,
30
+ // int32 gets min/max constraints, email gets validation pattern
31
+ OpenapiAdapter.init({
32
+ name: 'users-api',
33
+ url: 'https://api.example.com/openapi.json',
34
+ baseUrl: 'https://api.example.com',
35
+ generateOptions: {
36
+ resolveFormats: true,
37
+ },
38
+ }),
39
+
40
+ // Built-in + custom format resolvers
41
+ // Custom resolvers are merged with built-ins; custom takes precedence
42
+ OpenapiAdapter.init({
43
+ name: 'payments-api',
44
+ url: 'https://payments.example.com/openapi.json',
45
+ baseUrl: 'https://payments.example.com',
46
+ generateOptions: {
47
+ resolveFormats: true,
48
+ formatResolvers: {
49
+ // Domain-specific formats
50
+ phone: (schema) => ({
51
+ ...schema,
52
+ pattern: '^\\+[1-9]\\d{1,14}$',
53
+ description: 'E.164 international phone number (e.g., +14155552671)',
54
+ }),
55
+ currency: (schema) => ({
56
+ ...schema,
57
+ pattern: '^[A-Z]{3}$',
58
+ description: 'ISO 4217 currency code (e.g., USD, EUR, GBP)',
59
+ }),
60
+ 'country-code': (schema) => ({
61
+ ...schema,
62
+ pattern: '^[A-Z]{2}$',
63
+ description: 'ISO 3166-1 alpha-2 country code (e.g., US, GB, DE)',
64
+ }),
65
+ },
66
+ },
67
+ }),
68
+
69
+ // Custom resolvers only (no built-ins)
70
+ // Only the formats you explicitly define are resolved
71
+ OpenapiAdapter.init({
72
+ name: 'legacy-api',
73
+ url: 'https://legacy.example.com/openapi.json',
74
+ baseUrl: 'https://legacy.example.com',
75
+ generateOptions: {
76
+ // Without resolveFormats: true, only custom resolvers apply
77
+ formatResolvers: {
78
+ 'social-security': (schema) => ({
79
+ ...schema,
80
+ pattern: '^\\d{3}-\\d{2}-\\d{4}$',
81
+ description: 'US Social Security Number (XXX-XX-XXXX)',
82
+ }),
83
+ },
84
+ },
85
+ }),
86
+ ],
87
+ })
88
+ class FormatDemoApp {}
89
+
90
+ @FrontMcp({
91
+ info: { name: 'format-demo-server', version: '1.0.0' },
92
+ apps: [FormatDemoApp],
93
+ http: { port: 3000 },
94
+ })
95
+ class MyServer {}
96
+ ```
97
+
98
+ ## What This Demonstrates
99
+
100
+ - Enabling built-in format resolvers with `resolveFormats: true` for uuid, date-time, email, int32, etc.
101
+ - Adding custom format resolvers for domain-specific formats (phone, currency)
102
+ - Merging custom resolvers with built-ins where custom takes precedence
103
+ - Using custom-only resolvers without built-ins for full control
104
+
105
+ ## Related
106
+
107
+ - See `openapi-adapter` for all generate options, authentication, and $ref security
108
+ - See `create-tool` for building tools with manual schema definitions
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: multi-api-hub-with-inline-spec
3
- reference: official-adapters
3
+ reference: openapi-adapter
4
4
  level: advanced
5
5
  description: 'Demonstrates registering multiple OpenAPI adapters from different APIs in a single app, including one with an inline spec definition instead of a remote URL.'
6
6
  tags: [development, openapi, remote, adapters, multi, api]
@@ -126,5 +126,5 @@ class MyServer {}
126
126
 
127
127
  ## Related
128
128
 
129
- - See `official-adapters` for spec polling, `securityResolver`, and the adapter vs plugin comparison
129
+ - See `openapi-adapter` for spec polling, `securityResolver`, and filtering operations
130
130
  - See `decorators-guide` for the `@Adapter` decorator and how adapters fit in the hierarchy
@@ -0,0 +1,111 @@
1
+ ---
2
+ name: ref-security-and-filtering
3
+ reference: openapi-adapter
4
+ level: intermediate
5
+ description: 'Demonstrates configuring $ref resolution security to prevent SSRF attacks and filtering which API operations become MCP tools.'
6
+ tags: [development, openapi, adapters, security, ssrf, filtering]
7
+ features:
8
+ - 'Configuring `refResolution` to restrict which hosts and protocols are allowed for external `$ref` pointers'
9
+ - 'Using `allowedHosts` to restrict $refs to trusted schema servers'
10
+ - 'Using `allowedProtocols` to enable or disable file://, http://, https://, and other protocols'
11
+ - 'Filtering operations with `includeOperations`, `excludeOperations`, and `filterFn`'
12
+ - 'Combining security hardening with operation filtering for a production-ready setup'
13
+ ---
14
+
15
+ # $ref Security and Operation Filtering
16
+
17
+ Demonstrates configuring $ref resolution security to prevent SSRF attacks and filtering which API operations become MCP tools.
18
+
19
+ ## Code
20
+
21
+ ```typescript
22
+ // src/server.ts
23
+ import { FrontMcp, App } from '@frontmcp/sdk';
24
+ import { OpenapiAdapter } from '@frontmcp/adapters';
25
+
26
+ @App({
27
+ name: 'secure-app',
28
+ adapters: [
29
+ // Production-hardened: restrict $refs to trusted hosts + filter operations
30
+ OpenapiAdapter.init({
31
+ name: 'partner-api',
32
+ url: 'https://api.partner.com/openapi.json',
33
+ baseUrl: 'https://api.partner.com',
34
+ loadOptions: {
35
+ refResolution: {
36
+ // Only allow $refs pointing to the partner's own schema server
37
+ allowedHosts: ['schemas.partner.com', 'api.partner.com'],
38
+ // Block additional hosts known to be problematic
39
+ blockedHosts: ['internal.partner.com'],
40
+ },
41
+ },
42
+ generateOptions: {
43
+ // Only expose read operations to MCP clients
44
+ filterFn: (op) => op.method === 'get',
45
+ // Skip deprecated endpoints
46
+ includeDeprecated: false,
47
+ },
48
+ staticAuth: {
49
+ apiKey: process.env.PARTNER_API_KEY!,
50
+ },
51
+ }),
52
+
53
+ // Internal API: allow internal IPs but lock down to specific operations
54
+ OpenapiAdapter.init({
55
+ name: 'internal-api',
56
+ url: 'http://10.0.0.5:8080/openapi.json',
57
+ baseUrl: 'http://10.0.0.5:8080',
58
+ loadOptions: {
59
+ refResolution: {
60
+ // Allow internal IPs since this is a trusted internal service
61
+ allowInternalIPs: true,
62
+ },
63
+ },
64
+ generateOptions: {
65
+ // Only include specific safe operations
66
+ includeOperations: ['getStatus', 'listMetrics', 'getConfig'],
67
+ },
68
+ }),
69
+
70
+ // Maximum lockdown: no external $refs at all
71
+ OpenapiAdapter.init({
72
+ name: 'sandbox-api',
73
+ url: 'https://sandbox.example.com/openapi.json',
74
+ baseUrl: 'https://sandbox.example.com',
75
+ loadOptions: {
76
+ refResolution: {
77
+ // Block ALL external $ref resolution — only local #/ pointers work
78
+ allowedProtocols: [],
79
+ },
80
+ },
81
+ generateOptions: {
82
+ // Exclude admin and dangerous operations
83
+ excludeOperations: ['deleteAll', 'resetDatabase', 'adminPanel'],
84
+ // Only include billing-related paths
85
+ filterFn: (op) => op.path.startsWith('/billing') || op.path.startsWith('/invoices'),
86
+ },
87
+ }),
88
+ ],
89
+ })
90
+ class SecureApp {}
91
+
92
+ @FrontMcp({
93
+ info: { name: 'secure-server', version: '1.0.0' },
94
+ apps: [SecureApp],
95
+ http: { port: 3000 },
96
+ })
97
+ class MyServer {}
98
+ ```
99
+
100
+ ## What This Demonstrates
101
+
102
+ - Configuring `refResolution` to restrict which hosts and protocols are allowed for external `$ref` pointers
103
+ - Using `allowedHosts` to restrict $refs to trusted schema servers
104
+ - Using `allowedProtocols` to enable or disable file://, http://, https://, and other protocols
105
+ - Filtering operations with `includeOperations`, `excludeOperations`, and `filterFn`
106
+ - Combining security hardening with operation filtering for a production-ready setup
107
+
108
+ ## Related
109
+
110
+ - See `openapi-adapter` for all `refResolution` options and the full blocked IP list
111
+ - See `official-adapters` for the adapter vs plugin comparison
@@ -1,39 +1,41 @@
1
1
  ---
2
2
  name: official-adapters
3
- description: Convert OpenAPI specs and external definitions into MCP tools automatically
3
+ description: Overview of all official FrontMCP adapters that convert external definitions into MCP primitives
4
4
  ---
5
5
 
6
6
  # Official Adapters
7
7
 
8
- Adapters convert external definitions (OpenAPI specs, Lambda functions, etc.) into MCP tools, resources, and prompts automatically.
8
+ Adapters convert external definitions (OpenAPI specs, Lambda functions, etc.) into MCP tools, resources, and prompts automatically. They are registered in the `adapters` array of `@App`.
9
9
 
10
10
  ## When to Use This Skill
11
11
 
12
12
  ### Must Use
13
13
 
14
- - Converting an OpenAPI/Swagger specification into MCP tools automatically
15
- - Integrating a REST API that provides a public OpenAPI spec (Petstore, GitHub, Jira, Slack)
16
- - Setting up authentication (API key, bearer token, OAuth) for an adapter-generated API integration
14
+ - Integrating an external API or service that has a machine-readable specification
15
+ - Auto-generating MCP tools from an API definition instead of writing them manually
17
16
 
18
17
  ### Recommended
19
18
 
20
19
  - Registering multiple external APIs as namespaced tool sets in a single server
21
- - Enabling spec polling to auto-refresh tool definitions when the upstream API changes
22
- - Providing an inline OpenAPI spec for APIs without a hosted spec URL
20
+ - Setting up authentication, polling, or transforms for adapter-generated tools
23
21
 
24
22
  ### Skip When
25
23
 
26
- - The external API has no OpenAPI spec and uses a custom protocol (see `create-adapter`)
24
+ - The external API has no machine-readable spec and uses a custom protocol (see `create-adapter`)
27
25
  - You need cross-cutting behavior like caching or logging (see `create-plugin` or `official-plugins`)
28
26
  - You are building tools manually without an external spec (see `create-tool`)
29
27
 
30
- > **Decision:** Use this skill when you have an OpenAPI/Swagger spec and want to automatically generate MCP tools from it using `OpenapiAdapter`.
28
+ > **Decision:** Use this skill when you have an external API definition and want to automatically generate MCP primitives from it.
31
29
 
32
- ## OpenAPI Adapter
30
+ ## Available Adapters
33
31
 
34
- The primary official adapter. Converts OpenAPI/Swagger specifications into MCP tools — one tool per operation.
32
+ | Adapter | Package | Description | Dedicated Skill |
33
+ | ------------------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------- |
34
+ | **OpenAPI Adapter** | `@frontmcp/adapters` | Converts OpenAPI 3.x specifications into MCP tools — one tool per operation. Supports authentication, spec polling, filtering, transforms, format resolution, and $ref security. | [`openapi-adapter`](openapi-adapter.md) |
35
35
 
36
- ### Installation
36
+ > More adapters will be added in future releases. To build a custom adapter for a non-OpenAPI source, see `create-adapter`.
37
+
38
+ ## Quick Start
37
39
 
38
40
  ```typescript
39
41
  import { OpenapiAdapter } from '@frontmcp/adapters';
@@ -48,99 +50,10 @@ import { OpenapiAdapter } from '@frontmcp/adapters';
48
50
  ],
49
51
  })
50
52
  class MyApp {}
53
+ // Generated tools: petstore:addPet, petstore:getPetById, petstore:deletePet, etc.
51
54
  ```
52
55
 
53
- Each OpenAPI operation becomes an MCP tool named `petstore:operationId`.
54
-
55
- ### With Authentication
56
-
57
- ```typescript
58
- // API Key via static auth
59
- OpenapiAdapter.init({
60
- name: 'my-api',
61
- url: 'https://api.example.com/openapi.json',
62
- baseUrl: 'https://api.example.com',
63
- staticAuth: {
64
- apiKey: process.env.API_KEY!,
65
- },
66
- });
67
-
68
- // API Key via additional headers
69
- OpenapiAdapter.init({
70
- name: 'my-api',
71
- url: 'https://api.example.com/openapi.json',
72
- baseUrl: 'https://api.example.com',
73
- additionalHeaders: {
74
- 'X-API-Key': process.env.API_KEY!,
75
- },
76
- });
77
-
78
- // Bearer token via static auth
79
- OpenapiAdapter.init({
80
- name: 'my-api',
81
- url: 'https://api.example.com/openapi.json',
82
- baseUrl: 'https://api.example.com',
83
- staticAuth: {
84
- jwt: process.env.API_TOKEN!,
85
- },
86
- });
87
-
88
- // Dynamic auth per tool using securityResolver
89
- OpenapiAdapter.init({
90
- name: 'my-api',
91
- url: 'https://api.example.com/openapi.json',
92
- baseUrl: 'https://api.example.com',
93
- securityResolver: (tool, ctx) => {
94
- return { jwt: ctx.authInfo?.token };
95
- },
96
- });
97
- ```
98
-
99
- ### Spec Polling
100
-
101
- Automatically refresh the OpenAPI spec at intervals:
102
-
103
- ```typescript
104
- OpenapiAdapter.init({
105
- name: 'evolving-api',
106
- url: 'https://api.example.com/openapi.json',
107
- polling: {
108
- intervalMs: 300000, // Re-fetch every 5 minutes
109
- },
110
- });
111
- ```
112
-
113
- ### Inline Spec
114
-
115
- Provide the OpenAPI spec directly instead of fetching from URL:
116
-
117
- ```typescript
118
- OpenapiAdapter.init({
119
- name: 'my-api',
120
- spec: {
121
- openapi: '3.0.0',
122
- info: { title: 'My API', version: '1.0.0' },
123
- paths: { ... },
124
- },
125
- })
126
- ```
127
-
128
- ### Multiple Adapters
129
-
130
- Register adapters from different APIs in the same app:
131
-
132
- ```typescript
133
- @App({
134
- name: 'IntegrationHub',
135
- adapters: [
136
- OpenapiAdapter.init({ name: 'github', url: 'https://api.github.com/openapi.json' }),
137
- OpenapiAdapter.init({ name: 'jira', url: 'https://jira.example.com/openapi.json' }),
138
- OpenapiAdapter.init({ name: 'slack', url: 'https://slack.com/openapi.json' }),
139
- ],
140
- })
141
- class IntegrationHub {}
142
- // Tools: github:createIssue, jira:createTicket, slack:postMessage, etc.
143
- ```
56
+ For full configuration, authentication, security, and advanced features, see the [`openapi-adapter`](openapi-adapter.md) reference.
144
57
 
145
58
  ## Adapter vs Plugin
146
59
 
@@ -153,57 +66,15 @@ class IntegrationHub {}
153
66
 
154
67
  ## Common Patterns
155
68
 
156
- | Pattern | Correct | Incorrect | Why |
157
- | -------------------- | ---------------------------------------------------------------------------- | --------------------------------------------------- | -------------------------------------------------------------------------------- |
158
- | Adapter registration | `OpenapiAdapter.init({ name: 'petstore', url: '...' })` in `adapters` array | Placing adapter in `plugins` array | Adapters go in `adapters`, not `plugins`; they serve different purposes |
159
- | Tool naming | Tools auto-named as `petstore:operationId` using adapter `name` as namespace | Expecting flat names like `listPets` | Adapter name is prepended to prevent collisions across multiple adapters |
160
- | Auth configuration | `staticAuth: { jwt: process.env.API_TOKEN! }` or `additionalHeaders` | Hardcoding secrets: `staticAuth: { jwt: 'sk-xxx' }` | Always use environment variables for secrets; never commit tokens |
161
- | Spec source | Use `url` for hosted specs or `spec` for inline definitions | Using both `url` and `spec` simultaneously | Only one source should be provided; `spec` takes precedence and `url` is ignored |
162
- | Multiple APIs | Register separate `OpenapiAdapter.init()` calls with unique `name` values | Using the same `name` for different adapters | Duplicate names cause tool naming collisions |
163
-
164
- ## Verification Checklist
165
-
166
- ### Configuration
167
-
168
- - [ ] `@frontmcp/adapters` package is installed
169
- - [ ] `OpenapiAdapter.init()` is in the `adapters` array of `@App`
170
- - [ ] Adapter has a unique `name` for tool namespacing
171
- - [ ] `url` points to a valid, reachable OpenAPI JSON/YAML endpoint (or `spec` is inline)
172
-
173
- ### Runtime
174
-
175
- - [ ] Generated tools appear in `tools/list` with `<name>:<operationId>` naming
176
- - [ ] Auth headers are sent correctly on API calls
177
- - [ ] Spec polling refreshes tool definitions at the configured interval
178
- - [ ] Invalid spec URL produces a clear startup error
179
-
180
- ### Production
181
-
182
- - [ ] API tokens and secrets are loaded from environment variables
183
- - [ ] Polling interval is appropriate for the API's update frequency
184
- - [ ] Multiple adapter registrations use distinct names
185
-
186
- ## Troubleshooting
187
-
188
- | Problem | Cause | Solution |
189
- | ---------------------------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
190
- | No tools generated from spec | Spec URL returns non-OpenAPI content or is unreachable | Verify URL returns valid OpenAPI 3.x JSON; check network access |
191
- | Authentication errors on API calls | Wrong auth config or missing credentials | Configure `staticAuth` for fixed credentials, `securityResolver`/`authProviderMapper` for dynamic auth, or `additionalHeaders` for header-based tokens; verify env vars are set |
192
- | Duplicate tool name error | Two adapters registered with the same `name` | Give each adapter a unique `name` (e.g., `'github'`, `'jira'`) |
193
- | Stale tools after API update | Spec polling not configured | Add `polling: { intervalMs: 300000 }` to refresh every 5 minutes |
194
- | TypeScript error importing adapter | Wrong import path | Import from `@frontmcp/adapters`: `import { OpenapiAdapter } from '@frontmcp/adapters'` |
195
-
196
- ## Examples
197
-
198
- | Example | Level | Description |
199
- | ----------------------------------------------------------------------------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
200
- | [`authenticated-adapter-with-polling`](../examples/official-adapters/authenticated-adapter-with-polling.md) | Intermediate | Demonstrates configuring authentication (API key and bearer token) and automatic spec polling for OpenAPI adapters. |
201
- | [`basic-openapi-adapter`](../examples/official-adapters/basic-openapi-adapter.md) | Basic | Demonstrates converting an OpenAPI specification into MCP tools automatically using `OpenapiAdapter` with minimal configuration. |
202
- | [`multi-api-hub-with-inline-spec`](../examples/official-adapters/multi-api-hub-with-inline-spec.md) | Advanced | Demonstrates registering multiple OpenAPI adapters from different APIs in a single app, including one with an inline spec definition instead of a remote URL. |
203
-
204
- > See all examples in [`examples/official-adapters/`](../examples/official-adapters/)
69
+ | Pattern | Correct | Incorrect | Why |
70
+ | -------------------- | ---------------------------------------------------------------------------- | -------------------------------------------- | ------------------------------------------------------------------------ |
71
+ | Adapter registration | `OpenapiAdapter.init({ ... })` in `adapters` array | Placing adapter in `plugins` array | Adapters go in `adapters`, not `plugins`; they serve different purposes |
72
+ | Tool naming | Tools auto-named as `<name>:<operationId>` using adapter `name` as namespace | Expecting flat names like `listPets` | Adapter name is prepended to prevent collisions across multiple adapters |
73
+ | Multiple APIs | Register separate `OpenapiAdapter.init()` calls with unique `name` values | Using the same `name` for different adapters | Duplicate names cause tool naming collisions |
205
74
 
206
75
  ## Reference
207
76
 
77
+ - [`openapi-adapter`](openapi-adapter.md) — Full OpenAPI adapter reference
78
+ - `create-adapter` — Build a custom adapter for non-OpenAPI sources
79
+ - `create-plugin` — Build plugins for cross-cutting concerns
208
80
  - [Adapter Overview Documentation](https://docs.agentfront.dev/frontmcp/adapters/overview)
209
- - Related skills: `create-adapter`, `create-plugin`, `create-tool`
@@ -0,0 +1,431 @@
1
+ ---
2
+ name: openapi-adapter
3
+ description: Convert OpenAPI 3.x specifications into MCP tools with authentication, polling, transforms, format resolution, and $ref security
4
+ ---
5
+
6
+ # OpenAPI Adapter
7
+
8
+ The OpenAPI adapter converts OpenAPI 3.x specifications into MCP tools — one tool per operation. It supports authentication, spec polling, operation filtering, input/output/tool transforms, format resolution, and built-in SSRF protection.
9
+
10
+ ## When to Use This Skill
11
+
12
+ ### Must Use
13
+
14
+ - Converting an OpenAPI/Swagger 3.x specification into MCP tools automatically
15
+ - Integrating a REST API that provides a public OpenAPI spec (Petstore, GitHub, Jira, Slack)
16
+ - Setting up authentication (API key, bearer token, OAuth) for adapter-generated tools
17
+
18
+ ### Recommended
19
+
20
+ - Enriching tool schemas with format resolution (uuid, date-time, email, etc.)
21
+ - Filtering which API operations become tools
22
+ - Hiding sensitive inputs and injecting server-side values via input transforms
23
+ - Enabling spec polling to auto-refresh tools when the upstream API changes
24
+
25
+ ### Skip When
26
+
27
+ - The external API has no OpenAPI spec (see `create-adapter` for custom adapters)
28
+ - You need to build tools manually with custom logic (see `create-tool`)
29
+ - You only need adapters overview and comparison (see `official-adapters`)
30
+
31
+ > **Decision:** Use this skill when you have an OpenAPI 3.x spec and want comprehensive guidance on `OpenapiAdapter` configuration.
32
+
33
+ ## Quick Start
34
+
35
+ ```typescript
36
+ import { FrontMcp, App } from '@frontmcp/sdk';
37
+ import { OpenapiAdapter } from '@frontmcp/adapters';
38
+
39
+ @App({
40
+ name: 'MyApp',
41
+ adapters: [
42
+ OpenapiAdapter.init({
43
+ name: 'petstore',
44
+ url: 'https://petstore3.swagger.io/api/v3/openapi.json',
45
+ }),
46
+ ],
47
+ })
48
+ class MyApp {}
49
+
50
+ @FrontMcp({
51
+ info: { name: 'my-server', version: '1.0.0' },
52
+ apps: [MyApp],
53
+ http: { port: 3000 },
54
+ })
55
+ class MyServer {}
56
+ // Generated tools: petstore:addPet, petstore:getPetById, petstore:deletePet, etc.
57
+ ```
58
+
59
+ Each OpenAPI operation becomes a tool named `<adapter-name>:<operationId>`.
60
+
61
+ ## Authentication
62
+
63
+ Five strategies with different security risk levels:
64
+
65
+ ```typescript
66
+ // 1. Static Headers (Medium Risk) — server-to-server APIs
67
+ OpenapiAdapter.init({
68
+ name: 'my-api',
69
+ url: 'https://api.example.com/openapi.json',
70
+ baseUrl: 'https://api.example.com',
71
+ additionalHeaders: {
72
+ 'x-api-key': process.env.API_KEY!,
73
+ },
74
+ });
75
+
76
+ // 2. Auth Provider Mapper (Low Risk) ⭐ Recommended — multi-provider
77
+ OpenapiAdapter.init({
78
+ name: 'multi-auth-api',
79
+ url: 'https://api.example.com/openapi.json',
80
+ baseUrl: 'https://api.example.com',
81
+ authProviderMapper: {
82
+ GitHubAuth: (ctx) => ctx.authInfo.user?.githubToken,
83
+ SlackAuth: (ctx) => ctx.authInfo.user?.slackToken,
84
+ },
85
+ });
86
+
87
+ // 3. Custom Security Resolver (Low Risk) — full control
88
+ OpenapiAdapter.init({
89
+ name: 'my-api',
90
+ url: 'https://api.example.com/openapi.json',
91
+ baseUrl: 'https://api.example.com',
92
+ securityResolver: (tool, ctx) => {
93
+ return { jwt: ctx.authInfo?.token };
94
+ },
95
+ });
96
+
97
+ // 4. Static Auth (Medium Risk) — fixed credentials
98
+ OpenapiAdapter.init({
99
+ name: 'my-api',
100
+ url: 'https://api.example.com/openapi.json',
101
+ baseUrl: 'https://api.example.com',
102
+ staticAuth: {
103
+ jwt: process.env.API_TOKEN!,
104
+ },
105
+ });
106
+
107
+ // 5. Dynamic Headers & Body Mapping (Low Risk) — context injection
108
+ OpenapiAdapter.init({
109
+ name: 'my-api',
110
+ url: 'https://api.example.com/openapi.json',
111
+ baseUrl: 'https://api.example.com',
112
+ headersMapper: (ctx, headers) => {
113
+ headers.set('Authorization', `Bearer ${ctx.authInfo?.token}`);
114
+ return headers;
115
+ },
116
+ });
117
+ ```
118
+
119
+ | Risk Level | Strategy | Description |
120
+ | ---------- | ------------------------------------------ | ---------------------------------------------------- |
121
+ | LOW | `authProviderMapper` or `securityResolver` | Auth from user context, not exposed to clients |
122
+ | MEDIUM | `staticAuth`, `additionalHeaders` | Static credentials |
123
+ | HIGH | `includeSecurityInInput: true` | Auth fields exposed to MCP clients (not recommended) |
124
+
125
+ ## Spec Polling
126
+
127
+ Auto-refresh tool definitions when the upstream API changes:
128
+
129
+ ```typescript
130
+ OpenapiAdapter.init({
131
+ name: 'evolving-api',
132
+ url: 'https://api.example.com/openapi.json',
133
+ polling: {
134
+ enabled: true,
135
+ intervalMs: 300000, // Re-fetch every 5 minutes
136
+ },
137
+ });
138
+ ```
139
+
140
+ ## Inline Spec
141
+
142
+ Provide the OpenAPI spec directly instead of fetching from URL:
143
+
144
+ ```typescript
145
+ OpenapiAdapter.init({
146
+ name: 'my-api',
147
+ spec: {
148
+ openapi: '3.0.0',
149
+ info: { title: 'My API', version: '1.0.0' },
150
+ paths: {
151
+ '/users': {
152
+ get: {
153
+ operationId: 'listUsers',
154
+ summary: 'List all users',
155
+ responses: { '200': { description: 'OK' } },
156
+ },
157
+ },
158
+ },
159
+ },
160
+ });
161
+ ```
162
+
163
+ ## Multiple Adapters
164
+
165
+ Register adapters from different APIs in the same app:
166
+
167
+ ```typescript
168
+ @App({
169
+ name: 'IntegrationHub',
170
+ adapters: [
171
+ OpenapiAdapter.init({ name: 'github', url: 'https://api.github.com/openapi.json' }),
172
+ OpenapiAdapter.init({ name: 'jira', url: 'https://jira.example.com/openapi.json' }),
173
+ OpenapiAdapter.init({ name: 'slack', url: 'https://slack.com/openapi.json' }),
174
+ ],
175
+ })
176
+ class IntegrationHub {}
177
+ // Tools: github:createIssue, jira:createTicket, slack:postMessage, etc.
178
+ ```
179
+
180
+ ## Filtering Operations
181
+
182
+ Control which API operations become MCP tools:
183
+
184
+ ```typescript
185
+ // Filter by path prefix
186
+ OpenapiAdapter.init({
187
+ name: 'billing-api',
188
+ url: 'https://api.example.com/openapi.json',
189
+ generateOptions: {
190
+ filterFn: (op) => op.path.startsWith('/invoices') || op.path.startsWith('/customers'),
191
+ },
192
+ });
193
+
194
+ // Include only specific operations
195
+ OpenapiAdapter.init({
196
+ name: 'my-api',
197
+ url: 'https://api.example.com/openapi.json',
198
+ generateOptions: {
199
+ includeOperations: ['getUser', 'createUser', 'updateUser'],
200
+ },
201
+ });
202
+
203
+ // Exclude specific operations
204
+ OpenapiAdapter.init({
205
+ name: 'my-api',
206
+ url: 'https://api.example.com/openapi.json',
207
+ generateOptions: {
208
+ excludeOperations: ['deprecatedEndpoint', 'internalOnly'],
209
+ },
210
+ });
211
+ ```
212
+
213
+ ## Input Transforms
214
+
215
+ Hide inputs from AI/users and inject values server-side:
216
+
217
+ ```typescript
218
+ OpenapiAdapter.init({
219
+ name: 'tenant-api',
220
+ url: 'https://api.example.com/openapi.json',
221
+ baseUrl: 'https://api.example.com',
222
+ inputTransforms: {
223
+ global: [
224
+ // Hide tenant header from AI, inject from user context
225
+ { inputKey: 'X-Tenant-Id', inject: (ctx) => ctx.authInfo.user?.tenantId },
226
+ // Add correlation ID to all requests
227
+ { inputKey: 'X-Correlation-Id', inject: () => crypto.randomUUID() },
228
+ ],
229
+ perTool: {
230
+ createAuditLog: [{ inputKey: 'userId', inject: (ctx) => ctx.authInfo.user?.id }],
231
+ },
232
+ },
233
+ });
234
+ ```
235
+
236
+ ## Format Resolution
237
+
238
+ Enrich generated tool schemas with concrete constraints from OpenAPI `format` values (uuid, date-time, email, int32, etc.):
239
+
240
+ ```typescript
241
+ // Enable built-in format resolvers
242
+ OpenapiAdapter.init({
243
+ name: 'my-api',
244
+ url: 'https://api.example.com/openapi.json',
245
+ generateOptions: {
246
+ resolveFormats: true,
247
+ },
248
+ });
249
+
250
+ // Add custom format resolvers (merged with built-ins when resolveFormats: true)
251
+ OpenapiAdapter.init({
252
+ name: 'my-api',
253
+ url: 'https://api.example.com/openapi.json',
254
+ generateOptions: {
255
+ resolveFormats: true,
256
+ formatResolvers: {
257
+ phone: (schema) => ({
258
+ ...schema,
259
+ pattern: '^\\+[1-9]\\d{1,14}$',
260
+ description: 'E.164 phone number',
261
+ }),
262
+ currency: (schema) => ({
263
+ ...schema,
264
+ pattern: '^[A-Z]{3}$',
265
+ description: 'ISO 4217 currency code',
266
+ }),
267
+ },
268
+ },
269
+ });
270
+
271
+ // Custom resolvers only (no built-ins)
272
+ OpenapiAdapter.init({
273
+ name: 'my-api',
274
+ url: 'https://api.example.com/openapi.json',
275
+ generateOptions: {
276
+ formatResolvers: {
277
+ phone: (schema) => ({ ...schema, pattern: '^\\+[1-9]\\d{1,14}$' }),
278
+ },
279
+ },
280
+ });
281
+ ```
282
+
283
+ | Option | Type | Default | Description |
284
+ | ----------------- | -------------------------------- | ----------- | -------------------------------------------------------------------------------------------- |
285
+ | `resolveFormats` | `boolean` | `false` | Enable built-in format resolvers (uuid, date-time, email, int32, etc.) |
286
+ | `formatResolvers` | `Record<string, FormatResolver>` | `undefined` | Custom resolvers; merged with built-ins when `resolveFormats: true`, custom takes precedence |
287
+
288
+ ## $ref Resolution Security
289
+
290
+ By default, the adapter blocks dangerous `$ref` resolution patterns to prevent SSRF attacks:
291
+
292
+ - `file://` protocol is blocked (prevents local file reads)
293
+ - Internal/private IPs are blocked (prevents cloud metadata theft, internal network probing)
294
+ - `http://` and `https://` to public hosts are allowed
295
+
296
+ Configure via `loadOptions.refResolution`:
297
+
298
+ ```typescript
299
+ // Restrict $refs to specific hosts only
300
+ OpenapiAdapter.init({
301
+ name: 'my-api',
302
+ url: 'https://api.example.com/openapi.json',
303
+ loadOptions: {
304
+ refResolution: {
305
+ allowedHosts: ['schemas.example.com'],
306
+ },
307
+ },
308
+ });
309
+
310
+ // Allow file:// protocol (for specs referencing local schema files)
311
+ OpenapiAdapter.init({
312
+ name: 'my-api',
313
+ url: 'https://api.example.com/openapi.json',
314
+ loadOptions: {
315
+ refResolution: {
316
+ allowedProtocols: ['http', 'https', 'file'],
317
+ },
318
+ },
319
+ });
320
+
321
+ // Allow internal IPs (only in trusted environments)
322
+ OpenapiAdapter.init({
323
+ name: 'internal-api',
324
+ url: 'http://10.0.0.5:8080/openapi.json',
325
+ loadOptions: {
326
+ refResolution: {
327
+ allowInternalIPs: true,
328
+ },
329
+ },
330
+ });
331
+
332
+ // Block ALL external refs (only resolve local #/ pointers)
333
+ OpenapiAdapter.init({
334
+ name: 'my-api',
335
+ url: 'https://api.example.com/openapi.json',
336
+ loadOptions: {
337
+ refResolution: {
338
+ allowedProtocols: [],
339
+ },
340
+ },
341
+ });
342
+ ```
343
+
344
+ | Option | Type | Default | Description |
345
+ | ------------------ | ---------- | ------------------- | ----------------------------------------------------------------------------------------- |
346
+ | `allowedProtocols` | `string[]` | `['http', 'https']` | Protocols allowed for external `$ref` resolution (http, https, ftp, ws, etc.) |
347
+ | `allowedHosts` | `string[]` | `undefined` | When set, only refs to these hostnames are resolved |
348
+ | `blockedHosts` | `string[]` | `undefined` | Additional hostnames/IPs to block beyond the built-in list |
349
+ | `allowInternalIPs` | `boolean` | `false` | Disable the built-in internal IP block list (127.x, 10.x, 172.16.x, 169.254.x, localhost) |
350
+
351
+ ## Load Options
352
+
353
+ Configure how the OpenAPI spec is loaded:
354
+
355
+ ```typescript
356
+ OpenapiAdapter.init({
357
+ name: 'my-api',
358
+ url: 'https://api.example.com/openapi.json',
359
+ baseUrl: 'https://api.example.com',
360
+ loadOptions: {
361
+ headers: { authorization: `Bearer ${process.env.SPEC_ACCESS_TOKEN}` },
362
+ timeout: 10000,
363
+ validate: true,
364
+ dereference: true,
365
+ },
366
+ });
367
+ ```
368
+
369
+ ## Common Patterns
370
+
371
+ | Pattern | Correct | Incorrect | Why |
372
+ | -------------------- | ---------------------------------------------------------- | --------------------------------------------------- | ----------------------------------------------- |
373
+ | Adapter registration | `OpenapiAdapter.init({ ... })` in `adapters` array | Placing adapter in `plugins` array | Adapters go in `adapters`, not `plugins` |
374
+ | Tool naming | Tools auto-named as `<name>:<operationId>` | Expecting flat names like `listPets` | Adapter name prevents collisions |
375
+ | Auth configuration | `staticAuth: { jwt: process.env.API_TOKEN! }` | Hardcoding secrets: `staticAuth: { jwt: 'sk-xxx' }` | Always use environment variables |
376
+ | Spec source | Use `url` for hosted specs or `spec` for inline | Using both `url` and `spec` simultaneously | Only one source; `spec` takes precedence |
377
+ | Multiple APIs | Separate `OpenapiAdapter.init()` with unique `name` values | Same `name` for different adapters | Duplicate names cause tool collisions |
378
+ | $ref security | Use default `refResolution` (blocks file://, internal IPs) | Setting `allowInternalIPs: true` in production | Default protects against SSRF |
379
+ | Format resolution | `generateOptions: { resolveFormats: true }` | Writing manual patterns for standard formats | Built-in resolvers handle uuid, date-time, etc. |
380
+
381
+ ## Verification Checklist
382
+
383
+ ### Configuration
384
+
385
+ - [ ] `@frontmcp/adapters` package is installed
386
+ - [ ] `OpenapiAdapter.init()` is in the `adapters` array of `@App`
387
+ - [ ] Adapter has a unique `name` for tool namespacing
388
+ - [ ] `url` points to a valid, reachable OpenAPI JSON/YAML endpoint (or `spec` is inline)
389
+
390
+ ### Runtime
391
+
392
+ - [ ] Generated tools appear in `tools/list` with `<name>:<operationId>` naming
393
+ - [ ] Auth headers are sent correctly on API calls
394
+ - [ ] Spec polling refreshes tool definitions at the configured interval
395
+ - [ ] Invalid spec URL produces a clear startup error
396
+
397
+ ### Production
398
+
399
+ - [ ] API tokens and secrets are loaded from environment variables
400
+ - [ ] Polling interval is appropriate for the API's update frequency
401
+ - [ ] Multiple adapter registrations use distinct names
402
+ - [ ] $ref resolution defaults are appropriate (or explicitly configured)
403
+
404
+ ## Troubleshooting
405
+
406
+ | Problem | Cause | Solution |
407
+ | ---------------------------------- | ------------------------------------------------------ | --------------------------------------------------------------------------------------------------------- |
408
+ | No tools generated from spec | Spec URL returns non-OpenAPI content or is unreachable | Verify URL returns valid OpenAPI 3.x JSON; check network access |
409
+ | Authentication errors on API calls | Wrong auth config or missing credentials | Configure `staticAuth`, `securityResolver`, `authProviderMapper`, or `additionalHeaders`; verify env vars |
410
+ | Duplicate tool name error | Two adapters with the same `name` | Give each adapter a unique `name` |
411
+ | Stale tools after API update | Spec polling not configured | Add `polling: { intervalMs: 300000 }` |
412
+ | External $refs not resolving | Default SSRF protection blocks external refs | Add `loadOptions.refResolution.allowedHosts` or `allowedProtocols` |
413
+ | SSRF warning / $ref to internal IP | Spec contains $refs to internal services | Blocked by default; use `refResolution.allowInternalIPs: true` only in trusted environments |
414
+ | TypeScript error importing adapter | Wrong import path | Import from `@frontmcp/adapters` |
415
+
416
+ ## Examples
417
+
418
+ | Example | Level | Description |
419
+ | ----------------------------------------------------------------------------------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
420
+ | [`basic-openapi-adapter`](../examples/openapi-adapter/basic-openapi-adapter.md) | Basic | Demonstrates converting an OpenAPI specification into MCP tools automatically using `OpenapiAdapter` with minimal configuration. |
421
+ | [`authenticated-adapter-with-polling`](../examples/openapi-adapter/authenticated-adapter-with-polling.md) | Intermediate | Demonstrates configuring authentication (API key and bearer token) and automatic spec polling for OpenAPI adapters. |
422
+ | [`format-resolution-and-custom-resolvers`](../examples/openapi-adapter/format-resolution-and-custom-resolvers.md) | Intermediate | Demonstrates using built-in and custom format resolvers to enrich tool input schemas with concrete constraints from OpenAPI format values. |
423
+ | [`ref-security-and-filtering`](../examples/openapi-adapter/ref-security-and-filtering.md) | Intermediate | Demonstrates configuring $ref resolution security to prevent SSRF attacks and filtering which API operations become MCP tools. |
424
+ | [`multi-api-hub-with-inline-spec`](../examples/openapi-adapter/multi-api-hub-with-inline-spec.md) | Advanced | Demonstrates registering multiple OpenAPI adapters from different APIs in a single app, including one with an inline spec definition instead of a remote URL. |
425
+
426
+ > See all examples in [`examples/openapi-adapter/`](../examples/openapi-adapter/)
427
+
428
+ ## Reference
429
+
430
+ - [OpenAPI Adapter Documentation](https://docs.agentfront.dev/frontmcp/adapters/openapi-adapter)
431
+ - Related skills: `official-adapters`, `create-adapter`, `create-tool`
@@ -1348,8 +1348,25 @@
1348
1348
  },
1349
1349
  {
1350
1350
  "name": "official-adapters",
1351
- "description": "Convert OpenAPI specs and external definitions into MCP tools automatically",
1351
+ "description": "Overview of all official FrontMCP adapters that convert external definitions into MCP primitives",
1352
+ "examples": []
1353
+ },
1354
+ {
1355
+ "name": "openapi-adapter",
1356
+ "description": "Convert OpenAPI 3.x specifications into MCP tools with authentication, polling, transforms, format resolution, and $ref security",
1352
1357
  "examples": [
1358
+ {
1359
+ "name": "basic-openapi-adapter",
1360
+ "description": "Demonstrates converting an OpenAPI specification into MCP tools automatically using `OpenapiAdapter` with minimal configuration.",
1361
+ "level": "basic",
1362
+ "tags": ["development", "openapi", "adapters", "adapter"],
1363
+ "features": [
1364
+ "Using `OpenapiAdapter.init()` with just `name` and `url` to auto-generate MCP tools",
1365
+ "Each OpenAPI operation becomes a tool named `<adapter-name>:<operationId>`",
1366
+ "The adapter is registered in the `adapters` array of `@App`, not in `plugins`",
1367
+ "The `name` field serves as the namespace prefix to prevent tool name collisions"
1368
+ ]
1369
+ },
1353
1370
  {
1354
1371
  "name": "authenticated-adapter-with-polling",
1355
1372
  "description": "Demonstrates configuring authentication (API key and bearer token) and automatic spec polling for OpenAPI adapters.",
@@ -1364,15 +1381,28 @@
1364
1381
  ]
1365
1382
  },
1366
1383
  {
1367
- "name": "basic-openapi-adapter",
1368
- "description": "Demonstrates converting an OpenAPI specification into MCP tools automatically using `OpenapiAdapter` with minimal configuration.",
1369
- "level": "basic",
1370
- "tags": ["development", "openapi", "adapters", "adapter"],
1384
+ "name": "format-resolution-and-custom-resolvers",
1385
+ "description": "Demonstrates using built-in and custom format resolvers to enrich tool input schemas with concrete constraints from OpenAPI format values.",
1386
+ "level": "intermediate",
1387
+ "tags": ["development", "openapi", "adapters", "format", "schema", "validation"],
1371
1388
  "features": [
1372
- "Using `OpenapiAdapter.init()` with just `name` and `url` to auto-generate MCP tools",
1373
- "Each OpenAPI operation becomes a tool named `<adapter-name>:<operationId>`",
1374
- "The adapter is registered in the `adapters` array of `@App`, not in `plugins`",
1375
- "The `name` field serves as the namespace prefix to prevent tool name collisions"
1389
+ "Enabling built-in format resolvers with `resolveFormats: true` for uuid, date-time, email, int32, etc.",
1390
+ "Adding custom format resolvers for domain-specific formats (phone, currency)",
1391
+ "Merging custom resolvers with built-ins where custom takes precedence",
1392
+ "Using custom-only resolvers without built-ins for full control"
1393
+ ]
1394
+ },
1395
+ {
1396
+ "name": "ref-security-and-filtering",
1397
+ "description": "Demonstrates configuring $ref resolution security to prevent SSRF attacks and filtering which API operations become MCP tools.",
1398
+ "level": "intermediate",
1399
+ "tags": ["development", "openapi", "adapters", "security", "ssrf", "filtering"],
1400
+ "features": [
1401
+ "Configuring `refResolution` to restrict which hosts and protocols are allowed for external `$ref` pointers",
1402
+ "Using `allowedHosts` to restrict $refs to trusted schema servers",
1403
+ "Using `allowedProtocols` to enable or disable file://, http://, https://, and other protocols",
1404
+ "Filtering operations with `includeOperations`, `excludeOperations`, and `filterFn`",
1405
+ "Combining security hardening with operation filtering for a production-ready setup"
1376
1406
  ]
1377
1407
  },
1378
1408
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontmcp/skills",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Curated skills catalog for FrontMCP projects",
5
5
  "author": "AgentFront <info@agentfront.dev>",
6
6
  "homepage": "https://docs.agentfront.dev",