Skip to main content

Expose a REST API as MCP Tools

An MCP server registry entry can be backed by a plain REST API instead of an upstream MCP server. Register the API's OpenAPI 3.x document with type set to openapi, and AISIX generates one MCP tool per operation. A tools/call executes as an HTTP request against the API's base URL with the gateway-held credential attached. The MCP caller never receives the credential, and the API needs no MCP server of its own.

This turns existing internal services, such as an ERP, inventory system, or payroll API, into agent-callable tools. Tool access control, traffic controls, guardrails, and observability apply with both management paths. AISIX Cloud also provides server review and shared access policies.

Prerequisites

Before starting, prepare the following:

  • For AISIX Cloud, an environment and a write-scoped admin token. For On-Premises, follow the AISIX Cloud Quickstart. To request Hybrid Cloud access, contact API7.
  • For an open-source AISIX gateway, complete Set Up MCP Gateway, then remain in its shell and working directory without cleaning up its temporary Docker network.
  • cURL and jq for the AISIX Cloud example.

How Tools Are Generated

AISIX walks the document's paths and generates one tool per operation for the get, post, put, delete, and patch methods:

  • Tool name: the operation's operationId, lowercased, with any character outside a-z, 0-9, _, and - replaced by _, capped at 128 characters. An operation without an operationId is named <method>_<path> under the same rules. Tools are exposed to callers as <server-name>__<tool-name>, like every MCP tool.
  • Input schema: each path and query parameter becomes a property with its type, description, enum values, and required flag. A JSON request body becomes a single body object property, marked required when the spec says so. Local $refs, including referenced component schemas inside the body, are resolved so the agent sees the real shape. Header and cookie parameters are not exposed because upstream headers belong to the gateway, not the caller.
  • Skipped operations: an operation whose request body has no application/json variant, such as a multipart/form-data file upload, is skipped rather than generating a tool that cannot succeed.

Validation timing differs by management path. AISIX Cloud validates the document during registration. It rejects a document that cannot be parsed, a Swagger 2.0 document, a document with no tool-generatable operations, or operationIds that collide after normalization. The create response returns the generated names in tool_names.

With resources.yaml, aisix validate checks the resource shape, including that spec is a mapping and is not a Swagger document. The gateway generates the tools when a client lists or calls them. If the document has no usable paths object, that server contributes no tools to the aggregated list and the gateway logs the error. Normalized name collisions receive _2, _3, and subsequent suffixes so every operation remains reachable. List tools after loading the file to verify the generated surface.

Register a REST API

The registration shape differs between AISIX Cloud and an open-source AISIX gateway. In both cases, url is the REST API base URL, and generated calls are issued against <url><path>.

AISIX Cloud

Provide the document in one of two ways:

  • spec_content: the document itself, as JSON or YAML text. Use this when the control plane cannot reach the API's network.
  • spec_url: a URL the control plane fetches once during registration. The fetched document is validated, normalized, and stored; the data plane never re-fetches it, so the tool set only changes when you update the registry entry. By default, URLs that resolve to non-public addresses are refused. An On-Premises deployment can allow them by setting AISIX_CLOUD_MCP_SPEC_ALLOW_PRIVATE_URLS=true on the control plane. Otherwise, paste the document instead.

AISIX Cloud caps OpenAPI documents at 1 MiB.

Export the control-plane address, admin token, and environment ID:

export AISIX_CP="http://localhost:8080/api"
export AISIX_TOKEN="YOUR_ADMIN_TOKEN"
export ENV_ID="YOUR_ENVIRONMENT_ID"

Register the REST API and its OpenAPI document:

MCP_SERVER_RESPONSE=$(curl -sS -X POST "$AISIX_CP/mcp_servers" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "erp",
"type": "openapi",
"url": "https://erp.internal/api/v1",
"spec_content": "{\"openapi\":\"3.0.0\",\"info\":{\"title\":\"ERP API\",\"version\":\"1.0.0\"},\"paths\":{\"/items\":{\"get\":{\"operationId\":\"getItem\",\"responses\":{\"200\":{\"description\":\"OK\"}}}}}}",
"auth_type": "bearer",
"secret": "erp-service-token",
"allowed_environments": ["'$ENV_ID'"]
}')

echo "$MCP_SERVER_RESPONSE" | jq
export MCP_SERVER_ID=$(echo "$MCP_SERVER_RESPONSE" | jq -r '.mcp_server.id')

The response includes the generated tool_names:

{
"mcp_server": {
"id": "6f64f080-17d7-44d9-b995-6a353e71f6bc",
"name": "erp",
"type": "openapi",
"url": "https://erp.internal/api/v1",
"tool_names": ["getitem"],
"approval_status": "approved"
}
}

A caller whose API key permits the tool can now discover and call erp__getitem through /mcp, exactly like a tool from a real upstream MCP server.

