One multiplex MCP · Streamable HTTP

MCP servers

One agentgateway path for every Viper SandboxAgent. Clients hit http://172.16.10.135:30100/mcp on the LAN. The gateway multiplexes tools/list and tools/call onto seven ClusterIP MCP pods. Vault stays on the pod, not the gateway.

Streamable HTTP :30100/mcp LAN only 185 tools FailOpen prefixMode Conditional
01

Front door

Same agentgateway-proxy already used for OpenAI and Spark. MCP is one more path on that Gateway — not a second proxy.

Gateway
agentgateway-proxy
Namespace
agentgateway-system
NodePort
30100
MCP URL
http://172.16.10.135:30100/mcp
Transport
Streamable HTTP
Client auth
none (same as /spark)
LAN only. Do not publish kagent :30500 or the gateway admin UI as a public URL. :30100/mcp is the home subnet, no bearer. Never put Vault values in git or on this site — path names only.
02

Seven MCP servers

Every server is a Deployment + ClusterIP in kagent, STREAMABLE_HTTP on :8084/mcp. Images are imported on the node (IfNotPresent). Creds come from Vault via ExternalSecret.

PrefixServiceSandboxAgentTargetVault pathGit
fortigate_fortigate-mcpfortigateFortiGate 80F 172.16.10.1secret/platform/fortigatek8s-viper platform/kagent-ai/fortigate-*.yaml
f5-bigip_f5-bigip-mcpf5-bigipBIG-IP 172.16.10.10secret/platform/f5-bigipk8s-viper platform/kagent-ai/f5-bigip-*.yaml
arista-ceos_arista-ceos-mcparista-ceosContainerlab cEOS eAPIsecret/platform/arista-ceosk8s-viper platform/kagent-ai/arista-ceos-*.yaml
aws-budget_aws-budget-mcpaws-budgetAWS us-east-2 billing / capacitysecret/platform/aws-budgetdemos aws-sandbox-agent
servicenow_servicenow-mcpservicenowServiceNow IT ticketssecret/platform/servicenowdemos service-now-sandbox-agent
gcp-budget_gcp-budget-mcpgcp-budgetGCP us-east1 billing / capacitysecret/platform/gcp-budgetdemos gcp-sandbox-agent
kagent-tools_kagent-toolshello-substratein-cluster k8s reads(kagent SA)RemoteMCPServer · kagent Helm + hello-substrate

Demos repo: sebbycorp/kagent-agent-substrate-demos. kagent SandboxAgents still talk to the ClusterIP Services directly (RemoteMCPServer in kagent). The gateway is the extra front door for Grok Bot and other MCP clients.

03

Live tools/list

A live tools/list through the gateway (2026-08-18) returned 185 tools. Prefixes keep names from colliding.

Total
185 tools
fortigate_
22
f5-bigip_
6
arista-ceos_
6
aws-budget_
11
servicenow_
8
gcp-budget_
8
kagent-tools_
124
04

Traffic flow

A client hits one URL. The gateway multiplexes onto the right ClusterIP MCP. Those pods hold the Vault creds and talk to the real boxes and APIs. The client never sees FortiOS / iControl / eAPI / cloud keys.

flowchart LR subgraph clients["LAN clients"] GB["Grok Bot"] CUR["Cursor"] KA["kagent UI"] end subgraph gw["agentgateway-proxy :30100"] direction TB MCP["/mcp viper-mcp"] LLM["/v1 gpt-5.5"] SP["/spark Qwen"] DESK["/desktop"] end subgraph pods["kagent ClusterIP :8084"] direction TB FG["fortigate-mcp"] F5["f5-bigip-mcp"] AR["arista-ceos-mcp"] CL["aws / servicenow / gcp"] KT["kagent-tools"] end subgraph edge["Outside the cluster"] T1["FortiGate 80F"] T2["BIG-IP"] T3["cEOS lab"] T4["AWS GCP ServiceNow"] T5["k8s API"] V["Vault ESO"] end GB --> MCP CUR --> MCP KA --> LLM KA -.->|"tools skip the gateway"| pods MCP --> FG MCP --> F5 MCP --> AR MCP --> CL MCP --> KT FG --> T1 F5 --> T2 AR --> T3 CL --> T4 KT --> T5 V -.-> FG V -.-> F5 V -.-> AR V -.-> CL classDef gwn fill:#111111,stroke:#111111,color:#f6f6f4 classDef mcp fill:#e8f3ee,stroke:#0b6b4f,color:#111111 class MCP,LLM,SP,DESK gwn class FG,F5,AR,CL,KT mcp

