use super::*;
pub async fn cmd_mcp_list(url: &str, json: bool) -> Result<(), Box<dyn std::error::Error>> {
let (DIM, BOLD, ACCENT, GREEN, YELLOW, RED, CYAN, RESET, MONO) = colors();
let (OK, ACTION, WARN, DETAIL, ERR) = icons();
let c = RoboticusClient::new(url)?;
let data = c.get("/api/mcp/servers").await.map_err(|e| {
RoboticusClient::check_connectivity_hint(&*e);
e
})?;
if json {
println!("{}", serde_json::to_string_pretty(&data)?);
return Ok(());
}
heading("MCP Servers");
let servers = data.as_array().cloned().unwrap_or_default();
if servers.is_empty() {
eprintln!(" {DIM}No MCP servers configured.{RESET}");
} else {
kv("Configured servers", &servers.len().to_string());
for server in &servers {
let name = server["name"].as_str().unwrap_or("?");
let enabled = server["enabled"].as_bool().unwrap_or(false);
let connected = server["connected"].as_bool().unwrap_or(false);
let tool_count = server["tool_count"].as_u64().unwrap_or(0);
let status = if !enabled {
format!("{YELLOW}disabled{RESET}")
} else if connected {
format!("{GREEN}connected{RESET}")
} else {
format!("{RED}disconnected{RESET}")
};
kv(name, &format!("{status} tools={tool_count}"));
}
}
eprintln!();
Ok(())
}
pub fn cmd_mcp_add(
name: &str,
stdio: Option<&str>,
sse: Option<&str>,
args: &[String],
) -> Result<(), Box<dyn std::error::Error>> {
let (DIM, BOLD, ACCENT, GREEN, YELLOW, RED, CYAN, RESET, MONO) = colors();
let (OK, ACTION, WARN, DETAIL, ERR) = icons();
match (stdio, sse) {
(Some(command), None) => {
eprintln!();
eprintln!(" {ACCENT}Adding STDIO MCP server '{name}'{RESET}");
eprintln!(" {DIM}command:{RESET} {MONO}{command}{RESET}");
if !args.is_empty() {
let arg_str = args
.iter()
.map(|a| format!("\"{}\"", a))
.collect::<Vec<_>>()
.join(", ");
eprintln!(" {DIM}args:{RESET} {MONO}[{arg_str}]{RESET}");
}
eprintln!();
eprintln!(" {DIM}Add the following to your {MONO}roboticus.toml{RESET}{DIM}:{RESET}");
eprintln!();
println!("[[mcp.servers]]");
println!("name = \"{name}\"");
println!("enabled = true");
println!("[mcp.servers.spec]");
println!("type = \"stdio\"");
println!("command = \"{command}\"");
if !args.is_empty() {
let arg_str = args
.iter()
.map(|a| format!("\"{}\"", a))
.collect::<Vec<_>>()
.join(", ");
println!("args = [{arg_str}]");
}
eprintln!();
}
(None, Some(url)) => {
eprintln!();
eprintln!(" {ACCENT}Adding SSE MCP server '{name}'{RESET}");
eprintln!(" {DIM}url:{RESET} {MONO}{url}{RESET}");
eprintln!();
eprintln!(" {DIM}Add the following to your {MONO}roboticus.toml{RESET}{DIM}:{RESET}");
eprintln!();
println!("[[mcp.servers]]");
println!("name = \"{name}\"");
println!("enabled = true");
println!("[mcp.servers.spec]");
println!("type = \"sse\"");
println!("url = \"{url}\"");
eprintln!();
}
_ => {
return Err("Specify either --stdio <command> or --sse <url>".into());
}
}
Ok(())
}
pub fn cmd_mcp_remove(name: &str) -> Result<(), Box<dyn std::error::Error>> {
let (DIM, BOLD, ACCENT, GREEN, YELLOW, RED, CYAN, RESET, MONO) = colors();
let (OK, ACTION, WARN, DETAIL, ERR) = icons();
eprintln!();
eprintln!(" {ACCENT}Remove MCP server '{name}'{RESET}");
eprintln!();
eprintln!(
" Delete the {MONO}[[mcp.servers]]{RESET} block with {MONO}name = \"{name}\"{RESET}"
);
eprintln!(" from your {MONO}roboticus.toml{RESET}, then restart the daemon:");
eprintln!();
println!(" roboticus daemon restart");
eprintln!();
Ok(())
}
pub async fn cmd_mcp_test(url: &str, name: &str) -> Result<(), Box<dyn std::error::Error>> {
let (DIM, BOLD, ACCENT, GREEN, YELLOW, RED, CYAN, RESET, MONO) = colors();
let (OK, ACTION, WARN, DETAIL, ERR) = icons();
let c = RoboticusClient::new(url)?;
eprintln!();
eprintln!(" {DIM}Testing MCP server '{MONO}{name}{RESET}{DIM}'...{RESET}");
let endpoint = format!("/api/mcp/servers/{name}/test");
match c.post(&endpoint, serde_json::json!({})).await {
Ok(data) => {
let ok = data["success"].as_bool().unwrap_or(false);
if ok {
eprintln!(" {GREEN}{OK} Connection test: PASSED{RESET}");
let tool_count = data["tool_count"].as_u64().unwrap_or(0);
eprintln!(" {DIM}Tools discovered:{RESET} {tool_count}");
} else {
let err = data["detail"].as_str().unwrap_or("unknown error");
eprintln!(" {RED}{ERR} Connection test: FAILED{RESET}");
eprintln!(" {DIM}Error:{RESET} {err}");
}
}
Err(e) => {
RoboticusClient::check_connectivity_hint(&*e);
eprintln!(" {RED}{ERR} Connection test: FAILED{RESET}");
eprintln!(" {DIM}Error:{RESET} {e}");
}
}
eprintln!();
Ok(())
}