MCP server for persistent SSH sessions via local tmux
Project description
mcp-ssh-tmux
A high-performance, persistent Model Context Protocol (MCP) server that manages SSH sessions via a local tmux instance.
Why this exists?
Traditional SSH automation runs individual commands without state tracking between executions. Other implementations rely on complex regex patterns to detect command completion. By using tmux as a persistent terminal multiplexer, this project eliminates that complexity entirely. The AI agent simply "looks" at the screen like a human would - the server provides visual snapshots, and the agent interprets prompts, errors, and output naturally.
Key Features
- Persistence: SSH connections stay alive in
tmuxeven if the MCP server or your AI client restarts. - Observability: You can manually run
tmux attach -t mcp-sshto see exactly what the agent is doing in real-time. - Reliability: Uses
ssh -Gfor robust config resolution (handles aliases, identity files, etc.). - Safety: Built-in command validation to prevent common dangerous operations.
- File Transfer: Native tools for reading and writing remote files. Reads prefer a full-file SSH transfer and fall back to the existing PTY when needed.
Installation
Requirements
- tmux must be installed on your system
- Ubuntu/Debian:
apt install tmux - macOS:
brew install tmux - Arch:
pacman -S tmux
- Ubuntu/Debian:
Via uv (Recommended)
uv tool install mcp-ssh-tmux
Via pip
pip install mcp-ssh-tmux
Configuration
Add this to your mcp.json (e.g., in Claude Desktop, Cursor, or 1mcp):
{
"mcpServers": {
"ssh-tmux": {
"command": "uv",
"args": [
"run",
"mcp-ssh-tmux"
]
}
}
}
Note: If you installed via uv tool install, you can just use mcp-ssh-tmux as the command.
Tools
open_session(host, username, port): Opens a new SSH connection in a unique tmux window.send_command(session_id, command, lines, timeout): Sends a command and polls for a prompt/output. Returns only the lastlinesof terminal output/scrollback.timeout(default 2.0s) controls how long to wait — increase for slower commands like package installs.send_keys(session_id, keys): Sends raw keystrokes without Enter. Use for Ctrl+C, Ctrl+D, interactive input, etc.get_snapshot(session_id, lines): Captures the current screen state. Returns only the lastlinesof terminal output/scrollback.read_remote_file(session_id, remote_path, fallback_lines): Reads a remote text file. Prefer this overcatviasend_command()when you need the full file contents.fallback_linescontrols bounded tmux-history capture if direct SSH read is unavailable.write_remote_file(session_id, remote_path, content, append): Writes content to a remote file.list_sessions(): Lists all active SSH windows.close_session(session_id): Kills the window and cleans up. WARNING: This terminates any running processes in the session. For long-running tasks, leave the session open and monitor withget_snapshot().
Important Notes
Reading Files
- Use
read_remote_file()for file contents:send_command("cat ...")andget_snapshot()are screen/snapshot tools, so they only return the tail of terminal output. linescontrols snapshot depth: Increaselinesonsend_command()orget_snapshot()when you need more terminal history, but useread_remote_file()for actual file reads.fallback_linescontrols PTY fallback depth: If direct SSH file read is unavailable,read_remote_file()inspects only the lastfallback_linesof tmux history. Increase it when needed, but keep it bounded.- Best for text files:
read_remote_file()is intended for configs, source, logs, and similar text content.
Session Management
- Do not close sessions with active processes: Closing a session terminates all running commands (builds, downloads, etc.)
- Monitor long-running tasks: Use
get_snapshot()to check progress without closing the session - Sessions persist: SSH connections remain alive in tmux even if the MCP server restarts
- Manual inspection: Run
tmux attach -t mcp-sshto see what's happening in real-time
Acknowledgments
Built with FastMCP and libtmux.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
Star History
If you find this project useful, please consider giving it a star! ⭐
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcp_ssh_tmux-0.2.4.tar.gz.
File metadata
- Download URL: mcp_ssh_tmux-0.2.4.tar.gz
- Upload date:
- Size: 100.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f0e6a1e56712eb584e4a294a89b9a5cdab8f3b163572b674a7faa7951e7f24ca
|
|
| MD5 |
eca760c1dcad0ea2ef7c1b07f6c588ed
|
|
| BLAKE2b-256 |
ca214711b7d4147ed8f98973a1c375ae9d360e7582c007a9759ecfa7f7bfbe2a
|
Provenance
The following attestation bundles were made for mcp_ssh_tmux-0.2.4.tar.gz:
Publisher:
release.yml on devnullvoid/mcp-ssh-tmux
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mcp_ssh_tmux-0.2.4.tar.gz -
Subject digest:
f0e6a1e56712eb584e4a294a89b9a5cdab8f3b163572b674a7faa7951e7f24ca - Sigstore transparency entry: 1388770085
- Sigstore integration time:
-
Permalink:
devnullvoid/mcp-ssh-tmux@ccdc877d1ab9f59209049b8b4458ee9aa7d1ea17 -
Branch / Tag:
refs/tags/v0.2.4 - Owner: https://github.com/devnullvoid
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@ccdc877d1ab9f59209049b8b4458ee9aa7d1ea17 -
Trigger Event:
push
-
Statement type:
File details
Details for the file mcp_ssh_tmux-0.2.4-py3-none-any.whl.
File metadata
- Download URL: mcp_ssh_tmux-0.2.4-py3-none-any.whl
- Upload date:
- Size: 14.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7502358ef550a88657b51cddd1e84ff44e23b02f1193a9bcec6b97a7752eef93
|
|
| MD5 |
18c123eab7cc6de2007474d508fe9532
|
|
| BLAKE2b-256 |
859b7818509deaef6c070240c1ce90d8cdf8b0fd5ac02828ce5e0ecb8ebfadbb
|
Provenance
The following attestation bundles were made for mcp_ssh_tmux-0.2.4-py3-none-any.whl:
Publisher:
release.yml on devnullvoid/mcp-ssh-tmux
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mcp_ssh_tmux-0.2.4-py3-none-any.whl -
Subject digest:
7502358ef550a88657b51cddd1e84ff44e23b02f1193a9bcec6b97a7752eef93 - Sigstore transparency entry: 1388770265
- Sigstore integration time:
-
Permalink:
devnullvoid/mcp-ssh-tmux@ccdc877d1ab9f59209049b8b4458ee9aa7d1ea17 -
Branch / Tag:
refs/tags/v0.2.4 - Owner: https://github.com/devnullvoid
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@ccdc877d1ab9f59209049b8b4458ee9aa7d1ea17 -
Trigger Event:
push
-
Statement type: