Out of the box every `allow_*` gate is `true`, the command filter is `off`, and no socket, session or pane allowlist is set — convenient locally, but that is not a sandbox. The practical hardening is an isolated socket plus a `config.toml` that sets `allowed_sockets` and denies the `@raw-input` group, so shell input has to go through `execute-command` where the regex command filter and tracking apply; `TMUX_MCP_TOOLS=deny:@raw-input` does the same for one process without a file.
An MCP server for tmux, written in Rust. Every tmux operation is a named tool with typed parameters and stable IDs, so a client never has to infer a pane ID from captured text or guess whether a command has finished. Long-running work runs as a tracked command that returns a `commandId` and a resource URI; completion arrives through a private tmux exit buffer and `wait-for` signal rather than scraped scrollback. Because the session is a normal tmux session, a human can attach to it mid-task.
- Sessions, windows and panes created, renamed, split, resized, zoomed, joined, broken out and killed — `create-session`, `create-window`, `split-pane`, `rename-session`, `rename-window`, `rename-pane`, `select-layout`, `resize-pane`, `zoom-pane`, `join-pane`, `break-pane`, `swap-pane`, `kill-session`, `kill-window`, `kill-pane`
- Shell commands run with tracking: a command ID, a status of `queued`, `running`, `completed`, `failed` or `tracking_error`, and the output between markers — `execute-command`, `get-command-result`
- Live pane text for progress checks, plus listings of sessions, windows, panes and clients — `capture-pane`, `list-sessions`, `find-session`, `list-windows`, `list-panes`, `list-clients`, `get-current-session`
- Tmux buffers used as an external search space: read a slice, search literal or regex with byte offsets and resume cursors, then write or file the result — `list-buffers`, `show-buffer`, `search-buffer`, `subsearch-buffer`, `set-buffer`, `append-buffer`, `save-buffer`, `load-buffer`, `delete-buffer`, `rename-buffer`
- Raw keystrokes for prompts, REPLs, pagers and TUIs, including the special keys — `send-keys`, `paste-text`, `send-hex`, `send-cancel`, `send-eof`, `send-escape`, `send-enter`, `send-tab`, `send-backspace`, `send-up`, `send-down`, `send-left`, `send-right`, `send-page-up`, `send-page-down`, `send-home`, `send-end`
- A deterministic per-project socket path, and read-only resources for server info, pane tails, window and session trees and tracked command results — `socket-for-path`, `tmux://server/info`, `tmux://pane/{paneId}/tail/{lines}`, `tmux://session/{sessionId}/tree`, `tmux://command/{commandId}/result`
Tmux 3.0 or newer on `PATH`, and a shell the command tracker supports — `bash`, `zsh` or `fish`. The server runs `tmux -V` on startup and exits if it finds tmux 2.x, whose output formats and split flags differ. Install with `cargo install tmux-mcp-rs`, `brew install bnomei/tmux-mcp/tmux-mcp-rs`, `npx @bnomei/tmux-mcp-rs`, or the container image `ghcr.io/bnomei/tmux-mcp:0.6.0`; building from source needs Rust 1.70 or newer. It speaks stdio. `--socket` or `TMUX_MCP_SOCKET` pins it to one tmux server, `--ssh` routes tmux commands to a remote host over a non-interactive SSH login, and `--config` loads a TOML policy file — nothing is auto-loaded.
One command — cargo install tmux-mcp-rs
