|
| 1 | +#![deny(missing_docs)] |
| 2 | + |
| 3 | +//! # sacp-proxy |
| 4 | +//! |
| 5 | +//! Framework for building ACP proxy components that extend agent functionality. |
| 6 | +//! |
| 7 | +//! ## What are proxies? |
| 8 | +//! |
| 9 | +//! Proxies are modular components that sit between an editor and an agent, intercepting and transforming messages. |
| 10 | +//! They enable **composable agent architectures** where functionality can be added without modifying the base agent. |
| 11 | +//! |
| 12 | +//! ```text |
| 13 | +//! Editor → Proxy 1 → Proxy 2 → Agent |
| 14 | +//! ``` |
| 15 | +//! |
| 16 | +//! Use cases: |
| 17 | +//! - Add MCP tools/resources/prompts to any agent |
| 18 | +//! - Inject context or modify prompts before they reach the agent |
| 19 | +//! - Filter or transform agent responses |
| 20 | +//! - Add logging, metrics, or policy enforcement |
| 21 | +//! |
| 22 | +//! ## Quick Start |
| 23 | +//! |
| 24 | +//! The simplest proxy just forwards messages unchanged: |
| 25 | +//! |
| 26 | +//! ```rust,no_run |
| 27 | +//! use sacp::JrConnection; |
| 28 | +//! use sacp_proxy::{AcpProxyExt, McpServiceRegistry}; |
| 29 | +//! use tokio_util::compat::{TokioAsyncReadCompatExt, TokioAsyncWriteCompatExt}; |
| 30 | +//! |
| 31 | +//! # #[tokio::main] |
| 32 | +//! # async fn main() -> Result<(), Box<dyn std::error::Error>> { |
| 33 | +//! JrConnection::new( |
| 34 | +//! tokio::io::stdout().compat_write(), |
| 35 | +//! tokio::io::stdin().compat() |
| 36 | +//! ) |
| 37 | +//! .name("my-proxy") |
| 38 | +//! .provide_mcp(McpServiceRegistry::default()) // Provide MCP services |
| 39 | +//! .proxy() // Enable proxy mode |
| 40 | +//! .serve() |
| 41 | +//! .await?; |
| 42 | +//! # Ok(()) |
| 43 | +//! # } |
| 44 | +//! ``` |
| 45 | +//! |
| 46 | +//! To add MCP tools to the proxy, provide an MCP server: |
| 47 | +//! |
| 48 | +//! ```rust,no_run |
| 49 | +//! use sacp::JrConnection; |
| 50 | +//! use sacp_proxy::{AcpProxyExt, McpServiceRegistry}; |
| 51 | +//! use tokio_util::compat::{TokioAsyncReadCompatExt, TokioAsyncWriteCompatExt}; |
| 52 | +//! |
| 53 | +//! # #[tokio::main] |
| 54 | +//! # async fn main() -> Result<(), Box<dyn std::error::Error>> { |
| 55 | +//! JrConnection::new( |
| 56 | +//! tokio::io::stdout().compat_write(), |
| 57 | +//! tokio::io::stdin().compat() |
| 58 | +//! ) |
| 59 | +//! .name("my-proxy") |
| 60 | +//! // Add MCP servers to provide tools/resources/prompts |
| 61 | +//! .provide_mcp( |
| 62 | +//! McpServiceRegistry::default() |
| 63 | +//! // .with_rmcp_server("my-server", || MyMcpServer::new())? |
| 64 | +//! ) |
| 65 | +//! .proxy() |
| 66 | +//! .serve() |
| 67 | +//! .await?; |
| 68 | +//! # Ok(()) |
| 69 | +//! # } |
| 70 | +//! ``` |
| 71 | +//! |
| 72 | +//! See the `with_mcp_server.rs` example for a complete implementation. |
| 73 | +//! |
| 74 | +//! ## Key Concepts |
| 75 | +//! |
| 76 | +//! **Predecessor vs Successor:** |
| 77 | +//! - **Predecessor** - The component closer to the editor (could be editor or another proxy) |
| 78 | +//! - **Successor** - The component farther from the editor (could be agent or another proxy) |
| 79 | +//! |
| 80 | +//! Messages flow: `Predecessor → This Proxy → Successor` |
| 81 | +//! |
| 82 | +//! **Extension Traits:** |
| 83 | +//! - [`AcpProxyExt`] - Adds proxy-specific methods to [`JrConnection`](sacp::JrConnection) |
| 84 | +//! - [`JrCxExt`] - Adds forwarding methods (`send_to_predecessor`, `send_to_successor`) |
| 85 | +//! |
| 86 | +//! ## Examples |
| 87 | +//! |
| 88 | +//! See the [examples directory](https://github.com/symposium-org/symposium-acp/tree/main/src/sacp-proxy/examples): |
| 89 | +//! |
| 90 | +//! - **[`minimal.rs`](https://github.com/symposium-org/symposium-acp/blob/main/src/sacp-proxy/examples/minimal.rs)** - Simplest possible proxy that forwards everything unchanged |
| 91 | +//! - **[`with_mcp_server.rs`](https://github.com/symposium-org/symposium-acp/blob/main/src/sacp-proxy/examples/with_mcp_server.rs)** - Proxy that adds MCP tools to any agent |
| 92 | +//! |
| 93 | +//! ## How Proxies Work |
| 94 | +//! |
| 95 | +//! When you call `.proxy()`, the framework: |
| 96 | +//! 1. Handles capability negotiation with predecessor and successor |
| 97 | +//! 2. Sets up message routing between components |
| 98 | +//! 3. Wraps your handlers to intercept specific message types |
| 99 | +//! 4. Forwards everything else automatically |
| 100 | +//! |
| 101 | +//! You only need to handle the messages you want to intercept or transform. |
| 102 | +//! |
| 103 | +//! ## Related Crates |
| 104 | +//! |
| 105 | +//! - **[sacp](https://crates.io/crates/sacp)** - Core ACP SDK |
| 106 | +//! - **[sacp-conductor](https://crates.io/crates/sacp-conductor)** - Binary for orchestrating proxy chains |
| 107 | +//! - **[sacp-tokio](https://crates.io/crates/sacp-tokio)** - Tokio utilities for spawning agents |
| 108 | +
|
1 | 109 | /// Proxying MCP messages over ACP. |
2 | 110 | mod mcp_over_acp; |
3 | 111 | pub use mcp_over_acp::*; |
|
0 commit comments