use crate::error::Result;
use crate::registry;
use super::{block_on_oci, render_table};
pub fn cmd_mcp_search(query: &str, limit: usize, registry_url: &str, json: bool) -> Result<()> {
let servers = block_on_oci(registry::search(registry_url, query, limit))?;
if json {
let rows: Vec<serde_json::Value> = servers
.iter()
.map(|server| {
let id = registry::default_capability_id(&server.name);
let (installable, detail) = match registry::to_manifest(server, &id) {
Ok(_) => (true, None),
Err(error) => (false, Some(error.to_string())),
};
serde_json::json!({
"name": server.name,
"version": server.version,
"description": server.description,
"id": id,
"installable": installable,
"detail": detail,
})
})
.collect();
println!("{}", serde_json::to_string_pretty(&rows)?);
return Ok(());
}
if servers.is_empty() {
println!("no servers in the registry match '{query}'");
return Ok(());
}
let rows: Vec<Vec<String>> = servers
.iter()
.map(|server| {
let id = registry::default_capability_id(&server.name);
let install = match registry::to_manifest(server, &id) {
Ok(manifest) => manifest
.server
.as_ref()
.and_then(|config| config.command.clone())
.unwrap_or_else(|| "http".to_string()),
Err(_) => "unsupported".to_string(),
};
vec![
server.name.clone(),
server.version.clone(),
install,
truncate(&server.description, 60),
]
})
.collect();
println!(
"{}",
render_table(&["NAME", "VERSION", "INSTALL", "DESCRIPTION"], &rows)
);
println!("install one with: tuff add mcp <NAME>");
Ok(())
}
fn truncate(value: &str, max: usize) -> String {
let single_line = value.replace(['\n', '\r'], " ");
if single_line.chars().count() <= max {
return single_line;
}
let kept: String = single_line.chars().take(max.saturating_sub(1)).collect();
format!("{}…", kept.trim_end())
}