Agent Client Protocol (ACP) Rust SDK

repository·main·Indexed 41 days ago

https://github.com/agentclientprotocol/rust-sdk

A suite of Rust crates for implementing standardized communication between AI coding agents and code editors. It supports roles for Client, Agent, Proxy, and Conductor, providing transport layers for HTTP/SSE and WebSockets, as well as integration with the Model Context Protocol (MCP). The SDK supports stable protocol v1 and draft v2 (via the unstable_protocol_v2 feature), and includes a conductor binary for orchestrating proxy chains.

Tokens
80.1K
Snippets
191
Records
319
Agent score
53%

What's inside ACP Rust SDK

  1. Overview of the Agent Client Protocol (ACP) Rust SDK

    main

    The Agent Client Protocol (ACP) Rust SDK standardizes communication between code editors (Clients) and coding agents. It provides a suite of crates to build clients, agents, and proxies, as well as a conductor to orchestrate chains of proxies. This allows developers to extend agent behavior without modifying the agent itself.

    Core Components

    • Roles: The SDK defines roles for Client, Agent, Proxy, and Conductor.
    • Transports: Supports various communication methods including HTTP/SSE and WebSockets via the agent-client-protocol-http crate.
    • MCP Integration: Provides integration with the Model Context Protocol (MCP) via agent-client-protocol-rmcp and native MCP-over-ACP support (opt-in via unstable_mcp_over_acp feature).
  2. Overview of agent-client-protocol-http components

    main

    The agent-client-protocol-http crate provides two primary components for ACP transport:

    • AcpHttpServer: Exposes agents over HTTP and Server-Sent Events (SSE), with an optional WebSocket upgrade path.
    • HttpClient: Connects to remote agents using HTTP and SSE.

    Additionally, this transport layer supports forwarding Core SDK request cancellation.

  3. Integrate RMCP with Agent Client Protocol

    main

    The agent-client-protocol-rmcp crate provides a bridge between rmcp-based MCP (Model Context Protocol) server implementations and the runtime-agnostic MCP server framework in agent-client-protocol.

    This integration allows you to:

    • Define MCP tools in Rust and serve them directly.
    • Attach MCP servers to an ACP proxy.
    • Advertise attached servers using native MCP-over-ACP transport (via McpServer::Acp and the mcp/connect, mcp/message, and mcp/disconnect methods).

    Important Note on Features: To use with_mcp_server, you must enable the unstable_mcp_over_acp feature in this crate. If your final agent accepts HTTP but does not support ACP-transport MCP servers, use agent-client-protocol-polyfill instead.

  4. Understand the Agent Client Protocol (ACP) Crate Organization

    main

    The ACP Rust SDK is organized into several specialized crates to separate core logic from specific transport or integration needs:

    • agent-client-protocol: The core SDK. It provides role types (Client, Agent, Proxy, Conductor), connection builders (builder(), connect_to(), connect_with()), message handling hooks, protocol schemas, and various transport implementations (Channel, Lines, ByteStreams, Stdio, AcpAgent). It also includes runtime-agnostic interfaces for attaching MCP servers via the unstable_mcp_over_acp transport.
    • agent-client-protocol-http: Provides optional HTTP/SSE and WebSocket clients and servers built on the core transport-frame boundary.
    • agent-client-protocol-rmcp: Provides integration with the rmcp crate. You can use McpServer::builder() to define MCP tools in Rust or McpServer::from_rmcp() to wrap an existing rmcp server. Enabling the unstable_mcp_over_acp feature allows an attached server to be advertised as McpServer::Acp.
  5. What is P/ACP (Proxying ACP)?

    main

    P/ACP (Proxying ACP) is an extension to the Agent Client Protocol (ACP) designed for composable agent architectures. It allows developers to build modular components that form a proxy chain.

    In a P/ACP setup, an Orchestrator (the conductor) manages a chain of components. These components can intercept, transform, or add capabilities to messages flowing between an Editor and an Agent without requiring changes to either the editor or the base agent.

    Key Actors:

    • Editors: Spawn the orchestrator and communicate via standard ACP.
    • Orchestrator (Conductor): Manages the proxy chain and presents as a normal ACP agent to the editor.
    • Proxies: Intercept and transform messages, communicating with downstream components via the _proxy/successor/* protocol.
    • Agents: Provide the base AI model behavior using standard ACP.
  6. How the Conductor Chain Model works

    main

    The agent-client-protocol-conductor crate manages a chain of ACP proxy components. Instead of components connecting directly to each other, the Conductor owns every transport and manages the logical routing between them.

    Traffic Flow:

    • Upstream: Traffic from the client is delivered to the first proxy as standard ACP messages.
    • Downstream (Proxy to Proxy): A proxy uses the _proxy/successor method to send requests or notifications to the next component in the chain.
    • Upstream (Successor to Predecessor): Traffic returning from a successor is presented to its predecessor through the same typed proxy abstraction.
    • Final Agent: The last component in the chain (the agent) receives ordinary ACP and does not need to implement any special proxy extensions.

    JSON-RPC responses remain paired with their original request context throughout the chain.

  7. Understand JSON-RPC batching behavior in ACP

    main

    The transport supports JSON-RPC batches to improve efficiency, but behavior differs between initialization and established connections.

    Initializing with Batches

    While HttpClient typically sends an individual initialize request, the server accepts an initial batch if the first call-shaped entry is an initialize request.

    • A successful initialize in a batch will return the Acp-Connection-Id in the POST response.
    • If the agent emits notifications before initialization completes, the server buffers them for the connection's SSE stream.

    Batches after Initialization

    • HTTP: One complete batch occupies one POST body. The server returns 202 Accepted. Grouped replies are delivered via SSE as a single array. If entries in a batch have different session routes, the reply is sent on the connection-level stream to ensure the array remains intact.
    • WebSocket: One complete batch is sent in one text frame, and the grouped reply is written in one text frame.
  8. How Lazy Initialization works in the Conductor

    main

    Components in the chain are not instantiated immediately. Instead, they are created when the first initialize request arrives.

    Initialization Process:

    • For non-final components, the conductor sends _proxy/initialize.
    • The final component (in agent mode) receives a standard initialize request.
    • Proxies can initialize their successor before completing their own response, allowing capabilities to flow back toward the client.

    Protocol Versioning (v1 vs v2): With the unstable_protocol_v2 feature enabled, the conductor inspects the protocolVersion in the raw request before deserialization. This ensures that v2-specific fields (like info, capabilities, or metadata) are not accidentally dropped by being interpreted as a permissive v1 request.

    If you are implementing custom instantiators, you can implement the feature-gated instantiate_v2_proxies_and_agent or instantiate_v2_proxies methods to handle v2-specific logic.

  9. Understand the ACP Transport Architecture

    main

    The Agent Client Protocol (ACP) SDK uses a layered architecture to separate protocol semantics (JSON-RPC) from the physical transport mechanism (I/O). This allows the same protocol logic to run over WebSockets, named pipes, byte streams, or even in-process memory channels without changing the application code.

    Layered Responsibilities

    1. Protocol Layer: Handles JSON-RPC logic, including request ID assignment, request/response correlation, method dispatching to handlers, and error handling.
    2. Transport and Framing Layer: Handles the movement of messages, serialization/deserialization, and maintaining JSON-RPC envelope validity (including batch boundaries).

    The TransportFrame Boundary

    The TransportFrame is the transport-neutral boundary between these layers. It carries either a single RawJsonRpcMessage, a non-empty TransportBatch, or a malformed wire value (to allow relays to forward it without modification).

  10. How the MCP Bridge works in P/ACP

    main

    The MCP Bridge allows components to provide Model Context Protocol (MCP) servers to an agent, even if the agent does not natively support MCP.

    • If the agent supports mcpCapabilities.acp, the Conductor passes MCP servers with ACP transport through unchanged.
    • If the agent does not support it, the Conductor spawns conductor mcp $port processes to bridge the gap between stdio (the standard MCP transport) and ACP messages.

    This enables tool provision without requiring modifications to the base agent.

  11. How the MCP-over-ACP Polyfill transforms requests

    main

    When the polyfill encounters an McpServer::Acp entry in a session setup request, it performs the following transformation steps:

    1. Endpoint Creation: Creates or reuses a connection-scoped localhost bridge endpoint for the specific serverId and replaces the native declaration with an HTTP transport URL for the final agent.
    2. Routing: Retains the native serverId so connections can be routed back to the original provider.
    3. Connection: Opens the native connection by sending an mcp/connect request with that serverId toward the provider.
    4. Relay: Relays requests and notifications via mcp/message, using the returned connectionId for the active MCP connection.
    5. Cleanup: Sends an mcp/disconnect request when the local transport closes and removes the connection from the bridge.

    Endpoints are cached by serverId across session setup requests. The polyfill preserves name, _meta, and other extension fields even when reusing an endpoint.

  12. How session projection and completion work

    main

    In the coordination prototype, the projection is a raw, lossless SessionUpdate log rather than a general reducer.

    • Availability: Loads only expose the shared projection after the resume response is received. Live updates continue appending to the log after this point.
    • Completeness: The complete resume setup response is retained alongside the log by the operation result.
    • Implementation Note: This prototype does not expose partial replay to a loading view. Production applications should implement their own projection of protocol entities based on UI needs outside of SDK callbacks.
    • Idle State: Do not treat the idle state as the completion of a specific prompt. In v2, state is session-wide, updates lack prompt identity, and background updates may continue even when the session is idle.