MCP Federation

Expose a single MCP endpoint that aggregates tools from multiple backend MCP servers with unified routing on Kubernetes.

What you’ll build

In this tutorial, you will:

  1. Set up a local Kubernetes cluster with agentgateway
  2. Deploy two separate MCP servers (echo and filesystem)
  3. Federate both servers into a single AgentgatewayBackend
  4. Access tools from both servers through one unified endpoint

Before you begin

Make sure you have the following tools installed:

For detailed installation instructions, see the LLM Gateway tutorial.


Step 1: Create a kind cluster

kind create cluster --name agentgateway

Step 2: Install agentgateway

# Gateway API CRDs
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.0/standard-install.yaml

# agentgateway CRDs
helm upgrade -i --create-namespace \
  --namespace agentgateway-system \
  --version v2.2.1 agentgateway-crds oci://ghcr.io/kgateway-dev/charts/agentgateway-crds

# Control plane
helm upgrade -i -n agentgateway-system agentgateway oci://ghcr.io/kgateway-dev/charts/agentgateway \
  --version v2.2.1

Verify the control plane is running:

kubectl get pods -n agentgateway-system

Step 3: Create a Gateway

kubectl apply -f- <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: agentgateway-proxy
  namespace: agentgateway-system
spec:
  gatewayClassName: agentgateway
  listeners:
  - protocol: HTTP
    port: 80
    name: http
    allowedRoutes:
      namespaces:
        from: All
EOF

Wait for the proxy to be ready:

kubectl get deployment agentgateway-proxy -n agentgateway-system

Step 4: Deploy the MCP servers

Deploy two separate MCP servers that provide different sets of tools.

MCP “Everything” server

This server provides general-purpose tools like echo, add, and longRunningOperation.

kubectl apply -f- <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mcp-everything
  namespace: agentgateway-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mcp-everything
  template:
    metadata:
      labels:
        app: mcp-everything
    spec:
      containers:
      - name: mcp-server
        image: node:22-alpine
        command: ["npx", "-y", "mcp-proxy", "--port", "8080", "--", "npx", "-y", "@modelcontextprotocol/server-everything"]
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: mcp-everything
  namespace: agentgateway-system
spec:
  selector:
    app: mcp-everything
  ports:
  - port: 80
    targetPort: 8080
    appProtocol: kgateway.dev/mcp
EOF

MCP “Filesystem” server

This server provides file operation tools like read_file, write_file, and list_directory.

kubectl apply -f- <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mcp-filesystem
  namespace: agentgateway-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mcp-filesystem
  template:
    metadata:
      labels:
        app: mcp-filesystem
    spec:
      containers:
      - name: mcp-server
        image: node:22-alpine
        command: ["npx", "-y", "mcp-proxy", "--port", "8080", "--", "npx", "-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: mcp-filesystem
  namespace: agentgateway-system
spec:
  selector:
    app: mcp-filesystem
  ports:
  - port: 80
    targetPort: 8080
    appProtocol: kgateway.dev/mcp
EOF

Wait for both pods to be ready:

kubectl get pods -n agentgateway-system -l 'app in (mcp-everything, mcp-filesystem)' -w

Step 5: Create the federated backend

Create a single AgentgatewayBackend that targets both MCP servers. Tools from each server are automatically prefixed with their target name.

kubectl apply -f- <<EOF
apiVersion: agentgateway.dev/v1alpha1
kind: AgentgatewayBackend
metadata:
  name: mcp-federated
  namespace: agentgateway-system
spec:
  mcp:
    targets:
    - name: everything
      static:
        host: mcp-everything.agentgateway-system.svc.cluster.local
        port: 80
        protocol: SSE
    - name: filesystem
      static:
        host: mcp-filesystem.agentgateway-system.svc.cluster.local
        port: 80
        protocol: SSE
EOF

Step 6: Create the HTTPRoute

kubectl apply -f- <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: mcp-federated
  namespace: agentgateway-system
spec:
  parentRefs:
    - name: agentgateway-proxy
      namespace: agentgateway-system
  rules:
    - backendRefs:
      - name: mcp-federated
        namespace: agentgateway-system
        group: agentgateway.dev
        kind: AgentgatewayBackend
EOF

Step 7: Test the federated endpoint

Set up port-forwarding:

kubectl port-forward deployment/agentgateway-proxy -n agentgateway-system 8080:80 &

Initialize an MCP session:

curl -s -i http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}},"id":1}'

Copy the mcp-session-id from the response headers, then list all available tools:

curl -s http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Mcp-Session-Id: YOUR_SESSION_ID" \
  -d '{"jsonrpc":"2.0","method":"tools/list","id":2}'

You should see tools from both servers, prefixed with their target name:

  • everything_echo, everything_add, everything_longRunningOperation, …
  • filesystem_read_file, filesystem_write_file, filesystem_list_directory, …

Call a tool from each server

Call the echo tool from the “everything” server:

curl -s http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Mcp-Session-Id: YOUR_SESSION_ID" \
  -d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"everything_echo","arguments":{"message":"Hello from federation!"}},"id":3}'

Call the list_directory tool from the “filesystem” server:

curl -s http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Mcp-Session-Id: YOUR_SESSION_ID" \
  -d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"filesystem_list_directory","arguments":{"path":"/tmp"}},"id":4}'

Cleanup

kill %1 2>/dev/null
kind delete cluster --name agentgateway

Next steps

Agentgateway assistant

Ask me anything about agentgateway configuration, features, or usage.

Note: AI-generated content might contain errors; please verify and test all returned information.

↑↓ navigate select esc dismiss

What could be improved?