agent_client_protocol/schema/
proxy_protocol.rs1use crate::{JsonRpcMessage, JsonRpcNotification, JsonRpcRequest, UntypedMessage};
6use agent_client_protocol_schema::InitializeResponse;
7use serde::{Deserialize, Serialize};
8
9pub const METHOD_SUCCESSOR_MESSAGE: &str = "_proxy/successor";
15
16#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct SuccessorMessage<M: JsonRpcMessage = UntypedMessage> {
21 #[serde(flatten)]
23 pub message: M,
24
25 #[serde(
27 rename = "_meta",
28 alias = "meta",
29 skip_serializing_if = "Option::is_none"
30 )]
31 pub meta: Option<serde_json::Value>,
32}
33
34impl<M: JsonRpcMessage> JsonRpcMessage for SuccessorMessage<M> {
35 fn matches_method(method: &str) -> bool {
36 method == METHOD_SUCCESSOR_MESSAGE
37 }
38
39 fn method(&self) -> &str {
40 METHOD_SUCCESSOR_MESSAGE
41 }
42
43 fn to_untyped_message(&self) -> Result<UntypedMessage, crate::Error> {
44 UntypedMessage::new(
45 METHOD_SUCCESSOR_MESSAGE,
46 SuccessorMessage {
47 message: self.message.to_untyped_message()?,
48 meta: self.meta.clone(),
49 },
50 )
51 }
52
53 fn parse_message(method: &str, params: &impl Serialize) -> Result<Self, crate::Error> {
54 if method != METHOD_SUCCESSOR_MESSAGE {
55 return Err(crate::Error::method_not_found());
56 }
57 let outer = crate::util::json_cast_params::<_, SuccessorMessage<UntypedMessage>>(params)?;
58 if !M::matches_method(&outer.message.method) {
59 return Err(crate::Error::method_not_found());
60 }
61 let inner = M::parse_message(&outer.message.method, &outer.message.params)?;
62 Ok(SuccessorMessage {
63 message: inner,
64 meta: outer.meta,
65 })
66 }
67}
68
69impl<Req: JsonRpcRequest> JsonRpcRequest for SuccessorMessage<Req> {
70 type Response = Req::Response;
71}
72
73impl<Notif: JsonRpcNotification> JsonRpcNotification for SuccessorMessage<Notif> {}
74
75pub const METHOD_MCP_CONNECT_REQUEST: &str = "_mcp/connect";
81
82#[derive(Debug, Clone, Serialize, Deserialize, crate::JsonRpcRequest)]
84#[request(method = "_mcp/connect", response = McpConnectResponse, crate = crate)]
85pub struct McpConnectRequest {
86 pub acp_id: String,
88
89 #[serde(
91 rename = "_meta",
92 alias = "meta",
93 skip_serializing_if = "Option::is_none"
94 )]
95 pub meta: Option<serde_json::Value>,
96}
97
98#[derive(Debug, Clone, Serialize, Deserialize, crate::JsonRpcResponse)]
100#[response(crate = crate)]
101pub struct McpConnectResponse {
102 pub connection_id: String,
104
105 #[serde(
107 rename = "_meta",
108 alias = "meta",
109 skip_serializing_if = "Option::is_none"
110 )]
111 pub meta: Option<serde_json::Value>,
112}
113
114pub const METHOD_MCP_DISCONNECT_NOTIFICATION: &str = "_mcp/disconnect";
116
117#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, crate::JsonRpcNotification)]
119#[notification(method = "_mcp/disconnect", crate = crate)]
120pub struct McpDisconnectNotification {
121 pub connection_id: String,
123
124 #[serde(
126 rename = "_meta",
127 alias = "meta",
128 skip_serializing_if = "Option::is_none"
129 )]
130 pub meta: Option<serde_json::Value>,
131}
132
133pub const METHOD_MCP_MESSAGE: &str = "_mcp/message";
135
136#[derive(Debug, Clone, Serialize, Deserialize)]
141#[serde(rename_all = "camelCase")]
142pub struct McpOverAcpMessage<M = UntypedMessage> {
143 pub connection_id: String,
145
146 #[serde(flatten)]
148 pub message: M,
149
150 #[serde(
152 rename = "_meta",
153 alias = "meta",
154 skip_serializing_if = "Option::is_none"
155 )]
156 pub meta: Option<serde_json::Value>,
157}
158
159impl<M: JsonRpcMessage> JsonRpcMessage for McpOverAcpMessage<M> {
160 fn matches_method(method: &str) -> bool {
161 method == METHOD_MCP_MESSAGE
162 }
163
164 fn method(&self) -> &str {
165 METHOD_MCP_MESSAGE
166 }
167
168 fn to_untyped_message(&self) -> Result<UntypedMessage, crate::Error> {
169 let message = self.message.to_untyped_message()?;
170 UntypedMessage::new(
171 METHOD_MCP_MESSAGE,
172 McpOverAcpMessage {
173 connection_id: self.connection_id.clone(),
174 message,
175 meta: self.meta.clone(),
176 },
177 )
178 }
179
180 fn parse_message(method: &str, params: &impl Serialize) -> Result<Self, crate::Error> {
181 if method != METHOD_MCP_MESSAGE {
182 return Err(crate::Error::method_not_found());
183 }
184 let outer = crate::util::json_cast_params::<_, McpOverAcpMessage<UntypedMessage>>(params)?;
185 if !M::matches_method(&outer.message.method) {
186 return Err(crate::Error::method_not_found());
187 }
188 let inner = M::parse_message(&outer.message.method, &outer.message.params)?;
189 Ok(McpOverAcpMessage {
190 connection_id: outer.connection_id,
191 message: inner,
192 meta: outer.meta,
193 })
194 }
195}
196
197impl<R: JsonRpcRequest> JsonRpcRequest for McpOverAcpMessage<R> {
198 type Response = R::Response;
199}
200
201impl<R: JsonRpcNotification> JsonRpcNotification for McpOverAcpMessage<R> {}
202
203pub const METHOD_INITIALIZE_PROXY: &str = "_proxy/initialize";
209
210#[derive(Debug, Clone, Serialize, Deserialize, crate::JsonRpcRequest)]
216#[request(method = "_proxy/initialize", response = InitializeResponse, crate = crate)]
217pub struct InitializeProxyRequest {
218 #[serde(flatten)]
220 pub initialize: agent_client_protocol_schema::InitializeRequest,
221}
222
223impl From<agent_client_protocol_schema::InitializeRequest> for InitializeProxyRequest {
224 fn from(initialize: agent_client_protocol_schema::InitializeRequest) -> Self {
225 Self { initialize }
226 }
227}