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