fix(#2033): gate matrix mcp bridge startup on token, not daemon socket

This commit is contained in:
damocles 2026-06-26 23:56:20 +02:00 committed by mara
commit 652acf8c6e

View file

@ -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(());
}