Skip to main content

Crate agent_client_protocol

Crate agent_client_protocol 

Source
Expand description

§agent-client-protocol – the Agent Client Protocol (ACP) SDK

agent-client-protocol is a Rust SDK for building Agent-Client Protocol (ACP) applications. ACP is a protocol for communication between AI agents and their clients (IDEs, CLIs, etc.), enabling features like tool use, permission requests, and streaming responses.

§What can you build with agent-client-protocol?

  • Clients that talk to ACP agents (like building your own Claude Code interface)
  • Proxies that add capabilities to existing agents (like adding custom tools via MCP)
  • Agents that respond to prompts with AI-powered responses

§Protocol versions

Every connection names the ACP protocol version it speaks:

  • Client.v1(), Agent.v1() and Proxy.v1() start a stable protocol v1 connection. Its types are in v1 and its messages in v1::schema.
  • With the unstable_protocol_v2 feature, Client.v2(), Agent.v2() and Proxy.v2() start a draft protocol v2 connection. Its types are in agent_client_protocol::v2 and its messages in v2::schema.

The v1 and v2 modules use the same names for the connection, the builder, the request handles and schema (ConnectionTo, Builder, Responder, Dispatch, SentRequest, …). Their session APIs differ: v1::ActiveSession reads the session’s updates from its own stream, while v2::ActiveSession only sends commands and the updates arrive through typed handlers on the connection. Some names exist in only one module, such as v1::LoadSessionBuilder and v1::SessionMessage, or v2::InitializeOutcome. The crate root holds what every version shares: transports, roles, the JSON-RPC traits, Error, the generic request handles (which default to the version-neutral Raw marker) and, with unstable_protocol_v2, the routers that serve both versions. Builder::new remains as the raw, version-neutral escape hatch: it applies no protocol-version guard.

§Quick Start: Connecting to an Agent

The most common use case is connecting to an existing ACP agent as a client. This example uses stable ACP protocol v1. The draft protocol v2 feature provides a command-only v2::ActiveSession API and receives updates and interactive requests through typed connection handlers because prompt acceptance and inbound traffic are independent. With both v2 and MCP-over-ACP features, Proxy.v2() supports global MCP attachment, while v2::SessionBuilder and v2::ResumeSessionBuilder support per-session attachment plus non-blocking proxy setup. With unstable_session_fork, v2::ForkSessionBuilder provides the same shape for forked sessions and uses the response’s new session ID. Per-session MCP routes and runners are ready before a setup request is published, as is proxy session routing for resume replay. Successful v2 setup detaches MCP handlers for the connection lifetime; dropping the returned v2::ActiveSession does not unregister them. In v1, v1::ActiveSession owns per-session MCP registrations until drop, unless a proxy handoff detaches them (proxy_remaining_messages or successful on_proxy_session_start). Global proxy attachments are connection-scoped in both versions.

Here’s a minimal example that initializes a v1 connection, creates a session, and sends a prompt:

use agent_client_protocol::Client;
use agent_client_protocol::{schema::ProtocolVersion, v1::schema::InitializeRequest};
use agent_client_protocol::v1::SessionSetup;

Client.v1()
    .name("my-client")
    .connect_with(transport, async |cx| {
        // Step 1: Initialize the connection
        cx.send_request(InitializeRequest::new(ProtocolVersion::V1))
            .block_task().await?;

        // Step 2: Create a session and send a prompt
        cx.build_session_cwd()?
            .block_task()
            .run_until(async |SessionSetup { mut session, .. }| {
                session.send_prompt("What is 2 + 2?")?;
                let response = session.read_to_string().await?;
                println!("{}", response);
                Ok(())
            })
            .await
    })
    .await

For a complete working example, see yolo_one_shot_client.rs.

§Cookbook

The agent_client_protocol_cookbook crate contains practical guides and examples:

  • Connecting as a client
  • Global MCP server
  • Per-session MCP server with workspace context
  • Building agents and reusable components
  • Running proxies with the conductor

§Cargo Features

No features are enabled by default. Protocol serialization, connections, sessions, custom MCP servers, and the generic transport adapters remain available without opting in to native I/O or JSON Schema generation.

  • process: native subprocess support through AcpAgent and AcpAgentConfig.
  • stdio: the native Stdio adapter.
  • schemars: JsonSchema implementations on protocol types and typed MCP tool helpers in mcp_server.

For example, a native client launching an agent opts into process:

agent-client-protocol = { version = "5", features = ["process"] }

Enable stdio for an agent using Stdio, or schemars for typed MCP tool definitions. LineDirection is available on native targets with either process or stdio; neither feature enables the other.

