Forward nested token claims as upstream headersv3.14+
Use upstream_headers to extract values from nested objects in a validated JWT
and forward them as HTTP headers to the upstream MCP server.
Each entry specifies the target header name and a path array that describes how
to traverse the token payload. For example, ["realm_access", "roles"] maps the
value at token.realm_access.roles.
upstream_headers and claim_to_header are mutually exclusive. Use upstream_headers
when the claims you need are inside nested objects. Use claim_to_header for top-level
claims only.
Environment variables
-
MCP_RESOURCE_URL: The resource identifier for the MCP server (for example,https://api.example.com/mcp). -
AUTHORIZATION_SERVER_URL: The authorization server URL (for example,https://auth.example.com). -
JWKS_ENDPOINT_URL: The JWKS endpoint URL for fetching the authorization server’s public keys. If not provided, the plugin attempts to discover it from the authorization server metadata.
Add this section to your kong.yaml configuration file:
_format_version: "3.0"
plugins:
- name: ai-mcp-oauth2
config:
resource: ${{ env "DECK_MCP_RESOURCE_URL" }}
authorization_servers:
- ${{ env "DECK_AUTHORIZATION_SERVER_URL" }}
jwks_endpoint: ${{ env "DECK_JWKS_ENDPOINT_URL" }}
upstream_headers:
- header: X-Org-Id
path:
- org
- id
- header: X-User-Role
path:
- realm_access
- roles
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_RESOURCE_URL'",
"authorization_servers": [
"'$AUTHORIZATION_SERVER_URL'"
],
"jwks_endpoint": "'$JWKS_ENDPOINT_URL'",
"upstream_headers": [
{
"header": "X-Org-Id",
"path": [
"org",
"id"
]
},
{
"header": "X-User-Role",
"path": [
"realm_access",
"roles"
]
}
]
},
"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_RESOURCE_URL'",
"authorization_servers": [
"'$AUTHORIZATION_SERVER_URL'"
],
"jwks_endpoint": "'$JWKS_ENDPOINT_URL'",
"upstream_headers": [
{
"header": "X-Org-Id",
"path": [
"org",
"id"
]
},
{
"header": "X-User-Role",
"path": [
"realm_access",
"roles"
]
}
]
},
"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_RESOURCE_URL'
authorization_servers:
- '$AUTHORIZATION_SERVER_URL'
jwks_endpoint: '$JWKS_ENDPOINT_URL'
upstream_headers:
- header: X-Org-Id
path:
- org
- id
- header: X-User-Role
path:
- realm_access
- roles
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_resource_url
authorization_servers = [var.authorization_server_url]
jwks_endpoint = var.jwks_endpoint_url
upstream_headers = [
{
header = "X-Org-Id"
path = ["org", "id"]
},
{
header = "X-User-Role"
path = ["realm_access", "roles"]
} ]
}
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 "jwks_endpoint_url" {
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_RESOURCE_URL" }}
authorization_servers:
- ${{ env "DECK_AUTHORIZATION_SERVER_URL" }}
jwks_endpoint: ${{ env "DECK_JWKS_ENDPOINT_URL" }}
upstream_headers:
- header: X-Org-Id
path:
- org
- id
- header: X-User-Role
path:
- realm_access
- roles
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_RESOURCE_URL'",
"authorization_servers": [
"'$AUTHORIZATION_SERVER_URL'"
],
"jwks_endpoint": "'$JWKS_ENDPOINT_URL'",
"upstream_headers": [
{
"header": "X-Org-Id",
"path": [
"org",
"id"
]
},
{
"header": "X-User-Role",
"path": [
"realm_access",
"roles"
]
}
]
},
"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_RESOURCE_URL'",
"authorization_servers": [
"'$AUTHORIZATION_SERVER_URL'"
],
"jwks_endpoint": "'$JWKS_ENDPOINT_URL'",
"upstream_headers": [
{
"header": "X-Org-Id",
"path": [
"org",
"id"
]
},
{
"header": "X-User-Role",
"path": [
"realm_access",
"roles"
]
}
]
},
"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_RESOURCE_URL'
authorization_servers:
- '$AUTHORIZATION_SERVER_URL'
jwks_endpoint: '$JWKS_ENDPOINT_URL'
upstream_headers:
- header: X-Org-Id
path:
- org
- id
- header: X-User-Role
path:
- realm_access
- roles
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_resource_url
authorization_servers = [var.authorization_server_url]
jwks_endpoint = var.jwks_endpoint_url
upstream_headers = [
{
header = "X-Org-Id"
path = ["org", "id"]
},
{
header = "X-User-Role"
path = ["realm_access", "roles"]
} ]
}
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 "jwks_endpoint_url" {
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_RESOURCE_URL" }}
authorization_servers:
- ${{ env "DECK_AUTHORIZATION_SERVER_URL" }}
jwks_endpoint: ${{ env "DECK_JWKS_ENDPOINT_URL" }}
upstream_headers:
- header: X-Org-Id
path:
- org
- id
- header: X-User-Role
path:
- realm_access
- roles
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_RESOURCE_URL'",
"authorization_servers": [
"'$AUTHORIZATION_SERVER_URL'"
],
"jwks_endpoint": "'$JWKS_ENDPOINT_URL'",
"upstream_headers": [
{
"header": "X-Org-Id",
"path": [
"org",
"id"
]
},
{
"header": "X-User-Role",
"path": [
"realm_access",
"roles"
]
}
]
},
"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_RESOURCE_URL'",
"authorization_servers": [
"'$AUTHORIZATION_SERVER_URL'"
],
"jwks_endpoint": "'$JWKS_ENDPOINT_URL'",
"upstream_headers": [
{
"header": "X-Org-Id",
"path": [
"org",
"id"
]
},
{
"header": "X-User-Role",
"path": [
"realm_access",
"roles"
]
}
]
},
"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_RESOURCE_URL'
authorization_servers:
- '$AUTHORIZATION_SERVER_URL'
jwks_endpoint: '$JWKS_ENDPOINT_URL'
upstream_headers:
- header: X-Org-Id
path:
- org
- id
- header: X-User-Role
path:
- realm_access
- roles
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_resource_url
authorization_servers = [var.authorization_server_url]
jwks_endpoint = var.jwks_endpoint_url
upstream_headers = [
{
header = "X-Org-Id"
path = ["org", "id"]
},
{
header = "X-User-Role"
path = ["realm_access", "roles"]
} ]
}
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 "jwks_endpoint_url" {
type = string
}