HTTP APIs as Tools
The HTTP APIs as Tools use case describes exposing a plain REST API as MCP tools with no MCP server in front of it. This tutorial runs that pattern end to end: httpbin stands in for "any REST API you want to expose," and its /anything endpoint echoes back whatever request reaches it, so you can see exactly what get_payment_status sends upstream.
Prerequisites
docker-compose.yaml
services:
gateway:
image: ghcr.io/aklivity/zilla:latest
pull_policy: always
depends_on:
- payments-api
ports:
- 7114:7114
- 7190:7190
volumes:
- ./zilla.yaml:/etc/zilla/zilla.yaml
command: start -v -e
payments-api:
image: kennethreitz/httpbin
ports:
- 8000:80zilla.yaml
name: http-apis-as-tools
catalogs:
payments_catalog:
type: inline
options:
subjects:
get_payment_status_params:
schema: |
{
"type": "object",
"properties": {
"paymentId": {
"type": "string"
}
},
"required": [
"paymentId"
]
}
stores:
cache:
type: memory
bindings:
north_tcp_server:
type: tcp
kind: server
options:
host: 0.0.0.0
port: 7114
routes:
- when:
- port: 7114
exit: north_http_server
north_http_server:
type: http
kind: server
options:
access-control:
policy: cross-origin
routes:
- when:
- headers:
":path": /mcp
exit: north_mcp_server
north_mcp_server:
type: mcp
kind: server
exit: north_mcp_proxy
telemetry:
metrics:
- mcp.*
attributes:
method: ${mcp.method}
tool: ${mcp.tool}
outcome: ${mcp.outcome}
north_mcp_proxy:
type: mcp
kind: proxy
options:
cache:
store: cache
ttl: PT5M
routes:
- exit: payments_http_proxy
when:
- toolkit: payments
#region new_binding
payments_http_proxy:
type: mcp-http
kind: proxy
options:
tools:
get_payment_status:
description: Look up the status of a payment by identifier.
summary: "Routed to ${result.url}"
schemas:
input:
model: json
catalog:
payments_catalog:
- subject: get_payment_status_params
version: latest
routes:
- when:
- tool: get_payment_status
exit: sys:http_client
with:
headers:
":method": GET
":scheme": http
":authority": payments-api:80
":path": /anything/payments/${args.paymentId}
#endregion new_binding
telemetry:
metrics:
- mcp.initialize
- mcp.initialize.duration
- mcp.tools.list
- mcp.tools.list.duration
- mcp.tools.call
- mcp.tools.call.duration
exporters:
prometheus_exporter:
type: prometheus
options:
endpoints:
- scheme: http
port: 7190
path: /metricspayments_http_proxy names one tool, validates its paymentId argument, and maps tools/call to a GET request against httpbin, no MCP client, no upstream MCP server:
payments_http_proxy:
type: mcp-http
kind: proxy
options:
tools:
get_payment_status:
description: Look up the status of a payment by identifier.
summary: "Routed to ${result.url}"
schemas:
input:
model: json
catalog:
payments_catalog:
- subject: get_payment_status_params
version: latest
routes:
- when:
- tool: get_payment_status
exit: sys:http_client
with:
headers:
":method": GET
":scheme": http
":authority": payments-api:80
":path": /anything/payments/${args.paymentId}Start the Stack
docker compose up -dThis starts AI Gateway on port 7114 and the payments-api stand-in on port 8000.
Call the Tool
Point an MCP client at http://localhost:7114/mcp. After initialize, tools/list returns the toolkit-prefixed tool:
{"name":"payments__get_payment_status","description":"Look up the status of a payment by identifier.","inputSchema":{"type":"object","properties":{"paymentId":{"type":"string"}},"required":["paymentId"]}}Calling it with {"paymentId": "pay_123"} returns:
{
"structuredContent": {
"method": "GET",
"url": "http://payments-api:80/anything/payments/pay_123",
"headers": { "Host": "payments-api:80" },
"args": {},
"json": null
},
"content": [{ "type": "text", "text": "Routed to http://payments-api:80/anything/payments/pay_123" }],
"isError": false
}paymentId was resolved directly from the tool call's arguments into the upstream path, structuredContent is httpbin's own response passed straight through, and content[0].text is the summary template ("Routed to ${result.url}") interpolated against that same response.
To see the same round trip without an MCP client, hit the upstream directly:
curl http://localhost:8000/anything/payments/pay_123Verify Metrics
curl http://localhost:7190/metricsmcp_tools_call_total{namespace="http-apis-as-tools",binding="north_mcp_server",tool="payments__get_payment_status",outcome="ok"} 1Stop the Stack
docker compose downNext Steps
- See OpenAPI Specs as Tools for deriving a tool automatically from an OpenAPI document instead of hand-authoring it.
- See MCP Gateway Setup for adding a REST-backed toolkit like this one to an already-running, multi-upstream gateway.

