Skip to content

Commit ebdc0ae

Browse files
committed
feat(polyfill): Support v2 MCP-over-ACP bridge
1 parent 2deebdd commit ebdc0ae

9 files changed

Lines changed: 1768 additions & 375 deletions

File tree

md/conductor.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,11 @@ adapted to HTTP. Keeping the polyfill explicit prevents instrumentation or
155155
orchestration from silently changing session MCP declarations. See [MCP
156156
Bridge](./mcp-bridge.md).
157157

158+
The polyfill supports v1 by default. For a draft-v2 chain, enable
159+
`unstable_protocol_v2` on both the conductor and polyfill crates; without the
160+
polyfill feature, it rejects v2 initialization instead of interpreting v2
161+
traffic as v1.
162+
158163
## Tracing
159164

160165
The conductor can record an idealized logical sequence of ACP and MCP messages.

md/mcp-bridge.md

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,20 @@ Native MCP-over-ACP requires the core SDK's `unstable_mcp_over_acp` feature. The
1919
polyfill enables that feature on its core dependency, so applications using the
2020
polyfill receive it through Cargo feature unification.
2121

22+
The polyfill supports stable protocol v1 by default. To place it in a draft-v2
23+
conductor chain, enable `unstable_protocol_v2` on both the conductor and
24+
polyfill dependencies:
25+
26+
```toml
27+
agent-client-protocol-conductor = { version = "...", features = ["unstable_protocol_v2"] }
28+
agent-client-protocol-polyfill = { version = "...", features = ["unstable_protocol_v2"] }
29+
```
30+
31+
The feature makes this concrete compatibility proxy recognize v2
32+
initialization, capability, session setup, and `mcp/*` wire types. It does not
33+
add high-level v2 global MCP attachment or proxy-session helpers to the core
34+
SDK; those remain v1-only.
35+
2236
## Placement
2337

2438
Insert the polyfill immediately before the final agent that lacks native
@@ -37,17 +51,23 @@ ConductorImpl::new_agent("conductor", components)
3751
.await?;
3852
```
3953

40-
The application proxy can attach a high-level
41-
`agent_client_protocol::mcp_server::McpServer`. The SDK advertises it in
42-
session setup requests as `McpServer::Acp`; callers do not need to construct a
43-
transport placeholder themselves.
54+
For v1, the application proxy can attach a high-level
55+
`agent_client_protocol::mcp_server::McpServer`. The SDK advertises it in session
56+
setup requests as `McpServer::Acp`; callers do not need to construct a transport
57+
placeholder themselves. In a v2 chain, a version-aware proxy currently supplies
58+
the `schema::v2::McpServer::Acp` declaration directly because the high-level
59+
global proxy attachment helpers remain v1-only.
4460

45-
During initialization, the polyfill forwards the request to its successor and
46-
sets `agentCapabilities.mcpCapabilities.acp` in the response seen upstream when
47-
the successor advertises HTTP MCP support. In this chain position that
48-
capability means the chain can consume native MCP-over-ACP declarations through
49-
the adapter; it does not imply that the final agent implements the transport
50-
itself.
61+
During initialization, the polyfill forwards the request to its successor. When
62+
the successor advertises HTTP MCP support, the polyfill advertises native ACP
63+
MCP support in the response seen upstream:
64+
65+
- v1 sets `agentCapabilities.mcpCapabilities.acp` to `true`.
66+
- v2 adds the `capabilities.session.mcp.acp` marker.
67+
68+
In this chain position that capability means the chain can consume native
69+
MCP-over-ACP declarations through the adapter; it does not imply that the final
70+
agent implements the transport itself.
5171

5272
If the successor already advertises native ACP MCP support, the polyfill leaves
5373
the capability, declarations, and `mcp/message` traffic unchanged. If it
@@ -56,8 +76,8 @@ support and rejects any native declaration that is nevertheless supplied.
5676

5777
## Transformation
5878

59-
For each `McpServer::Acp` entry in `session/new`, `session/load`,
60-
`session/resume`, or feature-gated `session/fork`, the polyfill:
79+
For each schema-selected `McpServer::Acp` entry in a session setup request, the
80+
polyfill:
6181

6282
1. Creates or reuses a connection-scoped localhost bridge endpoint for the
6383
`serverId` and replaces the declaration with the HTTP transport for the
@@ -72,11 +92,17 @@ For each `McpServer::Acp` entry in `session/new`, `session/load`,
7292
the connection from the bridge.
7393

7494
Enable the polyfill crate's `unstable_session_fork` feature when adapting fork
75-
requests.
95+
requests. Stable v1 setup includes `session/new`, `session/load`, and
96+
`session/resume`; draft v2 includes `session/new` and `session/resume`. Both
97+
versions include `session/fork` when `unstable_session_fork` is enabled.
98+
99+
Declarations using another transport are left unchanged, including extension
100+
transports represented by v2's `McpServer::Other`.
76101

77102
Endpoints are cached by `serverId` across session setup requests on the ACP
78103
connection. The output declaration is rebuilt for each occurrence, preserving
79-
that occurrence's `name` and `_meta` even when its endpoint is reused.
104+
that occurrence's `name`, `_meta`, and other unmodified extension fields even
105+
when its endpoint is reused.
80106

81107
The native wire envelopes are documented in the [SDK Protocol
82108
Reference](./protocol.md#native-mcp-over-acp).

md/protocol-v2.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,21 @@ validates the final agent's initialize response against that selection.
251251
The proxy connection also routes v2 `session/new` requests and responses
252252
without interpreting them as v1 payloads.
253253

254+
### MCP compatibility polyfill
255+
256+
The concrete
257+
`agent_client_protocol_polyfill::mcp_over_acp::McpOverAcpPolyfill` can
258+
participate in a v2 conductor chain when its `unstable_protocol_v2` feature is
259+
enabled. It selects v1 or v2 from `_proxy/initialize`, uses that version's MCP
260+
capability and wire types, and adapts native `McpServer::Acp` declarations in
261+
v2 `session/new`, `session/resume`, and feature-gated `session/fork` requests.
262+
Other declarations and unrelated request fields remain unchanged. See
263+
[MCP-over-ACP Compatibility Bridge](./mcp-bridge.md) for placement and feature
264+
configuration.
265+
266+
This feature extends the concrete compatibility proxy only. Global MCP
267+
attachment and proxy-session helpers in the core SDK remain v1-only.
268+
254269
The SDK handles the `initialize` negotiation at the JSON-RPC boundary:
255270

256271
- A v2 client advertises protocol v2 as its latest supported version.

src/agent-client-protocol-conductor/Cargo.toml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,15 @@ agent-client-protocol-test.workspace = true
4343
yopo.workspace = true
4444
expect-test.workspace = true
4545
regex.workspace = true
46-
rmcp = { workspace = true, features = ["client", "server", "transport-io", "transport-child-process"] }
46+
rmcp = { workspace = true, features = [
47+
"client",
48+
"server",
49+
"transport-io",
50+
"transport-child-process",
51+
"transport-streamable-http-client-reqwest",
52+
] }
4753
schemars.workspace = true
48-
agent-client-protocol-polyfill.workspace = true
54+
agent-client-protocol-polyfill = { workspace = true, features = ["unstable_protocol_v2"] }
4955

5056
[lints]
5157
workspace = true

0 commit comments

Comments
 (0)