pub(crate) mod dispatch;
pub(crate) mod protocol;
pub(crate) mod tools;
pub(crate) mod transport;
pub(crate) mod worker_commit;
use std::path::{Path, PathBuf};
use tokio::io::{self, BufReader, BufWriter};
pub(crate) type ModelKeysFn = fn(&Path, Option<&str>) -> anyhow::Result<Vec<String>>;
pub(crate) struct McpConfig {
pub(crate) path: Option<PathBuf>,
pub(crate) model_keys: ModelKeysFn,
}
pub(crate) async fn serve(config: McpConfig) -> anyhow::Result<()> {
let root = crate::root::find(config.path, &crate::root::default_markers())?;
let model_keys = config.model_keys;
let stdin = io::stdin();
let stdout = io::stdout();
let mut reader = BufReader::new(stdin);
let mut writer = BufWriter::new(stdout);
loop {
let request = match transport::read_message(&mut reader).await {
Ok(Some(req)) => req,
Ok(None) => {
break;
}
Err(e) => {
let resp = protocol::JsonRpcResponse::error(
None,
-32700,
"Parse error".to_owned(),
Some(serde_json::json!({ "message": e.to_string() })),
);
transport::write_message(&mut writer, &resp).await?;
continue;
}
};
let response = tools::dispatch(&request, &root, model_keys);
transport::write_message(&mut writer, &response).await?;
}
Ok(())
}