You can use Squid to create a simple forward proxy for testing.
Squid runs as its own Docker container, separate from the AI Gateway data plane container. In the following examples, the data plane reaches Squid through host.docker.internal, the special hostname that Docker Desktop and OrbStack resolve to the host machine from inside any container. This works because the compose file below publishes Squid’s port to the host, so any container — including the AI Gateway data plane, which runs in its own separate Docker network — can reach it via the host machine, without needing to share a Docker network or edit your machine’s hosts file.
In a production deployment your forward proxy should authenticate users, including AI Gateway. To do this. set auth_username and auth_password. You can reference secrets from an AI Vault.
-
Create a minimal config file for Squid:
echo '
# Allow your local machine. Different container runtimes (Docker Desktop, OrbStack, Colima)
# allocate bridge networks in different private ranges, so this allows all of them.
acl localnet src 10.0.0.0/8
acl localnet src 172.16.0.0/12
acl localnet src 192.168.0.0/16
acl SSL_ports port 443
acl Safe_ports port 80 443
http_access deny !Safe_ports
http_access allow localnet
http_access allow localhost
http_access deny all
http_port 3128
access_log /var/log/squid/access.log combined
cache_log /var/log/squid/cache.log
' > squid.conf
-
Create a docker compose file:
echo '
services:
squid:
image: ubuntu/squid
container_name: squid
ports:
- "3128:3128"
volumes:
- ./squid.conf:/etc/squid/squid.conf:ro
' > docker-compose.yml
-
Run Squid using docker:
To create a new AI Gateway using Konnect, do the following:
- Create a new personal access token from the Konnect PAT page by selecting Generate Token.
-
Export your token as an environment variable:
export KONNECT_TOKEN='YOUR_KONNECT_PAT'
-
Run the AI Gateway quickstart script to automatically provision a control plane in Kong Konnect and a local data plane:
curl -Ls https://get.konghq.com/ai | bash -s -- -k $KONNECT_TOKEN
This sets up a AI Gateway control plane named ai-quickstart, provisions a local data plane, and prints out the following environment variables export:
export AI_GATEWAY_ID=your-gateway-id
export DECK_KONNECT_TOKEN=$KONNECT_TOKEN
export DECK_KONNECT_CONTROL_PLANE_NAME=quickstart
export KONNECT_CONTROL_PLANE_URL=https://us.api.konghq.com
export KONNECT_PROXY_URL='http://localhost:8000'
Copy and paste these into your terminal to configure your session.
Generate an Anthropic API key, then export it as an environment variable:
export ANTHROPIC_API_KEY='YOUR_ANTHROPIC_API_KEY'
Create an AI Provider entity to define your LLM service and store authentication credentials:
kongctl apply -f - --auto-approve --pat "$KONNECT_TOKEN" << 'EOF'
ai_gateway_model_providers:
- ref: generic-anthropic
ai_gateway: !lookup {id: !env AI_GATEWAY_ID}
name: generic-anthropic
display_name: "generic-anthropic"
type: anthropic
config:
auth:
type: basic
headers:
- name: x-api-key
value: !secret {source: !env ANTHROPIC_API_KEY}
EOF
Create an AI Model entity and specify your forward proxy host:
kongctl apply -f - --auto-approve --pat "$KONNECT_TOKEN" << 'EOF'
ai_gateway_models:
- ref: my-claude
ai_gateway: !lookup {id: !env AI_GATEWAY_ID}
name: my-claude
display_name: "my-claude"
type: model
formats:
- type: anthropic
config:
route:
paths:
- /
model:
body_param: model
values:
- my-claude
proxy:
http_proxy:
host: host.docker.internal
port: 3128
https_proxy:
host: host.docker.internal
port: 3128
proxy_scheme: http
targets:
- name: claude-opus-4-8
provider: generic-anthropic
config:
type: anthropic
policies: []
capabilities:
- generate
EOF
-
Send a chat request. This will be forwarded through your proxy service to Anthropic:
curl -X POST "$KONNECT_PROXY_URL/v1/messages" \
--no-progress-meter --fail-with-body \
-H "Accept: application/json"\
-H "Content-Type: application/json"\
-H "Authorization: Bearer $ANTHROPIC_API_KEY" \
--json '{
"model": "my-claude",
"max_tokens": 100,
"messages": [
{
"role": "user",
"content": "Say this is a test!"
}
]
}'
-
Examine the Squid logs to verify your requests:
docker exec -it squid tail -f /var/log/squid/access.log
-
Run the Swagger Petstore sample API in its own Docker container:
docker run -d \
--name swagger-petstore-forward-proxy \
-p 8080:8080 \
swaggerapi/petstore3:latest
-
Create an AI MCP Server entity that exposes the Petstore API through a single MCP tool:
curl -X POST "https://us.api.konghq.com/v1/ai-gateways/$AI_GATEWAY_ID/mcp-servers" \
--no-progress-meter --fail-with-body \
-H "Authorization: Bearer $KONNECT_TOKEN"\
-H "Content-Type: application/json"\
-H "Accept: application/json, application/problem+json" \
--json '{
"display_name": "Petstore API (forward proxy)",
"name": "petstore-forward-proxy-mcp",
"type": "conversion-listener",
"enabled": true,
"policies": [],
"access": {
"acl_attribute_type": "consumer",
"acls": {
"allow": []
},
"default_tool_acls": {
"deny": []
}
},
"config": {
"url": "http://host.docker.internal:8080/api/v3",
"route": {
"paths": [
"/petstore-forward-proxy"
]
},
"logging": {
"payloads": false
},
"server": {
"timeout": 60000
}
},
"tools": [
{
"name": "get-pet-by-id",
"description": "Get a pet by ID",
"method": "GET",
"path": "/petstore-forward-proxy/pet/{petId}",
"parameters": [
{
"name": "petId",
"in": "path",
"required": true,
"schema": {
"type": "integer"
},
"description": "ID of the pet to retrieve"
}
]
}
]
}'
-
Use MCP Inspector CLI to verify that the MCP server exposes get-pet-by-id as a tool:
npx -y @modelcontextprotocol/inspector@0.22.0 --cli \
http://localhost:8000/petstore-forward-proxy \
--transport http --method tools/list | jq -r '.tools[].name'
You should see the following output:
-
This MCP Server does not route through your forward proxy, since conversion-listener doesn’t support it. Calling get-pet-by-id reaches Petstore directly:
npx -y @modelcontextprotocol/inspector@0.22.0 --cli \
http://localhost:8000/petstore-forward-proxy \
--transport http --method tools/call \
--tool-name get-pet-by-id \
--tool-arg path_petId=7 | jq -r '.content[0].text' | jq -c '.'
You should see the following response:
{"id":7,"category":{"id":4,"name":"Lions"},"name":"Lion 1","photoUrls":["url1","url2"],"tags":[{"id":1,"name":"tag1"},{"id":2,"name":"tag2"}],"status":"available"}