Skip to main content

Set Up MCP Gateway

In this guide, you will register an upstream MCP server and grant one of its tools to a caller API key. You will then verify that the caller can use only the granted tool through /mcp. AISIX Cloud and the open-source AISIX gateway configure the same runtime behavior through different management paths.

Prerequisites

Before starting, prepare the following:

Start an MCP Test Server

The example runs the official MCP Everything test server in Docker. The server and your existing gateway join a temporary Docker network, so the gateway can reach the server without a restart. Use the Everything server only for local testing: it has no authentication and includes a diagnostic tool that can return its process environment. The container used here receives no secrets. Stop and remove it after finishing the guide.

Set the gateway container name for your configuration path.

For AISIX Cloud:

export AISIX_GATEWAY_CONTAINER="aisix-dp"

For the open-source AISIX gateway:

export AISIX_GATEWAY_CONTAINER="aisix-quickstart"

Create a temporary network and connect the running gateway to it:

docker network create aisix-mcp
docker network connect aisix-mcp "$AISIX_GATEWAY_CONTAINER"

Start the Everything server on the same network:

docker run -d --name aisix-mcp-everything \
--network aisix-mcp \
node:22-alpine \
sh -c 'npx -y @modelcontextprotocol/server-everything@2026.7.4 streamableHttp'

Wait until the server is ready:

for attempt in $(seq 1 120); do
docker logs aisix-mcp-everything 2>&1 | grep -q "listening on port 3001" && break
sleep 1
done

docker logs aisix-mcp-everything 2>&1 | grep "listening on port 3001"

The final command prints a log line confirming that port 3001 is ready. From the gateway container, the MCP endpoint is available at http://aisix-mcp-everything:3001/mcp.

Register the Server and Grant a Tool

Register the server using the management path for your deployment. Both paths name the server everything and grant only its echo tool to the existing quickstart caller.

AISIX Cloud

Register the test server and allow it in the quickstart environment:

MCP_SERVER_RESPONSE=$(curl -fsS -X POST "$AISIX_CP/mcp_servers" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
--data-binary @- <<EOF
{
"name": "everything",
"type": "mcp",
"url": "http://aisix-mcp-everything:3001/mcp",
"auth_type": "none",
"allowed_environments": ["${ENV_ID}"]
}
EOF
)

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

name becomes the tool namespace.

allowed_environments controls which environments receive this organization-level resource.

The write-scoped admin token created by the quickstart approves the server immediately. The control plane then projects the server to the attached gateway automatically.

Grant the everything__echo tool to the caller API key created by the quickstart:

curl -fsS -X PATCH \
"$AISIX_CP/environments/$ENV_ID/api_keys/$API_KEY_ID" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"allowed_tools":["everything__echo"]}' | jq

export AISIX_MCP_KEY="$AISIX_API_KEY"

The partial update retains the key's existing model access. AISIX_MCP_KEY uses the plaintext caller key returned by the quickstart.

Open-Source AISIX Gateway

In the existing resources.yaml, add allowed_tools to the quickstart caller and add the mcp_servers collection. Keep the existing provider key and model entries unchanged:

resources.yaml
api_keys:
- display_name: quickstart-caller
key_env: CALLER_API_KEY
allowed_models:
- gpt-4o-mini
allowed_tools:
- everything__echo

mcp_servers:
- name: everything
type: mcp
url: http://aisix-mcp-everything:3001/mcp
auth_type: none

allowed_tools grants the quickstart caller only the namespaced echo tool.

❷ The server name becomes the tool namespace, so the upstream echo tool is exposed as everything__echo.

Validate the complete file inside the running gateway container, then reload it without restarting the container:

docker exec aisix-quickstart \
aisix validate --resources /etc/aisix/resources.yaml

docker kill --signal HUP aisix-quickstart

export AISIX_MCP_KEY="$CALLER_API_KEY"

If the updated file is invalid, the gateway keeps serving the last valid configuration. Check docker logs aisix-quickstart for the rejected load.

Verify MCP Tool Access

The commands in this section are the same for both management paths. They use the existing AISIX_PROXY value and the caller credential saved in AISIX_MCP_KEY.

An MCP client performs the initialization exchange automatically. Send an initialization request directly to verify the endpoint:

curl -fsS -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": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-11-25",
"capabilities": {},
"clientInfo": {"name": "aisix-setup", "version": "1.0"}
}
}' | jq -e '.result.capabilities.tools'

A successful response includes the server's tools capability. Complete the initialization exchange:

curl -fsS -o /dev/null -w "%{http_code}\n" \
-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",
"method": "notifications/initialized"
}'

The notification returns HTTP 202 with no response body.

The AISIX Cloud control plane can take a few seconds to project configuration to a gateway. Poll the tool list for up to 90 seconds, then verify that only the allowed tool is visible:

for attempt in $(seq 1 45); do
TOOLS_RESPONSE=$(curl -fsS -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/list",
"params": {}
}') || true

if echo "$TOOLS_RESPONSE" | jq -e \
'.result.tools | map(.name) == ["everything__echo"]' >/dev/null 2>&1; then
break
fi
sleep 2
done

echo "$TOOLS_RESPONSE" | jq -e \
'.result.tools | map(.name) == ["everything__echo"]'

The final command prints true. Call the permitted tool:

curl -fsS -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": 3,
"method": "tools/call",
"params": {
"name": "everything__echo",
"arguments": {"message": "hello through AISIX"}
}
}' | jq -e \
'.result.content[] | select(.text == "Echo: hello through AISIX")'

The command prints the matching tool-result content block. To verify that the allowlist is enforced, attempt to call another tool from the same upstream server:

curl -fsS -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": 4,
"method": "tools/call",
"params": {
"name": "everything__get-sum",
"arguments": {"a": 1, "b": 2}
}
}' | jq -e \
'.error.message == "tool '\''everything__get-sum'\'' is not available"'

The command prints true. AISIX rejects the call without sending it upstream.

Adapt the Setup for Your MCP Server

Replace the test server URL with a Streamable HTTP endpoint reachable from the gateway. Keep type: mcp, and configure the upstream credential with auth_type and its related fields. See Upstream Authentication.

For an open-source AISIX gateway, validate the complete resources file and send SIGHUP when the running gateway already has every referenced environment variable. If you add or change an environment variable, recreate the container with the new value. See Reload a Resources File.

AISIX Cloud stores upstream credentials in the control plane and projects the approved configuration to attached gateways. To let members submit servers without publishing them directly, use Review and Approve MCP Servers.

Clean Up

Keep the server and caller grant if you plan to continue with the other MCP Gateway guides. Otherwise, remove the resources added through your management path.

For AISIX Cloud, clear the caller's tool grant and delete the server:

curl -fsS -X PATCH \
"$AISIX_CP/environments/$ENV_ID/api_keys/$API_KEY_ID" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"allowed_tools":[]}' | jq

curl -fsS -X DELETE "$AISIX_CP/mcp_servers/$MCP_SERVER_ID" \
-H "Authorization: Bearer $AISIX_TOKEN"

For an open-source AISIX gateway, remove the allowed_tools and mcp_servers additions from resources.yaml, validate the file, and send SIGHUP again.

Remove the test server and temporary network:

docker rm -f aisix-mcp-everything
docker network disconnect aisix-mcp "$AISIX_GATEWAY_CONTAINER"
docker network rm aisix-mcp

Next Steps

You have now registered an MCP server, granted one tool, and verified both allowed and denied tool calls. Use these guides to extend the setup: