Skip to main content

agent_client_protocol/mcp_server/
connect.rs

1use std::sync::Arc;
2
3use crate::{
4    DynConnectTo,
5    mcp_server::McpConnectionTo,
6    role::{self, Role},
7};
8
9/// Trait for types that can create MCP server connections.
10///
11/// Implement this trait to create custom MCP servers. Each call to [`connect`](Self::connect)
12/// should return a new [`ConnectTo`](crate::ConnectTo) that serves MCP requests for a single
13/// connection.
14///
15/// # Example
16///
17/// ```rust,ignore
18/// use agent_client_protocol::mcp_server::{McpServerConnect, McpConnectionTo};
19/// use agent_client_protocol::{DynConnectTo, role::Role};
20///
21/// struct MyMcpServer {
22///     name: String,
23/// }
24///
25/// impl<R: Role> McpServerConnect<R> for MyMcpServer {
26///     fn name(&self) -> String {
27///         self.name.clone()
28///     }
29///
30///     fn connect(&self, cx: McpConnectionTo<R>) -> DynConnectTo<role::mcp::Client> {
31///         // Create and return a component that handles MCP requests
32///         DynConnectTo::new(MyMcpComponent::new(cx))
33///     }
34/// }
35/// ```
36pub trait McpServerConnect<Counterpart: Role>: Send + Sync + 'static {
37    /// The name of the MCP server, used in ACP declarations when attached.
38    fn name(&self) -> String;
39
40    /// Create a component to service a standalone connection or a native operation.
41    ///
42    /// Standalone serving invokes this factory once per connection. Native ACP
43    /// invokes it independently for each `mcp/message` operation. A native
44    /// component receives an MCP 2026-07-28 request directly; it must not wait
45    /// for `initialize` or share protocol state with a previous operation.
46    /// Prefer `McpService` for reusable native application services.
47    ///
48    /// Any communication primitives shared with the server's
49    /// [`RunWithConnectionTo`](crate::RunWithConnectionTo) task must be created
50    /// before the [`McpServer`](super::McpServer) is returned. The runner has no
51    /// separate readiness protocol and may continue asynchronous initialization
52    /// while connections and their messages are queued.
53    ///
54    /// [`McpConnectionTo`] distinguishes a direct MCP connection from an
55    /// ACP-attached operation and provides the corresponding host connection.
56    fn connect(&self, cx: McpConnectionTo<Counterpart>) -> DynConnectTo<role::mcp::Client>;
57}
58
59impl<Counterpart: Role, S: ?Sized + McpServerConnect<Counterpart>> McpServerConnect<Counterpart>
60    for Box<S>
61{
62    fn name(&self) -> String {
63        S::name(self)
64    }
65
66    fn connect(&self, cx: McpConnectionTo<Counterpart>) -> DynConnectTo<role::mcp::Client> {
67        S::connect(self, cx)
68    }
69}
70
71impl<Counterpart: Role, S: ?Sized + McpServerConnect<Counterpart>> McpServerConnect<Counterpart>
72    for Arc<S>
73{
74    fn name(&self) -> String {
75        S::name(self)
76    }
77
78    fn connect(&self, cx: McpConnectionTo<Counterpart>) -> DynConnectTo<role::mcp::Client> {
79        S::connect(self, cx)
80    }
81}