For the complete documentation index, see llms.txt. Markdown versions of all docs pages are available by appending .md to any docs URL.
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:
- Set up a local Kubernetes cluster with agentgateway
- Deploy two separate MCP servers (echo and filesystem)
- Federate both servers into a single AgentgatewayBackend
- 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 agentgatewayStep 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://oci://cr.agentgateway.dev/charts/agentgateway/charts/agentgateway-crds
# Control plane
helm upgrade -i -n agentgateway-system agentgateway oci://oci://cr.agentgateway.dev/charts/agentgateway/charts/agentgateway \
--version vVerify the control plane is running:
kubectl get pods -n agentgateway-systemStep 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
EOFWait for the proxy to be ready:
kubectl get deployment agentgateway-proxy -n agentgateway-systemStep 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
EOFMCP “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
EOFWait for both pods to be ready:
kubectl get pods -n agentgateway-system -l 'app in (mcp-everything, mcp-filesystem)' -wStep 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
EOFStep 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
EOFStep 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