@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
- > *resolved IP*, guards the spec-URL fetch (not just `$ref`s), and re-validates
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 | Incorrect | Why |
383
- | -------------------- | ---------------------------------------------------------- | --------------------------------------------------- | ----------------------------------------------- |
384
- | Adapter registration | `OpenapiAdapter.init({ ... })` in `adapters` array | Placing adapter in `plugins` array | Adapters go in `adapters`, not `plugins` |
385
- | Tool naming | Tools auto-named as `<name>:<operationId>` | Expecting flat names like `listPets` | Adapter name prevents collisions |
386
- | Auth configuration | `staticAuth: { jwt: process.env.API_TOKEN! }` | Hardcoding secrets: `staticAuth: { jwt: 'sk-xxx' }` | Always use environment variables |
387
- | Spec source | Use `url` for hosted specs or `spec` for inline | Using both `url` and `spec` simultaneously | Only one source; `spec` takes precedence |
388
- | Multiple APIs | Separate `OpenapiAdapter.init()` with unique `name` values | Same `name` for different adapters | Duplicate names cause tool collisions |
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 }` | Writing manual patterns for standard formats | Built-in resolvers handle uuid, date-time, etc. |
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 | Cause | Solution |
418
- | ---------------------------------- | ------------------------------------------------------ | --------------------------------------------------------------------------------------------------------- |
419
- | 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 |
420
- | Authentication errors on API calls | Wrong auth config or missing credentials | Configure `staticAuth`, `securityResolver`, `authProviderMapper`, or `additionalHeaders`; verify env vars |
421
- | Duplicate tool name error | Two adapters with the same `name` | Give each adapter a unique `name` |
422
- | Stale tools after API update | Spec polling not configured | Add `polling: { intervalMs: 300000 }` |
423
- | External $refs not resolving | External refs are **disabled by default** in FrontMCP | Set `loadOptions.refResolution.allowedProtocols: ['http','https']` (add `allowedHosts` to restrict) |
424
- | 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 |
425
- | 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) |
426
- | TypeScript error importing adapter | Wrong import path | Import from `@frontmcp/adapters` |
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
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontmcp/skills",
3
- "version": "1.5.4",
3
+ "version": "1.5.6",
4
4
  "description": "Curated skills catalog for FrontMCP projects",
5
5
  "author": "AgentFront <info@agentfront.dev>",
6
6
  "homepage": "https://docs.agentfront.dev",