Expose REST APIs as MCP Tools for AI Agents
The openapi-to-mcp plugin exposes existing REST APIs as tools that AI agents can discover and invoke through MCP (Model Context Protocol). Existing APIs stay unchanged, and their OpenAPI 3.x documents provide the tool definitions instead of requiring custom agent integrations.
The plugin forwards MCP traffic to the OpenAPI-to-MCP service deployed alongside the gateway. The service publishes each OpenAPI operation as a tool and translates tool calls into upstream HTTP requests.
How MCP Gateway Works
The request path is:
AI Agent -> MCP Client -> API7 Gateway -> OpenAPI-to-MCP Service -> Upstream REST APIs
The plugin does not start an MCP server. It proxies requests to the separately deployed OpenAPI-to-MCP service at 127.0.0.1:3000 by default. The service must share the gateway's network namespace and exposes two transport modes:
sse(default):GET /.api7_mcp/ssefor the event streamPOSTmessages on the MCP message endpoint
streamable_http:- Stateless
POST /.api7_mcp/mcp_stateless
- Stateless
For the SSE connection request and for Streamable HTTP requests, the plugin automatically injects x-openapi2mcp-base-url and x-openapi2mcp-openapi-spec headers from the plugin configuration before forwarding the request to the MCP sidecar. You do not need to set these headers manually.
Prerequisites
Before you begin, make sure you have:
-
API7 Enterprise Gateway running (
openapi-to-mcpis Enterprise-only). -
The OpenAPI-to-MCP service deployed in the same network namespace as the gateway. For Helm deployments, set
openapiToMcp.enabled: true. For Docker or bare-metal deployments, follow Prepare API7 Gateway. -
Create a token from the Dashboard and save it to an environment variable:
export API_KEY=your-dashboard-token # replace with your Dashboard token -
Replace
{gateway_group_id}with your gateway group ID. Usedefaultif you are following the quickstart. -
If you are following the Admin API examples, create or reuse a service in API7 Gateway. If you do not have one yet, follow Create or Reuse a Service, then save its ID to an environment variable:
export SERVICE_ID=your-service-id # replace with your service ID -
Start the pinned Petstore fixture in
openapi-to-mcp→ Start Petstore. For Kubernetes, replace the example namespaceaicwith the gateway namespace, typicallyapi7. The fixture then serves its OpenAPI document and API athttp://petstore:8080from the gateway network. -
An MCP client (for example, Claude Desktop or another MCP-compatible client) for validation.
Configure the MCP Gateway
Configure a route that exposes the pinned Petstore fixture as MCP tools. The fixture provides both the OpenAPI document and the API used by the generated tools.
- Admin API
- ADC
curl -k "https://localhost:7443/apisix/admin/routes/openapi-to-mcp-route?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
--data-binary @- <<EOF
{
"name": "openapi-to-mcp-route",
"service_id": "$SERVICE_ID",
"paths": ["/.api7_mcp/*"],
"plugins": {
"openapi-to-mcp": {
"openapi_url": "http://petstore:8080/api/v3/openapi.json",
"base_url": "http://petstore:8080/api/v3",
"transport": "sse",
"headers": {},
"flatten_parameters": false
}
}
}
EOF
❶ openapi_url points to your OpenAPI 3.x document. The OpenAPI-to-MCP service parses this spec and builds MCP tools from its operations.
❷ base_url is the upstream REST API base address used when a tool is invoked.
❸ transport selects the MCP transport. Use sse (default) or streamable_http.
❹ flatten_parameters controls whether nested parameters are flattened when generating tool input schemas.
services:
- name: MCP Gateway
labels:
docs-example: openapi-to-mcp-guide
routes:
- uris:
- /.api7_mcp/*
name: openapi-to-mcp-route
plugins:
openapi-to-mcp:
openapi_url: http://petstore:8080/api/v3/openapi.json
base_url: http://petstore:8080/api/v3
transport: sse
headers: {}
flatten_parameters: false
❶ openapi_url points to your OpenAPI 3.x document. The OpenAPI-to-MCP service parses this spec and builds MCP tools from its operations.
❷ base_url is the upstream REST API base address used when a tool is invoked.
❸ transport selects the MCP transport. Use sse (default) or streamable_http.
❹ flatten_parameters controls whether nested parameters are flattened when generating tool input schemas.
Preview the tutorial service and confirm that the diff contains no unintended updates or deletions:
adc diff -f adc.yaml \
--include-resource-type service \
--label-selector docs-example=openapi-to-mcp-guide
Synchronize the reviewed service configuration:
adc sync -f adc.yaml \
--include-resource-type service \
--label-selector docs-example=openapi-to-mcp-guide
Validate with an MCP Client
Step 1 — Connect and Discover Tools
SSE Mode
Connect the MCP client to the SSE endpoint:
curl -N "http://127.0.0.1:9080/.api7_mcp/sse"
A successful connection returns an event stream with a session-specific endpoint:
event: endpoint
data: /.api7_mcp/sse?sessionId=abc123xyz
The sessionId value identifies the SSE session created by the MCP sidecar. Use the session-specific endpoint returned by the event stream instead of the route pattern configured on the gateway.
Streamable HTTP Mode
The two transports are mutually exclusive for a route. Before using the Streamable HTTP examples, change transport from sse to streamable_http in the route configuration shown earlier, then reapply that configuration with the Admin API or adc sync.
Send a tools/list request to discover available tools:
curl -s "http://127.0.0.1:9080/.api7_mcp/mcp_stateless" \
-X POST \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list",
"params": {}
}'
The response should be an SSE message event whose tool list includes an entry similar to:
{
"name": "getPetById",
"description": "Returns a single pet"
}
Step 2 — Invoke a Tool
With the route configured for streamable_http, call a tool to verify end-to-end REST forwarding. The following example calls getPetById, which requires a path parameter petId. Because flatten_parameters is false, provide the parameter under pathParameters.
curl -s "http://127.0.0.1:9080/.api7_mcp/mcp_stateless" \
-X POST \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/call",
"params": {
"name": "getPetById",
"arguments": {
"pathParameters": {
"petId": 1
}
}
}
}'
A successful call returns HTTP 200 and an MCP result containing the Petstore resource with ID 1. Depending on the deployed OpenAPI-to-MCP service version, the resource can appear in a JSON-encoded upstream response envelope or directly in the result, including as structuredContent.
Security Considerations
When exposing APIs as MCP tools, apply the same controls as production API traffic:
- Authentication: enforce gateway auth (API key, JWT, mTLS) before MCP tool calls reach the OpenAPI-to-MCP service.
- Authorization: restrict which routes and operations an agent identity can access.
- Rate limiting: apply request or token-based limits to prevent abusive or runaway agent traffic.
- Sidecar egress: restrict network egress from the OpenAPI-to-MCP service because it fetches the OpenAPI document and sends upstream requests directly. Configure
allowed_hostswhenbase_urlcontains variables.
Next Steps
- Token-Based Rate Limiting and Quota Management — Control agent traffic and cost.
- AI Observability and Cost Tracking — Monitor tool usage and latency.
- For the full configuration reference, see
openapi-to-mcp.