agent_client_protocol/lib.rs
1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![deny(missing_docs)]
3
4//! # agent-client-protocol -- the Agent Client Protocol (ACP) SDK
5//!
6//! **agent-client-protocol** is a Rust SDK for building [Agent-Client Protocol (ACP)][acp] applications.
7//! ACP is a protocol for communication between AI agents and their clients (IDEs, CLIs, etc.),
8//! enabling features like tool use, permission requests, and streaming responses.
9//!
10//! [acp]: https://agentclientprotocol.com/
11//!
12//! ## What can you build with agent-client-protocol?
13//!
14//! - **Clients** that talk to ACP agents (like building your own Claude Code interface)
15//! - **Proxies** that add capabilities to existing agents (like adding custom tools via MCP)
16//! - **Agents** that respond to prompts with AI-powered responses
17//!
18//! ## Quick Start: Connecting to an Agent
19//!
20//! The most common use case is connecting to an existing ACP agent as a client.
21//! Here's a minimal example that initializes a connection, creates a session,
22//! and sends a prompt:
23//!
24//! ```no_run
25//! use agent_client_protocol::Client;
26//! use agent_client_protocol::schema::{ProtocolVersion, v1::InitializeRequest};
27//!
28//! # async fn run(transport: impl agent_client_protocol::ConnectTo<agent_client_protocol::Client>) -> agent_client_protocol::Result<()> {
29//! Client.builder()
30//! .name("my-client")
31//! .connect_with(transport, async |cx| {
32//! // Step 1: Initialize the connection
33//! cx.send_request(InitializeRequest::new(ProtocolVersion::V1))
34//! .block_task().await?;
35//!
36//! // Step 2: Create a session and send a prompt
37//! cx.build_session_cwd()?
38//! .block_task()
39//! .run_until(async |mut session| {
40//! session.send_prompt("What is 2 + 2?")?;
41//! let response = session.read_to_string().await?;
42//! println!("{}", response);
43//! Ok(())
44//! })
45//! .await
46//! })
47//! .await
48//! # }
49//! ```
50//!
51//! For a complete working example, see [`yolo_one_shot_client.rs`][yolo].
52//!
53//! [yolo]: https://github.com/agentclientprotocol/rust-sdk/blob/main/src/agent-client-protocol/examples/yolo_one_shot_client.rs
54//!
55//! ## Cookbook
56//!
57//! The [`agent_client_protocol_cookbook`] crate contains practical guides and examples:
58//!
59//! - Connecting as a client
60//! - Global MCP server
61//! - Per-session MCP server with workspace context
62//! - Building agents and reusable components
63//! - Running proxies with the conductor
64//!
65//! [`agent_client_protocol_cookbook`]: https://docs.rs/agent-client-protocol-cookbook
66//!
67//! ## Core Concepts
68//!
69//! The [`concepts`] module provides detailed explanations of how agent-client-protocol works,
70//! including connections, sessions, callbacks, ordering guarantees, and more.
71//!
72//! ## Related Crates
73//!
74//! - [`agent-client-protocol-conductor`] - Binary for running proxy chains
75//!
76//! [`agent-client-protocol-conductor`]: https://crates.io/crates/agent-client-protocol-conductor
77
78/// Capability management for the `_meta.symposium` object
79mod capabilities;
80/// Component abstraction for agents and proxies
81pub mod component;
82/// Core concepts for understanding and using agent-client-protocol
83pub mod concepts;
84/// JSON-RPC connection and handler infrastructure
85mod jsonrpc;
86/// Runtime-agnostic MCP server support, including optional attachment to ACP sessions.
87pub mod mcp_server;
88/// Role types for ACP connections
89pub mod role;
90/// ACP protocol schema types - all message types, requests, responses, and supporting types
91pub mod schema;
92/// Utility functions and types
93pub mod util;
94
95pub use capabilities::*;
96
97pub use jsonrpc::{
98 Builder, ByteStreams, Channel, ConnectionTo, Dispatch, DynamicHandlerGuard,
99 HandleConnectionClose, HandleDispatchFrom, Handled, INCOMING_TRANSPORT_CLOSED_REASON,
100 IntoHandled, JsonRpcMessage, JsonRpcNotification, JsonRpcRequest, JsonRpcResponse, Lines,
101 NullClose, NullHandler, RawJsonRpcMessage, RawJsonRpcParams, Responder, ResponseRouter,
102 SentRequest, TransportBatch, TransportBatchEntry, TransportFrame, UntypedMessage,
103 is_incoming_transport_closed,
104 run::{ChainRun, NullRun, RunWithConnectionTo},
105};
106pub use jsonrpc::{RequestCancellation, is_cancel_request_notification};
107
108#[cfg(feature = "unstable_protocol_v2")]
109pub use role::acp::AgentProtocolRouter;
110#[cfg(feature = "unstable_protocol_v2")]
111pub use role::acp::ClientProtocolConnector;
112pub use role::{
113 Role, RoleId, UntypedRole,
114 acp::{Agent, Client, Conductor, Proxy},
115};
116
117pub use component::{ConnectTo, DynConnectTo};
118
119/// Implementation details used by the derive macros.
120#[doc(hidden)]
121pub mod __private {
122 pub use serde;
123 pub use serde_json;
124}
125
126// Re-export BoxFuture for implementing SDK traits that return boxed futures.
127pub use futures::future::BoxFuture;
128
129// Re-export commonly used infrastructure types for convenience
130pub use schema::v1::{Error, ErrorCode, Result};
131
132// Re-export derive macros for custom JSON-RPC types
133pub use agent_client_protocol_derive::{JsonRpcNotification, JsonRpcRequest, JsonRpcResponse};
134
135mod session;
136pub use session::*;
137
138mod acp_agent;
139pub use acp_agent::{AcpAgent, AcpAgentConfig, LineDirection};
140
141mod stdio;
142pub use stdio::Stdio;
143
144/// This is a hack that must be given as the final argument of
145/// the MCP server builder's `tool_fn_mut` method when defining tools.
146///
147/// The `agent-client-protocol-rmcp` crate provides the builder this macro is
148/// typically used with.
149/// Look away, lest ye be blinded by its vileness!
150///
151/// Fine, if you MUST know, it's a horrific workaround for not having
152/// [return-type notation](https://github.com/rust-lang/rust/issues/109417)
153/// and for [this !@$#!%! bug](https://github.com/rust-lang/rust/issues/110338).
154/// Trust me, the need for it hurts me more than it hurts you. --nikomatsakis
155#[macro_export]
156macro_rules! tool_fn_mut {
157 () => {
158 |func, params, context| Box::pin(func(params, context))
159 };
160}
161
162/// This is a hack that must be given as the final argument of
163/// the MCP server builder's `tool_fn` method when defining stateless concurrent tools.
164///
165/// The `agent-client-protocol-rmcp` crate provides the builder this macro is
166/// typically used with.
167/// See [`tool_fn_mut!`] for the gory details.
168#[macro_export]
169macro_rules! tool_fn {
170 () => {
171 |func, params, context| Box::pin(func(params, context))
172 };
173}
174
175/// This macro is used for the value of the `to_future_hack` parameter of
176/// [`Builder::on_receive_request`] and [`Builder::on_receive_request_from`].
177///
178/// It expands to `|f, req, responder, cx| Box::pin(f(req, responder, cx))`.
179///
180/// This is needed until [return-type notation](https://github.com/rust-lang/rust/issues/109417)
181/// is stabilized.
182#[macro_export]
183macro_rules! on_receive_request {
184 () => {
185 |f: &mut _, req, responder, cx| Box::pin(f(req, responder, cx))
186 };
187}
188
189/// This macro is used for the value of the `to_future_hack` parameter of
190/// [`Builder::on_receive_notification`] and [`Builder::on_receive_notification_from`].
191///
192/// It expands to `|f, notif, cx| Box::pin(f(notif, cx))`.
193///
194/// This is needed until [return-type notation](https://github.com/rust-lang/rust/issues/109417)
195/// is stabilized.
196#[macro_export]
197macro_rules! on_receive_notification {
198 () => {
199 |f: &mut _, notif, cx| Box::pin(f(notif, cx))
200 };
201}
202
203/// This macro is used for the value of the `to_future_hack` parameter of
204/// [`Builder::on_receive_dispatch`] and [`Builder::on_receive_dispatch_from`].
205///
206/// It expands to `|f, dispatch, cx| Box::pin(f(dispatch, cx))`.
207///
208/// This is needed until [return-type notation](https://github.com/rust-lang/rust/issues/109417)
209/// is stabilized.
210#[macro_export]
211macro_rules! on_receive_dispatch {
212 () => {
213 |f: &mut _, dispatch, cx| Box::pin(f(dispatch, cx))
214 };
215}