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(skip_serializing_if = "Option::is_none")]
27 pub meta: Option<serde_json::Value>,
28}
29
30impl<M: JsonRpcMessage> JsonRpcMessage for SuccessorMessage<M> {
31 fn matches_method(method: &str) -> bool {
32 method == METHOD_SUCCESSOR_MESSAGE
33 }
34
35 fn method(&self) -> &str {
36 METHOD_SUCCESSOR_MESSAGE
37 }
38
39 fn to_untyped_message(&self) -> Result<UntypedMessage, crate::Error> {
40 UntypedMessage::new(
41 METHOD_SUCCESSOR_MESSAGE,
42 SuccessorMessage {
43 message: self.message.to_untyped_message()?,
44 meta: self.meta.clone(),
45 },
46 )
47 }
48
49 fn parse_message(method: &str, params: &impl Serialize) -> Result<Self, crate::Error> {
50 if method != METHOD_SUCCESSOR_MESSAGE {
51 return Err(crate::Error::method_not_found());
52 }
53 let outer = crate::util::json_cast_params::<_, SuccessorMessage<UntypedMessage>>(params)?;
54 if !M::matches_method(&outer.message.method) {
55 return Err(crate::Error::method_not_found());
56 }
57 let inner = M::parse_message(&outer.message.method, &outer.message.params)?;
58 Ok(SuccessorMessage {
59 message: inner,
60 meta: outer.meta,
61 })
62 }
63}
64
65impl<Req: JsonRpcRequest> JsonRpcRequest for SuccessorMessage<Req> {
66 type Response = Req::Response;
67}
68
69impl<Notif: JsonRpcNotification> JsonRpcNotification for SuccessorMessage<Notif> {}
70
71pub const METHOD_MCP_CONNECT_REQUEST: &str = "_mcp/connect";
77
78#[derive(Debug, Clone, Serialize, Deserialize, crate::JsonRpcRequest)]
80#[request(method = "_mcp/connect", response = McpConnectResponse, crate = crate)]
81pub struct McpConnectRequest {
82 pub acp_url: String,
84
85 #[serde(skip_serializing_if = "Option::is_none")]
87 pub meta: Option<serde_json::Value>,
88}
89
90#[derive(Debug, Clone, Serialize, Deserialize, crate::JsonRpcResponse)]
92#[response(crate = crate)]
93pub struct McpConnectResponse {
94 pub connection_id: String,
96
97 #[serde(skip_serializing_if = "Option::is_none")]
99 pub meta: Option<serde_json::Value>,
100}
101
102pub const METHOD_MCP_DISCONNECT_NOTIFICATION: &str = "_mcp/disconnect";
104
105#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, crate::JsonRpcNotification)]
107#[notification(method = "_mcp/disconnect", crate = crate)]
108pub struct McpDisconnectNotification {
109 pub connection_id: String,
111
112 #[serde(skip_serializing_if = "Option::is_none")]
114 pub meta: Option<serde_json::Value>,
115}
116
117pub const METHOD_MCP_MESSAGE: &str = "_mcp/message";
119
120#[derive(Debug, Clone, Serialize, Deserialize)]
125#[serde(rename_all = "camelCase")]
126pub struct McpOverAcpMessage<M = UntypedMessage> {
127 pub connection_id: String,
129
130 #[serde(flatten)]
132 pub message: M,
133
134 #[serde(skip_serializing_if = "Option::is_none")]
136 pub meta: Option<serde_json::Value>,
137}
138
139impl<M: JsonRpcMessage> JsonRpcMessage for McpOverAcpMessage<M> {
140 fn matches_method(method: &str) -> bool {
141 method == METHOD_MCP_MESSAGE
142 }
143
144 fn method(&self) -> &str {
145 METHOD_MCP_MESSAGE
146 }
147
148 fn to_untyped_message(&self) -> Result<UntypedMessage, crate::Error> {
149 let message = self.message.to_untyped_message()?;
150 UntypedMessage::new(
151 METHOD_MCP_MESSAGE,
152 McpOverAcpMessage {
153 connection_id: self.connection_id.clone(),
154 message,
155 meta: self.meta.clone(),
156 },
157 )
158 }
159
160 fn parse_message(method: &str, params: &impl Serialize) -> Result<Self, crate::Error> {
161 if method != METHOD_MCP_MESSAGE {
162 return Err(crate::Error::method_not_found());
163 }
164 let outer = crate::util::json_cast_params::<_, McpOverAcpMessage<UntypedMessage>>(params)?;
165 if !M::matches_method(&outer.message.method) {
166 return Err(crate::Error::method_not_found());
167 }
168 let inner = M::parse_message(&outer.message.method, &outer.message.params)?;
169 Ok(McpOverAcpMessage {
170 connection_id: outer.connection_id,
171 message: inner,
172 meta: outer.meta,
173 })
174 }
175}
176
177impl<R: JsonRpcRequest> JsonRpcRequest for McpOverAcpMessage<R> {
178 type Response = R::Response;
179}
180
181impl<R: JsonRpcNotification> JsonRpcNotification for McpOverAcpMessage<R> {}
182
183pub const METHOD_INITIALIZE_PROXY: &str = "_proxy/initialize";
189
190#[derive(Debug, Clone, Serialize, Deserialize, crate::JsonRpcRequest)]
196#[request(method = "_proxy/initialize", response = InitializeResponse, crate = crate)]
197pub struct InitializeProxyRequest {
198 #[serde(flatten)]
200 pub initialize: agent_client_protocol_schema::InitializeRequest,
201}
202
203impl From<agent_client_protocol_schema::InitializeRequest> for InitializeProxyRequest {
204 fn from(initialize: agent_client_protocol_schema::InitializeRequest) -> Self {
205 Self { initialize }
206 }
207}