One tool call after connect. Prefix on the way in, Vault only on the pod, FailOpen on tools/list.

sequenceDiagram autonumber participant C as Grok Bot / Cursor participant G as agentgateway :30100/mcp participant P as fortigate-mcp participant V as Vault via ESO participant T as FortiGate 172.16.10.1 C->>G: initialize Streamable HTTP G-->>C: serverInfo agentgateway 1.4.1 C->>G: tools/list G->>P: list (and the other six, FailOpen) P-->>G: fg_list_policies … G-->>C: fortigate_fg_list_policies … C->>G: tools/call fortigate_fg_list_policies G->>P: fg_list_policies P->>V: token already in the pod P->>T: FortiOS REST T-->>P: policies P-->>G: result G-->>C: result

kagent UI skips the gateway for tools. It still uses this same Gateway for the model (/v1 → gpt-5.5).

05

Live CRs

Live kubectl captures on k3s-viper, 2026-08-18 (status Accepted). The agentgateway admin port (15000) is not published on this lab, so these are the live CRs — not a reconstructed admin UI.

kubectl list of AgentgatewayBackends and HTTPRoutes on agentgateway-system
Backends and HTTPRoutes — live kubectl on k3s-viper, 2026-08-18. viper-mcp is Accepted.
kubectl describe AgentgatewayBackend/viper-mcp showing StreamableHTTP targets
AgentgatewayBackend/viper-mcp — StreamableHTTP targets on :8084/mcp, failureMode FailOpen, prefixMode Conditional. Status Accepted.
kubectl describe HTTPRoute/viper-mcp attaching /mcp to agentgateway-proxy
HTTPRoute/viper-mcp — path prefix /mcp on agentgateway-proxy. Status Accepted.
06

How Grok Bot reaches it

Grok Bot (the k8s-viper agent) is the intended agentic front door. You ask it to do infra work. It jumps onto Viper. You do not paste tokens, and you do not publish /mcp.

  • LAN via the Viper host. The agent already has a jump onto Viper and can call http://127.0.0.1:30100/mcp from that host. Common case: no Grok Bot Plugins marketplace add.
  • This box cannot hit 172.16.10.135:30100 directly. The Grok Bot computer is not on the 172.16.10.0/24 LAN. A raw connector add of that URL times out unless a tunnel exists.
  • Until a tunnel exists, prefer the k8s-viper chat (jump onto Viper, then /mcp on localhost).
  • Cursor on the home LAN can point at the same URL. Still do not put this on a public machine.
{
  "mcpServers": {
    "viper": {
      "url": "http://172.16.10.135:30100/mcp"
    }
  }
}
Do not paste a Vault token into chat. If the route later grows a bearer header, use Grok Bot’s secret-request card — not a paste. MCP Inspector on the LAN: npx @modelcontextprotocol/inspector@0.21.2, transport Streamable HTTP, URL http://172.16.10.135:30100/mcp.
07

Gateway CRD

Chart 1.4.1. Same Gateway as /v1, /openai, /spark, /desktop/. Git: platform/agentgateway-ai/backend-viper-mcp.yaml, httproute-viper-mcp.yaml.

FieldValue on Viper
protocolStreamableHTTP
failureModeFailOpen
prefixModeConditional
targetstatic.host + port 8084 + path /mcp
backendRef*.kagent.svc.cluster.local:8084/mcp
HTTPRouteviper-mcp · path prefix /mcp
  • spec.mcp.failureMode: FailOpen — one down MCP does not kill the session or hide Fortigate tools.
  • spec.mcp.prefixMode: Conditional — tool names become target_tool because there are many targets.
  • backendRef is namespace-local only, so these use cluster DNS (*.kagent.svc.cluster.local).
  • Gateway does not inject Fortigate / F5 / cloud keys. The MCP pods already have ExternalSecrets.
docker exec k3s-viper kubectl -n agentgateway-system get agentgatewaybackend viper-mcp
docker exec k3s-viper kubectl -n agentgateway-system get httproute viper-mcp
Not on this lab yet (do not pretend they are): client auth on /mcp, tool-level allow lists, public internet exposure. GET / on :30100 is 404 route not found. That is expected. Use /mcp, /v1, or /spark.
08

Source

Canonical runbook (this page is the public send-link): docs/mcp-servers/README.md.