Skip to content
Merged
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
62 changes: 30 additions & 32 deletions src/agent-client-protocol-conductor/src/conductor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,52 +63,50 @@
//! Components are instantiated lazily when the first `initialize` request is received
//! from the editor. This enables dynamic proxy chain construction based on client capabilities.
//!
//! ### Simple Usage
//! ### Fixed Chains
//!
//! Pass a Vec of components that implement `Component`:
//! Use [`ProxiesAndAgent`] to assemble a conductor that presents as an agent:
//!
//! ```ignore
//! let conductor = Conductor::new(
//! use agent_client_protocol_conductor::{ConductorImpl, ProxiesAndAgent};
//!
//! let conductor = ConductorImpl::new_agent(
//! "my-conductor",
//! vec![proxy1, proxy2, agent],
//! None,
//! ProxiesAndAgent::new(agent)
//! .proxy(proxy1)
//! .proxy(proxy2),
//! );
//! ```
//!
//! All components are spawned in order when the editor sends the first `initialize` request.
//! A conductor that presents as a proxy takes only its internal proxies; its
//! final successor is supplied when the conductor is connected:
//!
//! ### Dynamic Component Selection
//! ```ignore
//! use agent_client_protocol_conductor::ConductorImpl;
//!
//! Pass a closure to examine the `InitializeRequest` and dynamically construct the chain:
//! let conductor = ConductorImpl::new_proxy("my-proxy-conductor", vec![proxy]);
//! ```
//!
//! ```ignore
//! let conductor = Conductor::new(
//! "my-conductor",
//! |cx, conductor_tx, init_req| async move {
//! // Examine capabilities
//! let needs_auth = has_auth_capability(&init_req);
//! ### Dynamic Chain Selection
//!
//! let mut components = Vec::new();
//! if needs_auth {
//! components.push(spawn_auth_proxy(&cx, &conductor_tx)?);
//! }
//! components.push(spawn_agent(&cx, &conductor_tx)?);
//! Both constructors also accept an instantiator closure. The closure receives
//! the `InitializeRequest` and returns the possibly modified request together
//! with type-erased connectors for the selected chain:
//!
//! // Return (potentially modified) request and component list
//! Ok((init_req, components))
//! },
//! None,
//! );
//! ```
//! ```ignore
//! use agent_client_protocol::{Client, Conductor, DynConnectTo};
//! use agent_client_protocol_conductor::ConductorImpl;
//!
//! The closure receives:
//! - `cx: &ConnectionTo` - Connection context for spawning components
//! - `conductor_tx: &mpsc::Sender<ConductorMessage>` - Channel for message routing
//! - `init_req: InitializeRequest` - The Initialize request from the editor
//! let conductor = ConductorImpl::new_agent("my-conductor", |init_req| async move {
//! let mut proxies: Vec<DynConnectTo<Conductor>> = Vec::new();
//! if has_auth_capability(&init_req) {
//! proxies.push(DynConnectTo::new(make_auth_proxy()));
//! }
//!
//! And returns:
//! - Modified `InitializeRequest` to forward downstream
//! - `Vec<ConnectionTo>` of spawned components
//! let agent: DynConnectTo<Client> = DynConnectTo::new(make_agent());
//! Ok((init_req, proxies, agent))
//! });
//! ```

use std::sync::Arc;

Expand Down
6 changes: 3 additions & 3 deletions src/agent-client-protocol-conductor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ use tracing_subscriber::{EnvFilter, layer::SubscriberExt, util::SubscriberInitEx
/// Wrapper for command-line component lists that can serve as either
/// proxies-only (for proxy mode) or proxies+agent (for agent mode).
///
/// This exists because `AcpAgent` implements `Component<L>` for all `L`,
/// so a `Vec<AcpAgent>` can be used as either a list of proxies or as
/// proxies + final agent depending on the conductor mode.
/// This exists because `AcpAgent` implements `ConnectTo<Client>` and
/// `ConnectTo<Conductor>`, so a `Vec<AcpAgent>` can be used as either a list
/// of proxies or as proxies + final agent depending on the conductor mode.
#[derive(Debug)]
pub struct CommandLineComponents(pub Vec<AcpAgent>);

Expand Down
12 changes: 10 additions & 2 deletions src/agent-client-protocol-rmcp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,20 @@ ACP-transport MCP servers.
Use the `McpServerExt` trait to build an MCP server with tools:

```rust
use agent_client_protocol::mcp_server::McpServer;
use agent_client_protocol::{ConnectTo, mcp_server::McpServer, role::mcp};
use agent_client_protocol_rmcp::McpServerExt;

let server = McpServer::builder("my-tools").build();
async fn serve(
client_transport: impl ConnectTo<mcp::Server>,
) -> agent_client_protocol::Result<()> {
let server = McpServer::<mcp::Client>::builder("my-tools").build();
server.connect_to(client_transport).await
}
```

Choosing `mcp::Client` as the counterpart makes this a standalone MCP server
that implements `ConnectTo<mcp::Client>`.

Or create an MCP server from an rmcp service:

```rust
Expand Down
11 changes: 8 additions & 3 deletions src/agent-client-protocol-rmcp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,16 @@
//!
//! Build an MCP server with tools using the extension trait:
//!
//! ```ignore
//! use agent_client_protocol::mcp_server::McpServer;
//! ```no_run
//! use agent_client_protocol::{ConnectTo, mcp_server::McpServer, role::mcp};
//! use agent_client_protocol_rmcp::McpServerExt;
//!
//! let server = McpServer::builder("my-tools").build();
//! # async fn serve(
//! # client_transport: impl ConnectTo<mcp::Server>,
//! # ) -> agent_client_protocol::Result<()> {
//! let server = McpServer::<mcp::Client>::builder("my-tools").build();
//! server.connect_to(client_transport).await
//! # }
//! ```
//!
//! Or create an MCP server from an rmcp service:
Expand Down
2 changes: 1 addition & 1 deletion src/agent-client-protocol/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ pub mod __private {
pub use serde_json;
}

// Re-export BoxFuture for implementing Component traits
// Re-export BoxFuture for implementing SDK traits that return boxed futures.
pub use futures::future::BoxFuture;

// Re-export commonly used infrastructure types for convenience
Expand Down