MCP Multiplexing with AgentGateway
Introduction
As your agentic AI environment grows, you end up with a sprawl of MCP servers β one for time utilities, one for general-purpose tools, one for Slack, another for GitHub. Each server exposes different tools, runs on a different port, and needs its own connection configuration.
Your MCP clients (Cursor, Claude Desktop, VS Code) shouldn’t need to know about every server individually. They should connect to one endpoint and see all available tools.
This guide walks you through MCP Multiplexing β federating multiple MCP servers behind a single AgentGateway endpoint.
We’ll deploy two MCP servers (mcp-server-everything for utility tools and mcp-website-fetcher for fetching web content), multiplex them behind AgentGateway, and connect from any IDE.
What You Get
- One endpoint, many servers: Clients connect to
/mcpand see tools from all federated servers - Automatic tool namespacing: Tools are prefixed with the server name to avoid conflicts
- Label-based federation: Add servers by just adding a Kubernetes label β no config changes
- IDE-agnostic: Works with Cursor, VS Code, Claude Code, Windsurf, OpenCode
Architecture
ββββββββββββββββ
β Cursor ββββ
ββββββββββββββββ€ β
β VS Code ββββ€
ββββββββββββββββ€ β ββββββββββββββββββββ ββββββββββββββββββββββββ
β Claude Code ββββΌβMCPβββΆβ AgentGateway ββββββββΆβ mcp-server-everythingβ
ββββββββββββββββ€ β β /mcp endpoint β β (echo, add, etc.) β
β Windsurf ββββ β ββββββββΆββββββββββββββββββββββββ€
ββββββββββββββββ β Multiplexing β β mcp-website-fetcher β
ββββββββββββββββββββ β (fetch web content) β
ββββββββββββββββββββββββ
Prerequisites
- Docker installed and running
- kind installed
kubectlandhelminstalled- At least one MCP client: Cursor, VS Code, Claude Code, Windsurf, or OpenCode
Step 1: Create a Kind Cluster
kind create cluster --name agentgateway-mcp
Verify it’s running:
kubectl get nodes
Step 2: Install AgentGateway OSS
Deploy the Kubernetes Gateway API CRDs:
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.0/standard-install.yaml
Install the AgentGateway CRDs and control plane:
helm upgrade -i --create-namespace \
--namespace agentgateway-system \
--version v2.2.1 \
agentgateway-crds oci://ghcr.io/kgateway-dev/charts/agentgateway-crds
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
You should see the agentgateway control plane pod in Running state.
Step 3: Create an AgentGateway Proxy
kubectl apply -f- <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: mcp-gateway
namespace: agentgateway-system
spec:
gatewayClassName: agentgateway
listeners:
- name: http
port: 80
protocol: HTTP
EOF
Wait for the proxy pod:
kubectl rollout status deploy/mcp-gateway -n agentgateway-system --timeout=60s
Step 4: Deploy Two MCP Servers
Server 1: mcp-server-everything
This is the reference MCP test server from the Model Context Protocol project. It provides utility tools like echo, add, longRunningOperation, and more. The streamableHttp argument tells it to listen over HTTP instead of stdio β which is exactly the transport AgentGateway’s multiplex feature requires.
kubectl apply -f- <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: mcp-server-everything
namespace: agentgateway-system
labels:
app: mcp-server-everything
spec:
replicas: 1
selector:
matchLabels:
app: mcp-server-everything
template:
metadata:
labels:
app: mcp-server-everything
spec:
containers:
- name: mcp-server-everything
image: node:20-alpine
command: ["npx"]
args: ["-y", "@modelcontextprotocol/server-everything", "streamableHttp"]
ports:
- containerPort: 3001
---
apiVersion: v1
kind: Service
metadata:
name: mcp-server-everything
namespace: agentgateway-system
labels:
app: mcp-server-everything
mcp-federation: "true"
spec:
selector:
app: mcp-server-everything
ports:
- protocol: TCP
port: 3001
targetPort: 3001
appProtocol: kgateway.dev/mcp
type: ClusterIP
EOF
Server 2: mcp-website-fetcher
This server provides a fetch tool that can retrieve and extract content from any URL β useful for giving your AI assistant web browsing capabilities. It’s already HTTP-native, no wrapper needed.
kubectl apply -f- <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: mcp-website-fetcher-fix
namespace: agentgateway-system
data:
app.py: |
import httpx
from mcp.server.fastmcp import FastMCP
mcp = FastMCP(
"mcp-website-fetcher",
host="0.0.0.0",
port=8000,
streamable_http_path="/mcp",
stateless_http=True,
)
@mcp.tool()
async def fetch(url: str) -> str:
"""Fetches a website and returns its content"""
headers = {"User-Agent": "MCP Test Server"}
async with httpx.AsyncClient(follow_redirects=True, headers=headers) as client:
response = await client.get(url)
response.raise_for_status()
return response.text
if __name__ == "__main__":
mcp.run(transport="streamable-http")
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mcp-website-fetcher
namespace: agentgateway-system
spec:
selector:
matchLabels:
app: mcp-website-fetcher
template:
metadata:
labels:
app: mcp-website-fetcher
spec:
containers:
- name: mcp-website-fetcher
image: ghcr.io/peterj/mcp-website-fetcher:main
imagePullPolicy: Always
command: ["python3", "/app/app.py"]
volumeMounts:
- name: fix
mountPath: /app/app.py
subPath: app.py
volumes:
- name: fix
configMap:
name: mcp-website-fetcher-fix
---
apiVersion: v1
kind: Service
metadata:
name: mcp-website-fetcher
namespace: agentgateway-system
labels:
app: mcp-website-fetcher
mcp-federation: "true"
spec:
selector:
app: mcp-website-fetcher
ports:
- port: 80
targetPort: 8000
appProtocol: kgateway.dev/mcp
type: ClusterIP
EOF
Wait for both servers to be ready:
kubectl rollout status deploy/mcp-server-everything -n agentgateway-system --timeout=60s
kubectl rollout status deploy/mcp-website-fetcher -n agentgateway-system --timeout=60s
Key detail: Both services have the label
mcp-federation: "true"andappProtocol: kgateway.dev/mcp. This is how AgentGateway discovers and federates them.
Step 5: Create the Multiplexed MCP Backend
Here’s where the magic happens. Instead of pointing to individual servers, you use a label selector to match all services with mcp-federation: "true":
kubectl apply -f- <<EOF
apiVersion: agentgateway.dev/v1alpha1
kind: AgentgatewayBackend
metadata:
name: mcp-federated
namespace: agentgateway-system
spec:
mcp:
targets:
- name: mcp-servers
selector:
services:
matchLabels:
mcp-federation: "true"
EOF
This single backend automatically discovers both mcp-server-everything and mcp-website-fetcher β and any future MCP server you deploy with the mcp-federation: "true" label.
Step 6: Create the HTTPRoute
kubectl apply -f- <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: mcp-route
namespace: agentgateway-system
spec:
parentRefs:
- name: mcp-gateway
namespace: agentgateway-system
rules:
- matches:
- path:
type: PathPrefix
value: /mcp
backendRefs:
- name: mcp-federated
group: agentgateway.dev
kind: AgentgatewayBackend
EOF
Step 7: Port-Forward and Test
Expose the gateway locally:
kubectl port-forward -n agentgateway-system deployment/mcp-gateway 8080:80
Test with MCP Inspector
npx @modelcontextprotocol/inspector@latest
Connect with:
- Transport: Streamable HTTP
- URL:
http://localhost:8080/mcp
Click Tools β List Tools. You should see tools from both servers, namespaced:
mcp-server-everything-3001_echoβ echo a messagemcp-server-everything-3001_addβ add two numbersmcp-server-everything-3001_longRunningOperationβ simulate a long taskmcp-website-fetcher-80_fetchβ fetch and extract content from a URL
One endpoint. Two servers. All tools.
Step 8: Connect from Your IDE
With port-forward running, configure your IDE:
Cursor
Create or edit ~/.cursor/mcp.json:
{
"mcpServers": {
"federated-tools": {
"url": "http://localhost:8080/mcp"
}
}
}
VS Code (with GitHub Copilot)
Add to settings.json:
{
"github.copilot.chat.mcp.servers": {
"federated-tools": {
"url": "http://localhost:8080/mcp"
}
}
}
Claude Code
claude mcp add federated-tools --transport sse http://localhost:8080/mcp
Windsurf
Create or edit ~/.windsurf/mcp.json:
{
"mcpServers": {
"federated-tools": {
"url": "http://localhost:8080/mcp"
}
}
}
OpenCode
Add to opencode.json:
{
"mcp": {
"servers": {
"federated-tools": {
"type": "sse",
"url": "http://localhost:8080/mcp"
}
}
}
}
Now try asking your IDE:
- “Echo back: AgentGateway is awesome” β uses the everything server
- “Add 42 and 58” β uses the everything server
- “Fetch the content from https://agentgateway.dev” β uses the website fetcher
The IDE doesn’t know or care that these tools come from different servers. It’s all one MCP endpoint.
Adding More MCP Servers
The beauty of label-based federation: adding a new server is just a deployment + service with the mcp-federation: "true" label. No AgentGateway config changes needed β the backend’s label selector picks it up automatically.
Cleanup
kubectl delete httproute mcp-route -n agentgateway-system
kubectl delete agentgatewaybackend mcp-federated -n agentgateway-system
kubectl delete deploy mcp-server-everything mcp-website-fetcher -n agentgateway-system
kubectl delete svc mcp-server-everything mcp-website-fetcher -n agentgateway-system
kind delete cluster --name agentgateway-mcp
Conclusion
MCP multiplexing solves one of the biggest challenges in production agentic AI environments: server sprawl. Developers shouldn’t need to configure connections to every MCP server individually. One gateway endpoint, all tools.
Federate all your MCP servers behind AgentGateway, add new servers with a label, and every connected client sees the new tools immediately. No agent code changes. No client reconfiguration.
One gateway. All your tools.