Matrix MCP tools and extra MCP servers

Built-in matrix MCP (mcp__matrix__*)

When hyperhive.matrix.enable = true and the host-level matrix tuwunel is configured, the harness auto-injects hive-matrix-mcp as a second stdio MCP server. Tools land as mcp__matrix__<name>:

Messaging

Reading

Room membership

Receipts

Architecture

The daemon (hive-matrix-daemon) holds the long-running matrix-sdk Client + sync loop; the stdio bridge (hive-matrix-mcp) is spawned per turn and forwards tool calls over /run/hive-matrix.sock. Both silently exit when <state>/matrix-token is absent (account not yet provisioned).

Incoming room events wake the agent via AgentRequest::Wake with from: "matrix". The wake body format depends on the unread state:

The same per-room breakdown is included in the UnreadMatrix entry returned by get_loose_ends so unread rooms surface in the loose-ends list between turns.

Invite wakes: when the daemon's sync loop receives an m.room.member invite event, it writes the invite to mcp-loose-ends/matrix.json and fires a hyperhive wake. The daemon does not auto-join — the agent calls list_invites to see pending invites and resolve_invite to accept or reject them.

Pending invites as loose ends: pending invites are written to mcp-loose-ends/matrix.json and appear in get_loose_ends output as [matrix] pending invite: <room> — use list_invites to see, resolve_invite to accept or reject. The file is updated atomically after each invite event and after each resolve_invite (or join_room) call clears the entry.

See docs/matrix.md for the homeserver setup, provisioning flow, and federation config.

Extra MCP servers (per-agent)

Each agent's NixOS config can declare additional MCP servers via hyperhive.extraMcpServers.<key> = { command, args, env, allowedTools }. The module writes the map to /etc/hyperhive/extra-mcp.json; the harness reads it at boot and merges every entry into --mcp-config (under mcpServers.<key>) and --allowedTools (as mcp__<key>__<pattern>).

The agent's flake.nix forwards every flake input to agent.nix as the flakeInputs module arg, so external MCP-server flakes are pulled in by adding them to inputs.* and referenced as flakeInputs.<name>.packages.${pkgs.system}.default — the resolved sha lands in the agent's own flake.lock and rolls up to meta's.

allowedTools defaults to ["*"], which expands to mcp__<key>__* (every tool from that server auto-approved). Restrict to specific tool names when you want finer control.