#![cfg(all(feature = "comms", unix))]
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, InboxAckParams, 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
}
#[tool(
description = "Acknowledge inbox messages by ADVANCING this agent's per-room read cursors \
— it does NOT delete anything and does NOT affect the shared append-only log or any other \
agent's inbox (message_get and room_history still return acked messages). Two modes, \
combinable: pass `message_ids` to ack specific messages (each resolved to its room+seq), \
and/or `room` + `to_seq` to bulk-ack everything up to `to_seq` in one room (stale-room \
cleanup). At least one mode is required. Needs --features comms."
)]
pub(crate) async fn inbox_ack(
&self,
Parameters(p): Parameters<InboxAckParams>,
) -> 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_ack(&self.state, p).await;
record_call(
&self.state,
"inbox_ack",
&__params_json,
__started,
&__result,
);
__result
}
}