Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 5 additions & 12 deletions agent-client-protocol-schema/src/serde_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,6 @@ mod default_on_null_tests {
$check::<v1::StartNesRequest>();
$check::<v1::CloseNesResponse>();
}
#[cfg(feature = "unstable_mcp_over_acp")]
{
$check::<v1::DisconnectMcpResponse>();
}

#[cfg(feature = "unstable_protocol_v2")]
{
Expand All @@ -163,10 +159,6 @@ mod default_on_null_tests {
$check::<v2::StartNesRequest>();
$check::<v2::CloseNesResponse>();
}
#[cfg(feature = "unstable_mcp_over_acp")]
{
$check::<v2::DisconnectMcpResponse>();
}
}
};
}
Expand Down Expand Up @@ -355,8 +347,9 @@ mod default_on_null_tests {

#[cfg(feature = "unstable_mcp_over_acp")]
{
let mcp: v1::MessageMcpResponse = serde_json::from_value(Value::Null).unwrap();
assert_eq!(serde_json::to_value(mcp).unwrap(), Value::Null);
let mcp: v1::MessageMcpResponse =
serde_json::from_value(json!({"result": null})).unwrap();
assert_eq!(serde_json::to_value(mcp).unwrap(), json!({"result": null}));
}

#[cfg(feature = "unstable_protocol_v2")]
Expand All @@ -367,8 +360,8 @@ mod default_on_null_tests {
#[cfg(feature = "unstable_mcp_over_acp")]
{
let mcp: crate::v2::MessageMcpResponse =
serde_json::from_value(Value::Null).unwrap();
assert_eq!(serde_json::to_value(mcp).unwrap(), Value::Null);
serde_json::from_value(json!({"result": null})).unwrap();
assert_eq!(serde_json::to_value(mcp).unwrap(), json!({"result": null}));
}
}
}
Expand Down
52 changes: 26 additions & 26 deletions agent-client-protocol-schema/src/v1/agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@ use super::{
};

#[cfg(feature = "unstable_mcp_over_acp")]
use super::mcp::{
MCP_MESSAGE_METHOD_NAME, MessageMcpNotification, MessageMcpRequest, MessageMcpResponse,
};
use super::mcp::{MCP_MESSAGE_METHOD_NAME, MessageMcpNotification};

