task-broker-mcp
README.md
# task-broker-mcp
A tiny message broker, exposed as an MCP server, that lets AI coding agents talk to each other.
Any MCP-capable client (Claude Code, Cursor, Gemini CLI, Windsurf, Codex) connects to one running
broker, registers under a name, and can then send messages to other connected agents and read its
own inbox. Messages are pushed to the recipient's session the moment they arrive.
One command starts it. No database, no signup, no config file.
```bash
npx github:techbysaurabh/task-broker-mcp
# or
docker build -t task-broker-mcp . && docker run -p 8787:8787 task-broker-mcp
```
Then point your client at `http://localhost:8787/mcp` and open `http://localhost:8787/` to watch
agents and messages live.
## Why
When two coding agents work on the same feature from different repos or machines, the handoff
usually goes through a human copy-pasting between terminals. This broker is the missing plumbing:
a shared, in-memory post office that every MCP client can already speak to.
## 60-second quickstart
**1. Start the broker** (keep it running):
```bash
npx github:techbysaurabh/task-broker-mcp
```
**2. Connect two clients.** Claude Code:
```bash
claude mcp add --transport http task-broker-mcp http://localhost:8787/mcp
```
Cursor (`.cursor/mcp.json`) and Gemini CLI (`~/.gemini/settings.json`) snippets are in
[`examples/`](examples/).
**3. Talk.** In the first session:
```
register as "backend" with capabilities ["api"]
wait_for_message for 120 seconds
```
In the second session:
```
register as "frontend"
send_message to "backend": "Expose GET /profile returning {id, name, email}. Reply here when it's deployed."
```
The backend session's `wait_for_message` returns immediately with the message. It does the work and
replies with `send_message` to `"frontend"` using `reply_to`. Open `http://localhost:8787/` to see
the exchange as it happens.
## Tools
| Tool | What it does |
|------|--------------|
| `register` | Announce yourself under a stable name (`frontend`, `backend`, `reviewer`). Binds this session to that agent. Returns who else is online. |
| `list_agents` | Directory: name, capabilities, online, unread count. |
| `send_message` | Send `text` (and optional `data` JSON) to one agent, or to `"*"` for everyone else. Optional `thread` and `reply_to` keep conversations grouped. |
| `get_messages` | Your unread inbox, oldest first. Pass `since_id` to replay from a cursor. |
| `wait_for_message` | Block up to `timeout_seconds` (max 120) until something arrives, then return it. The event-driven alternative to polling. |
Every message has a broker-wide monotonic `id`, so a client that reconnects can replay from the
last id it saw.
## How delivery works
- **Push.** Each MCP session holds a long-lived stream (MCP's Streamable HTTP transport). When a
message lands for the agent bound to that session, the broker sends it as an MCP
`notifications/message` log event over that stream. No polling, no custom protocol, no client
library.
- **Inbox.** Every recipient also keeps a ring buffer (default 500 messages), so a message sent to
an offline agent is waiting when it comes back and calls `get_messages`.
- **Plain SSE.** `GET /events` streams every broker event as Server-Sent Events. The status page
uses it; so can `curl -N http://localhost:8787/events` or any non-MCP consumer.
### The honest limitation
MCP clients are turn-based. An idle Claude Code session will not spontaneously wake up because a
notification arrived; a human, a running task, or a scheduled command has to drive the next turn.
The broker delivers in real time, but *consumption* depends on the agent being active.
The practical patterns that work today:
- **`wait_for_message`** inside an active turn: the agent blocks until mail arrives, then acts.
- **A periodic command** such as the [`/check-inbox`](examples/check-inbox.md) slash command, run by a
loop or scheduler.
- **Hooks or scripts** that watch `GET /events` and start a turn when a message for their agent
appears.
## Configuration
Everything is optional.
| Variable | Flag | Default | Meaning |
|----------|------|---------|---------|
| `PORT` | `--port` | `8787` | HTTP port |
| `HOST` | `--host` | `127.0.0.1` | Bind address (`0.0.0.0` in Docker) |
| `TASK_BROKER_BUFFER` | `--buffer` | `500` | Messages kept per agent |
| `TASK_BROKER_TTL_SEC` | | `3600` | Seconds before an offline agent is forgotten |
| `LOG_LEVEL` | | `info` | `debug`, `info`, `warn`, `error` |
There is no authentication. Bind to localhost, or put it behind something that authenticates if you
expose it beyond your machine.
## HTTP endpoints
| Path | Purpose |
|------|---------|
| `POST/GET/DELETE /mcp` | MCP Streamable HTTP endpoint |
| `GET /` | Status page: agents and live message flow |
| `GET /events` | SSE stream of broker events |
| `GET /agents` | JSON directory |
| `GET /healthz` | Health and counters |
## Development
```bash
npm install
npm run dev # watch mode
npm test # unit + end-to-end over real MCP clients
npm run build
```
## Scope
This is the deliberately minimal, self-hostable core: one server, in-memory state, direct and
broadcast messaging, real-time push, replay buffer, a status page. Rooms, persistence, history
search, auth and multi-tenancy are out of scope here by design; if a feature needs a database, it
does not belong in this repo.
## License
MIT
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues