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";