Configure the AI MCP Oauth2 plugin
Configure the AI MCP Oauth2 plugin.
The AI MCP OAuth2 plugin is in a tech preview state. The OAuth 2.0 specification for MCP is still new and evolving, and most identity providers do not yet fully implement the required metadata and flows. As a result, the plugin behavior and configuration options may change in future releases.
Audience validation
This example sets insecure_relaxed_audience_validation to true to skip audience validation for MCP tokens
if the authorization server doesn’t include the resource URL in the audience (aud) claim.
This is defined in RFC 8707, but not all authorization servers implement it yet.
Environment variables
-
MCP_AUTH_URL: The MCP authentication resource endpoint. -
KEYCLOAK_AUTHZ_URL: The Keycloak authorization server URL. -
KEYCLOAK_INTROSPECTION_URL: The Keycloak token introspection endpoint. Kong Gateway uses this endpoint to verify access tokens sent by MCP client. -
CLIENT_ID: The client ID used by Kong Gateway in introspection. -
CLIENT_SECRET: The client secret used by Kong Gateway in introspection.
Add this section to your kong.yaml configuration file:
_format_version: "3.0"
plugins:
- name: ai-mcp-oauth2
config:
resource: ${{ env "DECK_MCP_AUTH_URL" }}
authorization_servers:
- ${{ env "DECK_KEYCLOAK_AUTHZ_URL" }}
introspection_endpoint: ${{ env "DECK_KEYCLOAK_INTROSPECTION_URL" }}
client_id: ${{ env "DECK_CLIENT_ID" }}
client_secret: ${{ env "DECK_CLIENT_SECRET" }}
claim_to_header:
- claim: sub
header: X-User-Id
insecure_relaxed_audience_validation: true
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-oauth2",
"config": {
"resource": "'$MCP_AUTH_URL'",
"authorization_servers": [
"'$KEYCLOAK_AUTHZ_URL'"
],
"introspection_endpoint": "'$KEYCLOAK_INTROSPECTION_URL'",
"client_id": "'$CLIENT_ID'",
"client_secret": "'$CLIENT_SECRET'",
"claim_to_header": [
{
"claim": "sub",
"header": "X-User-Id"
}
],
"insecure_relaxed_audience_validation": true
},
"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-oauth2",
"config": {
"resource": "'$MCP_AUTH_URL'",
"authorization_servers": [
"'$KEYCLOAK_AUTHZ_URL'"
],
"introspection_endpoint": "'$KEYCLOAK_INTROSPECTION_URL'",
"client_id": "'$CLIENT_ID'",
"client_secret": "'$CLIENT_SECRET'",
"claim_to_header": [
{
"claim": "sub",
"header": "X-User-Id"
}
],
"insecure_relaxed_audience_validation": true
},
"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-oauth2
namespace: kong
annotations:
kubernetes.io/ingress.class: kong
konghq.com/tags: ''
labels:
global: 'true'
config:
resource: '$MCP_AUTH_URL'
authorization_servers:
- '$KEYCLOAK_AUTHZ_URL'
introspection_endpoint: '$KEYCLOAK_INTROSPECTION_URL'
client_id: '$CLIENT_ID'
client_secret: '$CLIENT_SECRET'
claim_to_header:
- claim: sub
header: X-User-Id
insecure_relaxed_audience_validation: true
plugin: ai-mcp-oauth2
" | 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_oauth2" "my_ai_mcp_oauth2" {
enabled = true
config = {
resource = var.mcp_auth_url
authorization_servers = [var.keycloak_authz_url]
introspection_endpoint = var.keycloak_introspection_url
client_id = var.client_id
client_secret = var.client_secret
claim_to_header = [
{
claim = "sub"
header = "X-User-Id"
} ]
insecure_relaxed_audience_validation = true
}
tags = []
control_plane_id = konnect_gateway_control_plane.my_konnect_cp.id
}
This example requires the following variables to be added to your manifest. You can specify values at runtime by setting TF_VAR_name=value.
variable "client_secret" {
type = string
}
Add this section to your kong.yaml configuration file:
_format_version: "3.0"
plugins:
- name: ai-mcp-oauth2
service: serviceName|Id
config:
resource: ${{ env "DECK_MCP_AUTH_URL" }}
authorization_servers:
- ${{ env "DECK_KEYCLOAK_AUTHZ_URL" }}
introspection_endpoint: ${{ env "DECK_KEYCLOAK_INTROSPECTION_URL" }}
client_id: ${{ env "DECK_CLIENT_ID" }}
client_secret: ${{ env "DECK_CLIENT_SECRET" }}
claim_to_header:
- claim: sub
header: X-User-Id
insecure_relaxed_audience_validation: true
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-oauth2",
"config": {
"resource": "'$MCP_AUTH_URL'",
"authorization_servers": [
"'$KEYCLOAK_AUTHZ_URL'"
],
"introspection_endpoint": "'$KEYCLOAK_INTROSPECTION_URL'",
"client_id": "'$CLIENT_ID'",
"client_secret": "'$CLIENT_SECRET'",
"claim_to_header": [
{
"claim": "sub",
"header": "X-User-Id"
}
],
"insecure_relaxed_audience_validation": true
},
"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-oauth2",
"config": {
"resource": "'$MCP_AUTH_URL'",
"authorization_servers": [
"'$KEYCLOAK_AUTHZ_URL'"
],
"introspection_endpoint": "'$KEYCLOAK_INTROSPECTION_URL'",
"client_id": "'$CLIENT_ID'",
"client_secret": "'$CLIENT_SECRET'",
"claim_to_header": [
{
"claim": "sub",
"header": "X-User-Id"
}
],
"insecure_relaxed_audience_validation": true
},
"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-oauth2
namespace: kong
annotations:
kubernetes.io/ingress.class: kong
konghq.com/tags: ''
config:
resource: '$MCP_AUTH_URL'
authorization_servers:
- '$KEYCLOAK_AUTHZ_URL'
introspection_endpoint: '$KEYCLOAK_INTROSPECTION_URL'
client_id: '$CLIENT_ID'
client_secret: '$CLIENT_SECRET'
claim_to_header:
- claim: sub
header: X-User-Id
insecure_relaxed_audience_validation: true
plugin: ai-mcp-oauth2
" | 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-oauth2
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_oauth2" "my_ai_mcp_oauth2" {
enabled = true
config = {
resource = var.mcp_auth_url
authorization_servers = [var.keycloak_authz_url]
introspection_endpoint = var.keycloak_introspection_url
client_id = var.client_id
client_secret = var.client_secret
claim_to_header = [
{
claim = "sub"
header = "X-User-Id"
} ]
insecure_relaxed_audience_validation = true
}
tags = []
control_plane_id = konnect_gateway_control_plane.my_konnect_cp.id
service = {
id = konnect_gateway_service.my_service.id
}
}
This example requires the following variables to be added to your manifest. You can specify values at runtime by setting TF_VAR_name=value.
variable "client_secret" {
type = string
}
Add this section to your kong.yaml configuration file:
_format_version: "3.0"
plugins:
- name: ai-mcp-oauth2
route: routeName|Id
config:
resource: ${{ env "DECK_MCP_AUTH_URL" }}
authorization_servers:
- ${{ env "DECK_KEYCLOAK_AUTHZ_URL" }}
introspection_endpoint: ${{ env "DECK_KEYCLOAK_INTROSPECTION_URL" }}
client_id: ${{ env "DECK_CLIENT_ID" }}
client_secret: ${{ env "DECK_CLIENT_SECRET" }}
claim_to_header:
- claim: sub
header: X-User-Id
insecure_relaxed_audience_validation: true
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-oauth2",
"config": {
"resource": "'$MCP_AUTH_URL'",
"authorization_servers": [
"'$KEYCLOAK_AUTHZ_URL'"
],
"introspection_endpoint": "'$KEYCLOAK_INTROSPECTION_URL'",
"client_id": "'$CLIENT_ID'",
"client_secret": "'$CLIENT_SECRET'",
"claim_to_header": [
{
"claim": "sub",
"header": "X-User-Id"
}
],
"insecure_relaxed_audience_validation": true
},
"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-oauth2",
"config": {
"resource": "'$MCP_AUTH_URL'",
"authorization_servers": [
"'$KEYCLOAK_AUTHZ_URL'"
],
"introspection_endpoint": "'$KEYCLOAK_INTROSPECTION_URL'",
"client_id": "'$CLIENT_ID'",
"client_secret": "'$CLIENT_SECRET'",
"claim_to_header": [
{
"claim": "sub",
"header": "X-User-Id"
}
],
"insecure_relaxed_audience_validation": true
},
"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-oauth2
namespace: kong
annotations:
kubernetes.io/ingress.class: kong
konghq.com/tags: ''
config:
resource: '$MCP_AUTH_URL'
authorization_servers:
- '$KEYCLOAK_AUTHZ_URL'
introspection_endpoint: '$KEYCLOAK_INTROSPECTION_URL'
client_id: '$CLIENT_ID'
client_secret: '$CLIENT_SECRET'
claim_to_header:
- claim: sub
header: X-User-Id
insecure_relaxed_audience_validation: true
plugin: ai-mcp-oauth2
" | 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-oauth2
kubectl annotate -n kong ingress konghq.com/plugins=ai-mcp-oauth2
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_oauth2" "my_ai_mcp_oauth2" {
enabled = true
config = {
resource = var.mcp_auth_url
authorization_servers = [var.keycloak_authz_url]
introspection_endpoint = var.keycloak_introspection_url
client_id = var.client_id
client_secret = var.client_secret
claim_to_header = [
{
claim = "sub"
header = "X-User-Id"
} ]
insecure_relaxed_audience_validation = true
}
tags = []
control_plane_id = konnect_gateway_control_plane.my_konnect_cp.id
route = {
id = konnect_gateway_route.my_route.id
}
}
This example requires the following variables to be added to your manifest. You can specify values at runtime by setting TF_VAR_name=value.
variable "client_secret" {
type = string
}