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