From ccac95fcf4f55a41462d0477d030cb88aa02a5f4 Mon Sep 17 00:00:00 2001 From: damocles Date: Sat, 7 Nov 2026 18:46:37 +0100 Subject: [PATCH] matrix-mcp: document the bare name in the DM tool schemas, expand it once --- hive-matrix-mcp/src/handlers.rs | 20 +++++++++----------- hive-matrix-mcp/src/mcp.rs | 11 +++++++---- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/hive-matrix-mcp/src/handlers.rs b/hive-matrix-mcp/src/handlers.rs index e1bb42d2..15e893b6 100644 --- a/hive-matrix-mcp/src/handlers.rs +++ b/hive-matrix-mcp/src/handlers.rs @@ -524,7 +524,8 @@ fn expand_user_id(own_server: Option<&str>, input: &str) -> String { } } -/// Find the existing DM room with `user_id` or create one, and say where the +/// Find the existing DM room with `user_id` (a full id, or a bare agent name, +/// see [`expand_user_id`]) or create one, and say where the /// recipient stands in it. Shared by `send_dm` and `open_dm`. /// `direct_targets()` (cached state) is used rather than the async /// `is_direct()`. @@ -535,7 +536,7 @@ fn expand_user_id(own_server: Option<&str>, input: &str) -> String { async fn resolve_or_create_dm( client: &Client, user_id: &str, -) -> Result<(matrix_sdk::Room, Recipient), DaemonResponse> { +) -> Result<(matrix_sdk::Room, Recipient, OwnedUserId), DaemonResponse> { let own = client.user_id().map(|u| u.server_name().to_string()); let user_id = expand_user_id(own.as_deref(), user_id); let uid: OwnedUserId = user_id @@ -567,7 +568,7 @@ async fn resolve_or_create_dm( room.room_id() ))); } - Ok((room, recipient)) + Ok((room, recipient, uid)) } /// The JSON fields that tell the caller where the recipient stands, with a @@ -583,10 +584,7 @@ fn recipient_fields(recipient: Recipient) -> serde_json::Value { } pub async fn send_dm(client: &Client, user_id: &str, body: &str) -> DaemonResponse { - let own = client.user_id().map(|u| u.server_name().to_string()); - let user_id = expand_user_id(own.as_deref(), user_id); - let user_id = user_id.as_str(); - let (room, recipient) = match resolve_or_create_dm(client, user_id).await { + let (room, recipient, uid) = match resolve_or_create_dm(client, user_id).await { Ok(r) => r, Err(e) => return e, }; @@ -599,12 +597,12 @@ pub async fn send_dm(client: &Client, user_id: &str, body: &str) -> DaemonRespon let mut payload = serde_json::json!({ "event_id": resp.response.event_id.to_string(), "room_id": room.room_id().to_string(), - "user_id": user_id, + "user_id": uid.to_string(), }); merge(&mut payload, recipient_fields(recipient)); DaemonResponse::ok(&payload) } - Err(e) => DaemonResponse::error(format!("send DM to {user_id}: {e}")), + Err(e) => DaemonResponse::error(format!("send DM to {uid}: {e}")), } } @@ -691,13 +689,13 @@ pub async fn send_file( /// tools (`send_file`, `send_message`, …) against that id — so there is /// no per-tool `_dm` variant. pub async fn open_dm(client: &Client, user_id: &str) -> DaemonResponse { - let (room, recipient) = match resolve_or_create_dm(client, user_id).await { + let (room, recipient, uid) = match resolve_or_create_dm(client, user_id).await { Ok(r) => r, Err(e) => return e, }; let mut payload = serde_json::json!({ "room_id": room.room_id().to_string(), - "user_id": user_id, + "user_id": uid.to_string(), }); merge(&mut payload, recipient_fields(recipient)); DaemonResponse::ok(&payload) diff --git a/hive-matrix-mcp/src/mcp.rs b/hive-matrix-mcp/src/mcp.rs index 18c46f8c..a96a88e3 100644 --- a/hive-matrix-mcp/src/mcp.rs +++ b/hive-matrix-mcp/src/mcp.rs @@ -57,7 +57,8 @@ struct SendMessageArgs { #[derive(Debug, Deserialize, JsonSchema)] struct SendDmArgs { - /// Matrix user id of the recipient (`@user:server`). DM room is + /// Matrix user id of the recipient (`@user:server`), or just an agent's + /// name such as `iris` for that agent on this homeserver. DM room is /// created if one doesn't already exist between this agent and /// the recipient. user_id: String, @@ -87,8 +88,9 @@ struct SendFileArgs { #[derive(Debug, Deserialize, JsonSchema)] struct OpenDmArgs { - /// Matrix user id (`@user:server`) to open a DM with. The DM room is - /// created if one doesn't already exist. + /// Matrix user id (`@user:server`), or just an agent's name such as + /// `iris` for that agent on this homeserver, to open a DM with. The DM + /// room is created if one doesn't already exist. user_id: String, /// Matrix account to act as (a `name` from `services.hyperhive.agent.matrixAccounts`). /// Omit to use the agent's primary account. @@ -308,7 +310,8 @@ impl MatrixMcp { } #[tool(description = "Resolve (find-or-create) the DM room with `user_id` \ - (@user:server) and return its room id, without sending anything. Use the \ + (@user:server, or an agent's name such as `iris` for that agent on this \ + homeserver) and return its room id, without sending anything. Use the \ returned room id with the room-based tools (`send_file`, `send_message`, \ …) to deliver into the DM — there is no per-tool DM variant.")] async fn open_dm(&self, Parameters(args): Parameters) -> String {