use serde::Serialize;
use crate::output::CliReport;
use crate::output::human::{Human, Table};
#[derive(Serialize)]
pub struct ToolInfo {
pub name: String,
#[serde(skip_serializing_if = "String::is_empty")]
pub description: String,
}
#[derive(Serialize)]
pub struct ServerToolsView {
pub server: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub tools: Option<Vec<ToolInfo>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
}
#[derive(Serialize)]
pub struct ToolsListReport {
pub servers: Vec<ServerToolsView>,
}
impl CliReport for ToolsListReport {
fn render(&self, h: &mut Human<'_>) -> std::io::Result<()> {
for s in &self.servers {
if let Some(err) = &s.error {
h.line(&format!("{} — error: {err}", s.server))?;
} else if let Some(tools) = &s.tools {
if tools.is_empty() {
h.line(&format!("{} (no tools advertised)", s.server))?;
} else {
h.line(&format!("{} ({})", s.server, tools.len()))?;
for t in tools {
if t.description.is_empty() {
h.line(&format!(" {}", t.name))?;
} else {
h.line(&format!(" {} — {}", t.name, t.description))?;
}
}
}
}
}
Ok(())
}
}
#[derive(Serialize)]
pub struct ServerStatusView {
pub server: String,
pub ok: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub latency_ms: Option<u128>,
pub transport: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
}
#[derive(Serialize)]
pub struct ToolsStatusReport {
pub servers: Vec<ServerStatusView>,
}
impl CliReport for ToolsStatusReport {
fn render(&self, h: &mut Human<'_>) -> std::io::Result<()> {
let mut t = Table::new(["SERVER", "STATUS", "LATENCY", "TRANSPORT"]);
for s in &self.servers {
t.push([
s.server.clone(),
if s.ok { "ok".into() } else { "FAIL".into() },
s.latency_ms
.map(|ms| format!("{ms}ms"))
.unwrap_or_else(|| "-".into()),
s.transport.clone(),
]);
}
h.table(&t)
}
}
#[derive(Serialize)]
pub struct ToolsDiscoverReport {
pub server: String,
pub yaml: String,
}
impl CliReport for ToolsDiscoverReport {
fn render(&self, h: &mut Human<'_>) -> std::io::Result<()> {
for line in self.yaml.lines() {
h.line(line)?;
}
Ok(())
}
}