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