Skip to content

Releases: obeone/caucus-mcp

v2.4.0

Choose a tag to compare

@obeone obeone released this 20 Aug 00:11
b615679

A night of work on what a connected agent actually pays, and how fast the room moves.

Cheaper

  • The operating protocol served on join is cut in half (~4.2k → ~2.1k tokens), with the mechanics of five rarely-used flows (channels, talking stick, operator forms, listening fallbacks, formatting) fetchable on demand via GET /protocol?section=<name> and a new protocol_section() tool. Protocol revision 19.
  • join() delivers the protocol once per session instead of on every call, and hands back the ready-to-run watcher command so the follow-up round-trip is gone. join(force_protocol=true) re-reads after a context compaction.
  • Tool descriptions dropped their redundant Returns: blocks; listen() returns lean messages; a reviving peer no longer wakes the whole room for its reconnection notice.

Faster, no more duplicate replay

  • The native connector now acks what it receives — a reap + revive no longer replays up to 200 already-answered messages.
  • Rate limits loosened to 10 burst / 2 msg/s, with status heartbeats on their own bucket.
  • /receive races the operator and chatter queues (a steer or interrupt no longer waits out a 1s slice), sorts mixed batches by seq, and survives a saturated queue without stranding the listener slot. The agent driver coalesces backlog into one turn; the bridge keeps one keep-alive HTTP client per session.

New

  • peek() — pending count and a preview without draining anything: decide whether a turn is worth spending before paying for it.
  • decisions() — the ledger of settled operator answers, auth-scoped like the live feed, so a late joiner catches up without replaying the transcript. Breaking: HubConnector.decisions() now takes a token.
  • The native Claude connector publishes a "composing a reply" status around each turn.

Full detail in the CHANGELOG.

What's Changed

  • Stop the protocol from making passive hosts poll (v18) by @obeone in #69
  • chore(deps): bump cryptography and undici to patched versions by @obeone in #70
  • Cut what a connected agent pays in tokens per session by @obeone in #72
  • Faster hops, no duplicate replay by @obeone in #73
  • Room awareness: peek, turn status, decisions ledger by @obeone in #74
  • Slim the operating protocol to a fetch-on-demand core (v19) by @obeone in #71

Full Changelog: v2.3.1...v2.4.0

v2.3.1

Choose a tag to compare

@obeone obeone released this 04 Aug 14:27

Two fixes, both worth taking promptly if you installed 2.3.0 from PyPI.

A fresh install of 2.3.0 does not run

The mcp dependency was declared mcp[cli]>=1.9 with no ceiling, and mcp
2.0.0 removed mcp.server.fastmcp, which mcp_bridge and mcp_http are both
built on. Any install resolving to 2.x had no working entry point: caucus-bridge
died on import, and caucus-hub died at boot on a loopback bind, because it
imports mcp_http to serve /mcp. Environments built from uv.lock were fine,
which is why CI never caught it. The range is now mcp[cli]>=1.9,<2.

Two /mcp clients could merge into one identity

The default join name was resolved once per hub process, but one hub process
serves every Streamable HTTP client, so every client joining without an explicit
project asked for the same name. Since the hub measures liveness by the
in-flight long-poll, the incumbent looked dead between polls and the newcomer
inherited its Client record, token and inbox included. Two agents, one identity,
no error raised.

The default is now per session, from the MCP handshake's clientInfo.name, and a
name held by another live session is refused with name_in_use. Note that
clientInfo.name names the MCP host rather than the agent, so two sessions of the
same host still collide, just explicitly now. Pass join(project=...) when
several agents share a hub.

CAUCUS_PROJECT no longer affects the /mcp default. It still names the bridge
and the native connector, which run one process per agent.

Security

join over /mcp skips POST /register to avoid the per-host anti-flood bucket,
and was also skipping the model that rejects reserved names. A client could
register as human, hub or system and fabricate operator authority in the
sender field other agents read. Those guards, plus the 1-64 character bound, now
apply on that path too.

Full details in CHANGELOG.md.

What's Changed

  • chore(deps-dev): bump postcss from 8.5.15 to 8.5.23 in /web by @dependabot[bot] in #61
  • fix(deps): cap mcp below 2.0 so a fresh install still runs by @obeone in #65
  • fix(mcp-http): give each /mcp session its own join identity by @obeone in #64
  • docs(changelog): cut 2.3.1 by @obeone in #68

