Skip to content

Commit fcea65f

Browse files
authored
Merge pull request #785 from agentgateway/adb-mcp-spec
MCP 2026-07-28 spec support
2 parents e53ad62 + 9669db7 commit fcea65f

10 files changed

Lines changed: 237 additions & 16 deletions

File tree

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
**MCP Apps** (the `io.modelcontextprotocol/ui` extension) let MCP tools return interactive user-interface (UI) resources that an MCP host can render, rather than plain text. A tool can return a UI resource identified by a `ui://` URI, and the host displays it to the user. Agentgateway supports MCP Apps automatically, including when you federate multiple MCP servers.
2+
3+
## How agentgateway handles MCP Apps
4+
5+
You do not need to configure anything to use MCP Apps through agentgateway. UI resources pass through the gateway like any other MCP resource, with two behaviors worth knowing about:
6+
7+
- **Multiplexing**: When you federate multiple MCP servers into one endpoint, agentgateway rewrites the `ui://` resource URIs so that they still route to the correct upstream target while remaining valid `ui://` URIs that hosts can render. For more information, see the {{< conditional-text include-if="standalone" >}}[Virtual MCP]({{< link-hextra path="/mcp/connect/virtual" >}}){{< /conditional-text >}}{{< conditional-text include-if="kubernetes" >}}[Virtual MCP]({{< link-hextra path="/mcp/virtual" >}}){{< /conditional-text >}} guide.
8+
- **Authorization**: Any authorization rules that you configure also apply to UI resources. If a rule denies access to a UI resource, agentgateway does not advertise it to the client. For more information, see {{< conditional-text include-if="standalone" >}}[MCP authorization]({{< link-hextra path="/mcp/mcp-authz" >}}){{< /conditional-text >}}{{< conditional-text include-if="kubernetes" >}}[Tool access]({{< link-hextra path="/mcp/tool-access" >}}){{< /conditional-text >}}.
9+
10+
## MCP Apps and tool name prefixing
11+
12+
MCP Apps can call tools from within the rendered UI. By default, agentgateway prefixes tool names with the target name when you federate multiple MCP servers, which can interfere with app-originated tool calls that use the tool's plain name. To expose unprefixed tool names, adjust the tool name prefixing behavior on the MCP backend. For more information, see the {{< conditional-text include-if="standalone" >}}[Virtual MCP]({{< link-hextra path="/mcp/connect/virtual#tool-name-prefixing" >}}){{< /conditional-text >}}{{< conditional-text include-if="kubernetes" >}}[Virtual MCP]({{< link-hextra path="/mcp/virtual" >}}){{< /conditional-text >}} guide.

