Set access control rules for MCP tools based on consumer groups
Define which consumer groups can access specific MCP tools in conversion-listener mode. Use default rules that apply to all tools, then override access for individual tools as needed.
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-keyCopied!
In conversion-listener and conversion-only modes, the plugin defines MCP tools directly from HTTP endpoint configurations. Each tool can optionally specify access control rules per consumer group.
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-listener
include_consumer_groups: true
default_acl:
- scope: tools
allow:
- developer
- admin
deny:
- suspended
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
- 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-listener",
"include_consumer_groups": true,
"default_acl": [
{
"scope": "tools",
"allow": [
"developer",
"admin"
],
"deny": [
"suspended"
]
}
],
"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"
]
}
},
{
"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-listener",
"include_consumer_groups": true,
"default_acl": [
{
"scope": "tools",
"allow": [
"developer",
"admin"
],
"deny": [
"suspended"
]
}
],
"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"
]
}
},
{
"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-listener
include_consumer_groups: true
default_acl:
- scope: tools
allow:
- developer
- admin
deny:
- suspended
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
- 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-listener"
include_consumer_groups = true
default_acl = [
{
scope = "tools"
allow = ["developer", "admin"]
deny = ["suspended"]
} ]
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"]
}
},
{
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-listener
include_consumer_groups: true
default_acl:
- scope: tools
allow:
- developer
- admin
deny:
- suspended
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
- 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-listener",
"include_consumer_groups": true,
"default_acl": [
{
"scope": "tools",
"allow": [
"developer",
"admin"
],
"deny": [
"suspended"
]
}
],
"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"
]
}
},
{
"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-listener",
"include_consumer_groups": true,
"default_acl": [
{
"scope": "tools",
"allow": [
"developer",
"admin"
],
"deny": [
"suspended"
]
}
],
"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"
]
}
},
{
"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-listener
include_consumer_groups: true
default_acl:
- scope: tools
allow:
- developer
- admin
deny:
- suspended
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
- 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-listener"
include_consumer_groups = true
default_acl = [
{
scope = "tools"
allow = ["developer", "admin"]
deny = ["suspended"]
} ]
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"]
}
},
{
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-listener
include_consumer_groups: true
default_acl:
- scope: tools
allow:
- developer
- admin
deny:
- suspended
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
- 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-listener",
"include_consumer_groups": true,
"default_acl": [
{
"scope": "tools",
"allow": [
"developer",
"admin"
],
"deny": [
"suspended"
]
}
],
"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"
]
}
},
{
"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-listener",
"include_consumer_groups": true,
"default_acl": [
{
"scope": "tools",
"allow": [
"developer",
"admin"
],
"deny": [
"suspended"
]
}
],
"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"
]
}
},
{
"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-listener
include_consumer_groups: true
default_acl:
- scope: tools
allow:
- developer
- admin
deny:
- suspended
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
- 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-listener"
include_consumer_groups = true
default_acl = [
{
scope = "tools"
allow = ["developer", "admin"]
deny = ["suspended"]
} ]
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"]
}
},
{
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
}
}