Envoy AI Gateway 后端包含两个 MCP server 的 Kagenti

本示例部署 Rosso 天气和餐厅预订 MCP server,将它们聚合到一个 Envoy Gateway 数据平面之后,并将一个 Kagenti 通用智能体连接到单一的 /mcp endpoint。

这些 manifest 位于 docs/en/ai_applications/components/kagenti/assets/envoy_ai_gateway_mcp。它们面向 kagenti-mcp-demo namespace。如果你的环境使用不同的值,请在应用之前修改 namespace 和 GatewayClass 名称。

已验证版本

本示例于 2026-07-28 在以下环境中完成验证:

组件版本
Alauda Build of Envoy Gateway1.7.0-build.20260625161000
Alauda Build of Envoy AI Gateway0.6.0-1
MCPRoute APIaigateway.envoyproxy.io/v1beta1

Envoy AI Gateway 0.6 通过 MCPRoute 支持 MCP 聚合、认证、工具授权以及上游凭据。

Kuadrant mcp-gateway 与此 API 不可互换。它的 controller 会创建一个 Istio EnvoyFilter,并且在 MCPGatewayExtension 变为 ready 之前需要该资源。Envoy Gateway 的原生 EnvoyExtensionPolicy 不暴露 Kuadrant MCP Gateway 目前用于重写 :authority 所需的 mutation_rules.allow_all_routing 设置。请在 Envoy Gateway 中使用此处展示的原生 Envoy AI Gateway MCPRoute,或者使用 Kuadrant MCP Gateway 及其受支持的 Istio provider。

拓扑和 HTTPRoute 数量

Kagenti generic agent
        |
        | one authenticated MCP URL
        v
Envoy Gateway :80 /mcp
        |
        | Envoy AI Gateway MCP proxy
        +-----------------------+
        |                       |
        v                       v
weather:8000/mcp       reservation:8000/mcp

只需使用两个 backendRefs 编写一个 MCPRoute;不要手动编写 backend HTTPRoute。controller 会准确创建两个 backend 路由和一个必需的面向客户端的路由:

  • ai-eg-mcp-br-kagenti-tools-weather
  • ai-eg-mcp-br-kagenti-tools-reservation
  • ai-eg-mcp-main-kagenti-tools

前两个是请求的按 server 划分的 HTTPRoute。第三个暴露统一的 /mcp endpoint。三者都归 MCPRoute 所有,且不得直接编辑。

来源和镜像

这些 workload 来自 rossoctl/examples 的提交 ec17c73235c8ef291a6d4aaa346b50a4fba35e72

  • mcp/weather_tool
  • mcp/reservation_tool
  • a2a/generic_agent

YAML 固定了发布在 ghcr.io/rossoctl/examples 的不可变多架构 image digest。

部署 gateway 和两个 MCP server

如果示例 namespace 不存在,请创建它:

kubectl create namespace kagenti-mcp-demo --dry-run=client -o yaml | kubectl apply -f -

在将此示例用于一次性开发环境之外的场景前,请先替换 03-mcp-route-auth-rate-limit.yaml 中的 replace-this-demo-key。然后应用 server、gateway 和 policy manifest:

EXAMPLE_DIR=docs/en/ai_applications/components/kagenti/assets/envoy_ai_gateway_mcp

kubectl apply -f "$EXAMPLE_DIR/01-mcp-servers.yaml"
kubectl apply -f "$EXAMPLE_DIR/02-gateway.yaml"
kubectl apply -f "$EXAMPLE_DIR/03-mcp-route-auth-rate-limit.yaml"

该示例使用 API key 认证,并为每个已认证 client ID 设置每分钟 30 次请求的本地限流。sanitize: true 会在请求发送到上游之前移除 API key。生成的 client ID 会作为 x-mcp-client-id 转发,这也是限流 key。

验证结果:

kubectl -n kagenti-mcp-demo rollout status deploy/weather-mcp
kubectl -n kagenti-mcp-demo rollout status deploy/reservation-mcp
kubectl -n kagenti-mcp-demo get gateway kagenti-mcp
kubectl -n kagenti-mcp-demo get mcproute kagenti-tools
kubectl -n kagenti-mcp-demo get httproute

预期条件为 Gateway Programmed=TrueMCPRoute Accepted,以及所有三个生成的 HTTPRoute 上的 Accepted=True

测试统一的 MCP endpoint

转发由 02-gateway.yaml 创建的稳定 Envoy Service:

kubectl -n envoy-gateway-system \
  port-forward service/kagenti-mcp-envoy 8080:80

在另一个终端中初始化会话。省略 API key 必须返回 401;提供 API key 必须返回 MCP 响应和 mcp-session-id header。

MCP_URL='http://127.0.0.1:8080/mcp?api-key=replace-this-demo-key'

curl -i "$MCP_URL" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  --data '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1.0"}}}'

使用返回的 session ID 列出工具:

SESSION_ID='<mcp-session-id>'

curl -sS "$MCP_URL" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H "mcp-session-id: $SESSION_ID" \
  --data '{"jsonrpc":"2.0","method":"notifications/initialized"}'

curl -sS "$MCP_URL" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H "mcp-session-id: $SESSION_ID" \
  --data '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
  | sed -n 's/^data: //p' | jq

工具名称会以前端 backend 作为前缀,例如 weather__get_weatherreservation__search_restaurants

部署 Kagenti 智能体

创建带有 OpenAI-compatible endpoint 的 LLM 配置 Secret:

kubectl -n kagenti-mcp-demo create secret generic generic-agent-llm \
  --from-literal=api-base='https://your-openai-compatible-endpoint/v1' \
  --from-literal=api-key='replace-me' \
  --from-literal=model='replace-me'

kubectl apply -f docs/en/ai_applications/components/kagenti/assets/envoy_ai_gateway_mcp/04-agent.yaml

kubectl -n kagenti-mcp-demo get agentruntime generic-agent
kubectl -n kagenti-mcp-demo rollout status deploy/generic-agent

MCP_URLS 只包含统一的 Envoy endpoint,因此智能体通过一次 MCP 连接即可发现两组工具。当前通用智能体仅暴露 URL 配置,而不支持按 server 设置请求 header;因此本示例使用 API key query parameter。智能体会在启动期间记录 MCP_URLS,所以仅应在开发环境中使用此方式。对于生产环境,请为智能体添加基于 header 的 MCP client 配置,或使用带有 OAuth/JWT 的 Kagenti AuthBridge,并将 MCPRoute 切换为 securityPolicy.oauth

可以尝试如下提示:

  • What is the weather in Taipei?
  • Find Italian restaurants in Boston.

清理

生成的 HTTPRoute 会随着 MCPRoute 一并删除:

EXAMPLE_DIR=docs/en/ai_applications/components/kagenti/assets/envoy_ai_gateway_mcp

kubectl delete -f "$EXAMPLE_DIR/04-agent.yaml" --ignore-not-found
kubectl delete -f "$EXAMPLE_DIR/03-mcp-route-auth-rate-limit.yaml"
kubectl delete -f "$EXAMPLE_DIR/02-gateway.yaml"
kubectl delete -f "$EXAMPLE_DIR/01-mcp-servers.yaml"
kubectl -n kagenti-mcp-demo delete secret generic-agent-llm --ignore-not-found