Hookway

Import OpenAPI operations as MCP tools

Last revised: October 31, 2026.

Use hookway import-openapi to generate a new Hookway configuration from selected API operations. The importer runs locally, makes no network requests, does not expand environment variables, and never loads credential secrets. Generated tools run through the existing MCP gateway.

Run a complete local example

This read-only walkthrough uses a synthetic customer API on loopback. You need Git, Make, the Go version from go.mod, Python 3, curl and OpenSSL. Work from the repository root; make build downloads Go dependencies when needed.

In one terminal, build Hookway and start the fixture API:

make build
python3 examples/openapi/demo-server.py

In a second terminal, generate a fresh configuration. The importer refuses to overwrite an existing output, so choose a new output filename on a repeat run.

mkdir -p .scratch/openapi-guide
bin/hookway import-openapi --spec examples/openapi/api.yaml \
  --settings examples/openapi/demo-settings.yaml \
  --out .scratch/openapi-guide/core.yaml
bin/hookway validate --config .scratch/openapi-guide/core.yaml --no-env --strict
export MCP_READER_TOKEN="$(openssl rand -hex 24)"
bin/hookway serve --config .scratch/openapi-guide/core.yaml

The demo settings select only GET /customers/{id}. The source spec also contains a write operation, but it is not imported or granted. Private upstream targets are explicitly permitted only for this local demonstration. Keep the terminal running.

In a third terminal, set MCP_READER_TOKEN to the same generated value from the server terminal using your normal local credential handling. Do not generate a second value or put the token in a public issue. Then call the read tool:

curl --fail-with-body -sS http://127.0.0.1:18091/customers/mcp \
  -H "Authorization: Bearer $MCP_READER_TOKEN" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'MCP-Protocol-Version: 2025-11-25' \
  -H 'MCP-Method: tools/call' \
  --data-binary '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_customer","arguments":{"path":{"id":"customer-1"}}}}'

The JSON-RPC result includes Sample customer and the string ID customer-1. Depending on transport negotiation, the response is JSON or a server-sent event containing JSON. This verifies a tool call through Hookway to the local API; it is not proof that any hosted agent can reach your computer.

Expected failure cases:

Use Ctrl-C in the server terminals to stop both processes. The generated YAML contains an environment reference, not the actual token. Remove the disposable scratch output when no longer needed. Continue below for the full importer contract or use the browser wizard with your own API document.

Inspect, select, generate

hookway import-openapi --spec examples/openapi/api.yaml --list
hookway import-openapi --spec examples/openapi/api.yaml --list --json
hookway import-openapi --spec examples/openapi/api.yaml \
  --settings examples/openapi/settings.yaml --out core.yaml
hookway validate --config core.yaml --no-env --strict

Build the CLI with make build, or substitute go run ./cmd/hookway for hookway. Review the generated configuration, provision its referenced secrets, then deploy it using your normal process. The importer neither deploys nor merges into another configuration. --out creates a new file and refuses to overwrite an existing one; without it, only YAML is written to stdout. Diagnostics go to stderr. A selected unsupported operation fails generation without partial output. Inspection reports unsupported operations without requiring grants or upstream credentials.

The complete source API, import settings, and generated configuration demonstrate a read tool and an explicitly authorized write tool. The upstream URL is illustrative.

Import settings

FieldMeaning
serverHookway server settings. Omitted address defaults to loopback; request-size and other server validation still apply.
endpointMCP path, public_url, auth, allowed_origins, and max_inflight. Uses existing API-key/OAuth configuration; anonymous endpoints are refused.
upstream.base_urlRequired literal HTTP(S) URL, including any base path. OpenAPI server URLs are not selected automatically.
upstream.allow_private_targetsExplicitly permit internal upstreams. Off by default. Credential profiles need their own matching permission.
credentialsExisting outbound credential profiles, containing secret references.
operationsExplicit list of method, path, optional name, description, credential, and required access grants.

Operation methods are uppercase. GET is read-only; other methods require access.allow_mutation: true. Every tool needs explicit API-key or OAuth grants. No tool retries automatically. An API's security declaration does not grant agent access: bind its supported security requirement to an explicit credential profile. Operator-configured profiles must supply the appropriate credential material and upstream scopes. MCP caller credentials are never forwarded as upstream credentials.

