Deploy an MCP server with Context Mesh and Kong Operator

Incompatible with
on-prem
Related Documentation
Minimum Version
Kong Gateway - 3.13
TL;DR

Install Kong Operator 2.3 with the mcp-server feature gate, create a Konnect-managed control plane and data plane, then create and deploy the MCP server with the Konnect API.

Prerequisites

  1. Create a new personal access token by opening the Konnect PAT page and selecting Generate Token.

  2. Export the token and the Konnect API URL for your region:

    export KONNECT_TOKEN='YOUR_KONNECT_PAT'
    export KONNECT_CONTROL_PLANE_URL='us.api.konghq.com'

Set up a local Kubernetes cluster. This example uses minikube:

minikube start

Once started, open a separate terminal window, and activate load balancing on your cluster:

minikube tunnel

Type your password when prompted. Leave this window open on the side as you follow this guide.

  1. Install Claude Code:
     curl -fsSL https://claude.ai/install.sh | bash
  2. Verify the installation:
     claude --version
  1. Create an account at openweathermap.org
  2. Generate an API key (may take several hours to activate)
export OPENWEATHERMAP_API_KEY='<your-api-key'

Download the OpenWeatherMap OpenAPI specification. You upload this file to Konnect later in this guide:

curl -O https://developer.konghq.com/assets/context-mesh/openweathermap.json

Add the Kong Helm repository

Map the name kong to the Kong Helm charts URL and download the latest chart index:

helm repo add kong https://charts.konghq.com
helm repo update

Install Kong Operator

Kong Gateway needs Kong Operator to run a Context Mesh MCP server:

helm upgrade --install kong-operator kong/kong-operator -n kong \
  --create-namespace \
  --set image.tag=2.3 \
  --set env.ENABLE_CONTROLLER_KONNECT=true \
  --set env.FEATURE_GATES=mcp-server

This command creates the kong namespace containing:

  • The operator itself (kong-operator-kong-operator-controller-manager).
  • CustomResourceDefinitions (CRDs) that add resource types such as DataPlane to your Kubernetes cluster.
  • Role-based access control (RBAC) rules that let the operator manage those resources on your behalf.
  • Webhook configurations that validate the resources before they’re applied.

Wait for the Kong Operator deployment to become available before you create any Konnect resources:

kubectl -n kong wait --for=condition=Available=true --timeout=120s \
  deployment/kong-operator-kong-operator-controller-manager

Deploy a Konnect control plane and data plane

The following manifest creates the four resources that Kong Operator needs to run a Konnect-managed data plane in your cluster:

  • KonnectAPIAuthConfiguration: Authenticates Kong Operator against the Konnect API with your personal access token. The serverURL is read from KONNECT_CONTROL_PLANE_URL, so it points at whichever region your account uses.
  • KonnectGatewayControlPlane: Creates a control plane named context-mesh-demo in Konnect. This is the control plane you attach the MCP server to in a later step.
  • KonnectExtension: Links the cluster to that control plane and provisions the mTLS certificates the data plane uses to connect to it.
  • DataPlane: Deploys three Kong Gateway 3.16 proxy replicas. The KonnectExtension reference configures them to run in hybrid mode and pull their configuration from context-mesh-demo.

Apply the manifest:

kubectl apply -f - <<EOF
kind: KonnectAPIAuthConfiguration
apiVersion: konnect.konghq.com/v1alpha1
metadata:
  name: konnect-api-auth
  namespace: default
spec:
  type: token
  token: ${KONNECT_TOKEN}
  serverURL: ${KONNECT_CONTROL_PLANE_URL}
---
kind: KonnectGatewayControlPlane
apiVersion: konnect.konghq.com/v1alpha2
metadata:
  name: test
  namespace: default
spec:
  createControlPlaneRequest:
    name: context-mesh-demo
    labels:
      app: context-mesh-demo
  konnect:
    authRef:
      name: konnect-api-auth
---
kind: KonnectExtension
apiVersion: konnect.konghq.com/v1alpha2
metadata:
  name: my-konnect-config
  namespace: default
spec:
  konnect:
    controlPlane:
      ref:
        type: konnectNamespacedRef
        konnectNamespacedRef:
          name: test
---
apiVersion: gateway-operator.konghq.com/v1beta1
kind: DataPlane
metadata:
  name: dataplane
  namespace: default
spec:
  extensions:
  - kind: KonnectExtension
    name: my-konnect-config
    group: konnect.konghq.com
  deployment:
    replicas: 3
    podTemplateSpec:
      spec:
        containers:
        - name: proxy
          image: kong/kong-gateway:3.16
EOF

Wait for the data plane to be ready

kubectl wait --timeout=3m dataplane dataplane -n default --for=condition=Ready

Get the control plane ID

Retrieve the context-mesh-demo control plane ID that Kong Operator created. You’ll use it to attach it to the MCP server when you deploy it:

CONTROL_PLANE_ID=$(curl -X GET "https://us.api.konghq.com/v2/control-planes?filter%5Bname%5D%5Beq%5D=context-mesh-demo" \
     --no-progress-meter --fail-with-body  \
     -H "Authorization: Bearer $KONNECT_TOKEN" | jq -r ".data[0].id"
)

Add the OpenWeather API as a source

A source holds the OpenAPI specification that Context Mesh generates the MCP server from. The specification is sent as a single JSON string, so build the request body from the file you downloaded:

