Skip to content
Closed
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
15 changes: 13 additions & 2 deletions cmux-tui/crates/acpmux/src/acpmux_mcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ const STATUS_WAIT: Duration = Duration::from_secs(5);
const MAX_LAST: u64 = 20;

fn tools() -> Value {
json!([
tools_with_artifacts(crate::artifacts_tools::enabled())
}

fn tools_with_artifacts(enabled: bool) -> Value {
let mut tools = json!([
{
"name": "send",
"description": "Message another agent session: a lane, a coordinator, or a chat on a peer (host/name). Use it instead of running `acpmux send` in a shell. It goes through this daemon's outbox, like `acpmux send --no-wait`: it returns within seconds with the message's promptId and delivery id, and a slow target or a peer that is down is retried; it does not wait for a reply (read one later with last). The receiver's chat shows the message as yours. By default it steers: an agent in the middle of a turn reads it at its next tool step; steer: false queues it behind that turn.",
Expand Down Expand Up @@ -77,7 +81,11 @@ fn tools() -> Value {
"required": ["name"]
}
}
])
]);
if enabled {
tools.as_array_mut().expect("tool list").extend(crate::artifacts_tools::definitions());
}
tools
}

/// Runs the server on stdin and stdout.
Expand Down Expand Up @@ -110,6 +118,9 @@ pub(crate) async fn call(daemon: &Arc<Client>, params: &Value) -> Value {
return error_result("arguments must be an object".to_owned());
}
match params["name"].as_str().unwrap_or_default() {
"artifact_save" | "artifact_list" | "memory_search" => {
crate::artifacts_tools::call(params["name"].as_str().unwrap_or_default(), &args).await
}
"send" => send(daemon, &args).await,
"ls" => ls(daemon, &args).await,
"last" => {
Expand Down
17 changes: 16 additions & 1 deletion cmux-tui/crates/acpmux/src/acpmux_mcp_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ fn text(result: &Value) -> String {

#[test]
fn the_tools_say_they_message_other_sessions_instead_of_the_shell() {
let tools = tools();
let tools = tools_with_artifacts(false);
let names: Vec<&str> =
tools.as_array().unwrap().iter().filter_map(|t| t["name"].as_str()).collect();
assert_eq!(names, ["send", "ls", "last", "info"]);
Expand Down Expand Up @@ -152,3 +152,18 @@ async fn an_unknown_session_or_a_missing_argument_is_an_error_the_agent_reads()
let r = call(&client, &tool("nope", json!({}))).await;
assert_eq!(text(&r), "unknown tool: nope", "{r}");
}

#[test]
fn artifact_tools_are_only_advertised_after_opt_in() {
let enabled = tools_with_artifacts(true);
for name in ["artifact_save", "artifact_list", "memory_search"] {
assert!(enabled.as_array().unwrap().iter().any(|tool| tool["name"] == name));
assert!(
!tools_with_artifacts(false)
.as_array()
.unwrap()
.iter()
.any(|tool| tool["name"] == name)
);
}
}
3 changes: 2 additions & 1 deletion cmux-tui/crates/acpmux/src/agent_tools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,8 @@ fn resolve_with_cua_helper(
env: vec![],
});
// send, ls, last and info (`acpmux_mcp.rs`): messages another session as this one,
// instead of `acpmux send` in a shell.
// instead of `acpmux send` in a shell. This same server lists the artifact
// tools only after config.artifacts_sync.enabled is explicitly enabled.
servers.push(McpServer {
name: crate::acpmux_mcp::SERVER_NAME.into(),
command: acpmux.exe.clone(),
Expand Down
Loading
Loading