Configure consumer groups and key authentication for per-tool MCP access control
Configure consumer groups and key authentication to control access to individual MCP tools based on consumer roles. This configuration applies access control rules at the tool level without a default policy.
For this configuration to work properly, you need to create the following Kong Gateway entities:
services: - name: mcp-service url: http://host.docker.internal:3000 routes: - name: mcp-route paths: - /marketplace plugins: - name: key-auth route: mcp-route config: key_names: - apikey consumer_groups: - name: admin - name: developer - name: suspended consumers: - username: alice groups: - name: admin keyauth_credentials: - key: alice-key - username: bob groups: - name: developer keyauth_credentials: - key: bob-key - username: carol groups: - name: suspended keyauth_credentials: - key: carol-key - username: eason keyauth_credentials: - key: eason-keyCopied!
Before using the AI MCP Proxy plugin, you’ll need an upstream HTTP API to expose.
Use this mock API to test the plugin without relying on an external service. It simulates a small marketplace with sample users and orders exposed through /marketplace/users and /marketplace/{userId}/orders endpoints:
curl -s -o api.js "https://gist.githubusercontent.com/subnetmarco/5ddb23876f9ce7165df17f9216f75cce/raw/a44a947d69e6f597465050cc595b6abf4db2fbea/api.js"
npm install express
node api.js
Prerequisites
- A running and exposed API
Add this section to your kong.yaml configuration file:
_format_version: "3.0"
plugins:
- name: ai-mcp-proxy
config:
mode: conversion-only
include_consumer_groups: true
tools:
- description: Get users
method: GET
path: "/marketplace/users"
annotations:
title: Get users
parameters:
- name: id
in: query
required: false
schema:
type: string
description: Optional user ID
acl:
allow:
- admin
- eason
deny:
- developer
- description: Get orders for a user
method: GET
path: "/marketplace/orders"
annotations:
title: Get users orders
parameters:
- name: userid
in: query
required: true
schema:
type: string
description: User ID to filter orders
acl:
allow:
- admin
- developer
server:
timeout: 60000
max_request_body_size: 8192
Make the following request:
curl -i -X POST http://localhost:8001/plugins/ \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data '
{
"name": "ai-mcp-proxy",
"config": {
"mode": "conversion-only",
"include_consumer_groups": true,
"tools": [
{
"description": "Get users",
"method": "GET",
"path": "/marketplace/users",
"annotations": {
"title": "Get users"
},
"parameters": [
{
"name": "id",
"in": "query",
"required": false,
"schema": {
"type": "string"
},
"description": "Optional user ID"
}
],
"acl": {
"allow": [
"admin",
"eason"
],
"deny": [
"developer"
]
}
},
{
"description": "Get orders for a user",
"method": "GET",
"path": "/marketplace/orders",
"annotations": {
"title": "Get users orders"
},
"parameters": [
{
"name": "userid",
"in": "query",
"required": true,
"schema": {
"type": "string"
},
"description": "User ID to filter orders"
}
],
"acl": {
"allow": [
"admin",
"developer"
]
}
}
],
"server": {
"timeout": 60000
},
"max_request_body_size": 8192
},
"tags": []
}
'
Make the following request:
curl -X POST https://{region}.api.konghq.com/v2/control-planes/{controlPlaneId}/core-entities/plugins/ \
--header "accept: application/json" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer $KONNECT_TOKEN" \
--data '
{
"name": "ai-mcp-proxy",
"config": {
"mode": "conversion-only",
"include_consumer_groups": true,
"tools": [
{
"description": "Get users",
"method": "GET",
"path": "/marketplace/users",
"annotations": {
"title": "Get users"
},
"parameters": [
{
"name": "id",
"in": "query",
"required": false,
"schema": {
"type": "string"
},
"description": "Optional user ID"
}
],
"acl": {
"allow": [
"admin",
"eason"
],
"deny": [
"developer"
]
}
},
{
"description": "Get orders for a user",
"method": "GET",
"path": "/marketplace/orders",
"annotations": {
"title": "Get users orders"
},
"parameters": [
{
"name": "userid",
"in": "query",
"required": true,
"schema": {
"type": "string"
},
"description": "User ID to filter orders"
}
],
"acl": {
"allow": [
"admin",
"developer"
]
}
}
],
"server": {
"timeout": 60000
},
"max_request_body_size": 8192
},
"tags": []
}
'
Make sure to replace the following placeholders with your own values:
-
region: Geographic region where your Kong Konnect is hosted and operates. -
KONNECT_TOKEN: Your Personal Access Token (PAT) associated with your Konnect account. -
controlPlaneId: Theidof the control plane.
See the Konnect API reference to learn about region-specific URLs and personal access tokens.
echo "
apiVersion: configuration.konghq.com/v1
kind: KongClusterPlugin
metadata:
name: ai-mcp-proxy
namespace: kong
annotations:
kubernetes.io/ingress.class: kong
konghq.com/tags: ''
labels:
global: 'true'
config:
mode: conversion-only
include_consumer_groups: true
tools:
- description: Get users
method: GET
path: '/marketplace/users'
annotations:
title: Get users
parameters:
- name: id
in: query
required: false
schema:
type: string
description: Optional user ID
acl:
allow:
- admin
- eason
deny:
- developer
- description: Get orders for a user
method: GET
path: '/marketplace/orders'
annotations:
title: Get users orders
parameters:
- name: userid
in: query
required: true
schema:
type: string
description: User ID to filter orders
acl:
allow:
- admin
- developer
server:
timeout: 60000
max_request_body_size: 8192
plugin: ai-mcp-proxy
" | kubectl apply -f -
Prerequisite: Configure your Personal Access Token
terraform {
required_providers {
konnect = {
source = "kong/konnect"
}
}
}
provider "konnect" {
personal_access_token = "$KONNECT_TOKEN"
server_url = "https://us.api.konghq.com/"
}
Add the following to your Terraform configuration to create a Konnect Gateway Plugin:
resource "konnect_gateway_plugin_ai_mcp_proxy" "my_ai_mcp_proxy" {
enabled = true
config = {
mode = "conversion-only"
include_consumer_groups = true
tools = [
{
description = "Get users"
method = "GET"
path = "/marketplace/users"
annotations = {
title = "Get users"
}
parameters = [
{
name = "id"
in = "query"
required = false
schema = {
type = "string"
}
description = "Optional user ID"
} ]
acl = {
allow = ["admin", "eason"]
deny = ["developer"]
}
},
{
description = "Get orders for a user"
method = "GET"
path = "/marketplace/orders"
annotations = {
title = "Get users orders"
}
parameters = [
{
name = "userid"
in = "query"
required = true
schema = {
type = "string"
}
description = "User ID to filter orders"
} ]
acl = {
allow = ["admin", "developer"]
}
} ]
server = {
timeout = 60000
}
max_request_body_size = 8192
}
tags = []
control_plane_id = konnect_gateway_control_plane.my_konnect_cp.id
}
Add this section to your kong.yaml configuration file:
_format_version: "3.0"
plugins:
- name: ai-mcp-proxy
service: serviceName|Id
config:
mode: conversion-only
include_consumer_groups: true
tools:
- description: Get users
method: GET
path: "/marketplace/users"
annotations:
title: Get users
parameters:
- name: id
in: query
required: false
schema:
type: string
description: Optional user ID
acl:
allow:
- admin
- eason
deny:
- developer
- description: Get orders for a user
method: GET
path: "/marketplace/orders"
annotations:
title: Get users orders
parameters:
- name: userid
in: query
required: true
schema:
type: string
description: User ID to filter orders
acl:
allow:
- admin
- developer
server:
timeout: 60000
max_request_body_size: 8192
Make sure to replace the following placeholders with your own values:
-
serviceName|Id: Theidornameof the service the plugin configuration will target.
Make the following request:
curl -i -X POST http://localhost:8001/services/{serviceName|Id}/plugins/ \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data '
{
"name": "ai-mcp-proxy",
"config": {
"mode": "conversion-only",
"include_consumer_groups": true,
"tools": [
{
"description": "Get users",
"method": "GET",
"path": "/marketplace/users",
"annotations": {
"title": "Get users"
},
"parameters": [
{
"name": "id",
"in": "query",
"required": false,
"schema": {
"type": "string"
},
"description": "Optional user ID"
}
],
"acl": {
"allow": [
"admin",
"eason"
],
"deny": [
"developer"
]
}
},
{
"description": "Get orders for a user",
"method": "GET",
"path": "/marketplace/orders",
"annotations": {
"title": "Get users orders"
},
"parameters": [
{
"name": "userid",
"in": "query",
"required": true,
"schema": {
"type": "string"
},
"description": "User ID to filter orders"
}
],
"acl": {
"allow": [
"admin",
"developer"
]
}
}
],
"server": {
"timeout": 60000
},
"max_request_body_size": 8192
},
"tags": []
}
'
Make sure to replace the following placeholders with your own values:
-
serviceName|Id: Theidornameof the service the plugin configuration will target.
Make the following request:
curl -X POST https://{region}.api.konghq.com/v2/control-planes/{controlPlaneId}/core-entities/services/{serviceId}/plugins/ \
--header "accept: application/json" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer $KONNECT_TOKEN" \
--data '
{
"name": "ai-mcp-proxy",
"config": {
"mode": "conversion-only",
"include_consumer_groups": true,
"tools": [
{
"description": "Get users",
"method": "GET",
"path": "/marketplace/users",
"annotations": {
"title": "Get users"
},
"parameters": [
{
"name": "id",
"in": "query",
"required": false,
"schema": {
"type": "string"
},
"description": "Optional user ID"
}
],
"acl": {
"allow": [
"admin",
"eason"
],
"deny": [
"developer"
]
}
},
{
"description": "Get orders for a user",
"method": "GET",
"path": "/marketplace/orders",
"annotations": {
"title": "Get users orders"
},
"parameters": [
{
"name": "userid",
"in": "query",
"required": true,
"schema": {
"type": "string"
},
"description": "User ID to filter orders"
}
],
"acl": {
"allow": [
"admin",
"developer"
]
}
}
],
"server": {
"timeout": 60000
},
"max_request_body_size": 8192
},
"tags": []
}
'
Make sure to replace the following placeholders with your own values:
-
region: Geographic region where your Kong Konnect is hosted and operates. -
KONNECT_TOKEN: Your Personal Access Token (PAT) associated with your Konnect account. -
controlPlaneId: Theidof the control plane. -
serviceId: Theidof the service the plugin configuration will target.
See the Konnect API reference to learn about region-specific URLs and personal access tokens.
echo "
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: ai-mcp-proxy
namespace: kong
annotations:
kubernetes.io/ingress.class: kong
konghq.com/tags: ''
config:
mode: conversion-only
include_consumer_groups: true
tools:
- description: Get users
method: GET
path: '/marketplace/users'
annotations:
title: Get users
parameters:
- name: id
in: query
required: false
schema:
type: string
description: Optional user ID
acl:
allow:
- admin
- eason
deny:
- developer
- description: Get orders for a user
method: GET
path: '/marketplace/orders'
annotations:
title: Get users orders
parameters:
- name: userid
in: query
required: true
schema:
type: string
description: User ID to filter orders
acl:
allow:
- admin
- developer
server:
timeout: 60000
max_request_body_size: 8192
plugin: ai-mcp-proxy
" | kubectl apply -f -
Next, apply the KongPlugin resource by annotating the service resource:
kubectl annotate -n kong service SERVICE_NAME konghq.com/plugins=ai-mcp-proxy
Prerequisite: Configure your Personal Access Token
terraform {
required_providers {
konnect = {
source = "kong/konnect"
}
}
}
provider "konnect" {
personal_access_token = "$KONNECT_TOKEN"
server_url = "https://us.api.konghq.com/"
}
Add the following to your Terraform configuration to create a Konnect Gateway Plugin:
resource "konnect_gateway_plugin_ai_mcp_proxy" "my_ai_mcp_proxy" {
enabled = true
config = {
mode = "conversion-only"
include_consumer_groups = true
tools = [
{
description = "Get users"
method = "GET"
path = "/marketplace/users"
annotations = {
title = "Get users"
}
parameters = [
{
name = "id"
in = "query"
required = false
schema = {
type = "string"
}
description = "Optional user ID"
} ]
acl = {
allow = ["admin", "eason"]
deny = ["developer"]
}
},
{
description = "Get orders for a user"
method = "GET"
path = "/marketplace/orders"
annotations = {
title = "Get users orders"
}
parameters = [
{
name = "userid"
in = "query"
required = true
schema = {
type = "string"
}
description = "User ID to filter orders"
} ]
acl = {
allow = ["admin", "developer"]
}
} ]
server = {
timeout = 60000
}
max_request_body_size = 8192
}
tags = []
control_plane_id = konnect_gateway_control_plane.my_konnect_cp.id
service = {
id = konnect_gateway_service.my_service.id
}
}
Add this section to your kong.yaml configuration file:
_format_version: "3.0"
plugins:
- name: ai-mcp-proxy
route: routeName|Id
config:
mode: conversion-only
include_consumer_groups: true
tools:
- description: Get users
method: GET
path: "/marketplace/users"
annotations:
title: Get users
parameters:
- name: id
in: query
required: false
schema:
type: string
description: Optional user ID
acl:
allow:
- admin
- eason
deny:
- developer
- description: Get orders for a user
method: GET
path: "/marketplace/orders"
annotations:
title: Get users orders
parameters:
- name: userid
in: query
required: true
schema:
type: string
description: User ID to filter orders
acl:
allow:
- admin
- developer
server:
timeout: 60000
max_request_body_size: 8192
Make sure to replace the following placeholders with your own values:
-
routeName|Id: Theidornameof the route the plugin configuration will target.
Make the following request:
curl -i -X POST http://localhost:8001/routes/{routeName|Id}/plugins/ \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data '
{
"name": "ai-mcp-proxy",
"config": {
"mode": "conversion-only",
"include_consumer_groups": true,
"tools": [
{
"description": "Get users",
"method": "GET",
"path": "/marketplace/users",
"annotations": {
"title": "Get users"
},
"parameters": [
{
"name": "id",
"in": "query",
"required": false,
"schema": {
"type": "string"
},
"description": "Optional user ID"
}
],
"acl": {
"allow": [
"admin",
"eason"
],
"deny": [
"developer"
]
}
},
{
"description": "Get orders for a user",
"method": "GET",
"path": "/marketplace/orders",
"annotations": {
"title": "Get users orders"
},
"parameters": [
{
"name": "userid",
"in": "query",
"required": true,
"schema": {
"type": "string"
},
"description": "User ID to filter orders"
}
],
"acl": {
"allow": [
"admin",
"developer"
]
}
}
],
"server": {
"timeout": 60000
},
"max_request_body_size": 8192
},
"tags": []
}
'
Make sure to replace the following placeholders with your own values:
-
routeName|Id: Theidornameof the route the plugin configuration will target.
Make the following request:
curl -X POST https://{region}.api.konghq.com/v2/control-planes/{controlPlaneId}/core-entities/routes/{routeId}/plugins/ \
--header "accept: application/json" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer $KONNECT_TOKEN" \
--data '
{
"name": "ai-mcp-proxy",
"config": {
"mode": "conversion-only",
"include_consumer_groups": true,
"tools": [
{
"description": "Get users",
"method": "GET",
"path": "/marketplace/users",
"annotations": {
"title": "Get users"
},
"parameters": [
{
"name": "id",
"in": "query",
"required": false,
"schema": {
"type": "string"
},
"description": "Optional user ID"
}
],
"acl": {
"allow": [
"admin",
"eason"
],
"deny": [
"developer"
]
}
},
{
"description": "Get orders for a user",
"method": "GET",
"path": "/marketplace/orders",
"annotations": {
"title": "Get users orders"
},
"parameters": [
{
"name": "userid",
"in": "query",
"required": true,
"schema": {
"type": "string"
},
"description": "User ID to filter orders"
}
],
"acl": {
"allow": [
"admin",
"developer"
]
}
}
],
"server": {
"timeout": 60000
},
"max_request_body_size": 8192
},
"tags": []
}
'
Make sure to replace the following placeholders with your own values:
-
region: Geographic region where your Kong Konnect is hosted and operates. -
KONNECT_TOKEN: Your Personal Access Token (PAT) associated with your Konnect account. -
controlPlaneId: Theidof the control plane. -
routeId: Theidof the route the plugin configuration will target.
See the Konnect API reference to learn about region-specific URLs and personal access tokens.
echo "
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: ai-mcp-proxy
namespace: kong
annotations:
kubernetes.io/ingress.class: kong
konghq.com/tags: ''
config:
mode: conversion-only
include_consumer_groups: true
tools:
- description: Get users
method: GET
path: '/marketplace/users'
annotations:
title: Get users
parameters:
- name: id
in: query
required: false
schema:
type: string
description: Optional user ID
acl:
allow:
- admin
- eason
deny:
- developer
- description: Get orders for a user
method: GET
path: '/marketplace/orders'
annotations:
title: Get users orders
parameters:
- name: userid
in: query
required: true
schema:
type: string
description: User ID to filter orders
acl:
allow:
- admin
- developer
server:
timeout: 60000
max_request_body_size: 8192
plugin: ai-mcp-proxy
" | kubectl apply -f -
Next, apply the KongPlugin resource by annotating the httproute or ingress resource:
kubectl annotate -n kong httproute konghq.com/plugins=ai-mcp-proxy
kubectl annotate -n kong ingress konghq.com/plugins=ai-mcp-proxy
Prerequisite: Configure your Personal Access Token
terraform {
required_providers {
konnect = {
source = "kong/konnect"
}
}
}
provider "konnect" {
personal_access_token = "$KONNECT_TOKEN"
server_url = "https://us.api.konghq.com/"
}
Add the following to your Terraform configuration to create a Konnect Gateway Plugin:
resource "konnect_gateway_plugin_ai_mcp_proxy" "my_ai_mcp_proxy" {
enabled = true
config = {
mode = "conversion-only"
include_consumer_groups = true
tools = [
{
description = "Get users"
method = "GET"
path = "/marketplace/users"
annotations = {
title = "Get users"
}
parameters = [
{
name = "id"
in = "query"
required = false
schema = {
type = "string"
}
description = "Optional user ID"
} ]
acl = {
allow = ["admin", "eason"]
deny = ["developer"]
}
},
{
description = "Get orders for a user"
method = "GET"
path = "/marketplace/orders"
annotations = {
title = "Get users orders"
}
parameters = [
{
name = "userid"
in = "query"
required = true
schema = {
type = "string"
}
description = "User ID to filter orders"
} ]
acl = {
allow = ["admin", "developer"]
}
} ]
server = {
timeout = 60000
}
max_request_body_size = 8192
}
tags = []
control_plane_id = konnect_gateway_control_plane.my_konnect_cp.id
route = {
id = konnect_gateway_route.my_route.id
}
}