assets/agw-docs/pages/agentgateway/mcp/multiplex.md

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -155,20 +155,34 @@ EOF
155155
EOF
156156
```
157157

158-
{{< callout type="info" >}}
159-
**Failure mode**: By default, agentgateway uses `FailClosed` behavior, which means that if any MCP target fails to initialize or becomes unavailable during a fanout, the entire session fails. To allow the gateway to skip failed targets and continue serving from the healthy ones, set the `failureMode` field to `FailOpen` on the {{< reuse "agw-docs/snippets/backend.md" >}}:
160-
161-
```yaml
162-
163-
spec:
164-
mcp:
165-
failureMode: FailOpen
166-
targets:
167-
...
168-
```
169-
170-
With `FailOpen`, if one MCP server is down, the gateway still serves tools from the remaining healthy servers. If all targets fail, the gateway returns an error.
171-
{{< /callout >}}
158+
> [!NOTE]
159+
> **Failure mode**: By default, agentgateway uses `FailClosed` behavior, which means that if any MCP target fails to initialize or becomes unavailable during a fanout, the entire session fails. To allow the gateway to skip failed targets and continue serving from the healthy ones, set the `failureMode` field to `FailOpen` on the {{< reuse "agw-docs/snippets/backend.md" >}}:
160+
>
161+
> ```yaml
162+
>
163+
> spec:
164+
> mcp:
165+
> failureMode: FailOpen
166+
> targets:
167+
> ...
168+
> ```
169+
>
170+
> With `FailOpen`, if one MCP server is down, the gateway still serves tools from the remaining healthy servers. If all targets fail, the gateway returns an error.
171+
172+
> [!NOTE]
173+
> **Tool name prefixing**: When multiplexing, agentgateway namespaces tool and prompt names with the target name so that identical names from different servers do not collide. Resource URIs always retain target routing information and are unaffected. Control this behavior with the `prefixMode` field on the {{< reuse "agw-docs/snippets/backend.md" >}}:
174+
>
175+
> * `Conditional` (default): Prefix names only when the backend has more than one target.
176+
> * `Always`: Always prefix names, even with a single target.
177+
> * `Never`: Never prefix names. Calls are routed by looking up which target serves the name, so names must be unique across all targets. Use this mode when clients need plain tool names, such as for [MCP Apps]({{< link-hextra path="/mcp/apps" >}}).
178+
>
179+
> ```yaml
180+
> spec:
181+
> mcp:
182+
> prefixMode: Never
183+
> targets:
184+
> ...
185+
> ```
172186
173187
## Step 2: Route with agentgateway {#agentgateway}
174188
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
Agentgateway supports MCP servers and clients across MCP specification versions and translates between them automatically. In most cases, you do not need to change your existing MCP servers or clients immediately to adopt the newer specification.
2+
3+
## Supported specification versions
4+
5+
Agentgateway supports MCP protocol versions as described in [Version support]({{< link-hextra path="/reference/versions/" >}}). Earlier versions are automatically negotiated as described later and typically work, but are not guaranteed.
6+
7+
### 2026-07-28 support
8+
9+
The `2026-07-28` revision changes how MCP works at its core. MCP becomes stateless and sessionless. Instead of a stateful `initialize` handshake and an `Mcp-Session-Id` for the lifetime of a session, a modern client discovers server capabilities with a `server/discover` request and carries the required context in each request's `_meta`.
10+
11+
The sessionless protocol is the recommended direction for MCP going forward, and agentgateway supports it by default. Older, session-based clients and servers remain supported, so a mix of older and newer clients and servers can coexist behind the same gateway.
12+
13+
## Automatic version negotiation
14+
15+
Agentgateway sits between a downstream client and one or more upstream MCP servers, and negotiates the protocol version for you.
16+
17+
- **Newer client to newer server**: The `server/discover` request is forwarded and answered directly. This is the optimal path, with no fallback requests.
18+
- **Newer client to older server**: The older server rejects the modern request, and the client falls back to the older `initialize` flow. Agentgateway handles the fallback transparently. Make sure that your client can handle the older flow gracefully.
19+
- **Older client to newer server**: The client uses the older `initialize` flow, which agentgateway continues to support.
20+
21+
When you federate multiple MCP servers into one endpoint, agentgateway takes the **intersection** of the protocol versions that the targets support, so the client only negotiates a version that every target can serve. For more information, see the {{< conditional-text include-if="standalone" >}}[Virtual MCP]({{< link-hextra path="/mcp/connect/virtual" >}}){{< /conditional-text >}}{{< conditional-text include-if="kubernetes" >}}[Virtual MCP]({{< link-hextra path="/mcp/virtual" >}}){{< /conditional-text >}} guide.
22+
23+
> [!NOTE]
24+
> Because most environments run a mix of MCP versions for the foreseeable future, this compatibility handling is on by default and requires no configuration. You do not need to upgrade all of your MCP servers to the newer specification at once.
25+
26+
## Response caching
27+
28+
The `2026-07-28` revision adds caching controls to responses such as `server/discover` and `tools/list`. Because agentgateway can apply policies (such as authorization, external authentication, or external processing) that make a response specific to an individual request, it cannot safely tell clients that a proxied response is cacheable. To guarantee correct behavior, agentgateway disables caching on the responses that it proxies.
29+
30+
## What you can still configure
31+
32+
Version negotiation, sessionless protocol support, and [MCP Apps]({{< link-hextra path="/mcp/apps" >}}) all work automatically.
33+
34+
The MCP behavior that you can tune includes:
35+
36+
- {{< conditional-text include-if="standalone" >}}[Session handling]({{< link-hextra path="/mcp/connect/http#stateless-sessions" >}}) (`statefulMode`) for how agentgateway proxies session-based servers.{{< /conditional-text >}}{{< conditional-text include-if="kubernetes" >}}[Session routing]({{< link-hextra path="/mcp/session" >}}) (`sessionRouting`) for how agentgateway proxies session-based servers.{{< /conditional-text >}}
37+
- Tool name prefixing when federating multiple MCP servers: {{< conditional-text include-if="standalone" >}}[Virtual MCP]({{< link-hextra path="/mcp/connect/virtual" >}}).{{< /conditional-text >}}{{< conditional-text include-if="kubernetes" >}}[Virtual MCP]({{< link-hextra path="/mcp/virtual" >}}).{{< /conditional-text >}}

assets/agw-docs/pages/reference/versions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Review the following information about supported release versions for the [agent
1212

1313
`*` Gateway API versions: The agentgateway project is conformant to the Kubernetes Gateway API specification. For more details, see the [Gateway API docs](https://gateway-api.sigs.k8s.io/docs/implementations/list/#agentgateway) and agentgateway conformance report per version, such as Gateway API [v1.5.0](https://github.com/kubernetes-sigs/gateway-api/tree/main/conformance/reports/v1.5.0/agentgateway-agentgateway).
1414

15-
`` Agentgateway supports the MCP spec at the listed version. Earlier versions might also work, but are not guaranteed. Make sure that your MCP clients are not running at a more recent version than your MCP servers.
15+
`` Agentgateway supports the MCP spec at the listed version. {{< version include-if="latest" >}}Earlier versions might also work, but are not guaranteed. Make sure that your MCP clients are not running at a more recent version than your MCP servers.{{< /version >}}{{< version include-if="main" >}}For more information, see [MCP spec compatibility]({{< link-hextra path="/mcp/spec-compatibility/" >}}).{{< /version >}}
1616

1717
`` Istio versions: Istio must run on a compatible version of Kubernetes. For example, Istio 1.29 is tested, but not supported, on Kubernetes 1.30. For more information, see the [Istio docs](https://istio.io/latest/docs/releases/supported-releases/).
1818

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
title: MCP Apps
3+
weight: 8
4+
description: Serve interactive MCP Apps (UI resources) through agentgateway, including across federated MCP servers.
5+
test: skip
6+
---
7+
8+
{{< reuse "agw-docs/pages/agentgateway/mcp/apps.md" >}}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
title: MCP spec compatibility
3+
weight: 7
4+
description: Learn how agentgateway supports and translates between MCP specification versions, including the stateless 2026-07-28 revision.
5+
test: skip
6+
---
7+
8+
{{< reuse "agw-docs/pages/agentgateway/mcp/spec-compatibility.md" >}}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
title: MCP Apps
3+
weight: 14
4+
description: Serve interactive MCP Apps (UI resources) through agentgateway, including across federated MCP servers.
5+
test: skip
6+
---
7+
8+
{{< reuse "agw-docs/pages/agentgateway/mcp/apps.md" >}}

content/docs/standalone/main/mcp/connect/http.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
title: Streamable HTTP
33
weight: 15
44
description: Connect to MCP servers via streamable HTTP with automatic session management
5+
test:
6+
mcp-stateless:
7+
- file: ${versionRoot}/mcp/connect/http.md
8+
path: mcp-stateless
59
---
610

711
Connect to an MCP server via streamable HTTP.
@@ -36,6 +40,100 @@ sequenceDiagram
3640
3. **State encoding**: The session state is encoded into the session ID using AES-256-GCM encryption
3741
4. **Session resumption**: Subsequent requests with the same session ID are automatically routed to the same backend
3842

43+
## Stateless sessions {#stateless-sessions}
44+
45+
By default, agentgateway proxies streamable HTTP in **stateful** mode, as described in the previous section. You can instead run in **stateless** mode with the `statefulMode` field, so that agentgateway does not create a session or return an `Mcp-Session-Id` header. Each request is treated independently, and the client must send the full context that the request needs. This mode suits stateless agents, or MCP servers where the client handles state directly.
46+
47+
{{< callout type="info" >}}
48+
The `statefulMode` field controls how agentgateway proxies session-based servers. It is separate from the newer, inherently sessionless `2026-07-28` MCP protocol, which agentgateway supports automatically through version negotiation. For more information, see [MCP spec compatibility]({{< link-hextra path="/mcp/spec-compatibility" >}}).
49+
{{< /callout >}}
50+
51+
To use stateless mode, set `statefulMode` to `stateless` on the MCP configuration.
52+
53+
```yaml
54+
# yaml-language-server: $schema=https://agentgateway.dev/schema/config
55+
mcp:
56+
port: 3000
57+
statefulMode: stateless
58+
targets:
59+
- name: mcp
60+
mcp:
61+
host: http://localhost:3005/mcp/
62+
```
63+
64+
When you send an `initialize` request through agentgateway in stateless mode, the response returns `HTTP 200` with no `Mcp-Session-Id` header. In the default stateful mode, the same request returns an `Mcp-Session-Id` header that pins the session to a backend.
65+
66+
{{< doc-test paths="mcp-stateless" >}}
67+
# WHAT THIS TEST VALIDATES:
68+
# * statefulMode: stateless is accepted and the MCP endpoint serves an initialize request (HTTP 200)
69+
# * In stateless mode, the initialize response does NOT include an Mcp-Session-Id header
70+
# WHAT THIS TEST DOES NOT VALIDATE (and why):
71+
# * The visible example uses a streamable HTTP upstream (host: http://localhost:3005/mcp/);
72+
# the hidden test config uses a self-contained stdio target so no external MCP server is
73+
# needed. statefulMode governs the downstream (client-facing) session, independent of the
74+
# upstream transport, so the stateless behavior under test is the same.
75+
# * The default stateful contrast (Mcp-Session-Id present) is covered by other pages that
76+
# use the default configuration.
77+
{{< /doc-test >}}
78+
79+
{{< doc-test paths="mcp-stateless" >}}
80+
# Install agentgateway binary
81+
{{< reuse "agw-docs/snippets/install-agentgateway-binary.md" >}}
82+
{{< /doc-test >}}
83+
84+
{{< doc-test paths="mcp-stateless" >}}
85+
cat <<'EOF' > config.yaml
86+
# yaml-language-server: $schema=https://agentgateway.dev/schema/config
87+
mcp:
88+
port: 3000
89+
statefulMode: stateless
90+
targets:
91+
- name: everything
92+
stdio:
93+
cmd: npx
94+
args: ["@modelcontextprotocol/server-everything"]
95+
EOF
96+
{{< /doc-test >}}
97+
98+
{{< doc-test paths="mcp-stateless" >}}
99+
agentgateway -f config.yaml &
100+
AGW_PID=$!
101+
trap 'kill $AGW_PID 2>/dev/null' EXIT
102+
sleep 3
103+
{{< /doc-test >}}
104+
105+
{{< doc-test paths="mcp-stateless" >}}
106+
YAMLTest -f - <<'EOF'
107+
- name: MCP endpoint accepts initialize request in stateless mode
108+
http:
109+
url: "http://localhost:3000"
110+
path: /mcp
111+
method: POST
112+
headers:
113+
content-type: application/json
114+
accept: "application/json, text/event-stream"
115+
body: |
116+
{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}},"id":1}
117+
source:
118+
type: local
119+
expect:
120+
statusCode: 200
121+
EOF
122+
{{< /doc-test >}}
123+
124+
{{< doc-test paths="mcp-stateless" >}}
125+
# Assert that stateless mode does not return an Mcp-Session-Id header
126+
if curl -sS -D - -o /dev/null -X POST http://localhost:3000/mcp/ \
127+
-H 'Content-Type: application/json' \
128+
-H 'Accept: application/json, text/event-stream' \
129+
-d '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}},"id":1}' \
130+
| grep -qi 'mcp-session-id'; then
131+
echo "FAIL: stateless mode returned an Mcp-Session-Id header"
132+
exit 1
133+
fi
134+
echo "PASS: no Mcp-Session-Id header in stateless mode"
135+
{{< /doc-test >}}
136+
39137
## Before you begin
40138

41139
{{< reuse "agw-docs/snippets/prereq-agentgateway.md" >}}

content/docs/standalone/main/mcp/connect/virtual.md

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Federate tools of multiple MCP servers on the agentgateway by using MCP {{< glos
88

99
## About multiplexing {#about}
1010

11-
Multiplexing combines multiple MCP servers (targets) within a single backend into one unified MCP server. All targets are exposed together so that clients can access tools from all targets simultaneously. Tools are prefixed with the target name (e.g., `time_get_current_time`, `everything_echo`)
11+
Multiplexing combines multiple MCP servers (targets) within a single backend into one unified MCP server. All targets are exposed together so that clients can access tools from all targets simultaneously. By default, when a backend has more than one target, tool names are prefixed with the target name (e.g., `time_get_current_time`, `everything_echo`) to avoid collisions. You can change this behavior with the `prefixMode` field, described in [Tool name prefixing](#tool-name-prefixing).
1212

1313
{{% details title="Example multiplexing configuration" closed="false" %}}
1414

@@ -129,6 +129,34 @@ routes:
129129
{{< reuse-image-light src="img/ui-tool-time-current.png" >}}
130130
{{< reuse-image-dark srcDark="img/ui-tool-time-current-dark.png" >}}
131131

132+
## Tool name prefixing {#tool-name-prefixing}
133+
134+
When you multiplex multiple targets, agentgateway namespaces tool and prompt names with the target name so that identical names from different servers do not collide. Resource URIs retain target routing information and are unaffected. Control this behavior with the `prefixMode` field on the MCP configuration.
135+
136+
| `prefixMode` | Behavior |
137+
|--------------|----------|
138+
| `conditional` (default) | Prefix tool and prompt names only when the backend has more than one target. |
139+
| `always` | Always prefix names, even when the backend has a single target. |
140+
| `never` | Never prefix names. Calls are routed by looking up which target serves the name, so names must be unique across all targets. |
141+
142+
Use `never` when clients need to call tools by their plain names, such as for [MCP Apps]({{< link-hextra path="/mcp/apps" >}}) that issue tool calls from a rendered UI. Because unprefixed names must be unique, agentgateway fails to start if two targets expose the same tool name in this mode.
143+
144+
```yaml
145+
# yaml-language-server: $schema=https://agentgateway.dev/schema/config
146+
mcp:
147+
port: 3000
148+
prefixMode: never
149+
targets:
150+
- name: time
151+
stdio:
152+
cmd: uvx
153+
args: ["mcp-server-time"]
154+
- name: everything
155+
stdio:
156+
cmd: npx
157+
args: ["@modelcontextprotocol/server-everything"]
158+
```
159+
132160
## Next steps
133161

134162
- Apply different policies to different MCP targets with [MCP target policies]({{< link-hextra path="/mcp/mcp-target-policies/" >}}).
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
title: MCP spec compatibility
3+
weight: 12
4+
description: Learn how agentgateway supports and translates between MCP specification versions, including the stateless 2026-07-28 revision.
5+
test: skip
6+
---
7+
8+
{{< reuse "agw-docs/pages/agentgateway/mcp/spec-compatibility.md" >}}

0 commit comments

Comments
 (0)