use mcp::{Server, http::Door, tools};
use std::path::Path;
use std::sync::{
Arc, Mutex, OnceLock,
atomic::{AtomicBool, Ordering},
};
static DOOR: OnceLock<Mutex<Option<Door>>> = OnceLock::new();
fn held() -> &'static Mutex<Option<Door>> {
DOOR.get_or_init(Mutex::default)
}
static WRITE: OnceLock<Arc<AtomicBool>> = OnceLock::new();
fn write() -> &'static Arc<AtomicBool> {
WRITE.get_or_init(|| Arc::new(AtomicBool::new(false)))
}
pub fn set_write(on: bool) {
write().store(on, Ordering::Relaxed);
}
static DELETE: OnceLock<Arc<AtomicBool>> = OnceLock::new();
fn delete() -> &'static Arc<AtomicBool> {
DELETE.get_or_init(|| Arc::new(AtomicBool::new(false)))
}
pub fn set_delete(on: bool) {
delete().store(on, Ordering::Relaxed);
}
pub fn serve(open: bool) {
let Ok(mut door) = held().lock() else {
return;
};
match open {
false => *door = None,
true if door.is_some() => {}
true => {
*door = super::acp::runtime()
.block_on(mcp::http::open(Arc::new(server())))
.ok();
}
}
}
pub fn url() -> Option<String> {
let door = held().lock().ok()?;
door.as_ref().map(|door| door.url().to_owned())
}
pub fn project(cwd: &Path) -> (&'static str, String) {
(mcp::http::PROJECT, mcp::http::encoded(cwd))
}
pub fn session(record: &str) -> (&'static str, String) {
(mcp::http::SESSION, record.to_owned())
}
fn server() -> Server {
Server::new()
.mount(&tools::article::TOOLS)
.mount(&tools::board::TOOLS)
.mount(&tools::project::TOOLS)
.mount(&tools::session::TOOLS)
.mount(&tools::workspace::TOOLS)
.writable(write().clone())
.deletes(delete().clone())
}