Skip to main content

agent_client_protocol_schema/v1/
mcp.rs

1//! MCP-over-ACP transport types.
2
3use std::sync::Arc;
4
5use derive_more::{Display, From};
6use schemars::JsonSchema;
7use serde::{Deserialize, Serialize};
8use serde_json::value::RawValue;
9use serde_with::skip_serializing_none;
10
11use crate::IntoOption;
12
13use super::{McpServerAcpId, Meta};
14
15/// **UNSTABLE**
16///
17/// This capability is not part of the spec yet, and may be removed or changed at any point.
18///
19/// A unique identifier for an active MCP-over-ACP connection.
20#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
21#[serde(transparent)]
22#[from(Arc<str>, String, &'static str)]
23#[non_exhaustive]
24pub struct McpConnectionId(pub Arc<str>);
25
26impl McpConnectionId {
27    /// Wraps a protocol string as a typed [`McpConnectionId`].
28    #[must_use]
29    pub fn new(id: impl Into<Arc<str>>) -> Self {
30        Self(id.into())
31    }
32}
33
34/// **UNSTABLE**
35///
36/// This capability is not part of the spec yet, and may be removed or changed at any point.
37///
38/// Request parameters for `mcp/connect`.
39#[skip_serializing_none]
40#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
41#[serde(rename_all = "camelCase")]
42#[schemars(extend("x-side" = "client", "x-method" = MCP_CONNECT_METHOD_NAME))]
43#[non_exhaustive]
44pub struct ConnectMcpRequest {
45    /// The ACP MCP server ID that was provided by the component declaring the MCP server.
46    pub acp_id: McpServerAcpId,
47    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
48    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
49    /// these keys.
50    ///
51    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
52    #[serde(rename = "_meta")]
53    pub meta: Option<Meta>,
54}
55
56impl ConnectMcpRequest {
57    /// Builds [`ConnectMcpRequest`] with the required request fields set; optional fields start unset or empty.
58    #[must_use]
59    pub fn new(acp_id: impl Into<McpServerAcpId>) -> Self {
60        Self {
61            acp_id: acp_id.into(),
62            meta: None,
63        }
64    }
65
66    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
67    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
68    /// these keys.
69    ///
70    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
71    #[must_use]
72    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
73        self.meta = meta.into_option();
74        self
75    }
76}
77
78/// **UNSTABLE**
79///
80/// This capability is not part of the spec yet, and may be removed or changed at any point.
81///
82/// Response to `mcp/connect`.
83#[skip_serializing_none]
84#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
85#[serde(rename_all = "camelCase")]
86#[schemars(extend("x-side" = "client", "x-method" = MCP_CONNECT_METHOD_NAME))]
87#[non_exhaustive]
88pub struct ConnectMcpResponse {
89    /// The unique identifier for this MCP-over-ACP connection.
90    pub connection_id: McpConnectionId,
91    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
92    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
93    /// these keys.
94    ///
95    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
96    #[serde(rename = "_meta")]
97    pub meta: Option<Meta>,
98}
99
100impl ConnectMcpResponse {
101    /// Builds [`ConnectMcpResponse`] with the required response fields set; optional fields start unset or empty.
102    #[must_use]
103    pub fn new(connection_id: impl Into<McpConnectionId>) -> Self {
104        Self {
105            connection_id: connection_id.into(),
106            meta: None,
107        }
108    }
109
110    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
111    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
112    /// these keys.
113    ///
114    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
115    #[must_use]
116    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
117        self.meta = meta.into_option();
118        self
119    }
120}
121
122/// **UNSTABLE**
123///
124/// This capability is not part of the spec yet, and may be removed or changed at any point.
125///
126/// Request parameters for `mcp/message`.
127#[skip_serializing_none]
128#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
129#[serde(rename_all = "camelCase")]
130#[schemars(extend("x-side" = "both", "x-method" = MCP_MESSAGE_METHOD_NAME))]
131#[non_exhaustive]
132pub struct MessageMcpRequest {
133    /// The MCP-over-ACP connection this message is sent on.
134    pub connection_id: McpConnectionId,
135    /// The inner MCP method name.
136    pub method: String,
137    /// Optional inner MCP params.
138    ///
139    /// If omitted or set to `null`, the inner MCP message has no params.
140    #[serde(default)]
141    pub params: Option<serde_json::Map<String, serde_json::Value>>,
142    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
143    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
144    /// these keys.
145    ///
146    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
147    #[serde(rename = "_meta")]
148    pub meta: Option<Meta>,
149}
150
151impl MessageMcpRequest {
152    /// Builds [`MessageMcpRequest`] with the required request fields set; optional fields start unset or empty.
153    #[must_use]
154    pub fn new(connection_id: impl Into<McpConnectionId>, method: impl Into<String>) -> Self {
155        Self {
156            connection_id: connection_id.into(),
157            method: method.into(),
158            params: None,
159            meta: None,
160        }
161    }
162
163    /// Optional inner MCP params.
164    ///
165    /// If omitted or set to `null`, the inner MCP message has no params.
166    #[must_use]
167    pub fn params(
168        mut self,
169        params: impl IntoOption<serde_json::Map<String, serde_json::Value>>,
170    ) -> Self {
171        self.params = params.into_option();
172        self
173    }
174
175    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
176    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
177    /// these keys.
178    ///
179    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
180    #[must_use]
181    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
182        self.meta = meta.into_option();
183        self
184    }
185}
186
187/// **UNSTABLE**
188///
189/// This capability is not part of the spec yet, and may be removed or changed at any point.
190///
191/// Notification parameters for `mcp/message`.
192///
193/// This is used when the wrapped MCP message is a notification and the outer JSON-RPC
194/// envelope has no `id`.
195#[skip_serializing_none]
196#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
197#[serde(rename_all = "camelCase")]
198#[schemars(extend("x-side" = "both", "x-method" = MCP_MESSAGE_METHOD_NAME))]
199#[non_exhaustive]
200pub struct MessageMcpNotification {
201    /// The MCP-over-ACP connection this message is sent on.
202    pub connection_id: McpConnectionId,
203    /// The inner MCP method name.
204    pub method: String,
205    /// Optional inner MCP params.
206    ///
207    /// If omitted or set to `null`, the inner MCP message has no params.
208    #[serde(default)]
209    pub params: Option<serde_json::Map<String, serde_json::Value>>,
210    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
211    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
212    /// these keys.
213    ///
214    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
215    #[serde(rename = "_meta")]
216    pub meta: Option<Meta>,
217}
218
219impl MessageMcpNotification {
220    /// Builds [`MessageMcpNotification`] with the required notification fields set; optional fields start unset or empty.
221    #[must_use]
222    pub fn new(connection_id: impl Into<McpConnectionId>, method: impl Into<String>) -> Self {
223        Self {
224            connection_id: connection_id.into(),
225            method: method.into(),
226            params: None,
227            meta: None,
228        }
229    }
230
231    /// Optional inner MCP params.
232    ///
233    /// If omitted or set to `null`, the inner MCP message has no params.
234    #[must_use]
235    pub fn params(
236        mut self,
237        params: impl IntoOption<serde_json::Map<String, serde_json::Value>>,
238    ) -> Self {
239        self.params = params.into_option();
240        self
241    }
242
243    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
244    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
245    /// these keys.
246    ///
247    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
248    #[must_use]
249    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
250        self.meta = meta.into_option();
251        self
252    }
253}
254
255/// **UNSTABLE**
256///
257/// This capability is not part of the spec yet, and may be removed or changed at any point.
258///
259/// Response to `mcp/message`.
260///
261/// This is the inner MCP response result payload. Any JSON value is valid.
262#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, From)]
263#[serde(transparent)]
264#[schemars(extend("x-side" = "both", "x-method" = MCP_MESSAGE_METHOD_NAME))]
265#[non_exhaustive]
266pub struct MessageMcpResponse(#[schemars(with = "serde_json::Value")] pub Arc<RawValue>);
267
268impl MessageMcpResponse {
269    /// Builds [`MessageMcpResponse`] with the required response fields set; optional fields start unset or empty.
270    #[must_use]
271    pub fn new(result: Arc<RawValue>) -> Self {
272        Self(result)
273    }
274}
275
276/// **UNSTABLE**
277///
278/// This capability is not part of the spec yet, and may be removed or changed at any point.
279///
280/// Request parameters for `mcp/disconnect`.
281#[skip_serializing_none]
282#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
283#[serde(rename_all = "camelCase")]
284#[schemars(extend("x-side" = "client", "x-method" = MCP_DISCONNECT_METHOD_NAME))]
285#[non_exhaustive]
286pub struct DisconnectMcpRequest {
287    /// The MCP-over-ACP connection to close.
288    pub connection_id: McpConnectionId,
289    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
290    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
291    /// these keys.
292    ///
293    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
294    #[serde(rename = "_meta")]
295    pub meta: Option<Meta>,
296}
297
298impl DisconnectMcpRequest {
299    /// Builds [`DisconnectMcpRequest`] with the required request fields set; optional fields start unset or empty.
300    #[must_use]
301    pub fn new(connection_id: impl Into<McpConnectionId>) -> Self {
302        Self {
303            connection_id: connection_id.into(),
304            meta: None,
305        }
306    }
307
308    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
309    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
310    /// these keys.
311    ///
312    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
313    #[must_use]
314    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
315        self.meta = meta.into_option();
316        self
317    }
318}
319
320/// **UNSTABLE**
321///
322/// This capability is not part of the spec yet, and may be removed or changed at any point.
323///
324/// Response to `mcp/disconnect`.
325#[skip_serializing_none]
326#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
327#[serde(rename_all = "camelCase")]
328#[schemars(extend("x-side" = "client", "x-method" = MCP_DISCONNECT_METHOD_NAME))]
329#[non_exhaustive]
330pub struct DisconnectMcpResponse {
331    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
332    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
333    /// these keys.
334    ///
335    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
336    #[serde(rename = "_meta")]
337    pub meta: Option<Meta>,
338}
339
340impl DisconnectMcpResponse {
341    /// Builds [`DisconnectMcpResponse`] with the required response fields set; optional fields start unset or empty.
342    #[must_use]
343    pub fn new() -> Self {
344        Self::default()
345    }
346
347    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
348    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
349    /// these keys.
350    ///
351    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
352    #[must_use]
353    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
354        self.meta = meta.into_option();
355        self
356    }
357}
358
359/// Method name for opening an MCP-over-ACP connection.
360pub(crate) const MCP_CONNECT_METHOD_NAME: &str = "mcp/connect";
361/// Method name for exchanging MCP-over-ACP messages.
362pub(crate) const MCP_MESSAGE_METHOD_NAME: &str = "mcp/message";
363/// Method name for closing an MCP-over-ACP connection.
364pub(crate) const MCP_DISCONNECT_METHOD_NAME: &str = "mcp/disconnect";