Skip to main content

mcp-ssh-tmux

PyPI version Downloads License: MIT GitHub stars

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 tmux even if the MCP server or your AI client restarts.
  • Observability: You can manually run tmux attach -t mcp-ssh to see exactly what the agent is doing in real-time.
  • Reliability: Uses ssh -G for 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

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 last lines of 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 last lines of terminal output/scrollback.
  • read_remote_file(session_id, remote_path, fallback_lines): Reads a remote text file. Prefer this over cat via send_command() when you need the full file contents. fallback_lines controls 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 with get_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-tmux

The 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 ...") and get_snapshot() are screen/snapshot tools, so they only return the tail of terminal output.
  • lines controls snapshot depth: Increase lines on send_command() or get_snapshot() when you need more terminal history, but use read_remote_file() for actual file reads.
  • fallback_lines controls PTY fallback depth: If direct SSH file read is unavailable, read_remote_file() inspects only the last fallback_lines of 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-ssh to 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

Release files for mcp-ssh-tmux 0.2.8

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mcp-ssh-tmux 0.2.8
File Size Uploaded
mcp_ssh_tmux-0.2.8.tar.gz 103.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mcp-ssh-tmux 0.2.8
File Interpreter ABI Platform
mcp_ssh_tmux-0.2.8-py3-none-any.whl Python 3 none any Details

Total release size: 119.6 kB

Release files / mcp_ssh_tmux-0.2.8.tar.gz

Download URL mcp_ssh_tmux-0.2.8.tar.gz
Size 103.4 kB
Tags Source
SHA-256 checksum
How to use checksums
a775b1f8f1aff399c231560eaff731b0bae7e6e661725d970be451aec904ac0d
BLAKE2b-256 checksum
How to use checksums
ecad23106cf62e994d62d3fe60dd8b0b7447475b115e0c04f34bf70c7b37704b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 5, 2026.

Transparency log

Release files / mcp_ssh_tmux-0.2.8-py3-none-any.whl

Download URL mcp_ssh_tmux-0.2.8-py3-none-any.whl
Size 16.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6d3ec93837e461cc0338c451707a1a9369a343ce7757e4a7e2656644f41700a4
BLAKE2b-256 checksum
How to use checksums
a0f77155a158762efc18419e8357a05cbeece1ecdf92677276a2364a650e0b62
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 5, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.8 This release

2 release files

0.2.7

2 release files

0.2.6

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page