#[cfg(feature = "unstable_nes")]
use super::{
Expand Down Expand Up @@ -2796,8 +2794,7 @@ impl McpServerSse {
/// Unique identifier for an MCP server using the ACP transport.
///
/// The value is opaque and generated by the ACP component providing the MCP server. It is
/// used by `mcp/connect` to route connection requests back to the component that declared the
/// server.
/// used by `mcp/message` to route requests to the component that declared the server.
#[cfg(feature = "unstable_mcp_over_acp")]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Display, From)]
Expand All @@ -2822,7 +2819,7 @@ impl McpServerAcpId {
/// ACP transport configuration for MCP.
///
/// The MCP server is provided by an ACP component and communicates over the ACP channel
/// using `mcp/connect`, `mcp/message`, and `mcp/disconnect`.
/// using `mcp/message`.
#[serde_as]
#[skip_serializing_none]
#[cfg(feature = "unstable_mcp_over_acp")]
Expand Down Expand Up @@ -4962,13 +4959,6 @@ pub enum ClientRequest {
/// The agent must cancel any ongoing work and then free up any resources
/// associated with the NES session.
CloseNesRequest(CloseNesRequest),
/// **UNSTABLE**
///
/// This capability is not part of the spec yet, and may be removed or changed at any point.
///
/// Exchanges an MCP-over-ACP message.
#[cfg(feature = "unstable_mcp_over_acp")]
MessageMcpRequest(MessageMcpRequest),
/// Handles extension method requests from the client.
///
/// Extension methods provide a way to add custom functionality while maintaining
Expand Down Expand Up @@ -5009,8 +4999,6 @@ impl ClientRequest {
Self::SuggestNesRequest(_) => AGENT_METHOD_NAMES.nes_suggest,
#[cfg(feature = "unstable_nes")]
Self::CloseNesRequest(_) => AGENT_METHOD_NAMES.nes_close,
#[cfg(feature = "unstable_mcp_over_acp")]
Self::MessageMcpRequest(_) => AGENT_METHOD_NAMES.mcp_message,
Self::ExtMethodRequest(ext_request) => &ext_request.method,
}
}
Expand Down Expand Up @@ -5076,9 +5064,6 @@ pub enum AgentResponse {
CloseNesResponse(#[serde(default)] CloseNesResponse),
/// Successful result returned by an extension method outside the core ACP method set.
ExtMethodResponse(ExtResponse),
/// Successful result returned by an MCP-over-ACP `mcp/message` request.
#[cfg(feature = "unstable_mcp_over_acp")]
MessageMcpResponse(MessageMcpResponse),
}

/// All possible notifications that a client can send to an agent.
Expand Down Expand Up @@ -5420,21 +5405,36 @@ mod test_serialization {
#[cfg(feature = "unstable_mcp_over_acp")]
#[test]
fn test_client_mcp_message_method_names() {
use serde_json::json;

assert_eq!(AGENT_METHOD_NAMES.mcp_message, "mcp/message");

let notification =
MessageMcpNotification::new("server-1", "req-1", "notifications/progress");
assert_eq!(
ClientRequest::MessageMcpRequest(MessageMcpRequest::new("conn-1", "tools/list"))
.method(),
ClientNotification::MessageMcpNotification(notification.clone()).method(),
"mcp/message"
);
assert_eq!(
ClientNotification::MessageMcpNotification(MessageMcpNotification::new(
"conn-1",
"notifications/progress"
))
.method(),
"mcp/message"
serde_json::to_value(notification).unwrap(),
json!({
"serverId": "server-1",
"requestId": "req-1",
"method": "notifications/progress"
})
);
let notification: MessageMcpNotification = serde_json::from_value(json!({
"serverId": "server-1", "requestId": "req-1", "method": "notifications/progress",
"params": null, "_meta": null
}))
.unwrap();
assert_eq!(notification.params, None);
assert_eq!(notification.meta, None);
for key in ["serverId", "requestId", "method"] {
let mut value = json!({"serverId":"server-1", "requestId":"req-1", "method":"notifications/progress"});
value.as_object_mut().unwrap().remove(key);
assert!(serde_json::from_value::<MessageMcpNotification>(value).is_err());
}
}

#[cfg(all(feature = "unstable_mcp_over_acp", feature = "schemars"))]
Expand Down
124 changes: 28 additions & 96 deletions agent-client-protocol-schema/src/v1/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,7 @@ use super::{
use super::{PlanCapabilities, PlanRemoved, PlanUpdate};

#[cfg(feature = "unstable_mcp_over_acp")]
use super::mcp::{
ConnectMcpRequest, ConnectMcpResponse, DisconnectMcpRequest, DisconnectMcpResponse,
MCP_CONNECT_METHOD_NAME, MCP_DISCONNECT_METHOD_NAME, MCP_MESSAGE_METHOD_NAME,
MessageMcpNotification, MessageMcpRequest, MessageMcpResponse,
};
use super::mcp::{MCP_MESSAGE_METHOD_NAME, MessageMcpRequest, MessageMcpResponse};

#[cfg(feature = "unstable_nes")]
use super::{ClientNesCapabilities, PositionEncodingKind};
Expand Down Expand Up @@ -2649,15 +2645,9 @@ pub struct ClientMethodNames {
pub terminal_wait_for_exit: &'static str,
/// Method for killing a terminal.
pub terminal_kill: &'static str,
/// Method for opening an MCP-over-ACP connection.
#[cfg(feature = "unstable_mcp_over_acp")]
pub mcp_connect: &'static str,
/// Method for exchanging MCP-over-ACP messages.
#[cfg(feature = "unstable_mcp_over_acp")]
pub mcp_message: &'static str,
/// Method for closing an MCP-over-ACP connection.
#[cfg(feature = "unstable_mcp_over_acp")]
pub mcp_disconnect: &'static str,
/// Method for elicitation.
pub elicitation_create: &'static str,
/// Notification for elicitation completion.
Expand All @@ -2676,11 +2666,7 @@ pub const CLIENT_METHOD_NAMES: ClientMethodNames = ClientMethodNames {
terminal_wait_for_exit: TERMINAL_WAIT_FOR_EXIT_METHOD_NAME,
terminal_kill: TERMINAL_KILL_METHOD_NAME,
#[cfg(feature = "unstable_mcp_over_acp")]
mcp_connect: MCP_CONNECT_METHOD_NAME,
#[cfg(feature = "unstable_mcp_over_acp")]
mcp_message: MCP_MESSAGE_METHOD_NAME,
#[cfg(feature = "unstable_mcp_over_acp")]
mcp_disconnect: MCP_DISCONNECT_METHOD_NAME,
elicitation_create: ELICITATION_CREATE_METHOD_NAME,
elicitation_complete: ELICITATION_COMPLETE_NOTIFICATION,
};
Expand Down Expand Up @@ -2806,23 +2792,9 @@ pub enum AgentRequest {
///
/// This capability is not part of the spec yet, and may be removed or changed at any point.
///
/// Opens an MCP-over-ACP connection.
#[cfg(feature = "unstable_mcp_over_acp")]
ConnectMcpRequest(ConnectMcpRequest),
/// **UNSTABLE**
///
/// This capability is not part of the spec yet, and may be removed or changed at any point.
///
/// Exchanges an MCP-over-ACP message.
#[cfg(feature = "unstable_mcp_over_acp")]
MessageMcpRequest(MessageMcpRequest),
/// **UNSTABLE**
///
/// This capability is not part of the spec yet, and may be removed or changed at any point.
///
/// Closes an MCP-over-ACP connection.
#[cfg(feature = "unstable_mcp_over_acp")]
DisconnectMcpRequest(DisconnectMcpRequest),
/// Handles extension method requests from the agent.
///
/// Allows the Agent to send an arbitrary request that is not part of the ACP spec.
Expand All @@ -2848,11 +2820,7 @@ impl AgentRequest {
Self::KillTerminalRequest(_) => CLIENT_METHOD_NAMES.terminal_kill,
Self::CreateElicitationRequest(_) => CLIENT_METHOD_NAMES.elicitation_create,
#[cfg(feature = "unstable_mcp_over_acp")]
Self::ConnectMcpRequest(_) => CLIENT_METHOD_NAMES.mcp_connect,
#[cfg(feature = "unstable_mcp_over_acp")]
Self::MessageMcpRequest(_) => CLIENT_METHOD_NAMES.mcp_message,
#[cfg(feature = "unstable_mcp_over_acp")]
Self::DisconnectMcpRequest(_) => CLIENT_METHOD_NAMES.mcp_disconnect,
Self::ExtMethodRequest(ext_request) => &ext_request.method,
}
}
Expand Down Expand Up @@ -2888,12 +2856,6 @@ pub enum ClientResponse {
KillTerminalResponse(#[serde(default)] KillTerminalResponse),
/// Successful result returned for a `elicitation/create` request.
CreateElicitationResponse(CreateElicitationResponse),
/// Successful result returned for a `mcp/connect` request.
#[cfg(feature = "unstable_mcp_over_acp")]
ConnectMcpResponse(ConnectMcpResponse),
/// Successful result returned for a `mcp/disconnect` request.
#[cfg(feature = "unstable_mcp_over_acp")]
DisconnectMcpResponse(#[serde(default)] DisconnectMcpResponse),
/// Successful result returned by an MCP-over-ACP `mcp/message` request.
#[cfg(feature = "unstable_mcp_over_acp")]
MessageMcpResponse(MessageMcpResponse),
Expand Down Expand Up @@ -2930,13 +2892,6 @@ pub enum AgentNotification {
///
/// See protocol docs: [Elicitation](https://agentclientprotocol.com/protocol/elicitation#url-completion)
CompleteElicitationNotification(CompleteElicitationNotification),
/// **UNSTABLE**
///
/// This capability is not part of the spec yet, and may be removed or changed at any point.
///
/// Receives an MCP-over-ACP notification.
#[cfg(feature = "unstable_mcp_over_acp")]
MessageMcpNotification(MessageMcpNotification),
/// Handles extension notifications from the agent.
///
/// Allows the Agent to send an arbitrary notification that is not part of the ACP spec.
Expand All @@ -2954,8 +2909,6 @@ impl AgentNotification {
match self {
Self::SessionNotification(_) => CLIENT_METHOD_NAMES.session_update,
Self::CompleteElicitationNotification(_) => CLIENT_METHOD_NAMES.elicitation_complete,
#[cfg(feature = "unstable_mcp_over_acp")]
Self::MessageMcpNotification(_) => CLIENT_METHOD_NAMES.mcp_message,
Self::ExtNotification(ext_notification) => &ext_notification.method,
}
}
Expand Down Expand Up @@ -3613,72 +3566,51 @@ mod tests {
let params: serde_json::Map<String, serde_json::Value> =
[("cursor".to_string(), json!("abc"))].into_iter().collect();

assert_eq!(CLIENT_METHOD_NAMES.mcp_connect, "mcp/connect");
assert_eq!(CLIENT_METHOD_NAMES.mcp_message, "mcp/message");
assert_eq!(CLIENT_METHOD_NAMES.mcp_disconnect, "mcp/disconnect");

assert_eq!(
AgentRequest::ConnectMcpRequest(ConnectMcpRequest::new("server-1")).method(),
"mcp/connect"
);
assert_eq!(
AgentRequest::MessageMcpRequest(MessageMcpRequest::new("conn-1", "tools/list"))
.method(),
"mcp/message"
);
assert_eq!(
AgentRequest::DisconnectMcpRequest(DisconnectMcpRequest::new("conn-1")).method(),
"mcp/disconnect"
);
assert_eq!(
AgentNotification::MessageMcpNotification(MessageMcpNotification::new(
"conn-1",
"notifications/progress"
AgentRequest::MessageMcpRequest(MessageMcpRequest::new(
"server-1",
"req-1",
"tools/list"
))
.method(),
"mcp/message"
);

assert_eq!(
serde_json::to_value(ConnectMcpRequest::new("server-1")).unwrap(),
json!({ "serverId": "server-1" })
);
assert_eq!(
serde_json::to_value(ConnectMcpResponse::new("conn-1")).unwrap(),
json!({ "connectionId": "conn-1" })
);
assert_eq!(
serde_json::to_value(MessageMcpRequest::new("conn-1", "tools/list").params(params))
.unwrap(),
serde_json::to_value(
MessageMcpRequest::new("server-1", "req-1", "tools/list").params(params)
)
.unwrap(),
json!({
"connectionId": "conn-1",
"serverId": "server-1",
"requestId": "req-1",
"method": "tools/list",
"params": { "cursor": "abc" }
})
);
assert_eq!(
serde_json::to_value(DisconnectMcpRequest::new("conn-1")).unwrap(),
json!({ "connectionId": "conn-1" })
);
assert_eq!(
serde_json::to_value(MessageMcpNotification::new(
"conn-1",
"notifications/progress"
))
.unwrap(),
json!({
"connectionId": "conn-1",
"method": "notifications/progress"
})
);

let request_with_null_params: MessageMcpRequest = serde_json::from_value(json!({
"connectionId": "conn-1",
"serverId": "server-1",
"requestId": "req-1",
"method": "tools/list",
"params": null
"params": null,
"_meta": null
}))
.unwrap();
assert_eq!(request_with_null_params.params, None);
assert_eq!(request_with_null_params.meta, None);
for key in ["serverId", "requestId", "method"] {
let mut value =
json!({"serverId":"server-1", "requestId":"req-1", "method":"tools/list"});
value.as_object_mut().unwrap().remove(key);
assert!(serde_json::from_value::<MessageMcpRequest>(value).is_err());
}
for key in ["serverId", "requestId", "method"] {
let mut value =
json!({"serverId":"server-1", "requestId":"req-1", "method":"tools/list"});
value[key] = serde_json::Value::Null;
assert!(serde_json::from_value::<MessageMcpRequest>(value).is_err());
}
}

#[test]
Expand Down
Loading
Loading