Skip to content

feat(acp-tunnel): inbound tunnel dispatch — parse frames + build replies (Part B slice 4) - #42

Merged
brettchien merged 1 commit into
mainfrom
feat/acp-tunnel-dispatch-v2
Aug 14, 2026
Merged

brettchien merged 1 commit into
mainfrom
feat/acp-tunnel-dispatch-v2

Conversation

@brettchien

Copy link
Copy Markdown
Contributor

Drafted by Orca (ecs-claude) — flagging authorship (shared GitHub identity).

Slice 4 (protocol half) of the reverse-MCP client ADR (#36). Rebased onto main after #40 (slice 3) merged — supersedes the auto-closed #41 (its stacked base branch was deleted on squash-merge).

The gateway-initiated tunnel routing, kept pure so the async work (relaying an inner MCP call to the running oab-mcp sidecar) stays in the transport, and routing is unit-testable.

What

  • Inbound classification: Connect / Message (request vs notification by outer-id presence) / Disconnect / Cancel / Other (ACP chat + unknown ignored).
  • parse_inbound (never fails) + reply builders connect_reply / message_reply / message_error / disconnect_reply.
  • Correlation by the outer ACP frame id; inner MCP result → ACP result verbatim; inner error → outer JSON-RPC error (contract §4).

Verification

cargo test -p acp-tunnel — 13/13 pass locally (7 lifecycle + 6 dispatch), no aws / no Tauri.

Next: the src-tauri WS transport + the configurable endpoint (editable config file) and an explicit "activate remote connection" button (per operator direction) — coming as the transport PR.

🤖 Generated with Claude Code

…ies (Part B slice 4)

The gateway-initiated tunnel routing, kept **pure** so the async work (forwarding
an inner MCP call to the running oab-mcp sidecar and awaiting it) stays in the
src-tauri transport and the routing is unit-testable without a runtime.

- `Inbound` classification of an `/acp` frame: `Connect` / `Message`
  (request vs notification by presence of the outer id) / `Disconnect` / `Cancel`
  / `Other` (ACP chat + unknown are ignored by the tunnel).
- `parse_inbound` (never fails; lenient sub-field reads) and the reply builders
  `connect_reply` / `message_reply` / `message_error` / `disconnect_reply`.
- Correlation is always by the OUTER ACP frame id; the inner MCP result becomes
  the ACP response result verbatim; an inner error becomes an outer JSON-RPC
  error (tunnel contract §4).

Verification: `cargo test -p acp-tunnel` — 13/13 pass locally (7 lifecycle + 6
dispatch), no aws / no Tauri.

Remaining for path (i): the src-tauri WS transport — dial `/acp`
(tokio-tungstenite), drive the `Session`, and on each `Inbound::Message` relay to
the sidecar `McpClient` and reply. That half compiles only under desktop.yml
(macOS) and runs end-to-end only against a real gateway (ADR §5, pending).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@brettchien
brettchien merged commit ffa1b24 into main Aug 14, 2026
2 checks passed
@brettchien
brettchien deleted the feat/acp-tunnel-dispatch-v2 branch August 14, 2026 06:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant