@frontmcp/skills 1.5.4 → 1.5.6
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.
|
@@ -137,6 +137,13 @@ OpenapiAdapter.init({
|
|
|
137
137
|
});
|
|
138
138
|
```
|
|
139
139
|
|
|
140
|
+
> **SSRF (GHSA-65h7-9wrw-629c):** the poll re-fetches the same attacker-influenceable
|
|
141
|
+
> spec `url` on a timer, so it runs through the **same SSRF guard** as the initial load —
|
|
142
|
+
> it inherits `loadOptions.refResolution` (validates the resolved IP, pins the connection,
|
|
143
|
+
> re-validates redirects). Loopback/private/internal spec servers are blocked by default;
|
|
144
|
+
> a blocked poll fails closed (no fetch, no update) and is logged. To poll an internal or
|
|
145
|
+
> localhost spec, set `loadOptions.refResolution.allowInternalIPs: true` — trusted/local only.
|
|
146
|
+
|
|
140
147
|
## Inline Spec
|
|
141
148
|
|
|
142
149
|
Provide the OpenAPI spec directly instead of fetching from URL:
|
|
@@ -292,7 +299,7 @@ OpenapiAdapter.init({
|
|
|
292
299
|
> vector. Hostname-string denylists are bypassable via DNS names that resolve to
|
|
293
300
|
> internal IPs (e.g. `http://127.0.0.1.nip.io/`), redirects, and IPv4-mapped IPv6.
|
|
294
301
|
> **Use `mcp-from-openapi` ≥ 2.5.0**, which resolves DNS and validates the
|
|
295
|
-
>
|
|
302
|
+
> _resolved IP_, guards the spec-URL fetch (not just `$ref`s), and re-validates
|
|
296
303
|
> every redirect hop.
|
|
297
304
|
|
|
298
305
|
FrontMCP's secure defaults:
|
|
@@ -350,12 +357,12 @@ OpenapiAdapter.init({
|
|
|
350
357
|
|
|
351
358
|
These apply to **both** the spec-URL fetch and external `$ref` resolution (`mcp-from-openapi` ≥ 2.5.0):
|
|
352
359
|
|
|
353
|
-
| Option | Type | Default (FrontMCP) | Description
|
|
354
|
-
| ------------------ | ---------- | ------------------ |
|
|
360
|
+
| Option | Type | Default (FrontMCP) | Description |
|
|
361
|
+
| ------------------ | ---------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
|
|
355
362
|
| `allowedProtocols` | `string[]` | `[]` | Protocols allowed for external `$ref` resolution. **FrontMCP defaults to `[]`** (external refs off); set `['http','https']` to enable |
|
|
356
|
-
| `allowedHosts` | `string[]` | `undefined` | When set, only the spec URL / `$ref` URLs to these hostnames are allowed
|
|
357
|
-
| `blockedHosts` | `string[]` | `undefined` | Additional hostnames/IPs to block beyond the built-in internal-address list
|
|
358
|
-
| `allowInternalIPs` | `boolean` | `false` | Allow loopback/private/internal targets for the spec URL **and** `$ref`s (skips ranges + DNS recheck). Trusted/local only
|
|
363
|
+
| `allowedHosts` | `string[]` | `undefined` | When set, only the spec URL / `$ref` URLs to these hostnames are allowed |
|
|
364
|
+
| `blockedHosts` | `string[]` | `undefined` | Additional hostnames/IPs to block beyond the built-in internal-address list |
|
|
365
|
+
| `allowInternalIPs` | `boolean` | `false` | Allow loopback/private/internal targets for the spec URL **and** `$ref`s (skips ranges + DNS recheck). Trusted/local only |
|
|
359
366
|
|
|
360
367
|
> `followRedirects` (a `loadOptions` field, not `refResolution`) defaults to `false` in FrontMCP.
|
|
361
368
|
|
|
@@ -379,15 +386,15 @@ OpenapiAdapter.init({
|
|
|
379
386
|
|
|
380
387
|
## Common Patterns
|
|
381
388
|
|
|
382
|
-
| Pattern | Correct
|
|
383
|
-
| -------------------- |
|
|
384
|
-
| Adapter registration | `OpenapiAdapter.init({ ... })` in `adapters` array
|
|
385
|
-
| Tool naming | Tools auto-named as `<name>:<operationId>`
|
|
386
|
-
| Auth configuration | `staticAuth: { jwt: process.env.API_TOKEN! }`
|
|
387
|
-
| Spec source | Use `url` for hosted specs or `spec` for inline
|
|
388
|
-
| Multiple APIs | Separate `OpenapiAdapter.init()` with unique `name` values
|
|
389
|
-
| Spec/$ref SSRF | Keep secure defaults (external refs off, redirects off, internal targets blocked) on `mcp-from-openapi` ≥ 2.5.0 | Setting `allowInternalIPs: true` in production; forwarding untrusted spec URLs without an `allowedHosts` allow-list | Defaults protect against SSRF (incl. DNS-name-to-internal) |
|
|
390
|
-
| Format resolution | `generateOptions: { resolveFormats: true }`
|
|
389
|
+
| Pattern | Correct | Incorrect | Why |
|
|
390
|
+
| -------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
|
|
391
|
+
| Adapter registration | `OpenapiAdapter.init({ ... })` in `adapters` array | Placing adapter in `plugins` array | Adapters go in `adapters`, not `plugins` |
|
|
392
|
+
| Tool naming | Tools auto-named as `<name>:<operationId>` | Expecting flat names like `listPets` | Adapter name prevents collisions |
|
|
393
|
+
| Auth configuration | `staticAuth: { jwt: process.env.API_TOKEN! }` | Hardcoding secrets: `staticAuth: { jwt: 'sk-xxx' }` | Always use environment variables |
|
|
394
|
+
| Spec source | Use `url` for hosted specs or `spec` for inline | Using both `url` and `spec` simultaneously | Only one source; `spec` takes precedence |
|
|
395
|
+
| Multiple APIs | Separate `OpenapiAdapter.init()` with unique `name` values | Same `name` for different adapters | Duplicate names cause tool collisions |
|
|
396
|
+
| Spec/$ref SSRF | Keep secure defaults (external refs off, redirects off, internal targets blocked) on `mcp-from-openapi` ≥ 2.5.0 | Setting `allowInternalIPs: true` in production; forwarding untrusted spec URLs without an `allowedHosts` allow-list | Defaults protect against SSRF (incl. DNS-name-to-internal); the spec **poller inherits the same guard** |
|
|
397
|
+
| Format resolution | `generateOptions: { resolveFormats: true }` | Writing manual patterns for standard formats | Built-in resolvers handle uuid, date-time, etc. |
|
|
391
398
|
|
|
392
399
|
## Verification Checklist
|
|
393
400
|
|
|
@@ -414,26 +421,27 @@ OpenapiAdapter.init({
|
|
|
414
421
|
|
|
415
422
|
## Troubleshooting
|
|
416
423
|
|
|
417
|
-
| Problem
|
|
418
|
-
|
|
|
419
|
-
| No tools generated from spec
|
|
420
|
-
| Authentication errors on API calls
|
|
421
|
-
| Duplicate tool name error
|
|
422
|
-
| Stale tools after API update
|
|
423
|
-
| External $refs not resolving
|
|
424
|
-
| Spec URL / $ref to internal host blocked
|
|
425
|
-
|
|
|
426
|
-
|
|
|
424
|
+
| Problem | Cause | Solution |
|
|
425
|
+
| ------------------------------------------------------------ | ------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------- |
|
|
426
|
+
| 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 |
|
|
427
|
+
| Authentication errors on API calls | Wrong auth config or missing credentials | Configure `staticAuth`, `securityResolver`, `authProviderMapper`, or `additionalHeaders`; verify env vars |
|
|
428
|
+
| Duplicate tool name error | Two adapters with the same `name` | Give each adapter a unique `name` |
|
|
429
|
+
| Stale tools after API update | Spec polling not configured | Add `polling: { intervalMs: 300000 }` |
|
|
430
|
+
| External $refs not resolving | External refs are **disabled by default** in FrontMCP | Set `loadOptions.refResolution.allowedProtocols: ['http','https']` (add `allowedHosts` to restrict) |
|
|
431
|
+
| Spec URL / $ref to internal host blocked | Target is loopback/private, or a DNS name resolving to one (SSRF guard) | Use `refResolution.allowInternalIPs: true` only in trusted/local environments |
|
|
432
|
+
| Polling never updates from an internal/localhost spec server | The poll re-fetch is SSRF-guarded and blocks internal targets by default | Set `loadOptions.refResolution.allowInternalIPs: true` (trusted/local only) |
|
|
433
|
+
| Spec URL redirect not followed | `followRedirects` defaults to `false` | Set `loadOptions.followRedirects: true` (each hop is re-validated on `mcp-from-openapi` ≥ 2.5.0) |
|
|
434
|
+
| TypeScript error importing adapter | Wrong import path | Import from `@frontmcp/adapters` |
|
|
427
435
|
|
|
428
436
|
## Examples
|
|
429
437
|
|
|
430
|
-
| Example | Level | Description
|
|
431
|
-
| ----------------------------------------------------------------------------------------------------------------- | ------------ |
|
|
432
|
-
| [`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.
|
|
433
|
-
| [`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.
|
|
434
|
-
| [`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.
|
|
435
|
-
| [`ref-security-and-filtering`](../examples/openapi-adapter/ref-security-and-filtering.md) | Intermediate | Demonstrates configuring $ref / spec-URL resolution security to prevent SSRF attacks (GHSA-65h7-9wrw-629c) and filtering which API operations become MCP tools.
|
|
436
|
-
| [`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.
|
|
438
|
+
| Example | Level | Description |
|
|
439
|
+
| ----------------------------------------------------------------------------------------------------------------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
440
|
+
| [`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. |
|
|
441
|
+
| [`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. |
|
|
442
|
+
| [`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. |
|
|
443
|
+
| [`ref-security-and-filtering`](../examples/openapi-adapter/ref-security-and-filtering.md) | Intermediate | Demonstrates configuring $ref / spec-URL resolution security to prevent SSRF attacks (GHSA-65h7-9wrw-629c) and filtering which API operations become MCP tools. |
|
|
444
|
+
| [`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. |
|
|
437
445
|
|
|
438
446
|
> See all examples in [`examples/openapi-adapter/`](../examples/openapi-adapter/)
|
|
439
447
|
|