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