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