From a854e418c749989ca8ee4b83380a40f771a9aa4f Mon Sep 17 00:00:00 2001 From: Shubham Katara Date: Mon, 29 Jun 2026 22:15:24 +0200 Subject: [PATCH 1/2] Blog for agentgateway Part 1 --- content/authors.json | 12 +- ...p-tools-with-agentgateway-on-kubernetes.md | 595 ++++++++++++++++++ lib/_blog-feed-data.js | 24 +- public/_redirects | 2 + public/_worker.js | 2 +- public/atom.xml | 14 +- public/img/authors/shubham-katara.jpg | Bin 0 -> 450765 bytes .../agent-request-flow.png | Bin 0 -> 340395 bytes .../architecture-to-build.png | Bin 0 -> 317621 bytes .../cover.png | Bin 0 -> 1694746 bytes public/llms.txt | 8 +- public/rss.xml | 10 +- vercel.json | 16 + 13 files changed, 663 insertions(+), 20 deletions(-) create mode 100644 content/blog/controlling-mcp-tools-with-agentgateway-on-kubernetes.md create mode 100644 public/img/authors/shubham-katara.jpg create mode 100644 public/img/blog/controlling-mcp-tools-with-agentgateway-on-kubernetes/agent-request-flow.png create mode 100644 public/img/blog/controlling-mcp-tools-with-agentgateway-on-kubernetes/architecture-to-build.png create mode 100644 public/img/blog/controlling-mcp-tools-with-agentgateway-on-kubernetes/cover.png diff --git a/content/authors.json b/content/authors.json index 2c8504416..28569e7aa 100644 --- a/content/authors.json +++ b/content/authors.json @@ -1,4 +1,14 @@ { + "shubham-katara": { + "handle": "shubham-katara", + "name": "Shubham Katara", + "avatar": "/img/authors/shubham-katara.jpg", + "bio": "Building Hybrid K8s Platforms @trivago | Tech Author & Speaker (freeCodeCamp, SREDays) | vCluster Ambassador | RHCA & GCP DevOps Professional", + "socials": { + "linkedin": "https://linkedin.com/in/shubhamkatara", + "github": "https://github.com/shkatara" + } + }, "engin-diri": { "handle": "engin-diri", "name": "Engin Diri", @@ -611,4 +621,4 @@ }, "postCount": 1 } -} +} \ No newline at end of file diff --git a/content/blog/controlling-mcp-tools-with-agentgateway-on-kubernetes.md b/content/blog/controlling-mcp-tools-with-agentgateway-on-kubernetes.md new file mode 100644 index 000000000..b6232abae --- /dev/null +++ b/content/blog/controlling-mcp-tools-with-agentgateway-on-kubernetes.md @@ -0,0 +1,595 @@ +--- +title: "Controlling MCP Tools with agentgateway on Kubernetes (Part 1)" +seoTitle: "agentgateway on Kubernetes: Control Which MCP Tools Agents Use" +seoDescription: "Run AI agents behind agentgateway on Kubernetes: route their LLM and MCP tool calls through one proxy, keep secrets out of the agent, and block tools by policy." +datePublished: 2026-06-29T10:00:00.000Z +slug: controlling-mcp-tools-with-agentgateway-on-kubernetes +author: shubham-katara +cover: /img/blog/controlling-mcp-tools-with-agentgateway-on-kubernetes/cover.png +tags: ["kubernetes", "ai-agents", "mcp", "platform-engineering"] +draft: true +--- + +This is Part 1 of a two-part series. In this part you stand up **agentgateway** on Kubernetes, put a Google ADK agent behind it so the agent holds zero secrets, and enforce tool-level access control that you can watch block a tool in real time. Part 2 adds cost and observability: Prometheus, Grafana, and a live token-spend dashboard. + +agentgateway is an open source, AI-native proxy. By the end of this part, your agent will talk to its tools (over MCP) and its model (over an OpenAI-compatible API) through the gateway, hold none of its own credentials, and be unable to call a tool you have not explicitly allowed. + +Who this is for: + +- Platform engineers, SREs, and backend engineers who are starting to run AI agents in production and are realizing that "the agent has every API key and can call every tool" is not a strategy. +- Anyone who has shipped one agent, watched three more appear, and now needs a single place to enforce security across all of them. + +What you'll build in Part 1: + +- A `kind` cluster running the agentgateway control plane and proxy. +- An LLM route, so the agent's model calls flow through the gateway and the provider key lives only in the gateway. +- An MCP route to the remote GitHub MCP server, with the GitHub token injected by the gateway. +- A Google ADK agent whose model and tools both go through the gateway and which carries no real secrets. +- Tool-level access control: you allow one tool and watch the gateway hide another, so calling it comes back as an `Unknown tool` error. + +> **Note:** agentgateway is a fast-moving project (a Linux Foundation / Agentic AI Foundation project, currently around the v1.2 to v1.3 line). Pin the versions shown here, and expect custom resource fields to evolve. Every command below was written against the `v1.2.x` charts and the `agentgateway.dev/v1alpha1` API. + +## Prerequisites + +For this tutorial, you'll need: + +- A machine with [Docker](https://docs.docker.com/get-docker/) and [`kind`](https://kind.sigs.k8s.io/) installed. +- [`kubectl`](https://kubernetes.io/docs/tasks/tools/) and [`helm`](https://helm.sh/docs/intro/install/) (v3+). +- Node.js (for `npx`, used to run the MCP Inspector verification tool). +- Python 3.10+ (required by the Google ADK agent and the `mcp` SDK it uses). +- An API key for an LLM provider. This guide uses OpenAI; an Anthropic key works too. A note for OpenAI users: the API is billed separately from a ChatGPT Plus or Pro subscription, so you need credit on the API account itself. +- A [GitHub Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) (classic or fine-grained): the agent's tools will be the remote GitHub MCP server, which is perfect for a tool-access demo because it exposes many tools. + +Every manifest in this post is inline and copy-pasteable. There is no repo to clone. + +## Why AI Agents Need Their Own Gateway + +Here's a scenario that is playing out in a lot of companies right now. + +A team ships their first agent. It needs an LLM, so they paste an OpenAI key into a Kubernetes Secret and mount it. It needs tools, so they wire it directly to a couple of MCP servers: one for GitHub, one for an internal database, one for filesystem access. It works. Everyone's happy. + +Then it scales. Now there are eight agents across four teams. Each one holds its own copy of the LLM key. Each one connects directly to whatever MCP servers it likes. Nobody can answer three questions that suddenly matter a lot: + +- **Who spent the $14,000 on OpenAI last month, and on which model?** +- **Which agents can call the `delete_repository` tool, and who approved that?** +- **When an agent does something dumb, where's the trace?** + +The first instinct is to put the existing API gateway in front of it all. That instinct is wrong, and it's worth understanding *why*, because it explains the entire reason agentgateway exists. + +Traditional API gateways are built for one shape of traffic: stateless, REST-style, one request in, pick a backend, one response out. Agent protocols like the **Model Context Protocol (MCP)** and **Agent-to-Agent (A2A)** are a completely different beast: + +| Traditional API Gateway | Agent traffic (MCP / A2A) | +| ----------------------------- | ----------------------------------------------------------------- | +| Stateless request/response | **Stateful JSON-RPC sessions** with long-lived connections | +| One request to one backend | **Session fan-out** across multiple MCP servers at once | +| Client-initiated only | **Bidirectional**: servers push events to clients over SSE | +| Routing by path/header | **Protocol-aware routing** that parses JSON-RPC message bodies | +| Static backend mapping | **Dynamic tool virtualization**: different clients see different tools | + +A normal gateway can't filter a `tools/list` response to hide a tool from one caller, because it has no idea what a `tools/list` response *is*. It can't authorize an individual tool call, because the tool name lives inside a JSON-RPC body it never parses. You'd be bolting agent-awareness onto something that was never designed for it. + +That's the gap. Agent traffic needs a data plane that speaks these protocols natively. + +## What agentgateway Actually Is + +[agentgateway](https://agentgateway.dev/) is an open source proxy and control plane, written in Rust, that unifies **HTTP, gRPC, LLM, MCP, and A2A** traffic in a single data plane. It's a project under the Linux Foundation (and the Agentic AI Foundation), not a single vendor's closed product. + +The important framing is that it is a *full* HTTP and gRPC proxy with the things you'd expect, such as load balancing, retries, timeouts, TLS, rate limiting, and authorization. On top of that, it implements the pieces that traditional gateways are missing for agents. So you don't run a "normal gateway" and a separate "AI gateway." It's one data plane. + +It does three jobs: + +1. **LLM Gateway.** It exposes a single, **OpenAI-compatible API** and routes to OpenAI, Anthropic, Gemini, Bedrock, Azure, Ollama, and many more. Your application code stops caring which provider is behind it. You get token metering, cost tracking, budgets, failover, and guardrails for free. + +2. **MCP Gateway.** It connects agents to tools over MCP, with **tool federation** (aggregate many MCP servers behind one endpoint), OpenAPI-to-MCP conversion, and **per-tool authentication and authorization**. + +3. **A2A Gateway.** It secures agent-to-agent communication so agents can discover and collaborate without exposing their internal tools and state. + +It runs anywhere: bare metal, VMs, Docker, or Kubernetes. And on Kubernetes it's built on the standard [Gateway API](https://gateway-api.sigs.k8s.io/), so `Gateway` and `HTTPRoute` resources work exactly as you'd expect, extended with a couple of custom resources (`AgentgatewayBackend`, `AgentgatewayPolicy`) for the agent-specific parts. + +## The Three Reasons You'd Actually Reach for It + +There are a lot of features. But in practice, teams adopt agentgateway for three reasons. + +### Reason 1: Security and governance you can enforce centrally + +This is the big one. With agentgateway in the path, you can: + +- **Stop handing LLM keys and tool tokens to agents.** The LLM provider key stays with the gateway. The GitHub token stays with the gateway. The agent talks to the gateway, and the gateway forwards the request to the LLM provider or MCP server with the real credentials. A compromised agent leaks nothing useful. +- **Control which tools an agent can call** with fine-grained, CEL-based RBAC rules, down to the individual tool name, optionally keyed on JWT claims. If a tool isn't allowed, the gateway hides it from the tool list entirely and rejects any attempt to call it. +- **Apply guardrails and prompt protection** on LLM and MCP traffic in one place. + +You'll see the tool control enforced live later in this part. + +### Reason 2: Cost and token visibility + +Agent traffic is expensive and, by default, invisible. agentgateway tracks token consumption for every request and exposes it as Prometheus metrics, with labels for the model, provider, and direction. From there you can calculate cost per request, per model, or per user, graph spend in Grafana, and alert when a budget is crossed. That is the entire subject of Part 2. + +### Reason 3: One data plane for any framework and any provider + +agentgateway sits at the network layer, so it is **framework-agnostic**. LangGraph, CrewAI, the OpenAI Agents SDK, and Google ADK all just point at a URL. And because the LLM side is OpenAI-compatible, **you can swap providers without touching agent code**. Change the backend from OpenAI to Anthropic in the gateway, and every agent follows, with no redeploys. + +## How agentgateway Touches Cost, Time, and Developer Experience + +Here's how those capabilities map to the three things people actually budget for: + +| Concern | Without a gateway | With agentgateway | +| ------------------------ | --------------------------------------------------------------------- | -------------------------------------------------------------------------------- | +| **Cost** | Token spend is opaque; no per-model or per-team breakdown; no budgets | Per-request token metrics, cost dashboards, PromQL queries, budget alerts | +| **Time** | Each team re-implements auth, secret handling, retries, and logging per agent | Implement it once at the gateway; new agents inherit it by pointing at a URL | +| **Developer experience** | Devs juggle provider keys and tool tokens, and rewrite code to switch providers | Agents hold no secrets; one OpenAI-compatible endpoint; swap providers with zero code change | + +The developer-experience point is the one engineers feel immediately. In the demo below, the agent's code contains a fake API key (`sk-not-a-real-key`) and *no* GitHub token at all, and it still works, because the gateway owns the real credentials. + +## The Architecture We'll Build + +Everything runs on one `kind` cluster. The agent runs on your laptop and reaches the gateway through a port-forward. The gateway is the only component that holds real secrets. + +![Architecture of agentgateway running on a kind cluster with an ADK agent and MCP backend](/img/blog/controlling-mcp-tools-with-agentgateway-on-kubernetes/architecture-to-build.png) + +Let's build it. + +## How to Spin Up a kind Cluster + +If you don't already have a cluster, `kind` gives you a real Kubernetes API in a Docker container in about thirty seconds: + +```sh +kind create cluster --name agentgateway-demo +``` + +Confirm it's up: + +```sh +kubectl cluster-info --context kind-agentgateway-demo +``` + +## How to Install agentgateway + +agentgateway on Kubernetes has two parts: a **control plane** (it watches Gateway API and agentgateway custom resources and translates them into proxy config) and the **data plane** proxies it spins up for you. + +**Step 1: Install the Kubernetes Gateway API CRDs.** We install the *experimental* channel because it enables a few features (like CORS filters) that make local verification with the MCP Inspector easier. + +```sh +kubectl apply --server-side --force-conflicts \ + -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.5.0/experimental-install.yaml +``` + +**Step 2: Install the agentgateway CRDs with Helm.** + +```sh +helm upgrade -i agentgateway-crds oci://cr.agentgateway.dev/charts/agentgateway-crds \ + --create-namespace --namespace agentgateway-system \ + --version v1.2.1 \ + --set controller.image.pullPolicy=Always +``` + +**Step 3: Install the agentgateway control plane.** The experimental feature gate matches the experimental CRDs from Step 1. + +```sh +helm upgrade -i agentgateway oci://cr.agentgateway.dev/charts/agentgateway \ + --namespace agentgateway-system \ + --version v1.2.1 \ + --set controller.image.pullPolicy=Always \ + --set controller.extraEnv.KGW_ENABLE_GATEWAY_API_EXPERIMENTAL_FEATURES=true \ + --wait +``` + +Verify the control plane is running: + +```sh +kubectl get pods -n agentgateway-system +``` + +```console +NAME READY STATUS RESTARTS AGE +agentgateway-5495d98459-46dpk 1/1 Running 0 19s +``` + +**Step 4: Create the gateway proxy.** This `Gateway` uses the `agentgateway` GatewayClass; the control plane sees it and deploys an actual proxy for you. + +```sh +kubectl apply -f- < **Want Anthropic instead?** Swap `provider.openai` for `provider.anthropic` and use an Anthropic key in the secret. The agent code does not change at all, because the agent only ever speaks the OpenAI-compatible API to the gateway. + +**Step 3: Route `/v1` to the LLM backend.** We use the `/v1` path prefix so the standard OpenAI path `/v1/chat/completions` lands here, and so it never collides with the `/mcp-github` route we add next. + +```sh +kubectl apply -f- <