The importer uses operationId for a proposed tool name, falling back to method/path. Names are normalized to Hookway's limits; collisions require an explicit name override. Descriptions come from the settings, API summary, API description, or method/path. Parameter aliases are reported when names need normalization. No AI is involved in generation.

Supported documents

OpenAPI 3.0.x and 3.1.x, JSON or YAML, up to 8 MiB. Same-document JSON Pointer references are supported, including recursive schemas. Structural and schema-size limits apply. External references, multiple documents, and YAML aliases/anchors are refused. Bundle external references before importing.

Supported operations are GET, POST, PUT, PATCH, and DELETE. Path-level parameters are inherited and may be overridden by an operation. Parameters must be non-null scalars: path/header simple and query form serialization. JSON bodies can be required or optional. Content must use exactly one application/json media type with a schema. Explicit numeric successful responses may contain JSON or be empty; status ranges and a default-only success contract are insufficient.

Swagger 2, multipart/form bodies, cookie parameters, array/object parameter serialization, callbacks, webhooks, streaming, custom schema dialects, and schema keywords that cannot be preserved are unsupported. Diagnostics identify the operation and document location. Unsupported unselected operations do not prevent importing supported operations.

Agent arguments and results

Arguments are grouped by location:

{"path":{"id":"customer-1"},"query":{"details":false}}

A write adds a separate body argument. Omitted optional parameters are omitted upstream; empty strings, zero, and false are preserved. Schema defaults are not inserted. Imported dollar signs use YAML Unicode escapes so server startup cannot reinterpret literal descriptions or schema values as environment references. An omitted optional body sends no bytes; an explicit JSON null sends null. Bodyless operations use http_request.body: none.

All generated results are objects: {"data": ...}. data preserves the API's object, array, or scalar JSON. It is null for declared empty success responses. Invalid JSON, undeclared empty responses, non-success statuses, and output-schema violations produce tool errors. Cancellation or a lost response after a write can mean an unknown outcome; inspect the upstream before attempting another mutation.

The generated graph uses native mcp_trigger → http_request → mcp_result branches with capture disabled. It can be reviewed and edited in the existing builder. internal/openapiimport also exposes pure Inspect, DecodeSettings, and Generate entry points shared by the CLI and browser wizard.

Builder wizard

In the builder, choose Config → Create MCP tools from OpenAPI. Upload one JSON/YAML file or paste its contents. Inspection and generation run locally in a dedicated Go WASM worker. The wizard does not upload the document, fetch remote specifications, or resolve secrets.

Select up to 64 supported operations. Expand Edit tool details to change a tool's name or description. Access setup separates Your API, Agent access, and Tool permissions. Add named callers using secret references, then grant each caller the tools it needs. API credentials, browser origins, and request limits are available in expandable sections. The generated configuration uses the importer’s default server settings; edit runtime settings separately in Config → Core server after opening it in the builder, or in the downloaded YAML. Nothing is selected or granted automatically. Writes require a separate mutation permission. Unsupported operations remain visible with their diagnostics.

Review configuration validates the complete configuration. Expand a tool to review its description, schemas, aliases, and grants; View core.yaml shows the complete YAML. Download core.yaml to use it with Hookway. Open in builder offers export of your current workspace and requires confirmation before replacing all flows and settings, including replay. Imported strings retain their literal dollar signs through editing, browser persistence, and split YAML exports. Ordinary authored environment references remain supported.

The wizard draft is held in memory only and is discarded when you close it. Settings-file import/export and configuration merging are not available. If a schema contains numbers the builder cannot represent precisely, direct download remains available and the current workspace is preserved.

After deploying the downloaded configuration and provisioning its referenced secrets, use Connect & test against that running MCP endpoint. This executes live tools; mutation calls require acknowledgment. The discovered catalog comes from the deployment and may differ from the wizard draft. Caller tokens stay in memory and are cleared on disconnect; they are never added to the configuration. Live arguments that would lose numeric precision in the browser are rejected; use a native MCP client for those values. String IDs retain their exact text. Browser connections require a reachable URL and an allowed browser origin; native clients can connect where browser network policy prevents access.

If matching WASM assets cannot load, retry inspection or use the CLI above. There is no server-side processing fallback.