OpenAPI Overlays

Overlays let you customize how operations are exposed as MCP tools without touching the original OpenAPI spec. They follow the OpenAPI Overlay 1.0 format using RFC 9535 JSONPath targeting.

Structure

overlay: 1.0.0
info:
  title: My Overlay
  version: 1.0.0
x-speakeasy-jsonpath: rfc9535      # required for RFC 9535 semantics

actions:
  - target: "$.paths[\"/pets\"].get"   # JSONPath targeting the operation
    update:                             # merge these properties
      x-mcp-tool-name: list_pets
      x-mcp-safe: true

  - target: "$.paths[\"/internal/metrics\"]"
    remove: true                        # or remove the node entirely

Configuring an overlay

upstreams:
  - name: kraken
    type: http
    tool_prefix: kraken
    base_url: https://api.kraken.com
    openapi:
      source: examples/kraken/spec.yaml
    overlay:
      source: examples/kraken/overlay.yaml   # local path or URL

Common use cases

Override tool name

- target: "$.paths[\"/0/public/Ticker\"].get"
  update:
    x-mcp-tool-name: get_ticker

Improve tool description

- target: "$.paths[\"/0/public/Ticker\"].get"
  update:
    description: >
      Get real-time ticker for any trading pair (e.g. XBTUSD).
      Returns ask, bid, last price, 24h volume, VWAP, high, and low.

Flatten nested response with jq

- target: "$.paths[\"/0/public/Ticker\"].get"
  update:
    x-mcp-response-transform: >
      .result | to_entries[0] | {
        pair: .key,
        ask: .value.a[0],
        bid: .value.b[0],
        lastPrice: .value.c[0],
        volume24h: .value.v[1]
      }

Disable an operation

- target: "$.paths[\"/admin/reset\"].post"
  update:
    x-mcp-enabled: false

Remove a path entirely

- target: "$.paths[\"/internal/debug\"]"
  remove: true

Mark operations as safe (read-only)

# Mark all GET operations as safe
- target: "$.paths.*.get"
  update:
    x-mcp-safe: true

Skip auth for public endpoints

- target: "$.paths[\"/public/status\"].get"
  update:
    x-mcp-auth-required: false

Handle binary responses

- target: "$.paths[\"/images/{id}\"].get"
  update:
    x-mcp-response-format: image

Full x-mcp extension reference

ExtensionTypeDefaultPurpose
x-mcp-enabledbooltrueInclude operation as a tool
x-mcp-tool-namestringderivedOverride generated tool name
x-mcp-auth-requiredbooltruePer-operation auth bypass
x-mcp-safeboolfalseMark as read-only for group filters
x-mcp-response-formatstringjsonjson | text | image | audio | binary | auto
x-mcp-request-transformstringgeneratedjq expression applied to request body
x-mcp-response-transformstring.jq expression applied to response body
x-mcp-error-transformstringdefaultjq expression for error responses
x-mcp-tierstringArbitrary label for JSONPath group filters

JSONPath targeting tips

  • Target a specific operation: $.paths["/pets/{id}"].get
  • Target all operations on a path: $.paths["/pets/{id}"].*
  • Target all GET operations: $.paths.*.get
  • Target all operations: $.paths.*.*
  • Filter by extension: $.paths.*[?(@['x-internal'] == true)]

Real-world example — Kraken

The full overlay used by the Kraken example is at examples/kraken/overlay.yaml. It renames five operations and adds jq transforms that extract and rename fields from Kraken's compact array format.

See also

  • HTTP APIs — x-mcp extensions applied by overlays
  • Tool Groups — filter tools using x-mcp-safe and x-mcp-tier