From 652acf8c6e508ad5a608ac11938cc026b6dda2f7 Mon Sep 17 00:00:00 2001 From: damocles Date: Fri, 26 Jun 2026 23:56:20 +0200 Subject: [PATCH] fix(#2033): gate matrix mcp bridge startup on token, not daemon socket --- hive-matrix-mcp/src/bin/mcp.rs | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/hive-matrix-mcp/src/bin/mcp.rs b/hive-matrix-mcp/src/bin/mcp.rs index e4c8e426..0cdc50ca 100644 --- a/hive-matrix-mcp/src/bin/mcp.rs +++ b/hive-matrix-mcp/src/bin/mcp.rs @@ -576,16 +576,28 @@ async fn main() -> Result<()> { .with_writer(std::io::stderr) .init(); - // Standalone-degraded boot: missing daemon socket → exit 0 - // cleanly so claude doesn't see an MCP startup error when matrix - // hasn't been provisioned for this agent yet. The daemon will - // appear once hive-c0re writes the token + systemd starts the - // daemon unit. - let socket = paths::daemon_socket(); - if !tokio::fs::try_exists(&socket).await.unwrap_or(false) { + // Standalone-degraded boot: matrix isn't provisioned for this agent + // (no token file) → exit 0 cleanly so claude doesn't register a + // matrix MCP server it can never use. + // + // Gate on the TOKEN, not the daemon socket. The daemon binds its + // socket only AFTER restoring its matrix session (~10s on a cold + // boot), so an exists-check on the socket here raced the daemon's + // startup: during that window the socket was absent, the bridge + // exited, and claude lost the matrix tools for the WHOLE session + // (the bridge isn't respawned mid-turn). The token, by contrast, is + // written by hive-c0re at provisioning time and is present well + // before the daemon finishes booting — so it cleanly distinguishes + // "matrix not set up for this agent" (token absent → exit) from + // "daemon still coming up" (token present → keep serving). When the + // token exists we serve regardless of socket state: tool calls + // `connect()` per-call and simply error until the daemon is up, but + // the tools stay registered for the session. (#2033) + let token_file = paths::token_file(); + if !tokio::fs::try_exists(&token_file).await.unwrap_or(false) { tracing::warn!( - path = %socket.display(), - "matrix daemon socket absent; exiting cleanly so MCP startup doesn't fail" + path = %token_file.display(), + "matrix not provisioned (no token file); exiting cleanly so MCP startup doesn't fail" ); return Ok(()); }