Full Changelog: v2.3.0...v2.3.1

v2.3.0

Choose a tag to compare

@obeone obeone released this 25 Jul 05:20
8602b2d

Added

  • missed on the send result. POST /send (and the say tool over it) now returns a missed list alongside delivered_to. A direct message addressed to a peer that is neither live nor reaped, so it was dropped rather than delivered, puts that peer's name in missed and logs a warning, turning a silent loss into an explicit signal. Broadcast and channel sends never populate it: there an empty delivered_to already means nobody heard the message.

Fixed

  • Stale ping() protocol guidance. The protocol text claimed only direct messages queue for a reaped peer; the hub has queued direct, broadcast and channel traffic for reaped peers alike since v1.0.0. The wording now matches the behaviour, and clarifies that "absent" means past the grace window. Bumps PROTOCOL_VERSION to 17.

Full changelog: v2.2.0...v2.3.0

What's Changed

  • ci: install the locked toolchain instead of re-resolving to latest by @obeone in #60
  • feat(hub): surface undeliverable direct sends via a missed field by @obeone in #52
  • chore(deps): bump mcp from 1.28.0 to 1.28.1 by @dependabot[bot] in #55
  • Add Claude Code GitHub Workflow by @obeone in #63
  • docs(changelog): cut 2.3.0, backfill 2.1.0/2.2.0, mandate continuous updates by @obeone in #62

Full Changelog: v2.2.0...v2.3.0

v2.2.0

Choose a tag to compare

@obeone obeone released this 20 Jul 06:14

Added

  • /mcp CORS support. The in-process Streamable HTTP MCP endpoint now
    answers the browser CORS preflight OPTIONS and exposes Mcp-Session-Id on
    its responses, so a browser-based MCP client (like the MCP Inspector, served
    from its own localhost origin) can connect. Loopback on any port is allowed by
    default, alongside the served host:port and any operator --allowed-origin
    entries; the allowlist is shared with the transport's DNS-rebinding check so
    the two never drift.

What's Changed

  • feat(mcp-http): answer CORS preflight on the /mcp endpoint by @obeone in #59

Full Changelog: v2.1.0...v2.2.0

v2.1.0

Choose a tag to compare

@obeone obeone released this 20 Jul 02:46

Run the hub as an on-demand background service

A new caucus-setup-service console script installs the Caucus hub as a
per-user service: a launchd agent on macOS, a systemd user unit on Linux. No
sudo, nothing written outside your home directory, --uninstall to undo it.

By default the hub starts on demand: the installer offers a SessionStart
hook that asks the service manager for the hub when an agent session opens, and
it stays idempotent even when several sessions start at once. --at-login keeps
it running permanently instead, and --no-hook leaves your settings file alone.

Any connector can wake the service, not just the one that first opens the room.

Safe by default: it refuses a non-loopback bind unless you pass
--operator-token, and --dry-run prints the plan and the generated unit
without touching anything.

See docs/running-as-a-service.md
for the options, the security notes, and the manual route.

Full Changelog: v2.0.0...v2.1.0

What's Changed

  • docs(readme): make Streamable HTTP the default transport by @obeone in #57
  • feat: run the caucus hub as an on-demand background service by @obeone in #58

Full Changelog: v2.0.0...v2.1.0

v2.0.0

Choose a tag to compare

@obeone obeone released this 17 Jul 10:06

Major bump because the MCP tool surface changed: hosts that call setup or the old talking-stick tools need an update.

Breaking

  • The five talking-stick tools (take_floor, pass_floor, drop_floor, raise_hand, floor_status) are now one floor(action, scope="all", reason=None), with action being take | pass | drop | raise | status. Per-action behaviour and return shapes are unchanged, so migrating is a rename.
  • The setup tool is gone. A session arms itself on its first tool call and fetches the protocol from the hub; join hands the protocol back. Read-only tools (list_peers, ping, list_channels, list_forms, floor(action="status")) still work before joining, so you can scout a room before committing to it.
  • Tool docstrings are trimmed of prose the hub-served protocol already carries. The bridge's tool-description footprint drops from roughly 4300 to 2300 tokens.
  • The operating PROTOCOL_VERSION moves to 16.

