mcp-ssh-tmux
Manage persistent SSH sessions in tmux, enabling command execution, file transfer, and monitoring.
Open SSH sessions with
open_session(host, username, port), returning a session ID and initial snapshot.Send commands and poll for output with
send_command(session_id, command, lines, timeout), with configurable timeouts for slower tasks.Send raw keystrokes (e.g., Ctrl+C, Ctrl+D, interactive input) using
send_keys(session_id, keys).Capture screen snapshots of active sessions with
get_snapshot(session_id, lines)to monitor long-running tasks.List all active and dead sessions with
list_sessions().Close sessions and terminate processes with
close_session(session_id); clean up dead sessions manually viacleanup_dead_sessions(max_age_seconds)or automatically via background reaper after 24 hours.Read remote files with
read_remote_file(session_id, remote_path, fallback_lines), preferring direct SSH transfer.Write remote files (including large/binary content) with
write_remote_file(session_id, remote_path, content, append).Persist SSH connections across MCP server restarts and inspect sessions manually via the dedicated tmux socket (
tmux -L mcp-ssh a).Switch transport between stdio (default) and Streamable HTTP via environment variables (
FASTMCP_TRANSPORT,FASTMCP_PORT).
Manages SSH sessions through a persistent tmux multiplexer, enabling AI agents to execute commands, read/write files, and monitor terminal output on remote hosts.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-ssh-tmux open session to myserver.com and run ls -la"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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.
Related MCP server: mcp-ssh-interactive
Key Features
Persistence: SSH connections stay alive in
tmuxeven if the MCP server or your AI client restarts.Observability: You can manually run
tmux -L mcp-ssh ato see exactly what the agent is doing in real-time.Isolation: Runs on its own dedicated tmux socket (
mcp-ssh), completely isolated from your personal tmux sessions.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 tmuxmacOS:
brew install tmuxArch:
pacman -S tmux
Via uv (Recommended)
uv tool install mcp-ssh-tmuxVia pip
pip install mcp-ssh-tmuxConfiguration
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.cleanup_dead_sessions(max_age_seconds): Kills all windows where the SSH connection has closed. Optionally filters by how long the session has been dead.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().
Transport Modes
By default, the server uses stdio for communication with MCP clients. You can switch to the modern Streamable HTTP transport using environment variables:
# Start server in HTTP mode on port 8080
FASTMCP_TRANSPORT=http FASTMCP_PORT=8080 mcp-ssh-tmuxThe server will be available at http://localhost:8080/mcp.
Important Notes
Automatic Cleanup
Background Reaper: The server automatically cleans up sessions that have been dead (disconnected) for more than 24 hours.
Manual Cleanup: Use
cleanup_dead_sessions()to manually clear disconnected sessions at any time.
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 sessionSessions persist: SSH connections remain alive in tmux even if the MCP server restarts
Isolated Tmux Socket: The server runs its own tmux server on a separate socket (
mcp-ssh) to prevent interfering with your personal tmux sessions.Manual inspection: To manually connect to the MCP tool's tmux session, you must use the
-Lflag and specify the socket:tmux -L mcp-ssh a # or tmux -L mcp-ssh attach -t mcp-ssh
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
Available Tools
9 toolscleanup_dead_sessionsA
Kill all sessions where the SSH connection has closed.
Args: max_age_seconds: Optional. Only kill sessions that have been dead for at least this many seconds. If omitted, all dead sessions are killed immediately.
Inputs: max_age_seconds. Returns: result
close_sessionA
Close an active SSH session and return its final screen state.
WARNING: Closing a session will terminate any running processes in that session. For long-running tasks (builds, downloads, etc.), leave the session open until the task completes. You can monitor progress using get_snapshot() without closing.
Inputs: session_id (required). Returns: result
get_snapshotA
Get the current screen state of a session.
Use this to check on long-running commands without sending new input. The response includes [INFO: ...] hints about detected prompts or interactive states.
Args: session_id: The ID of the session (format: user@host-). lines: Number of lines to capture from the end of the screen and tmux scrollback (default 40).
Inputs: session_id (required), lines. Returns: result
list_sessionsA
List all SSH sessions, including dead ones (SSH connection closed but pane not yet cleaned up).
Dead sessions still have their terminal output available via get_snapshot(). Use close_session() to clean them up.
Inputs: no named parameters. Returns: result
open_sessionA
Open a new SSH session in a tmux window. Returns the session_id.
The host can be an SSH config alias or a hostname/IP. The session_id will be in the format 'user@host-'. The initial snapshot is included in the response to verify connection success.
Inputs: host (required), port, username. Returns: result
read_remote_fileA
Read a file from the remote host using the established session.
Prefer this over running 'cat' via send_command/get_snapshot when you want file contents. send_command() and get_snapshot() only return the last N lines of visible terminal output.
read_remote_file() attempts a direct SSH file read first so agents can get the full file
instead of just the pane tail. If that is not possible, it falls back to reading via the
existing PTY. fallback_lines controls how much tmux history to inspect during that PTY
fallback (default 200). Best for text files such as configs, logs, and source code.
Inputs: session_id (required), remote_path (required), fallback_lines. Returns: result
send_commandA
Send a command to an active session and return the screen snapshot.
This tool automatically polls waiting for the command to complete. The response includes [INFO: ...] hints about detected prompts or interactive input requests.
For long-running commands (builds, downloads, etc.), use get_snapshot() to check progress periodically. Do NOT close the session while processes are running - they will be terminated.
Args: session_id: The ID of the session (format: user@host-). command: The command to send. lines: Number of lines to capture from the end of the screen and tmux scrollback (default 40). timeout: Max seconds to poll for command completion (default 2.0). Increase for slower commands like package installs.
Inputs: command (required), session_id (required), lines, timeout. Returns: result
send_keysA
Send raw keystrokes to a session without appending Enter.
Use this for:
Interrupting commands: keys="C-c" (Ctrl+C)
Sending EOF: keys="C-d" (Ctrl+D)
Interactive input: keys="yes" (without submitting)
Special keys: keys="Enter", keys="Tab", keys="BSpace"
Tmux key notation: C-x (Ctrl), M-x (Alt), S-x (Shift). Multiple keys: "C-c Enter" After sending keys, use get_snapshot() to see the result.
Args: session_id: The ID of the session (format: user@host-). keys: Keys to send using tmux notation.
Inputs: keys (required), session_id (required). Returns: result
write_remote_fileA
Write content to a file on the remote host using the established session.
Use this tool to write file contents instead of using echo, redirection, or heredocs with send_command. This method handles large files, binary data, and special characters correctly.
Inputs: content (required), session_id (required), remote_path (required), append. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 9 tools
Each tool has a clearly distinct purpose: session lifecycle (list, open, close, cleanup), command interaction (send_command, send_keys, get_snapshot), and file transfer (read, write). There is no overlap or ambiguity even between send_command and send_keys, as the former submits a command and waits, while the latter sends raw keystrokes.
All tool names follow a consistent verb_noun pattern in snake_case (e.g., list_sessions, open_session, send_command, write_remote_file). The naming is uniform, predictable, and clearly indicates the action and target.
With 9 tools, the set is well-scoped for an SSH/tmux server. Every tool serves a necessary function in session management, command execution, and file operations, without redundancy or bloat.
The tool surface provides full coverage of the SSH session lifecycle: open, list, close, cleanup, plus command sending, key injection, snapshot viewing, and file read/write. There are no obvious gaps that would prevent an agent from effectively managing remote sessions and files.
Maintenance
Related MCP Connectors
Remote MCP server exposing your Node Command fleet (files, shell, processes, browser) to AI hosts.
Secure and manage MCP servers through the Speakeasy AI Control Plane from your agent.
Remote MCP server to run your Atako AI agents: chat, projects, files, integrations and channels.
Remote MCP server for supportsheep: run AI interviews and manage support content for your blog.
Related MCP Servers
- AlicenseAqualityCmaintenanceMCP server for managing multiple SSH servers via AI assistants, offering tools for remote command execution, file operations, and system monitoring.1125 PyPI2MIT
- AlicenseNot gradedqualityDmaintenanceMCP server that enables AI agents to run fully interactive SSH sessions (via tmux) and execute commands like a human operator, with persistent sessions and multiple concurrent connections.6MIT
- AlicenseNot gradedqualityCmaintenanceMCP server enabling AI assistants to securely operate remote servers via persistent SSH sessions, with tools for command execution, file transfer, directory listing, and system monitoring.4MIT
- AlicenseNot gradedqualityCmaintenanceMCP server for persistent SSH sessions with tmux integration, port forwarding, and SFTP file writes, built for AI agent workflows.MIT