Skip to main content
Glama
mcp-ssh-tmux

mcp-ssh-tmux

by devnullvoid

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.

Related MCP server: mcp-ssh-interactive

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 -L mcp-ssh a to 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 -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

  • 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 -L flag 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 tools
cleanup_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

    A4.4/5.0

    Scored across 9 tools

    Disambiguation5/5

    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.

    Naming Consistency5/5

    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.

    Tool Count5/5

    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.

    Completeness5/5

    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

    ActivitySlowing
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      C
      maintenance
      MCP server for managing multiple SSH servers via AI assistants, offering tools for remote command execution, file operations, and system monitoring.
      11
      25 PyPI
      2
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      MCP 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.
      6
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      MCP 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.
      4
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      MCP server for persistent SSH sessions with tmux integration, port forwarding, and SFTP file writes, built for AI agent workflows.
      MIT