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
| Extension | Type | Default | Purpose |
|---|---|---|---|
x-mcp-enabled | bool | true | Include operation as a tool |
x-mcp-tool-name | string | derived | Override generated tool name |
x-mcp-auth-required | bool | true | Per-operation auth bypass |
x-mcp-safe | bool | false | Mark as read-only for group filters |
x-mcp-response-format | string | json | json | text | image | audio | binary | auto |
x-mcp-request-transform | string | generated | jq expression applied to request body |
x-mcp-response-transform | string | . | jq expression applied to response body |
x-mcp-error-transform | string | default | jq expression for error responses |
x-mcp-tier | string | — | Arbitrary 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-safeandx-mcp-tier