use std::time::Duration;
use crate::core::mcp_catalog::{GatewayServer, client};
#[derive(Debug, Clone)]
pub struct ProbeReport {
pub tool_count: usize,
pub tools: Vec<String>,
}
pub fn probe(server: &GatewayServer, timeout: Duration) -> Result<ProbeReport, String> {
let resolved = server.resolve()?;
let rt = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.map_err(|e| format!("failed to start runtime for the health probe: {e}"))?;
let tools = rt.block_on(client::fetch_tools(&resolved, timeout))?;
let mut names: Vec<String> = tools.iter().map(|t| t.name.to_string()).collect();
names.sort();
Ok(ProbeReport {
tool_count: names.len(),
tools: names,
})
}
#[cfg(test)]
mod tests {
use super::*;
use crate::core::mcp_catalog::TransportKind;
#[test]
fn probe_reports_a_clear_error_for_a_missing_binary() {
let server = GatewayServer {
name: "ghost".into(),
transport: TransportKind::Stdio,
command: "lean-ctx-no-such-mcp-binary-xyz".into(),
..Default::default()
};
let err = probe(&server, Duration::from_secs(5)).expect_err("missing binary must fail");
assert!(!err.is_empty());
}
#[test]
fn probe_rejects_an_unresolvable_server() {
let server = GatewayServer {
name: "broken".into(),
transport: TransportKind::Stdio,
..Default::default()
};
assert!(probe(&server, Duration::from_secs(1)).is_err());
}
}