Fixed

  • The bridge no longer serves a superseded protocol under a fresh version label. When join found the session behind, it handed the new text to the caller but left the old text cached while still advancing the revision counter, so the next join believed itself current and served the stale protocol under the new label. A session arms only once, so nothing refreshed the cache and only a restart cleared it. That is exactly the drift the mandatory PROTOCOL_VERSION bump exists to prevent.
  • Armed-but-unjoined MCP HTTP sessions no longer leak. A session that armed on a first tool call but never joined owns no hub client, so the sweep (which only inspected joined sessions) could never see it and it lived for the process lifetime. Those records now age out against the same client_ttl idle window a joined peer gets, while joined records keep following the hub's client verdict, because a listening peer's liveness comes from its watcher polls rather than its tool calls. Records left behind by leave get reaped too.

Full changelog: v1.5.0...v2.0.0

What's Changed

  • docs: add a testimonial to the README by @obeone in #53
  • refactor: slim the MCP tool surface (floor fusion, setup removal, docstring trim) by @obeone in #54
  • docs(changelog): cut 2.0.0 by @obeone in #56

Full Changelog: v1.5.0...v2.0.0

v1.5.0

Choose a tag to compare

@github-actions github-actions released this 06 Jul 00:22
v1.5.0

What's Changed

  • feat: per-agent operator interrupt and reset by @obeone in #50
  • docs(changelog): cut 1.5.0 by @obeone in #51

Full Changelog: v1.4.0...v1.5.0

v1.4.0

Choose a tag to compare

@github-actions github-actions released this 03 Jul 08:17
v1.4.0

What's Changed

  • feat(protocol): forbid harness-blocking tools in the caucus room by @obeone in #41
  • chore: derive version from git tags (hatch-vcs) by @obeone in #43
  • ci: remove release-please, keep tag-driven hatch-vcs releases by @obeone in #44
  • feat: operator rate control, pause-on-typing, quiet-peer liveness & forms-only protocol by @obeone in #40
  • feat(automode): count operator form answers as user decisions in Claude Code auto mode by @obeone in #46
  • docs: rewrite README with operator screenshots by @obeone in #47
  • feat(hub): serve MCP Streamable HTTP directly at /mcp by @obeone in #48
  • chore(deps): bump pydantic-settings to 2.14.2 (security) and cut 1.4.0 by @obeone in #49

Full Changelog: v1.3.0...v1.4.0

v1.3.0

Choose a tag to compare

@caucus-release-bot caucus-release-bot released this 18 Jun 02:49

1.3.0 (2026-06-18)

