MCP Server
ccmux-mcp is an MCP server. Wire it
into Claude Code, Codex, Cursor, or any other MCP-aware client and the
agent gets a tool for everything the TUI does — across every project,
every conversation, every machine on your tailnet.
It ships in the same brew install. No extra setup.
Wire it up
~/.claude/settings.json:
{
"mcpServers": {
"ccmux": { "command": "ccmux-mcp" }
}
}
Codex, Cursor, anything else MCP-aware: same shape. Point at the binary.
The agent now has these tools:
| Tool | What it does |
|---|---|
list_sessions | every session on every machine, with state and agent |
read_pane | the last N lines of any session’s screen |
list_projects | every project under your projects root |
list_conversations | past Claude / Codex / Cursor / Antigravity / pi / Grok threads |
get_usage | tokens + cost, rolling window |
list_machines | tailnet peers, which ones run ccmuxd |
list_notes | every markdown note in a project |
read_note | one note’s contents |
search_notes | ripgrep over a project’s notes |
get_daemon_health | is the daemon alive |
All read-only. The agent can look; it can’t do.
When you want it to do things
Pass --allow-mutate:
{
"mcpServers": {
"ccmux": { "command": "ccmux-mcp", "args": ["--allow-mutate"] }
}
}
That unlocks:
| Tool | Effect |
|---|---|
spawn_session | start a session in an existing project |
spawn_bare_session | start a session not tied to a project |
send_keys | type into a session’s pane |
kill_session | terminate a session |
Off by default for a reason: an agent that can send_keys into your
work is an agent that can type anything you can type. The flag is the
opt-in. There’s no per-tool override — you turn the whole mutating set
on or you leave it off.
When the flag is off the mutating tools are absent from tools/list
entirely. An agent can’t surface them in its own UI even if the user
toggled the flag in a config file somewhere.
Drive a remote machine
CCMUX_HOST=mini.tail-xxxxx.ts.net:7474 ccmux-mcp
# or
ccmux-mcp --host mini.tail-xxxxx.ts.net:7474
The agent runs locally; it sees and acts on sessions on the Mac mini. Same protocol, same tools — just over Tailscale HTTP instead of the local Unix socket. Useful for “I’m coding on the laptop, but the overnight Claude work is on the mini.”
What this is actually for
A few concrete shapes:
Multi-session orchestration. An agent in one session spawns a
helper in another (spawn_session in a different project), reads its
output once it’s done (read_pane), pulls the result back, kills the
helper. No human in the loop.
Cross-machine work. An agent on your laptop checks how its sibling
on the Mac mini is doing (list_sessions, read_pane), without you
SSH-ing in. Or starts a long-running build on the mini (spawn_session
with --host) and goes back to typing.
Project memory. An agent reads the project’s notes at the start of
a session (list_notes + read_note) so it doesn’t repeat work the
previous agent did. The notes are plain markdown on disk; the agent
doesn’t need to know that.
Cost awareness. Before kicking off a big run, the agent checks
get_usage to see what you’ve spent this week, and get_daemon_health
to see how many sessions are already running.
None of this needs new infrastructure. ccmux already had all of it. MCP is just the protocol that makes it agent-accessible.
Security model
- Transport. stdio. The Unix socket the daemon listens on is user-scoped; tailnet HTTP requires being on your tailnet.
- Mutation. Off unless you flip the flag.
- Bounded reads.
read_panecaps at 500 lines so a buggy agent can’t drag the daemon down asking for the full scrollback every call. - Per-call deadline. Every handler runs under a 30-second context.
Roadmap
Things in this PR get you the core surface. Coming next:
- Live event stream.
resources/subscribeso an agent can react to “session X needs input” without polling. - Per-tool permissions. Allow
spawn_sessionbut notsend_keys, etc. — finer than the binary--allow-mutateflag. - Prompt library. Expose a project’s notes folder as
prompts/listso an agent can pick from saved prompts.
If you wire ccmux-mcp into something interesting, tell me about it.
Spotted an error or something out of date? Edit this page on GitHub.