use super::daemon_utils::{daemon_base_url, mcp_http_addr_path};
use anyhow::Result;
use colored::Colorize;
use trusty_common::mcp::DaemonBridgeConfig;
pub async fn handle_serve(
with_http: bool,
port: u16,
http: Option<String>,
pinned_index: Option<String>,
) -> Result<()> {
let bind_addr: Option<String> = if let Some(addr) = http {
Some(addr)
} else if with_http {
Some(format!("127.0.0.1:{port}"))
} else {
None
};
let pin = |server: crate::mcp::McpServer| match pinned_index.clone() {
Some(id) => server.with_pinned_index(id),
None => server,
};
match bind_addr {
Some(addr) => {
let daemon_url = daemon_base_url();
let server = pin(crate::mcp::McpServer::new(daemon_url.clone()));
serve_http(server, addr, &daemon_url).await
}
None => {
let base_url = ensure_search_daemon_up().await?;
let server = pin(crate::mcp::McpServer::new(base_url.clone()));
if let Some(ref id) = pinned_index {
eprintln!(
"{} MCP session pinned to index {}",
"\u{25c9}".green(),
id.cyan()
);
}
eprintln!(
"{} MCP stdio (no HTTP) -> daemon {}",
"\u{25c9}".green(),
base_url.dimmed()
);
crate::mcp::stdio::run(server).await?;
std::process::exit(0);
}
}
}
async fn ensure_search_daemon_up() -> Result<String> {
let config = DaemonBridgeConfig {
service_name: "trusty-search".to_string(),
spawn_args: vec!["start".to_string(), "--foreground".to_string()],
health_path: "/health".to_string(),
base_url_fn: Box::new(|| match trusty_common::read_daemon_addr("trusty-search") {
Ok(Some(addr)) if !addr.is_empty() => {
if addr.starts_with("http://") || addr.starts_with("https://") {
addr
} else {
format!("http://{addr}")
}
}
_ => daemon_base_url(),
}),
startup_timeout: None,
poll_interval: None,
no_spawn: false, };
trusty_common::mcp::ensure_daemon_up(&config).await
}
async fn serve_http(server: crate::mcp::McpServer, addr: String, daemon_url: &str) -> Result<()> {
let listener = tokio::net::TcpListener::bind(&addr).await?;
let local = listener.local_addr()?;
let addr_file = mcp_http_addr_path();
if let Some(ref path) = addr_file {
if let Some(parent) = path.parent() {
let _ = std::fs::create_dir_all(parent);
}
if let Err(e) = std::fs::write(path, format!("{local}\n")) {
eprintln!(
"{} could not write {}: {e}",
"\u{26a0}".yellow(),
path.display()
);
}
}
eprintln!(
"trusty-search v{} -- HTTP admin panel: http://{}",
env!("CARGO_PKG_VERSION"),
local,
);
eprintln!(
"{} MCP HTTP/SSE on {} -> daemon {}",
"\u{25c9}".green(),
local.to_string().cyan(),
daemon_url.dimmed()
);
let app = crate::mcp::sse::router(server);
let serve_result = axum::serve(listener, app).await;
if let Some(path) = addr_file {
let _ = std::fs::remove_file(&path);
}
serve_result?;
Ok(())
}