Added

  • add an export button to the operator console (98541d7)
  • add war room hub and MCP bridge package (2689431)
  • bridge: add channel tools to the MCP bridge (6caad74)
  • bridge: add set_channel_topic tool and surface the join directory (d6b9a33)
  • bridge: add setup() gate and protocol version handshake (973d6d8)
  • bridge: deregister server-side on leave (8105700)
  • bridge: expose talking-stick tools (3dbc33f)
  • bridge: make the MCP bridge passive until join (9e7f656)
  • claude-agent: add talker/worker types and permission-mode selection (3d4ed05)
  • claude: add autonomous Claude connector on the Agent SDK (eb9f45b)
  • claude: add set_channel_topic tool and inject the channel directory (31673e5)
  • claude: let the native agent open and use private channels (b8e0dac)
  • connector: add ask_operator/list_forms to bridge and native connector (d35cbd2)
  • connector: add async HubConnector for native agents (d1f51ba)
  • connector: expose channel join/leave on the hub connector (e940bdd)
  • connector: expose set_channel_topic and the registration directory (dc001fc)
  • connector: resend token on re-join and handle name_in_use (d8e1067)
  • connector: talking-stick on the native path (a868e7a)
  • disklog: opt-in append-only JSONL event log (732448e)
  • export the chat log via a /export endpoint (4c1f4e3)
  • expose version via --version flag and /version endpoint (c6978e2)
  • hub: add message seq numbers and ACK mechanism with replay on reconnect (9dc443c)
  • hub: add peer ping and self-reported status (d65147e)
  • hub: add per-channel topics and a connect-time channel directory (d14ffef)
  • hub: add talking-stick floor control (e2fc79d)
  • hub: bump protocol to v5 for the one-shot watcher relaunch contract (cbd1247)
  • hub: dashboard WS protocol, auth/RBAC and static asset serving (93d62d4)
  • hub: expose /ask and /forms and form answering over /ui (55456e2)
  • hub: give channels a convener role for coordinated closes (8d291e3)
  • hub: make channels the default for focused pairs (7768c4c)
  • hub: open operator console in browser on startup (1d9054b)
  • hub: reap idle peers and add POST /leave endpoint (beb5b2c)
  • hub: refuse duplicate join under a name held by a live peer (bca30ce)
  • hub: revive idle-reaped peers on authenticated use (635ebfa)
  • hub: route messages to private channels (632ee39)
  • hub: serve a versioned operating protocol (b103bd1)
  • hub: teach the protocol about resuming work and the no-mailbox rule (16afd65)
  • invite agents to format messages in Markdown (10cb2b5)
  • models: add Field/Form models and answer message kind (b2e4c81)
  • models: reserve operator and hub identities and stamp message origin (d77489c)
  • protocol: keep watcher alive while awaiting a peer callback (1fd0a61)
  • protocol: make the shell watcher the default listener (064ef06)
  • ratelimit: add read-only available() probe to TokenBucket (f68d226)
  • state: add operator-form lifecycle (f77b7b8)
  • state: deregister and reap idle peers from the roster (023176e)
  • state: rich peer info, health metrics, per-peer pause, channel close (a08faef)
  • ui: add an operator kick button to the peer roster (a42b2e0)
  • ui: add operator console served by the hub (ea5831a)
  • ui: add operator-form wizard to the console (64b0d02)
  • ui: click names to target replies and highlight operator-bound messages (773949d)
  • ui: finish dashboard panels, add Vitest + Playwright suites (bb76fae)
  • ui: honor allow_other in operator forms (552aac5)
  • ui: operator dashboard SPA (Vite + React + TS + Tailwind + shadcn) (f2a4af6)
  • ui: readable operator feed with safe markdown rendering (b45bf78)
  • ui: rename console to Caucus, show hub version, add composer autocomplete (0ea61bb)
  • ui: show active talking sticks in the operator console (685e29e)
  • ui: show channel topics and load web fonts without blocking onload (9c742f8)
  • ui: stick-to-bottom auto-scroll in Flow timeline (d21442a)
  • ui: surface private channels in the operator console (1d53f50)
  • ui: v2 dashboard — left-rail layout, composer autocomplete, markdown flow (cb7dc50)
  • urlguard: fail-closed validation for the configurable hub URL (ebcb10b)
  • watch: add zero-token background watcher (d726eaf)

Fixed

  • agent: retry transient hub errors with backoff and guard...
Read more

v1.0.0 — first stable release

Choose a tag to compare

@obeone obeone released this 17 Jun 20:23
v1.0.0
70c921d

First stable release of Caucus — a supervised hub where multiple AI agents deliberate while a human keeps a hand on the kill switch. The protocol, HTTP API, and CLI surface are now stable under SemVer.

Highlights

  • Supervised multi-agent hub — agents talk directly, by broadcast, or in private #-channels, under a human operator who can pause, stop, reset, or kick.
  • Two connectors over one hub — a passive caucus-bridge (+ the zero-token caucus-watch listener) for turn-based MCP hosts, and a native autonomous caucus-claude-agent on the Claude Agent SDK.
  • Hub-owned operating protocol — served versioned at /protocol.
  • Talking stick floor control and private channels with topics and a convener role.
  • Operator forms — agents push questionnaires the operator answers in a console wizard.
  • Agent profilestalker vs worker, with a selectable permission mode.
  • Operator dashboard SPA (React + Tailwind) over WebSocket, with optional token auth and RBAC.
  • Loop safety — per-sender rate limiting, a hard operator Stop, and an idle reaper.

Install: uvx --from caucus-mcp caucus-hub — or pip install caucus-mcp.

See the README and CHANGELOG for full detail.