The agent-client-protocol-rmcp crate explicitly enables schemars for its tool builders. Unstable protocol features remain independent opt-ins. No features have been enabled by default since 3.0. When upgrading from 2.x, explicitly enable every feature your application uses; default-features = false is no longer needed for a lean dependency.

§Stability

  • The stable API, everything that is not behind an unstable_* feature, follows semver: it changes incompatibly only in a major release.
  • Everything behind an unstable_* feature may change in a minor release. This includes all of agent_client_protocol::v2 and the other items that unstable_protocol_v2 enables. Stabilizing protocol v2 only removes the unstable_protocol_v2 gate.
  • This crate depends on one exact version of agent-client-protocol-schema (an = requirement), and a minor release may move that pin to a newer schema release. Use each version’s message types through v1::schema and v2::schema, and the version-neutral items such as ProtocolVersion through schema, instead of depending on agent-client-protocol-schema directly. A direct dependency must allow the exact version this crate pins, or Cargo cannot resolve the dependency graph.
  • All SDK crates share one version number, so moving a public dependency of any of them to a new major version, such as axum or reqwest in agent-client-protocol-http, is a major release of all of them.

§WebAssembly

The runtime-neutral protocol engine and transport abstractions compile for wasm32-wasip1 and wasm32-wasip2 without additional features. For JavaScript-hosted wasm32-unknown-unknown, enable wasm_js to select Web Crypto through wasm-bindgen as the UUID randomness backend. The target does not imply a JavaScript host, so this feature is not enabled by default; other OS-less WebAssembly hosts must arrange a compatible UUID randomness backend instead.

This crate does not provide a WebAssembly executor or host I/O adapter. The native process and stdio features depend on process spawning and blocking-thread facilities, so their dependencies and exports (including LineDirection) remain excluded on WebAssembly even when enabled.

Embedders provide their own runtime and transport. They can exchange TransportFrame values through Channel, newline-delimited JSON through Lines, or use ByteStreams with futures::io::AsyncRead and AsyncWrite. The embedding runtime must drive the resulting connection future.

Handlers, transports, and connection futures must be Send on every target, including WebAssembly. JavaScript host values such as wasm_bindgen::JsValue are !Send, so keep them outside the connection and exchange Send data with it through Channel or ByteStreams. A later release may relax these bounds on WebAssembly. That change would not affect native code.

§Core Concepts

The concepts module provides detailed explanations of how agent-client-protocol works, including connections, sessions, callbacks, ordering guarantees, and more.

Re-exports§

pub use role::acp::AgentProtocolRouter;unstable_protocol_v2
pub use role::acp::ClientProtocolConnector;unstable_protocol_v2
pub use role::acp::ProxyProtocolRouter;unstable_protocol_v2
pub use role::Role;
pub use role::RoleId;
pub use role::UntypedRole;
pub use role::acp::Agent;
pub use role::acp::Client;
pub use role::acp::Conductor;
pub use role::acp::Proxy;
pub use component::ConnectTo;
pub use component::ConnectionDriver;
pub use component::DynConnectTo;

Modules§

component
Component abstraction for agents and proxies ConnectTo abstraction for agents and proxies.
concepts
Core concepts for understanding and using agent-client-protocol Core concepts for understanding and using agent-client-protocol.
mcp_server
Runtime-agnostic MCP server support, including optional attachment to ACP sessions. Runtime-agnostic MCP server support.
role
Role types for ACP connections Role types for ACP connections.
schema
Version-neutral ACP schema items.
util
Utility functions and types
v1
The SDK API for ACP protocol v1.
v2unstable_protocol_v2
The SDK API for draft ACP protocol v2.

Macros§

on_receive_dispatch
This macro is used for the value of the to_future_hack parameter of Builder::on_receive_dispatch and Builder::on_receive_dispatch_from.
on_receive_notification
This macro is used for the value of the to_future_hack parameter of Builder::on_receive_notification and Builder::on_receive_notification_from.
on_receive_request
This macro is used for the value of the to_future_hack parameter of Builder::on_receive_request and Builder::on_receive_request_from.
tool_fn
This is a hack that must be given as the final argument of the MCP server builder’s tool_fn method when defining stateless concurrent tools.
tool_fn_mut
This is a hack that must be given as the final argument of the MCP server builder’s tool_fn_mut method when defining tools.

Structs§