In the dashboard, choose REST API (OpenAPI) when registering an MCP server. Paste the document, provide its URL, or pick a local .json or .yaml file with Choose file…. A picked file is read into the editor, so you can review and adjust it before saving.

Open-Source AISIX Gateway

Set type: openapi on an mcp_servers entry and provide the document as a nested mapping under spec. The resources file does not accept the AISIX Cloud write fields spec_content or spec_url.

Start an HTTP fixture on the temporary Docker network created in Set Up MCP Gateway. The server exposes an empty directory over HTTP and requires no packages on the host:

docker run -d --name aisix-openapi-fixture \
--network aisix-mcp \
python:3.13-alpine \
python3 -m http.server 8081 --bind 0.0.0.0 --directory /tmp

The following resources expose the fixture's directory listing as fixture__list_directory and grant it to the existing quickstart caller:

resources.yaml
_format_version: "1"

api_keys:
- display_name: quickstart-caller
key_env: CALLER_API_KEY
allowed_models:
- gpt-4o-mini
mcp_access: { allow: ["fixture__list_directory"] }

mcp_servers:
- name: fixture
type: openapi
url: http://aisix-openapi-fixture:8081
auth_type: none
spec:
openapi: 3.0.0
info:
title: Local directory API
version: 1.0.0
paths:
/:
get:
operationId: list_directory
summary: List the fixture directory
responses:
"200":
description: Directory listing returned successfully

This example reuses CALLER_API_KEY, which is already present in the running gateway from the open-source quickstart. Validate and reload the complete resources file. Use the initialization request from Set Up MCP Gateway, then call the generated tool:

curl -sS -X POST "$AISIX_PROXY/mcp" \
-H "Authorization: Bearer $AISIX_MCP_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "fixture__list_directory",
"arguments": {}
}
}' | jq -e \
'.result.content[] | select(.text | contains("Directory listing for /"))'

The command prints the matching tool-result content block. Remove the fixture container when you finish:

docker rm -f aisix-openapi-fixture

Review the Generated Tools in AISIX Cloud

Each registered server's card lists the first few generated tool names and links to a tools page for that server, which lists every tool with:

  • its <server>__<tool> name, which is the form to copy into an API key's mcp_access block or an access policy pattern;
  • the HTTP operation it calls, such as GET /items/{id};
  • its description.

The same listing is available from the API:

curl -sS "$AISIX_CP/mcp_servers/$MCP_SERVER_ID/tools" \
-H "Authorization: Bearer $AISIX_TOKEN"
{
"data": [
{
"name": "getitem",
"namespaced_name": "erp__getitem",
"method": "GET",
"path": "/items",
"description": "GET /items"
}
]
}

The listing is derived from the stored document, so it always matches the tools the gateway serves. It applies to type: openapi servers only. An upstream MCP server's tools live on the upstream, and the endpoint returns 400 for one.

Authenticate to the REST API

The upstream authentication modes apply as-is; the credential is attached to every generated tool call:

  • bearer: Authorization: Bearer <secret>.
  • api_key: the key from secret, sent as the x-api-key header by default. REST APIs often expect a custom header: set api_key_header (for example X-ERP-Key) to override the header name. This field exists only on openapi servers with auth_type: api_key.
  • oauth2: AISIX mints an access token from the configured client credentials and sends it as a bearer, with the same token caching as MCP upstreams.

Redirects are never followed on generated tool calls, so the credential cannot be re-sent to a host you did not configure.

Call Results and Errors

A successful response's body is returned as the tool result text. A non-2xx response returns a tool-level error result (isError: true) carrying HTTP <status> and the response body, so the agent can see and react to the failure. A missing required path parameter is reported the same readable way. AISIX also rejects a path value that contains / or \, or that equals . or .., to keep the request on the configured path.

Update the Document

Replacing the document regenerates the tool list.

For an open-source AISIX gateway, replace the nested spec, validate the complete resources file, and reload the gateway. A rejected reload leaves the previous tool surface active. After a successful reload, list the tools to verify that the updated document produces the expected surface.

In AISIX Cloud, provide spec_content or spec_url on an update call, or use the Replace OpenAPI document editor in the dashboard. The control plane begins projecting the new tool surface when the call returns. The caller holds the permission that approves servers, so the replacement counts as its review and updates the review timestamp. User-session actions also record the reviewing user; admin-token actions do not carry a user ID. A role holding only write on mcp_server_submissions stages the replacement instead, and the current tools keep serving until a reviewer approves it. Changing api_key_header works the same way. Re-uploading a document that normalizes to the identical stored version is not treated as a change at all.

In AISIX Cloud, the server's type is fixed at creation: to switch between an MCP upstream and an OpenAPI backing, delete the entry and register a new one. In resources.yaml, change the entry and reload the file; the newly validated configuration replaces the previous runtime entry.

Next Steps

You can now expose a REST API as MCP tools through either management path. Use these guides to secure and govern the generated tools: