basemind 0.5.0

Full AI context layer over MCP — tree-sitter code-map, document RAG (PDF/Office/HTML/email + OCR + reranker), shared agent memory, on-demand web crawl, git history + blame + per-symbol diff. 300+ languages, 8 coding-agent harnesses, content-addressed Fjall + LanceDB.
//! Agent-comms tool shims for `BasemindServer`.
//!
//! Kept in a separate file so `tools.rs` stays under the 1000-line cap. Each shim is a thin
//! wrapper that delegates to a `helpers_comms::run_*` body and records telemetry; when the
//! `comms` feature is off it returns a graceful "not enabled" MCP error (mirroring the memory
//! tier). The whole router is registered only under `#[cfg(feature = "comms")]`.

#![cfg(feature = "comms")]

use rmcp::ErrorData as McpError;
use rmcp::handler::server::wrapper::Parameters;
use rmcp::model::CallToolResult;
use rmcp::tool;
use serde_json::Value;

use super::BasemindServer;
use super::helpers::record_call;
use super::types_comms::{
    AgentListParams, AgentRegisterParams, InboxReadParams, MessageGetParams, RoomCreateParams,
    RoomHistoryParams, RoomJoinParams, RoomLeaveParams, RoomListParams, RoomPostParams,
};

#[rmcp::tool_router(vis = "pub(super)", router = "tool_router_comms")]
impl BasemindServer {
    #[tool(
        description = "Register or update this agent's A2A card (name/description/version/skills) \
        with the user-global comms broker. Spawns the broker daemon on first use. \
        Needs --features comms."
    )]
    pub(crate) async fn agent_register(
        &self,
        Parameters(p): Parameters<AgentRegisterParams>,
    ) -> Result<CallToolResult, McpError> {
        let __started = std::time::Instant::now();
        let __params_json = serde_json::to_value(&p).unwrap_or(Value::Null);
        let __result = super::helpers_comms::run_agent_register(&self.state, p).await;
        record_call(
            &self.state,
            "agent_register",
            &__params_json,
            __started,
            &__result,
        );
        __result
    }

    #[tool(
        description = "List agents known to the comms broker, optionally restricted to the \
        subscribers of one room. Returns front-matter (id, card fields, first/last seen). \
        Needs --features comms."
    )]
    pub(crate) async fn agent_list(
        &self,
        Parameters(p): Parameters<AgentListParams>,
    ) -> Result<CallToolResult, McpError> {
        let __started = std::time::Instant::now();
        let __params_json = serde_json::to_value(&p).unwrap_or(Value::Null);
        let __result = super::helpers_comms::run_agent_list(&self.state, p).await;
        record_call(
            &self.state,
            "agent_list",
            &__params_json,
            __started,
            &__result,
        );
        __result
    }

    #[tool(
        description = "Create (and register) a comms room with an explicit scope: `global`, \
        `remote` (a git remote — every clone auto-joins), or `path_prefix` (agents at/below a \
        path auto-join). Idempotent. Needs --features comms."
    )]
    pub(crate) async fn room_create(
        &self,
        Parameters(p): Parameters<RoomCreateParams>,
    ) -> Result<CallToolResult, McpError> {
        let __started = std::time::Instant::now();
        let __params_json = serde_json::to_value(&p).unwrap_or(Value::Null);
        let __result = super::helpers_comms::run_room_create(&self.state, p).await;
        record_call(
            &self.state,
            "room_create",
            &__params_json,
            __started,
            &__result,
        );
        __result
    }

    #[tool(
        description = "List rooms whose scope matches this server's repo (git remote + cwd). \
        Returns room front-matter (id, title, created_at). Needs --features comms."
    )]
    pub(crate) async fn room_list(
        &self,
        Parameters(p): Parameters<RoomListParams>,
    ) -> Result<CallToolResult, McpError> {
        let __started = std::time::Instant::now();
        let __params_json = serde_json::to_value(&p).unwrap_or(Value::Null);
        let __result = super::helpers_comms::run_room_list(&self.state, p).await;
        record_call(
            &self.state,
            "room_list",
            &__params_json,
            __started,
            &__result,
        );
        __result
    }

    #[tool(
        description = "Subscribe this agent to a room (durable membership; drives the inbox). \
        Needs --features comms."
    )]
    pub(crate) async fn room_join(
        &self,
        Parameters(p): Parameters<RoomJoinParams>,
    ) -> Result<CallToolResult, McpError> {
        let __started = std::time::Instant::now();
        let __params_json = serde_json::to_value(&p).unwrap_or(Value::Null);
        let __result = super::helpers_comms::run_room_join(&self.state, p).await;
        record_call(
            &self.state,
            "room_join",
            &__params_json,
            __started,
            &__result,
        );
        __result
    }

    #[tool(description = "Unsubscribe this agent from a room. Needs --features comms.")]
    pub(crate) async fn room_leave(
        &self,
        Parameters(p): Parameters<RoomLeaveParams>,
    ) -> Result<CallToolResult, McpError> {
        let __started = std::time::Instant::now();
        let __params_json = serde_json::to_value(&p).unwrap_or(Value::Null);
        let __result = super::helpers_comms::run_room_leave(&self.state, p).await;
        record_call(
            &self.state,
            "room_leave",
            &__params_json,
            __started,
            &__result,
        );
        __result
    }

    #[tool(
        description = "Post a message (subject + optional markdown body + tags + reply_to) to a \
        room. Returns the new message_id. The body is stored separately from front-matter. \
        Needs --features comms."
    )]
    pub(crate) async fn room_post(
        &self,
        Parameters(p): Parameters<RoomPostParams>,
    ) -> Result<CallToolResult, McpError> {
        let __started = std::time::Instant::now();
        let __params_json = serde_json::to_value(&p).unwrap_or(Value::Null);
        let __result = super::helpers_comms::run_room_post(&self.state, p).await;
        record_call(
            &self.state,
            "room_post",
            &__params_json,
            __started,
            &__result,
        );
        __result
    }

    #[tool(
        description = "Read a room's history oldest-first, FRONT-MATTER ONLY (id, from, subject, \
        ts, tags) — bodies are NOT included; fetch them with message_get. Paginated: pass \
        `cursor` from the previous response. Default 100 max 1000. Needs --features comms."
    )]
    pub(crate) async fn room_history(
        &self,
        Parameters(p): Parameters<RoomHistoryParams>,
    ) -> Result<CallToolResult, McpError> {
        let __started = std::time::Instant::now();
        let __params_json = serde_json::to_value(&p).unwrap_or(Value::Null);
        let __result = super::helpers_comms::run_room_history(&self.state, p).await;
        record_call(
            &self.state,
            "room_history",
            &__params_json,
            __started,
            &__result,
        );
        __result
    }

    #[tool(
        description = "Fetch a single message BODY by id (the only body path; history/inbox \
        return front-matter only). Body is returned as a UTF-8 (lossy) markdown string. \
        Needs --features comms."
    )]
    pub(crate) async fn message_get(
        &self,
        Parameters(p): Parameters<MessageGetParams>,
    ) -> Result<CallToolResult, McpError> {
        let __started = std::time::Instant::now();
        let __params_json = serde_json::to_value(&p).unwrap_or(Value::Null);
        let __result = super::helpers_comms::run_message_get(&self.state, p).await;
        record_call(
            &self.state,
            "message_get",
            &__params_json,
            __started,
            &__result,
        );
        __result
    }

    #[tool(
        description = "Read this agent's inbox: new FRONT-MATTER across all subscribed rooms \
        (bodies NOT included — use message_get). `mark_read=true` advances read cursors. \
        Returns the page plus remaining unread count. Default 100 max 1000. \
        Needs --features comms."
    )]
    pub(crate) async fn inbox_read(
        &self,
        Parameters(p): Parameters<InboxReadParams>,
    ) -> Result<CallToolResult, McpError> {
        let __started = std::time::Instant::now();
        let __params_json = serde_json::to_value(&p).unwrap_or(Value::Null);
        let __result = super::helpers_comms::run_inbox_read(&self.state, p).await;
        record_call(
            &self.state,
            "inbox_read",
            &__params_json,
            __started,
            &__result,
        );
        __result
    }
}