jq -n --rawfile spec openweathermap.json '{
  "name": "openweathermap",
  "display_name": "OpenWeatherMap Current Weather API",
  "description": "Current weather data from OpenWeatherMap",
  "labels": {},
  "type": "api",
  "source": {
    "type": "raw",
    "config": {"spec": $spec}
  }
}' > source.json

Create the source:

SOURCE_ID=$(curl -X POST "https://us.api.konghq.com/v1/context-sources" \
     --no-progress-meter --fail-with-body  \
     -H "Authorization: Bearer $KONNECT_TOKEN" \
     --json "$(cat source.json)" | jq -r ".id"
)

The name must be unique within your organization and can only contain lowercase letters, digits, periods, and hyphens.

Create the MCP server

Create the MCP server:

MCP_SERVER_ID=$(curl -X POST "https://us.api.konghq.com/v1/context-interfaces" \
     --no-progress-meter --fail-with-body  \
     -H "Authorization: Bearer $KONNECT_TOKEN" \
     --json '{
       "name": "openweather-service",
       "display_name": "OpenWeather Service",
       "description": "Code Mode MCP server for the OpenWeatherMap API",
       "labels": {}
     }' | jq -r ".id"
)

The MCP server has no sources yet. Map the OpenWeather source to it:

SOURCE_MAPPING_ID=$(curl -X POST "https://us.api.konghq.com/v1/context-interfaces/$MCP_SERVER_ID/context-source-mappings" \
     --no-progress-meter --fail-with-body  \
     -H "Authorization: Bearer $KONNECT_TOKEN" \
     --json '{
       "context_source_id": "'$SOURCE_ID'"
     }' | jq -r ".id"
)

To expose more than one API or MCP server through the same MCP server, repeat this call for each source.

Deploy the MCP server

Mapping the MCP server to a control plane deploys it. Set mode to basic to let Konnect manage the underlying Kubernetes workload with its defaults:

CP_MAPPING_ID=$(curl -X POST "https://us.api.konghq.com/v1/context-interfaces/$MCP_SERVER_ID/control-plane-mappings" \
     --no-progress-meter --fail-with-body  \
     -H "Authorization: Bearer $KONNECT_TOKEN" \
     --json '{
       "control_plane_id": "'$CONTROL_PLANE_ID'",
       "mode": "basic"
     }' | jq -r ".id"
)

Wait for the MCP server pod to be ready

Kong Operator runs the MCP server as an mcpserver- prefixed deployment in the default namespace of your cluster. Wait for its pod to appear, then wait for it to become ready:

until kubectl get pods -n default -o name | grep -q '^pod/mcpserver-'; do sleep 5; done

kubectl wait --for=condition=Ready --timeout=3m -n default \
  $(kubectl get pods -n default -o name | grep '^pod/mcpserver-')

Confirm that the pod is running:

kubectl get pods -n default | grep mcpserver

The output looks like this:

mcpserver-test-45675cb3-764b4d6d6c-q2gnp   1/1     Running   0   57m

If the pod stays in Pending or CrashLoopBackOff, check its logs with kubectl logs -n default <pod-name>.

The MCP runtime is now exposed at /mcp/openweather-service.

Add the OpenWeather MCP server to Claude

Connect the MCP server to an agent:

claude mcp add --transport http context-mesh-weather http://localhost/mcp/openweather-service \
  --header "X-Upstream-Api-Key: ${OPENWEATHERMAP_API_KEY}"

Validate

Start Claude Code:

claude

Verify that the local context-mesh-weather MCP is in your list:

/mcp

If the MCP appears as disabled, select it and enable it. You might need to input your sudo password on the minikube tunnel terminal for this step.

Try a prompt in Claude Code:

Tell me the weather in Hawaii.

Cleanup

Stop the MCP server by deleting its control plane mapping, then delete the MCP server and its source:

Delete the control plane mapping:

curl -X DELETE "https://us.api.konghq.com/v1/context-interfaces/$MCP_SERVER_ID/control-plane-mappings/$CP_MAPPING_ID" \
     --no-progress-meter --fail-with-body  \
     -H "Authorization: Bearer $KONNECT_TOKEN"

Delete the MCP server:

curl -X DELETE "https://us.api.konghq.com/v1/context-interfaces/$MCP_SERVER_ID" \
     --no-progress-meter --fail-with-body  \
     -H "Authorization: Bearer $KONNECT_TOKEN"

Delete the MCP source:

curl -X DELETE "https://us.api.konghq.com/v1/context-sources/$SOURCE_ID" \
     --no-progress-meter --fail-with-body  \
     -H "Authorization: Bearer $KONNECT_TOKEN"
kubectl delete -n default dataplane dataplane
kubectl delete -n default konnectextension my-konnect-config
kubectl delete -n default konnectgatewaycontrolplane test
kubectl delete -n default konnectapiauthconfiguration konnect-api-auth

Deleting the KonnectGatewayControlPlane also deletes the context-mesh-demo control plane in Konnect. Run this step even if you plan to repeat the guide: control plane names must be unique within an organization, so a leftover context-mesh-demo makes the next run fail with a 409 Conflict and the data plane never becomes ready.

helm uninstall kong-operator -n kong
kubectl delete namespace kong

Help us make these docs great!

Kong Developer docs are open source. If you find these useful and want to make them better, contribute today!