Skip to content

MCP federation

Federate tools from multiple MCP servers through a single endpoint on Kubernetes

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 --server-side -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.5.0/standard-install.yaml

# agentgateway CRDs
helm upgrade -i --create-namespace \
  --namespace agentgateway-system \
  --version v agentgateway-crds oci://cr.agentgateway.dev/charts/agentgateway-crds

# Control plane
helm upgrade -i -n agentgateway-system agentgateway oci://cr.agentgateway.dev/charts/agentgateway \
  --version v

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: agentgateway.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: agentgateway.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

JWT Authorization

Secure with JWT authentication

MCP Documentation

Complete MCP configuration reference

Was this page helpful?
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.

Tip: one topic per conversation gives the best results. Use the + button in the chat header to start a new conversation.

Switching topics? Starting a new conversation improves accuracy.
↑↓ navigate select esc dismiss

What could be improved?

Your feedback helps us improve assistant answers and identify docs gaps we should fix.

Need more help? Join us on Discord: https://discord.gg/y9efgEmppm

Want to use your own agent? Add the Solo MCP server to query our docs directly. Get started here: https://search.solo.io/.