use crate::{JsonRpcMessage, JsonRpcNotification, JsonRpcRequest, UntypedMessage};
use agent_client_protocol_schema::InitializeResponse;
use serde::{Deserialize, Serialize};
pub const METHOD_SUCCESSOR_MESSAGE: &str = "_proxy/successor";
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SuccessorMessage<M: JsonRpcMessage = UntypedMessage> {
#[serde(flatten)]
pub message: M,
#[serde(skip_serializing_if = "Option::is_none")]
pub meta: Option<serde_json::Value>,
}
impl<M: JsonRpcMessage> JsonRpcMessage for SuccessorMessage<M> {
fn matches_method(method: &str) -> bool {
method == METHOD_SUCCESSOR_MESSAGE
}
fn method(&self) -> &str {
METHOD_SUCCESSOR_MESSAGE
}
fn to_untyped_message(&self) -> Result<UntypedMessage, crate::Error> {
UntypedMessage::new(
METHOD_SUCCESSOR_MESSAGE,
SuccessorMessage {
message: self.message.to_untyped_message()?,
meta: self.meta.clone(),
},
)
}
fn parse_message(method: &str, params: &impl Serialize) -> Result<Self, crate::Error> {
if method != METHOD_SUCCESSOR_MESSAGE {
return Err(crate::Error::method_not_found());
}
let outer = crate::util::json_cast_params::<_, SuccessorMessage<UntypedMessage>>(params)?;
if !M::matches_method(&outer.message.method) {
return Err(crate::Error::method_not_found());
}
let inner = M::parse_message(&outer.message.method, &outer.message.params)?;
Ok(SuccessorMessage {
message: inner,
meta: outer.meta,
})
}
}
impl<Req: JsonRpcRequest> JsonRpcRequest for SuccessorMessage<Req> {
type Response = Req::Response;
}
impl<Notif: JsonRpcNotification> JsonRpcNotification for SuccessorMessage<Notif> {}
pub const METHOD_MCP_CONNECT_REQUEST: &str = "_mcp/connect";
#[derive(Debug, Clone, Serialize, Deserialize, crate::JsonRpcRequest)]
#[request(method = "_mcp/connect", response = McpConnectResponse, crate = crate)]
pub struct McpConnectRequest {
pub acp_url: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub meta: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize, crate::JsonRpcResponse)]
#[response(crate = crate)]
pub struct McpConnectResponse {
pub connection_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub meta: Option<serde_json::Value>,
}
pub const METHOD_MCP_DISCONNECT_NOTIFICATION: &str = "_mcp/disconnect";
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, crate::JsonRpcNotification)]
#[notification(method = "_mcp/disconnect", crate = crate)]
pub struct McpDisconnectNotification {
pub connection_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub meta: Option<serde_json::Value>,
}
pub const METHOD_MCP_MESSAGE: &str = "_mcp/message";
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct McpOverAcpMessage<M = UntypedMessage> {
pub connection_id: String,
#[serde(flatten)]
pub message: M,
#[serde(skip_serializing_if = "Option::is_none")]
pub meta: Option<serde_json::Value>,
}
impl<M: JsonRpcMessage> JsonRpcMessage for McpOverAcpMessage<M> {
fn matches_method(method: &str) -> bool {
method == METHOD_MCP_MESSAGE
}
fn method(&self) -> &str {
METHOD_MCP_MESSAGE
}
fn to_untyped_message(&self) -> Result<UntypedMessage, crate::Error> {
let message = self.message.to_untyped_message()?;
UntypedMessage::new(
METHOD_MCP_MESSAGE,
McpOverAcpMessage {
connection_id: self.connection_id.clone(),
message,
meta: self.meta.clone(),
},
)
}
fn parse_message(method: &str, params: &impl Serialize) -> Result<Self, crate::Error> {
if method != METHOD_MCP_MESSAGE {
return Err(crate::Error::method_not_found());
}
let outer = crate::util::json_cast_params::<_, McpOverAcpMessage<UntypedMessage>>(params)?;
if !M::matches_method(&outer.message.method) {
return Err(crate::Error::method_not_found());
}
let inner = M::parse_message(&outer.message.method, &outer.message.params)?;
Ok(McpOverAcpMessage {
connection_id: outer.connection_id,
message: inner,
meta: outer.meta,
})
}
}
impl<R: JsonRpcRequest> JsonRpcRequest for McpOverAcpMessage<R> {
type Response = R::Response;
}
impl<R: JsonRpcNotification> JsonRpcNotification for McpOverAcpMessage<R> {}
pub const METHOD_INITIALIZE_PROXY: &str = "_proxy/initialize";
#[derive(Debug, Clone, Serialize, Deserialize, crate::JsonRpcRequest)]
#[request(method = "_proxy/initialize", response = InitializeResponse, crate = crate)]
pub struct InitializeProxyRequest {
#[serde(flatten)]
pub initialize: agent_client_protocol_schema::InitializeRequest,
}
impl From<agent_client_protocol_schema::InitializeRequest> for InitializeProxyRequest {
fn from(initialize: agent_client_protocol_schema::InitializeRequest) -> Self {
Self { initialize }
}
}