Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ members = [
"src/agent-client-protocol-conductor",
"src/agent-client-protocol-cookbook",
"src/agent-client-protocol-derive",
"src/agent-client-protocol-polyfill",
"src/agent-client-protocol-rmcp",
"src/agent-client-protocol-test",
"src/agent-client-protocol-trace-viewer",
Expand Down
4 changes: 2 additions & 2 deletions md/conductor.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,12 @@ See [Proxy Mode](#proxy-mode) below for hierarchical chain details.

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

**If agent has `mcp_acp_transport` capability:**
**If agent has `mcpCapabilities.acp` capability:**

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

**If agent lacks `mcp_acp_transport` capability:**
**If agent lacks `mcpCapabilities.acp` capability:**

- Bind TCP port for each ACP-transport MCP server
- Transform MCP server spec to use `conductor mcp $port`
Expand Down
2 changes: 1 addition & 1 deletion md/mcp-bridge.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ sequenceDiagram

Proxy->>Conductor: session/new {<br/> mcp_servers: [{<br/> name: "research-tools",<br/> url: "acp:uuid-123"<br/> }]<br/>}

Note over Conductor: Detects acp: transport<br/>Agent lacks mcp_acp_transport capability
Note over Conductor: Detects acp: transport<br/>Agent lacks mcpCapabilities.acp

Conductor->>Conductor: Bind TCP listener on port 54321

Expand Down
10 changes: 6 additions & 4 deletions md/protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -286,21 +286,23 @@ Send an MCP notification over the ACP connection. Bidirectional like `_mcp/reque
}
```

### Agent Capability: `mcp_acp_transport`
### Agent Capability: `mcpCapabilities.acp`

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

```json
{
"_meta": {
"mcp_acp_transport": true
"agentCapabilities": {
"mcpCapabilities": {
"acp": true
}
}
}
```

**Conductor behavior:**

- If the agent has `mcp_acp_transport: true`, conductor passes MCP server declarations through unchanged
- If the agent has `mcpCapabilities.acp: true`, conductor passes MCP server declarations through unchanged
- If the agent lacks this capability, conductor performs **bridging adaptation**:
1. Binds a TCP port (e.g., `localhost:54321`)
2. Transforms MCP server to use `conductor mcp PORT` command with stdio transport
Expand Down
24 changes: 12 additions & 12 deletions md/proxying-acp.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ P/ACP's orchestrator is called the **Conductor** (binary name: `conductor`). The

**Key adaptation: MCP Bridge**

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

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

#### Agent Capability: `mcp_acp_transport`
#### Agent Capability: `mcpCapabilities.acp`

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

```json
{
"_meta": {
"mcp_acp_transport": true
"agentCapabilities": {
"mcpCapabilities": {
"acp": true
}
}
}
```

**Conductor behavior:**

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

#### Bridging Transformation Example

Expand All @@ -393,7 +393,7 @@ Agents that natively support MCP-over-ACP declare this capability:
}
```

**Transformed spec (passed to agent without `mcp_acp_transport`):**
**Transformed spec (passed to agent without `mcpCapabilities.acp`):**

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

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

**Phase 3: `_mcp/*` Message Routing**
Expand Down
5 changes: 5 additions & 0 deletions src/agent-client-protocol-conductor/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Breaking Changes

- **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.
- **Removed `conductor mcp $port` CLI subcommand.** The stdio↔TCP bridge subprocess is no longer needed.

## [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

### Other
Expand Down
5 changes: 2 additions & 3 deletions src/agent-client-protocol-conductor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ test-support = []
agent-client-protocol.workspace = true
agent-client-protocol-trace-viewer.workspace = true
anyhow.workspace = true
async-stream.workspace = true
axum.workspace = true
chrono.workspace = true
clap.workspace = true
futures.workspace = true
Expand All @@ -31,20 +29,21 @@ rustc-hash.workspace = true
serde.workspace = true
serde_json.workspace = true
strip-ansi-escapes.workspace = true
thiserror.workspace = true
tokio.workspace = true
tokio-util.workspace = true
tracing.workspace = true
tracing-subscriber.workspace = true
uuid.workspace = true

[dev-dependencies]
agent-client-protocol = { workspace = true, features = ["unstable_mcp_over_acp"] }
agent-client-protocol-test.workspace = true
yopo.workspace = true
expect-test.workspace = true
regex.workspace = true
rmcp = { workspace = true, features = ["client", "server", "transport-io", "transport-child-process"] }
schemars.workspace = true
agent-client-protocol-polyfill = { path = "../agent-client-protocol-polyfill" }

[lints]
workspace = true
Loading
Loading