MCP server for cross-session Claude Code communication and coordination.
When running multiple Claude Code sessions (in separate terminals or worktrees), each session is isolated. This MCP server provides an event bus for sessions to:
- Announce presence - Know what other sessions are active
- Broadcast status - Share progress updates and task completion
- Coordinate work - Signal dependencies and handoffs
- Send notifications - System notifications with custom icon support
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ CC Session 1 │ │ CC Session 2 │ │ CC Session 3 │
└────────┬────────┘ └────────┬────────┘ └────────┬────────┘
└────────────────────┼────────────────────┘
▼
┌───────────────────────────────────┐
│ agent-event-bus (localhost) │
└───────────────────────────────────┘
Run the event bus server on this machine:
git clone https://github.com/evansenter/agent-event-bus.git
cd agent-event-bus
make install-serverInstalls: venv, LaunchAgent (auto-start), CLI (~/.local/bin/agent-event-bus-cli), MCP server pointing to localhost.
Connect to an event bus running on another machine (e.g., via Tailscale):
git clone https://github.com/evansenter/agent-event-bus.git
cd agent-event-bus
make install-client REMOTE_URL=https://your-server.tailnet.ts.net/agent-event-bus/mcpInstalls CLI and configures MCP to point to the remote server. Add the URL to your shell profile:
# In your shell profile (~/.extra, ~/.zshrc, etc.)
export AGENT_EVENT_BUS_URL="https://your-server.tailnet.ts.net/agent-event-bus/mcp"Ensure ~/.local/bin is in PATH: export PATH="$HOME/.local/bin:$PATH"
| Tool | Description |
|---|---|
register_session |
Register session, get session_id + cursor |
list_sessions |
List active sessions |
list_channels |
List channels with subscriber counts |
publish_event |
Publish event to channel |
get_events |
Poll for events (use resume=True for incremental) |
ack_events |
Mark events seen up to an id you already hold (pairs with peek) |
unregister_session |
Clean up on exit |
notify |
System notification |
register_webhook |
Register HTTP endpoint for push notifications |
list_webhooks |
List registered webhooks |
set_webhook_active |
Pause/resume a webhook without unregistering |
unregister_webhook |
Remove a webhook |
Events include channel metadata for context. All sessions see all events (broadcast model).
| Channel | Context |
|---|---|
all |
General broadcast (default) |
session:{id} |
Direct message (triggers notification) |
repo:{name} |
Repository-specific |
machine:{name} |
Machine-specific |
For shell scripts and hooks:
# Register (returns session_id)
SESSION_ID=$(agent-event-bus-cli register --name "my-feature" --client-id "$$" --json | jq -r .session_id)
# Publish and notify
agent-event-bus-cli publish --type "done" --payload "Finished" --channel "repo:my-project"
agent-event-bus-cli notify --title "Build" --message "Complete" --sound
# Poll for events (incremental)
agent-event-bus-cli events --session-id "$SESSION_ID" --resume --order asc
# Cleanup
agent-event-bus-cli unregister --session-id "$SESSION_ID"Push events to HTTP endpoints instead of polling. Webhooks are called asynchronously when events are published.
agent-event-bus-bridge is the experimental local consumer of this
mechanism: a daemon that wakes idle sessions when an actionable DM arrives
(RFC #122). On macOS, make install-bridge supervises it as a LaunchAgent;
elsewhere run it as uv run agent-event-bus-bridge from the checkout, since
nothing symlinks it onto PATH. See docs/BRIDGE.md.
# Register a webhook for all events
register_webhook(url="https://your-server.com/events")
# Filter by channel (prefix matching supported)
register_webhook(url="https://...", channel="session:")
# Filter by event type
register_webhook(url="https://...", event_types=["task_completed", "help_needed"])
# With HMAC signature verification
register_webhook(url="https://...", secret="your-shared-secret")
# List and manage
list_webhooks() # active_only=False also shows paused
set_webhook_active(webhook_id=1, active=False) # pause, keeping the registration
unregister_webhook(webhook_id=1)# Register
agent-event-bus-cli webhook register --url https://your-server.com/events
agent-event-bus-cli webhook register --url https://... --channel "session:" --secret "my-secret"
# List (paused webhooks only show under --all)
agent-event-bus-cli webhook list
agent-event-bus-cli webhook list --all
# Pause / resume - keeps the URL, filters, and secret
agent-event-bus-cli webhook disable 1
agent-event-bus-cli webhook enable 1
# Remove (permanent)
agent-event-bus-cli webhook unregister 1Webhooks receive a POST with JSON body:
{
"event_id": 123,
"event_type": "task_completed",
"payload": "Finished building feature X",
"session_id": "abc-123",
"timestamp": "2026-01-31T08:00:00",
"channel": "repo:my-project",
"correlation_id": null,
"signal_level": "info"
}correlation_id and signal_level are always present (signal_level is
server-derived); title and tags appear only when the event carries them.
If a secret is configured, requests include an X-Event-Bus-Signature header:
X-Event-Bus-Signature: sha256=<hmac-sha256-hex>
Verify by computing HMAC-SHA256 of the raw request body with your secret.
Run one server, connect from multiple machines via Tailscale (or any VPN).
Server machine:
make install-serverEdit ~/Library/LaunchAgents/com.evansenter.agent-event-bus.plist, add to EnvironmentVariables:
<key>HOST</key>
<string>0.0.0.0</string>Then restart: make restart
Note:
make install-serveroverwrites the plist. To persist this setting, also editscripts/com.evansenter.agent-event-bus.plist(uncomment the HOST lines).
Client machines:
make install-client REMOTE_URL=https://your-server.tailnet.ts.net/agent-event-bus/mcpThen add to your shell profile:
export AGENT_EVENT_BUS_URL="https://your-server.tailnet.ts.net/agent-event-bus/mcp"New Claude Code sessions will have full mcp__agent-event-bus__* tool access to the central server.
make dev # Install with dev dependencies
./scripts/dev.sh # Run in foreground with auto-reload
make check # Format + lint + testRequires terminal-notifier for custom icon: brew install terminal-notifier
All data in ~/.claude/contrib/agent-event-bus/: data.db (plus its WAL
sidecars data.db-wal and data.db-shm, which are part of the database),
agent-event-bus.log, agent-event-bus.err. Never copy data.db alone -
use sqlite3 data.db ".backup <dest>" for a consistent backup.
- claude-session-analytics - Historical session analysis
- dotfiles -
/parallel-workcommand and hooks