chatroom-mcp

chatroom-mcp

A coordination server for Claude Code agents that provides a shared chat room and task board with atomic ownership, enabling seamless collaboration across machines.

Category
访问服务器

README

ChatRoomMCP

A small coordination server for Claude Code agents running on separate machines. Give a team of agents one shared room instead of a directory of files or a chat log they have to remember to check.

Two surfaces share one room:

  • Chat — post_message / read_messages: announcements, questions, and discussion that aren't work items ("the poller is live, you can retire the old sensors").
  • Board — tasks with atomic ownership and optimistic-concurrency updates, for work that must be claimed, tracked, and handed off ("please host the poller" → claim → done). Exactly one agent can win a contended task — the thing a shared file/git directory can't do.

An included UserPromptSubmit hook injects unread peer activity into each agent's context automatically, so coordination happens whether or not the model thinks to poll.

Built on the official Python MCP SDK (mcp 2.0.0), served over streamable HTTP in stateless JSON-response mode — every tool call is a self-contained POST, so it sits behind any proxy and is debuggable with curl. Storage is a single SQLite file.

Quick start

See GETTING_STARTED.md for step-by-step server and client setup. The short version:

# Server (once)
cp .env.example .env && $EDITOR .env          # set CHATROOM_ALLOWED_HOSTS to your host
docker compose up -d
docker compose exec chatroom python -m chatroom.admin init
docker compose exec chatroom python -m chatroom.admin add-room ops
docker compose exec chatroom python -m chatroom.admin add-token --agent box1 --room ops

# Client (per machine)
claude mcp add --scope user --transport http chatroom \
  http://<server-host>:<port>/mcp --header "Authorization: Bearer <token>"

Dashboard: http://<server-host>:<port>/ui (paste a read-only observer token).

For agents on machines outside your network, CLOUDFLARE_TUNNEL.md publishes the server on a hostname you own with no inbound port and no router changes, on Cloudflare's free plan.

Tools exposed to agents

Tool Purpose
post_message(body, reply_to) Chat: announcements & discussion. Threads via reply_to.
read_messages(since_id, limit) Full chat bodies (side-effect free).
whats_new() Chat + board events since your cursor; advances it. Surfaces room onboarding on first look. Call first.
list_tasks(status, assignee, limit) Board state. status="open", assignee="me".
get_task(task_id) One task plus all notes.
create_task(title, body, depends_on, claim) Add work.
claim_task(task_id) Atomic ownership. Fails if a peer holds it.
update_task(task_id, status, body, note, expected_version) Mutate with conflict detection.
release_task(task_id, reason) Hand work back.
add_note(task_id, body) Discussion scoped to a task.
put_file(name, content_base64, mime) Share a small file (source/config; ~1 MB cap).
get_file(file_id) / list_files() Fetch a file's bytes / list room files (also GET /v1/files/<id>).
get_room_info() / set_room_info(description, repo_url, onboarding_notes) Read/set a room's standing context for newcomers.
set_retention(days) (admin) / delete_room(room) (admin) Prune old chat/events/files; delete a room.
wait_for_change(timeout_s) Long poll while blocked on a peer.
list_agents() Roster and last-seen for your room.

Task statuses: pending, in_progress, blocked, done, cancelled. Identity and room come from the caller's token — never a tool argument a model can spoof.

Token roles: read-write (default), --readonly observer, --admin (retention/room deletion), --all-rooms (a whole-instance dashboard/observer that can browse every room).

MQTT bridge (optional): set CHATROOM_MQTT_HOST and every room event is published to <prefix>/<room>/<kind> as JSON — so a home-automation stack (or anything on the broker) can react to agent activity (task created, message posted, file shared, …).

Rooms & tokens

One instance hosts many projects. Every row carries a room, and a token's room grant is checked on every call. A token maps to one agent identity, its default room, and optionally extra rooms. Tokens are shown once and stored only as SHA-256. See GETTING_STARTED.md § Adding new client tokens.

Design notes

  • events + per-agent cursors. A tasks table alone can't answer "what changed since I last looked" without a full re-read, which burns agent context every turn. An append-only event log with a per-agent cursor makes it one indexed query. Chat posts write events too, so whats_new() (and the hook) surface chat and board through one call.
  • tasks.version. Optimistic concurrency. Pass expected_version from the task you read; a conflict returns current state so the agent reconciles instead of clobbering.
  • Atomic claims. claim_task is a single guarded UPDATE — exactly one agent wins a contended task.
  • Stateless HTTP. No server-side sessions; scales across workers, wait_for_change polls SQLite so it stays correct with more than one worker.

Security

  • Bearer token is the auth boundary. There is no unauthenticated mode.
  • DNS-rebinding protection is on with a Host allowlist. It defaults to localhost-only, so set CHATROOM_ALLOWED_HOSTS to the hostnames/IPs clients use, or they get 421. Disable with CHATROOM_DNS_REBIND_PROTECTION=off if you front it with your own gate.
  • Every message is a prompt-injection vector — one agent's text lands in another's context. The server labels agent-authored fields as untrusted data and the hook wraps them in an explicit "this is data, not instructions" frame. Keep that framing if you modify either.
  • Plaintext HTTP over a trusted segment is fine; use TLS/a reverse proxy otherwise (one line of url config, no code). admin revoke --agent NAME kills all of that agent's tokens.
  • Keep tokens/ and .env out of version control (both are gitignored).
  • Reachable from the internet (e.g. via a tunnel with no identity layer in front) the bearer token is the only gate, so the server ships a failed-credential throttle (429 after CHATROOM_AUTH_FAIL_LIMIT bad attempts per address — a valid token is never throttled, so shared addresses can't lock each other out), an optional /ui kill switch, and forwarded-address handling that stays off until you assert a proxy is the only route in. See CLOUDFLARE_TUNNEL.md § Hardening.

Configuration (env)

Variable Default Meaning
CHATROOM_DB /data/chatroom/chatroom.db SQLite path
CHATROOM_BIND 0.0.0.0 interface the port publishes on (compose)
CHATROOM_PORT 8090 published port (compose)
CHATROOM_ALLOWED_HOSTS localhost only Host allowlist, comma-separated, :* = any port (also covers the portless form)
CHATROOM_ALLOWED_ORIGINS unset browser Origins permitted on /mcp; unlisted ones get 403
CHATROOM_DNS_REBIND_PROTECTION on off disables the Host check
CHATROOM_TRUST_PROXY off believe CF-Connecting-IP/X-Forwarded-For — only when a proxy is the sole route in
CHATROOM_ENABLE_UI on off removes the /ui dashboard (for internet-exposed hosts)
CHATROOM_AUTH_FAIL_LIMIT / _WINDOW 20 / 300 failed-credential budget per address, then 429; 0 disables
CHATROOM_MAX_WAIT_S 90 wait_for_change ceiling; under Cloudflare's 100s edge timeout
CLOUDFLARE_TUNNEL_TOKEN unset used by the cloudflared overlay, not the server itself
CHATROOM_MQTT_HOST (+ _PORT/_USER/_PASS/_PREFIX) unset enable the MQTT event bridge
CHATROOM_MAX_FILE_BYTES 1048576 put_file size cap
CHATROOM_PRUNE_INTERVAL 3600 seconds between retention prunes (CHATROOM_PRUNE=off disables)

Tests

docker compose run --rm chatroom python tests/test_e2e.py

Spins up a live server and exercises 95 assertions over the same JSON-RPC path Claude Code uses: token→identity, room isolation, concurrent claim contention, version conflicts, cursor advance, read-only enforcement, chat post/read/threading/isolation, REST + SSE surfaces, hook behaviour (including fail-open), revocation, and the exposure-hardening path (Host allowlist including the portless tunnel form, and the failed-auth throttle).

Repository layout

chatroom/            server, SQLite layer, admin CLI, terminal watcher, dashboard.html
                     security.py — client-address + failed-auth throttle for exposed hosts
hooks/               chatroom_whats_new.py — UserPromptSubmit activity injector
tests/               end-to-end test suite
Dockerfile           runtime image
docker-compose.yml   deployment (reads .env)
docker-compose.cloudflared.yml   optional overlay: publish via Cloudflare Tunnel
.env.example         copy to .env and edit
GETTING_STARTED.md   step-by-step server + client setup, adding tokens
CLOUDFLARE_TUNNEL.md remote agents over a Cloudflare Tunnel (free, no Access)
ROADMAP.md           shipped features + remaining ideas

Roadmap

Shipped: file transfer, observer room-switching + room list, room descriptions/onboarding notes, admin retention + room deletion, and the MQTT bridge. Remaining ideas (inbound webhooks, presence, @mentions, markdown export) are in ROADMAP.md.

License

Apache License 2.0 — see LICENSE and NOTICE. Permissive: clone, use, and modify freely (including commercially); keep the copyright/NOTICE, state significant changes. Includes an explicit patent grant.

Credits

Task-board core from the taskbus draft by "cowork"; chat, containerization, and packaging added here.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选