use std::env;
use std::fs::{self, OpenOptions};
use std::io::Write;
use std::path::{Path, PathBuf};
use std::process;
const PREBUILT: &[u8] = include_bytes!(env!("LAZY_MCP_PREBUILT"));
const VERSION: &str = env!("CARGO_PKG_VERSION");
fn prebuilt_hash() -> u64 {
const FNV_OFFSET: u64 = 0xcbf29ce484222325;
const FNV_PRIME: u64 = 0x100000001b3;
PREBUILT.iter().fold(FNV_OFFSET, |acc, &b| {
acc.wrapping_mul(FNV_PRIME) ^ (b as u64)
})
}
fn cache_dir() -> PathBuf {
#[cfg(windows)]
let base = env::var_os("LOCALAPPDATA")
.map(PathBuf::from)
.unwrap_or_else(env::temp_dir);
#[cfg(not(windows))]
let base = if let Some(xdg) = env::var_os("XDG_CACHE_HOME") {
PathBuf::from(xdg)
} else if let Some(home) = env::var_os("HOME") {
PathBuf::from(home).join(".cache")
} else {
env::temp_dir()
};
base.join("lazy-mcp").join(VERSION)
}
fn ensure_extracted(cache: &Path) -> PathBuf {
let bin_name = if cfg!(windows) {
"lazy-mcp.exe"
} else {
"lazy-mcp"
};
let bin_path = cache.join(bin_name);
let hash_path = cache.join(format!("{bin_name}.hash"));
let expected_hash = prebuilt_hash().to_string();
let cached_ok = bin_path.exists() && {
fs::read_to_string(&hash_path)
.map(|h| h.trim() == expected_hash)
.unwrap_or(false)
};
if cached_ok {
return bin_path;
}
fs::create_dir_all(cache).unwrap_or_else(|e| {
eprintln!(
"lazy-mcp: failed to create cache dir {}: {e}",
cache.display()
);
process::exit(1);
});
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
if let Ok(meta) = fs::metadata(cache) {
let mut perms = meta.permissions();
perms.set_mode(0o700);
fs::set_permissions(cache, perms).ok();
}
}
let tmp_path = cache.join(format!("{bin_name}.{}.tmp", process::id()));
let mut f = OpenOptions::new()
.write(true)
.create_new(true)
.open(&tmp_path)
.unwrap_or_else(|e| {
eprintln!("lazy-mcp: failed to create {}: {e}", tmp_path.display());
process::exit(1);
});
f.write_all(PREBUILT).unwrap_or_else(|e| {
eprintln!("lazy-mcp: failed to write binary: {e}");
let _ = fs::remove_file(&tmp_path);
process::exit(1);
});
drop(f);
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
if let Ok(meta) = fs::metadata(&tmp_path) {
let mut perms = meta.permissions();
perms.set_mode(0o755);
fs::set_permissions(&tmp_path, perms).unwrap_or_else(|e| {
eprintln!("lazy-mcp: failed to chmod binary: {e}");
let _ = fs::remove_file(&tmp_path);
process::exit(1);
});
}
}
fs::rename(&tmp_path, &bin_path).unwrap_or_else(|e| {
eprintln!("lazy-mcp: failed to move binary into place: {e}");
let _ = fs::remove_file(&tmp_path);
process::exit(1);
});
let _ = fs::write(&hash_path, &expected_hash);
bin_path
}
fn main() {
let cache = cache_dir();
let bin_path = ensure_extracted(&cache);
let args: Vec<String> = env::args().skip(1).collect();
#[cfg(unix)]
{
use std::os::unix::process::CommandExt;
let err = process::Command::new(&bin_path).args(&args).exec();
eprintln!("lazy-mcp: exec failed: {err}");
process::exit(1);
}
#[cfg(not(unix))]
{
let status = process::Command::new(&bin_path)
.args(&args)
.status()
.unwrap_or_else(|e| {
eprintln!("lazy-mcp: failed to start: {e}");
process::exit(1);
});
process::exit(status.code().unwrap_or(1));
}
}