Skip to content

Commit ef67cca

Browse files
nikomatsakisbenbrandtclaude
authored
feat: extract mcp-over-acp proxy (#146)
* Remove html_panel and file_comment metacapabilities from P/ACP design doc * Step 1/1b: Remove McpAcpTransport, rename acp_url → acp_id - Remove McpAcpTransport struct and MetaCapability impl from capabilities.rs (keep MetaCapability/MetaCapabilityExt traits for proxy capability) - Rename McpConnectRequest.acp_url to acp_id across all source and tests - Update snapshot tests for schema changes (mcpCapabilities.acp, auth removal) - Switch agent-client-protocol-schema to path dependency * Step 2: Extract MCP bridging into agent-client-protocol-polyfill crate New crate src/agent-client-protocol-polyfill with mcp_over_acp module: - McpOverAcpPolyfill proxy (ConnectTo<Conductor>) - BridgeConnectionActor, BridgeListeners, BridgeConnection - HTTP and stdio bridge transports - Uses own BridgeMessage enum instead of ConductorMessage Conductor bridge code still present (removed in Step 3). * Step 3: Remove MCP bridging from conductor (clean break) - Remove McpBridgeMode enum and mcp_bridge_mode parameter - Delete conductor/mcp_bridge module (actor, http, stdio) - Remove bridge fields from ConductorResponder - Remove bridge ConductorMessage variants and handling - Remove NewSessionRequest MCP server transformation - Update all 16 test files to remove McpBridgeMode - Mark 13 bridge-dependent tests as #[ignore] * Step 4: Update markdown docs (_meta.symposium.mcp_acp_transport → mcpCapabilities.acp) Replace all _meta.symposium.mcp_acp_transport references with mcpCapabilities.acp in: - md/proxying-acp.md (8 references) - md/protocol.md (3 references) - md/conductor.md (2 references) - md/mcp-bridge.md (1 reference) * Add acp_id(), fix 13 tests with polyfill, remove conductor mcp CLI - Add McpConnectionTo::acp_id(), deprecate acp_url() - Remove orphaned 'conductor mcp $port' CLI subcommand and mcp_bridge.rs - Fix all 13 previously-ignored tests to use McpOverAcpPolyfill::http() - Fix BridgeResponder bug: route through BridgeMessage::ConnectionEstablished instead of creating new HashMap in on_receiving_result callback - Auto-update 2 snapshot tests for new proxy in chain * Add breaking change entries to CHANGELOGs - agent-client-protocol: removed McpAcpTransport, renamed acp_url→acp_id, added acp_id(), deprecated acp_url() - agent-client-protocol-conductor: removed McpBridgeMode, removed conductor mcp CLI subcommand * Enable unstable_mcp_over_acp feature on schema dependency * Forward unstable_mcp_over_acp feature through SDK crate Instead of unconditionally enabling unstable_mcp_over_acp on the schema dependency, declare it as a feature on agent-client-protocol that forwards to agent-client-protocol-schema/unstable_mcp_over_acp. Conductor and polyfill crates opt in explicitly. * Only enable unstable_mcp_over_acp in test builds The conductor and polyfill don't reference McpServer::Acp or McpCapabilities.acp in their source — only snapshot tests see the field in serialized output. Move the feature to dev-dependencies. * Address PR review feedback - Restore doc comments in polyfill actor.rs and http.rs that were stripped during extraction from conductor - Polyfill now intercepts InitializeProxyRequest and sets mcpCapabilities.acp = true in the response - Re-enable unstable_mcp_over_acp feature for polyfill crate (it needs to set the acp field) - Update snapshot tests to reflect acp: true ProxiesAndAgent API redesign noted for separate PR. * Trim unused deps * test: refresh expect snapshots after schema 0.13.0 bump - Fix two stale test references to the removed McpAcpTransport type (regression from "Step 1/1b") by switching to TestCapability - Regenerate trace_* expect snapshots so they match the actual output under --all-features (adds auth capability fields exposed by unstable_auth_methods) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(polyfill): satisfy clippy under -D warnings CI runs clippy with `-D warnings` and surfaced three lints in the new mcp_over_acp module: - derivable_impls: replace the manual `impl Default for BridgeMode` with `#[derive(Default)]` and `#[default]` on the `Http` variant - must_use_candidate: add `#[must_use]` to `McpOverAcpPolyfill::http` and `::stdio` constructors Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Trip deps * More --------- Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 75f5b68 commit ef67cca

42 files changed

Lines changed: 926 additions & 1112 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Cargo.lock

Lines changed: 20 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ members = [
44
"src/agent-client-protocol-conductor",
55
"src/agent-client-protocol-cookbook",
66
"src/agent-client-protocol-derive",
7+
"src/agent-client-protocol-polyfill",
78
"src/agent-client-protocol-rmcp",
89
"src/agent-client-protocol-test",
910
"src/agent-client-protocol-trace-viewer",
@@ -50,7 +51,7 @@ tracing = "0.1"
5051
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
5152

5253
# MCP SDK
53-
rmcp = { version = "1.6.0", features = ["server", "transport-io", "schemars"] }
54+
rmcp = { version = "1.2.0", features = ["server", "transport-io", "schemars"] }
5455

5556
# CLI parsing
5657
clap = { version = "4.5", features = ["derive"] }

md/conductor.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,12 @@ See [Proxy Mode](#proxy-mode) below for hierarchical chain details.
9393

9494
When components provide MCP servers with ACP transport (`"url": "acp:$UUID"`):
9595

96-
**If agent has `mcp_acp_transport` capability:**
96+
**If agent has `mcpCapabilities.acp` capability:**
9797

9898
- Pass through MCP server declarations unchanged
9999
- Agent handles `_mcp/*` messages natively
100100

101-
**If agent lacks `mcp_acp_transport` capability:**
101+
**If agent lacks `mcpCapabilities.acp` capability:**
102102

103103
- Bind TCP port for each ACP-transport MCP server
104104
- Transform MCP server spec to use `conductor mcp $port`

md/mcp-bridge.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ sequenceDiagram
5353
5454
Proxy->>Conductor: session/new {<br/> mcp_servers: [{<br/> name: "research-tools",<br/> url: "acp:uuid-123"<br/> }]<br/>}
5555
56-
Note over Conductor: Detects acp: transport<br/>Agent lacks mcp_acp_transport capability
56+
Note over Conductor: Detects acp: transport<br/>Agent lacks mcpCapabilities.acp
5757
5858
Conductor->>Conductor: Bind TCP listener on port 54321
5959

md/protocol.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -286,21 +286,23 @@ Send an MCP notification over the ACP connection. Bidirectional like `_mcp/reque
286286
}
287287
```
288288

289-
### Agent Capability: `mcp_acp_transport`
289+
### Agent Capability: `mcpCapabilities.acp`
290290

291291
Agents that natively support MCP-over-ACP declare this capability:
292292

293293
```json
294294
{
295-
"_meta": {
296-
"mcp_acp_transport": true
295+
"agentCapabilities": {
296+
"mcpCapabilities": {
297+
"acp": true
298+
}
297299
}
298300
}
299301
```
300302

301303
**Conductor behavior:**
302304

303-
- If the agent has `mcp_acp_transport: true`, conductor passes MCP server declarations through unchanged
305+
- If the agent has `mcpCapabilities.acp: true`, conductor passes MCP server declarations through unchanged
304306
- If the agent lacks this capability, conductor performs **bridging adaptation**:
305307
1. Binds a TCP port (e.g., `localhost:54321`)
306308
2. Transforms MCP server to use `conductor mcp PORT` command with stdio transport

md/proxying-acp.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ P/ACP's orchestrator is called the **Conductor** (binary name: `conductor`). The
108108

109109
**Key adaptation: MCP Bridge**
110110

111-
- If the agent supports `mcp_acp_transport`, conductor passes MCP servers with ACP transport through unchanged
111+
- If the agent supports `mcpCapabilities.acp`, conductor passes MCP servers with ACP transport through unchanged
112112
- If not, conductor spawns `conductor mcp $port` processes to bridge between stdio (MCP) and ACP messages
113113
- Components can provide MCP servers without requiring agent modifications
114114
- See "MCP Bridge" section in Implementation Details for full protocol
@@ -216,9 +216,7 @@ An P/ACP-aware editor provides the following capability during ACP initializatio
216216
/// supports symposium proxy initialization.
217217
"_meta": {
218218
"symposium": {
219-
"version": "1.0",
220-
"html_panel": true, // or false, if this is the ToEditor proxy
221-
"file_comment": true, // or false, if this is the ToEditor proxy
219+
"version": "1.0"
222220
}
223221
}
224222
```
@@ -358,26 +356,28 @@ Components declare MCP servers with ACP transport by using the HTTP MCP server f
358356

359357
The `acp:$UUID` URL signals ACP transport. The component generates the UUID to identify which component handles calls to this MCP server.
360358

361-
#### Agent Capability: `mcp_acp_transport`
359+
#### Agent Capability: `mcpCapabilities.acp`
362360

363361
Agents that natively support MCP-over-ACP declare this capability:
364362

365363
```json
366364
{
367-
"_meta": {
368-
"mcp_acp_transport": true
365+
"agentCapabilities": {
366+
"mcpCapabilities": {
367+
"acp": true
368+
}
369369
}
370370
}
371371
```
372372

373373
**Conductor behavior:**
374374

375-
- If the final agent has `mcp_acp_transport: true`, conductor passes MCP server declarations through unchanged
375+
- If the final agent has `mcpCapabilities.acp: true`, conductor passes MCP server declarations through unchanged
376376
- If the final agent lacks this capability, conductor performs **bridging adaptation**:
377377
1. Binds a fresh TCP port (e.g., `localhost:54321`)
378378
2. Transforms the MCP server declaration to use `conductor mcp $port` as the command
379379
3. Spawns `conductor mcp $port` which connects back via TCP and bridges to ACP messages
380-
4. Always advertises `mcp_acp_transport: true` to intermediate components
380+
4. Always advertises `mcpCapabilities.acp: true` to intermediate components
381381

382382
#### Bridging Transformation Example
383383

@@ -393,7 +393,7 @@ Agents that natively support MCP-over-ACP declare this capability:
393393
}
394394
```
395395

396-
**Transformed spec (passed to agent without `mcp_acp_transport`):**
396+
**Transformed spec (passed to agent without `mcpCapabilities.acp`):**
397397

398398
```json
399399
{
@@ -588,12 +588,12 @@ These extensions are beyond the scope of this initial RFD and will be defined as
588588
**Phase 2: Conductor Agent Mode - MCP Detection & Bridging**
589589

590590
- [ ] Detect `"transport": "http", "url": "acp:$UUID"` MCP servers in initialization
591-
- [ ] Check final agent for `mcp_acp_transport` capability
591+
- [ ] Check final agent for `mcpCapabilities.acp` capability
592592
- [ ] Bind ephemeral TCP ports when bridging needed
593593
- [ ] Transform MCP server specs to use `conductor mcp $port`
594594
- [ ] Spawn `conductor mcp $port` subprocess per ACP-transport MCP server
595595
- [ ] Store mapping: `UUID → TCP port → bridge process`
596-
- [ ] Always advertise `mcp_acp_transport: true` to intermediate components
596+
- [ ] Always advertise `mcpCapabilities.acp: true` to intermediate components
597597
- [ ] Integration test: full chain with MCP bridging
598598

599599
**Phase 3: `_mcp/*` Message Routing**

src/agent-client-protocol-conductor/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Breaking Changes
11+
12+
- **Removed `McpBridgeMode`** and the `mcp_bridge_mode` parameter from `ConductorImpl::new`, `new_agent`, and `new_proxy`. MCP-over-ACP bridging is no longer built into the conductor. Use `agent-client-protocol-polyfill::mcp_over_acp::McpOverAcpPolyfill` as a proxy in the chain instead.
13+
- **Removed `conductor mcp $port` CLI subcommand.** The stdio↔TCP bridge subprocess is no longer needed.
14+
1015
## [0.11.1](https://github.com/agentclientprotocol/rust-sdk/compare/agent-client-protocol-conductor-v0.11.0...agent-client-protocol-conductor-v0.11.1) - 2026-04-21
1116

1217
### Other

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,9 @@ path = "src/main.rs"
1818
test-support = []
1919

2020
[dependencies]
21-
agent-client-protocol.workspace = true
21+
agent-client-protocol = { workspace = true }
2222
agent-client-protocol-trace-viewer.workspace = true
2323
anyhow.workspace = true
24-
async-stream.workspace = true
25-
axum.workspace = true
2624
chrono.workspace = true
2725
clap.workspace = true
2826
futures.workspace = true
@@ -31,20 +29,21 @@ rustc-hash.workspace = true
3129
serde.workspace = true
3230
serde_json.workspace = true
3331
strip-ansi-escapes.workspace = true
34-
thiserror.workspace = true
3532
tokio.workspace = true
3633
tokio-util.workspace = true
3734
tracing.workspace = true
3835
tracing-subscriber.workspace = true
3936
uuid.workspace = true
4037

4138
[dev-dependencies]
39+
agent-client-protocol = { workspace = true, features = ["unstable_mcp_over_acp"] }
4240
agent-client-protocol-test.workspace = true
4341
yopo.workspace = true
4442
expect-test.workspace = true
4543
regex.workspace = true
4644
rmcp = { workspace = true, features = ["client", "server", "transport-io", "transport-child-process"] }
4745
schemars.workspace = true
46+
agent-client-protocol-polyfill = { path = "../agent-client-protocol-polyfill" }
4847

4948
[lints]
5049
workspace = true

0 commit comments

Comments
 (0)