mod params;
mod tools;
use std::path::{Path, PathBuf};
use rmcp::ServiceExt;
use rmcp::handler::server::router::tool::ToolRouter;
use rmcp::model::{CallToolResult, ContentBlock};
use bears::error::Error;
#[derive(Clone)]
pub struct BeaMcp {
base: PathBuf,
#[allow(dead_code)]
tool_router: ToolRouter<Self>,
}
impl BeaMcp {
pub fn new(base: PathBuf) -> Self {
let tool_router = Self::build_tool_router();
Self { base, tool_router }
}
}
fn ok_json(value: serde_json::Value) -> Result<CallToolResult, Error> {
let text = serde_json::to_string(&value)?;
Ok(CallToolResult::success(vec![ContentBlock::text(text)]))
}
fn tool_ok(r: Result<CallToolResult, Error>) -> Result<CallToolResult, rmcp::ErrorData> {
Ok(r.unwrap_or_else(|e| CallToolResult::error(vec![ContentBlock::text(e.to_string())])))
}
pub async fn run(base: &Path) -> bears::error::Result<()> {
let server = BeaMcp::new(base.to_path_buf());
let service = server
.serve(rmcp::transport::stdio())
.await
.map_err(|e| std::io::Error::other(e.to_string()))?;
service
.waiting()
.await
.map_err(|e| std::io::Error::other(e.to_string()))?;
Ok(())
}