AcpAgentprocess and non-target_family=wasm
A component representing an external ACP agent running in a separate process.
AcpAgentConfigprocess and non-target_family=wasm
Configuration for launching an ACP agent subprocess.
Builder
A JSON-RPC connection that can act as either a server, client, or both.
ByteStreams
A component that communicates over byte streams (stdin/stdout, sockets, pipes, etc.).
ChainRun
Chains two RunIn implementations to run in parallel.
Channel
A channel endpoint representing one side of a bidirectional JSON-RPC transport.
ConnectionTo
Connection context for sending messages and spawning tasks.
DynamicHandlerGuard
A guard that keeps a dynamic message handler registered.
Error
A JSON-RPC error object, independent of the ACP protocol version.
ErrorCode
A JSON-RPC error code.
InitializationVersionMismatchunstable_protocol_v2
A successful initialize response that selected a lower protocol version than the local API requires.
Lines
A component that communicates over line streams.
NullClose
A close handler that does nothing.
NullHandler
Null handler that accepts no messages.
NullRun
A no-op RunIn that completes immediately.
PreparedRequest
A request that has not been published to its connection.
Raw
The version-neutral protocol marker of the raw dispatch layer, and the default.
RawJsonRpcError
A JSON-RPC error without ACP-specific interpretation.
RawJsonRpcNotification
A JSON-RPC notification with uninterpreted params.
RawJsonRpcRequest
A JSON-RPC request with uninterpreted params.
RequestCancellation
A request-local marker that is set when the peer asks to cancel the request.
RequestCancellationHandle
Explicit cancellation control for one outgoing request.
Responder
The context to respond to an incoming request.
ResponseRouter
Context for handling an incoming JSON-RPC response.
SentRequest
Represents a pending response of type R from an outgoing request.
Stdiostdio and non-target_family=wasm
A transport that connects to an ACP peer via standard input/output.
UntypedMessage
An incoming JSON message without any typing. Can be a request or a notification.
V1
ACP protocol version 1.
V2unstable_protocol_v2
ACP protocol version 2.

Enums§

ConnectionTermination
Why a driven connection stopped.
Dispatch
An incoming request, notification, or response being dispatched through handlers. Requests include the context used to answer them; responses include the context used to route them to the local requester.
Handled
Return type from JrHandler; indicates whether the request was handled or not.
LineDirection(process or stdio) and non-target_family=wasm
Direction of a line being sent or received by a native transport.
RawJsonRpcId
A JSON-RPC id exactly as it appears on the wire: an integer, a string or null.
RawJsonRpcMessage
One valid JSON-RPC message carried inside a TransportFrame.
RawJsonRpcParams
Raw JSON-RPC request or notification parameters.
RawJsonRpcResponse
A transport-level JSON-RPC response with an opaque result or raw error.
SelectedInitializeResponseunstable_protocol_v2
A peer’s initialization response, typed by the protocol version it selected.
TransportFrame
A JSON-RPC frame exchanged between protocol components and transports.

Constants§

CONNECTION_TERMINATED_REASON
Stable discriminator stored in the data.reason field of errors produced when a connection terminates for a reason other than clean incoming EOF before a request receives its response.
INCOMING_TRANSPORT_CLOSED_REASON
Stable discriminator stored in the data.reason field of errors produced when the incoming transport reaches clean EOF before a request receives its response.

Traits§

HandleConnectionClose
A handler that runs after the incoming transport reaches clean EOF.
HandleDispatchFrom
Handlers process incoming JSON-RPC messages on a connection.
IntoHandled
Trait for converting handler return values into Handled.
JsonRpcMessage
Common bounds for any JSON-RPC message.
JsonRpcNotification
A struct that represents a notification (JSON-RPC message that does not expect a response).
JsonRpcRequest
A struct that represents a request (JSON-RPC message expecting a response).
JsonRpcResponse
Defines the “payload” of a successful response to a JSON-RPC request.
Protocol
The protocol version of a request handle or builder, as a type.
RunWithConnectionTo
A background task that runs alongside a connection.

Functions§

is_cancel_request_notification
Whether a notification is a $/cancel_request, even when it is still wrapped in proxy/successor envelopes.
is_connection_terminated
Return whether error reports that the connection terminated before a request received its response.
is_incoming_transport_closed
Return whether error reports that the incoming transport reached clean EOF before a request received its response.

Type Aliases§

BoxFuturealloc
An owned dynamically typed Future for use in cases where you can’t statically type your result or need to add some indirection.
Result
Result type whose error defaults to the SDK’s Error.

Derive Macros§

JsonRpcNotification
Derive macro for implementing JsonRpcNotification and JsonRpcMessage traits.
JsonRpcRequest
Derive macro for implementing JsonRpcRequest and JsonRpcMessage traits.
JsonRpcResponse
Derive macro for implementing JsonRpcResponse trait.