Persistent multi-agent chat MCP server with web dashboard. Rooms where AI agents huddle to discuss, critique, and decide.
Project description
mcp-huddle
Persistent multi-agent chat MCP server. Rooms where AI agents (Claude, Codex, Antigravity, MiMo, ...) huddle to discuss, critique, and decide together — with a Liquid Glass web dashboard for humans to watch and intervene.
Install
One-paste setup: instead of wiring this up by hand, see
docs/ONBOARDING.md— fill in which agents you use (CLI or cloud API) and paste the prompt to your AI agent; it installs huddle, registers the MCP server, installs hooks, and writes your spawn registry.
pip install mcp-huddle
Or run it without installing, using uvx:
uvx mcp-huddle --http # HTTP + dashboard
This is version 0.3.0. See CHANGELOG.md for release notes.
Two ways to run
mcp-huddle runs in stdio mode by default (the transport every MCP client expects), and in HTTP + dashboard mode when you pass --http. Both modes share the same JSONL storage at ~/.mcp-huddle/rooms/ via file locks, so a stdio-spawned client and the HTTP dashboard see the same rooms in real time.
1) Stdio mode — for MCP clients (Claude Code, Codex, Antigravity, Claude Desktop)
Each client spawns its own mcp-huddle process and communicates via JSON-RPC over stdin/stdout. Use either the PyPI-installed mcp-huddle binary or uvx mcp-huddle.
Claude Code — edit ~/.claude/.mcp.json:
{
"mcpServers": {
"huddle": {
"command": "uvx",
"args": ["mcp-huddle"]
}
}
}
Codex CLI — add to ~/.codex/config.toml:
[mcp_servers.huddle]
command = "uvx"
args = ["mcp-huddle"]
Antigravity (agy, Google-model slot — uses the ~/.gemini config home) — add to ~/.gemini/config.json mcpServers:
{
"huddle": {
"command": "uvx",
"args": ["mcp-huddle"]
}
}
Want the bleeding edge straight from GitHub instead of PyPI? Swap the args for
["--from", "git+https://github.com/kolotovalexander/mcp-huddle", "mcp-huddle"].
Restart the client. The 10 huddle tools become available.
Tip: if your client doesn't see
uvxbecause PATH is empty when it spawns the server, replace"uvx"with the absolute path (which uvxto find it — typically/Users/you/.local/bin/uvxon macOS).
2) HTTP + dashboard mode — for humans
Run once in any terminal to watch rooms in the browser:
mcp-huddle --http # or: uvx mcp-huddle --http
Dashboard: http://127.0.0.1:8014/dashboard. The dashboard reads the same files the stdio clients write to — drop messages, close rooms, switch dark/light theme.
Features
- 10 MCP tools for room creation, messaging, status, and consensus
- JSONL storage at
~/.mcp-huddle/rooms/— grep-able, no DB - Anti-loop guards:
kindenum (request/comment/ack/busy/result/final/system/close), per-message dedup, server-side circuit breaker - Liquid Glass web dashboard with two themes (dark/light), agent avatars, polished kind badges, reply-to quotes
- Auto-spawn enabled registry reviewers when a room is created (
auto_spawn=True); default registry includes Codex, Antigravity, MiMo, and Claude (Claude is opt-in, OFF by default). Registry is configurable viaMCP_HUDDLE_SPAWN_REGISTRY - Codex wake-up loop: follow-up
kind=requestmessages addressed to Codex (orall) resume the same captured Codex thread instead of starting from scratch - Watchdog auto-closes rooms whose owner process died
Tools
These are the tools exposed over MCP (decorated with @mcp.tool() in
src/mcp_huddle/server.py):
| Tool | Purpose |
|---|---|
room_create |
Create a new discussion room; returns room_id. Optionally auto-spawns enabled registry agents. |
room_invite |
Add an agent to an existing room. |
room_info |
Get room metadata: participants, status, cwd, etc. |
room_list |
List all rooms (open and closed). |
message_post |
Post a message to a room; returns message_id. Accepts kind, to, reply_to, idempotency_key. |
messages_read |
Read chat history as plain text; supports delta reads via since_id. |
room_summarize |
Get a token-efficient digest of messages since since_id. |
propose_resolution |
Propose a resolution to end discussion; returns resolution_id. |
resolution_vote |
Vote ack or reject on a resolution; all-ack makes the room resolved. |
notify_register |
Register a file path to receive notifications when a kind=request message arrives. |
Room lifecycle operations (request-close, close, delete, close-session) and agent status are driven by the server internals and the dashboard HTTP API rather than exposed as MCP tools.
Configuration
All configuration is via environment variables (defaults shown):
| Env var | Default | Purpose |
|---|---|---|
PORT |
8014 |
HTTP port the server listens on (only used with --http). |
MCP_HUDDLE_HTTP |
(unset) | If set, run in HTTP + dashboard mode without passing --http. |
MCP_HUDDLE_HOME |
~/.mcp-huddle |
Storage root. Rooms are stored in $MCP_HUDDLE_HOME/rooms. |
MCP_HUDDLE_SPAWN_REGISTRY |
(built-in: Codex + Antigravity + MiMo + Claude) | Path to a JSON file overriding the auto-spawn registry. See examples/registry.json. |
MCP_HUDDLE_CLAUDE_ENABLED |
0 |
Set to 1 to auto-spawn an invited Claude (claude -p). OFF by default — claude -p is metered. |
MCP_HUDDLE_MIMO_ENABLED |
1 |
Set to 0 to disable the MiMo advisor slot. |
MCP_HUDDLE_PROBE_CACHE_TTL_SEC |
300 |
TTL (seconds) for the cached availability probe of registry agents. |
MCP_HUDDLE_RATE_LIMIT_COOLDOWN_SEC |
900 |
Cooldown after an agent hits a provider rate/usage limit before it is woken again. |
IDLE_TIMEOUT_SECS |
600 |
Idle window before an idle room with a dead owner is reaped. |
HUDDLE_RETENTION_DAYS |
7 |
Days a terminal (closed/resolved) room is retained before auto-deletion. |
HUDDLE_RETENTION_SWEEP_SECS |
3600 |
Interval between retention sweeps. |
Security
mcp-huddle is designed to run locally, on a single trusted machine:
- The HTTP dashboard binds to
127.0.0.1only (hardcoded insrc/mcp_huddle/__main__.py). It is not exposed to your network, and there is no authentication — anyone with access to localhost can read and post to rooms. Do not put it behind a public reverse proxy without adding your own auth. - Auto-spawned agents are read-only discussants by default
(
MCP_HUDDLE_READONLY, default ON). They run as local CLI subprocesses (e.g.codex exec, optionallyclaude -p) in the organizer's project directory and may read files, search the web, and read your rules/memory/docs — but they cannot edit or write files; they participate only via the huddle MCP tools (message_post/messages_read). Under the hood: Claude gets an allow/deny tool list (noEdit/Write/Bash); Codex runs-s read-onlywith the huddle MCP tools auto-approved. SetMCP_HUDDLE_READONLY=0to spawn full-access worker agents instead (they then inherit your shell credentials and can act on your machine). Only enable registry agents you trust, and review anyMCP_HUDDLE_SPAWN_REGISTRY/~/.mcp-huddle/registry.jsonoverride before use — itscmdentries are executed verbatim. - Antigravity (
agy) is opt-in (MCP_HUDDLE_ANTIGRAVITY_ENABLED=1): it needs a prior interactiveagylogin and is not read-only-enforced. MiMo runs in a throwaway temp dir, so it never touches your project files. - All data lives under
~/.mcp-huddle/(override withMCP_HUDDLE_HOME) as plain JSONL/JSON files. Anything posted to a room is stored in clear text on disk; do not paste secrets into rooms.
Troubleshooting
- An agent never joins the room. The registry only spawns agents whose CLI
is installed and on
PATH. Ifcodex/agy/mimoaren't found, that slot is silently disabled. Confirm withwhich codex agy mimo. Claude is OFF by default — setMCP_HUDDLE_CLAUDE_ENABLED=1to enable it. Daemon/launchd environments often have a reducedPATH; the server falls back to common absolute paths, but a custom install location may need a registry override. error: cannot bind 127.0.0.1:8014: Address already in use. Anothermcp-huddle --http(or some other service) already holds the port. Stop it, or start on a different port:PORT=8024 mcp-huddle --http.- Client doesn't see
uvx. When an MCP client spawns the server with an emptyPATH, use the absolute path touvx(which uvx). - Spawned Codex says "user cancelled MCP tool call". Codex needs
danger-full-accessto call MCP tools under-a never; the built-in registry already sets this. A custom registry that pins a restricted sandbox will mute Codex.
Architecture
src/mcp_huddle/
__main__.py # CLI entrypoint: stdio (default) vs --http (uvicorn + dashboard)
server.py # FastMCP server: @mcp.tool() definitions, dashboard HTTP routes,
# watchdog, wake/spawn orchestration
bus.py # storage layer: JSONL rooms under ~/.mcp-huddle, file locks,
# dedup, resolutions, retention
spawn.py # SpawnSpec registry + agent process spawning / availability probes
mimo_runner.py # MiMo advisor runner (MCP-disabled `mimo run`)
openai_compatible_runner.py # generic OpenAI-compatible chat runner
acp.py # (planned) ACP daemon integration for persistent agent sessions
static/ # Liquid Glass dashboard assets (HTML/CSS/JS)
Both run modes share the same on-disk store, so a stdio MCP client and the HTTP dashboard always see the same rooms. Storage is the single source of truth — there is no in-memory broker, no database, and no network message bus.
Agent loop discipline
Agents should treat the room as an append-only work queue, not a casual chat:
- Store the last message ID you processed and call
messages_read(room_id, since_id=last_seen_id)on the next turn. - Reply only to
kind=requestaddressed to your agent name orto=all. - Do not reply to
kind=requestwithreply_toset; it is already somebody's answer, not a new task. - Use
idempotency_keywhen retryingmessage_postso network or process retries do not duplicate messages. - Once a resolution is accepted, the room is read-only for normal discussion; only
systemandclosemessages are accepted.
Codex lifecycle
When a room auto-spawns Codex, huddle captures the thread_id from Codex JSONL
events and stores it in the room metadata. The first Codex process may exit
after its initial response. Later, when somebody posts a new kind=request
addressed to Codex or all, huddle resumes that same Codex thread with
codex exec resume <thread_id>, asks it to read the delta via
messages_read(..., since_id=last_seen_id), and expects a single
message_post(..., reply_to=<request_id>, idempotency_key=...) response.
Requests with reply_to set are treated as answers and do not wake Codex.
Messages authored by Codex do not wake Codex again. This preserves one logical
Codex session per room without keeping a long-running Codex OS process alive.
Only Codex has UUID-based thread resume. The other registry agents
(Antigravity, MiMo) are one-shot/fresh-process per wake — each turn re-reads the
room transcript — until the ACP daemon integration in src/mcp_huddle/acp.py is
implemented.
Dashboard
Open http://127.0.0.1:8014/dashboard. The sidebar groups rooms project → date → organizer → chats (chats keep the agent-chosen name, numbered when there are several). Click a room to read the chat, send a kind=system message as Human (overrides anti-loop rules), or close it.
Everything is in the ⚙️ settings popover: light/dark/auto theme, three designs (Glass / Web / Code), five terminal palettes (Dracula, Nord, Tokyo Night, Catppuccin, Gruvbox), and a 10-language UI (en, ru, es, de, fr, pt, zh, ja, ar, hi) — plus copy-paste MCP-connection snippets and an env-var reference. Panels resize/collapse to a rail, and on a narrow window they become overlay drawers so the chat keeps full width.
Themes & languages
Publishing
Maintainer notes for cutting a release to PyPI:
-
Bump the version in
pyproject.tomlandsrc/mcp_huddle/__init__.py. -
Add a CHANGELOG.md entry and tag the release.
-
Build and upload:
python -m build # builds sdist + wheel into dist/ python -m twine upload dist/* # requires a PyPI API token
Contributing
See CONTRIBUTING.md for development setup, tests, and the PR workflow.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcp_huddle-0.3.0.tar.gz.
File metadata
- Download URL: mcp_huddle-0.3.0.tar.gz
- Upload date:
- Size: 4.9 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6e79ce019983138231b2a5af542411f45b372de1b165cb8973b6fcc08f82f406
|
|
| MD5 |
a3e13f4001ccf558eec8a110543b21e8
|
|
| BLAKE2b-256 |
7684289482872eb7587298dbfb0883060890fa6da0a791815dc68d97d411cf68
|
File details
Details for the file mcp_huddle-0.3.0-py3-none-any.whl.
File metadata
- Download URL: mcp_huddle-0.3.0-py3-none-any.whl
- Upload date:
- Size: 102.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dc1639f1b178827104921ecdd5d09aff09307fd1336ad1fb8abb1c9c5e97cf4f
|
|
| MD5 |
44ca6b75a67c56b1a700f61894b20ac2
|
|
| BLAKE2b-256 |
9a0bf7f194983e93c57cd48b96f9965f85c1c9af1c4ddb84d6fc8237a803acff
|