Skip to main content
Glama
MCP SSH Session

MCP SSH Session

by AmritaBot

MCP SSH Session - Reloaded

An MCP (Model Context Protocol) server that enables AI agents to establish and manage persistent SSH sessions.

Features

  • Smart Command Execution - auto-transitions to async mode if timeout is reached

  • Persistent Sessions - SSH connections reused across commands

  • Async Commands - non-blocking execution for long-running tasks

  • SSH Config Support - reads ~/.ssh/config for aliases, ports, keys

  • Multi-host - manage connections to multiple hosts simultaneously

  • Network Devices - enable mode handling for Cisco, Juniper, MikroTik, etc.

  • Sudo Support - automatic password handling for Unix/Linux hosts

  • File Operations - read/write remote files via SFTP (sudo fallback)

  • Image Reading (experimental) - return remote PNG/JPEG/GIF/WebP files as MCP image content

  • Command Interruption - send Ctrl+C to stop running commands

  • Thread-safe - safe for concurrent operations

  • Async Native - built-in support for asynio.

Related MCP server: Simple SSH MCP Server

Quick Start

📦 Migrating from mcp-ssh-session

This project is a drop-in replacement for the original devnullvoid/mcp-ssh-session. To migrate:

  1. Replace the package name - mcp-ssh-session → mcp-ssh-reloaded

  2. Environment variables fully inherited - all OVRD_* and MCP_SSH_* env vars work the same

  3. That's it - reconnect and you're done

{
  "mcpServers": {
    "ssh-session": {
      "command": "uvx",
      "args": ["mcp-ssh-session", "serve", "mcp"]
    }
  }
}
{
  "mcpServers": {
    "ssh-session": {
      "command": "uvx",
      "args": ["mcp-ssh-reloaded", "serve", "mcp"]
    }
  }
}

Install

uvx mcp-ssh-reloaded

Development

uv venv
source .venv/bin/activate
uv pip install -e .

CLI

# MCP server (default)
mcp-ssh-reloaded serve mcp

# Direct execution (no MCP)
mcp-ssh-reloaded exec myserver "uname -a" -u admin

# List / close sessions
mcp-ssh-reloaded list
mcp-ssh-reloaded close-all

MCP Client Config

Claude Code / Desktop (~/.claude.json or claude_desktop_config.json):

{
  "mcpServers": {
    "ssh-session": {
      "type": "stdio",
      "command": "uvx",
      "args": ["mcp-ssh-reloaded", "serve", "mcp"],
      "env": {}
    }
  }
}

Quick Examples

// SSH config alias
{ "host": "myserver", "command": "uptime" }

// Explicit params
{ "host": "example.com", "username": "user", "command": "ls -la", "port": 2222 }

// Network device (Cisco enable mode)
{ "host": "router", "username": "admin", "enable_password": "secret", "command": "show run" }

// Unix with sudo
{ "host": "server", "username": "ops", "sudo_password": "secret", "command": "systemctl restart nginx" }

Full API reference: API-DOCS.md - all types, all methods, all MCP tools, error handling, server config tunables.

SSH Config

~/.ssh/config is read automatically:

Host myserver
    HostName example.com
    User myuser
    Port 2222
    IdentityFile ~/.ssh/id_rsa

Then use "host": "myserver" - the rest is resolved for you.

Credential Hiding (OVRD_*)

For production environments, store real credentials in env vars so AI agents only see aliases:

Variable

Description

OVRD_{alias}_HOST

Real hostname or IP

OVRD_{alias}_PORT

SSH port

OVRD_{alias}_USER

SSH username

OVRD_{alias}_PASS

SSH password

OVRD_{alias}_KEY

Path to SSH private key

OVRD_{alias}_SUDO_PASS

Sudo password

OVRD_{alias}_ENABLE_PASS

Enable password

Example config:

{
  "mcpServers": {
    "ssh-session": {
      "type": "stdio",
      "command": "uvx",
      "args": ["mcp-ssh-reloaded", "serve", "mcp"],
      "env": {
        "OVRD_prod_db_HOST": "192.168.1.100",
        "OVRD_prod_db_USER": "admin",
        "OVRD_prod_db_PASS": "secret123",
        "OVRD_prod_db_SUDO_PASS": "sudopass"
      }
    }
  }
}

The agent uses "host": "prod_db" - never sees real IPs or passwords.

Configuration

Timeouts & server settings

All tunables live in ServerConfig. Values resolve in priority:

  1. Constructor kwargs (highest)

  2. MCP_SSH_* environment variables

  3. Defaults (lowest)

Env Variable

Default

Description

MCP_SSH_DEFAULT_TIMEOUT

30

Command timeout (seconds)

MCP_SSH_MAX_TIMEOUT

300

Hard cap on timeout

MCP_SSH_CONNECT_TIMEOUT

30

SSH connect timeout

MCP_SSH_MAX_WORKERS

10

Thread pool size

MCP_SSH_MAX_FILE_BYTES

2097152

Max file read/write (2 MB)

MCP_SSH_MAX_OUTPUT_BYTES

10485760

Max command output (10 MB)

MCP_SSH_INTERACTIVE_MODE

true

Enable PTY terminal emulation

MCP_SSH_PTY_AWARE_VALIDATION

false

Relax validation for PTY inspection

MCP_SSH_MIKROTIK_AUTO_PAGING

true

Auto-handle MikroTik pagers

MCP_SSH_TERMINAL_WIDTH

100

PTY columns

MCP_SSH_TERMINAL_HEIGHT

24

PTY rows

MCP_SSH_LOG_DIR

/tmp/mcp_ssh_session_logs

Log directory

MCP_SSH_BACKGROUND_MONITOR_MAX_TIMEOUT

300

Background monitor max timeout

MCP_SSH_NORMAL_IDLE_TIMEOUT

2

Normal idle timeout (seconds)

MCP_SSH_PACKAGE_MANAGER_IDLE_TIMEOUT

10

Package manager idle timeout

MCP_SSH_ASYNC_DEFAULT_TIMEOUT

30

Async command default timeout

MCP_SSH_ENABLE_IMAGE_READING

false

Enable the experimental read_image tool

MCP_SSH_MAX_IMAGE_BYTES

4194304

Max image file size (4 MB)

MCP_SSH_MAX_IMAGE_PIXELS

16000000

Max image pixel count (16 MP)

Via CLI (serve modes)

mcp-ssh serve mcp --default-timeout 60 --max-workers 20
mcp-ssh serve http --port 8080 --interactive-mode false
mcp-ssh serve sse --port 9000 --connect-timeout 15

Via API

from mcp_ssh_reloaded import SSHService, ServerConfig

svc = SSHService(config=ServerConfig(default_timeout=60, max_timeout=600))

Experimental: image reading

read_image is off by default. Enable it with --enable-image-reading or MCP_SSH_ENABLE_IMAGE_READING=true to expose one more tool:

read_image(host, remote_path, username=None, password=None, key_filename=None,
           port=None, max_bytes=None, timeout=None)

The file is read over SFTP and returned as MCP image content. Only PNG, JPEG, GIF and WebP are accepted. Validation is based on magic bytes and container structure: signature, IHDR checksum and IEND for PNG; frame header and EOI for JPEG; trailer for GIF; RIFF length plus VP8/VP8L/VP8X headers for WebP. A file extension is never trusted, and truncated or unparsable payloads are rejected with Unsupported image format.

MCP_SSH_MAX_IMAGE_BYTES caps the file size, and MCP_SSH_MAX_IMAGE_PIXELS caps the decoded dimensions (with a per-side cap of 8192 pixels). The tool is only useful with clients that accept image content blocks.

How It Works

Commands run inside persistent interactive shells:

  • Directory persists: cd /tmp stays in /tmp for the next command

  • Env vars persist: export FOO=bar is visible across commands

  • Prompt detection: completion detected via captured prompt or idle timeout (2 s)

  • Session recovery: stuck shells auto-reset after repeated prompt-detection failures

Testing

# unit tests only - the integration suites self-skip without SSH_TEST_HOST
uv run pytest tests/

# everything, against a real host
SSH_TEST_HOST=myserver SSH_TEST_USER=admin SSH_TEST_PASSWORD=secret uv run pytest tests/

# or spin up a throw-away sshd container (the same image CI uses)
docker build -t mcp-ssh-test .github/sshd-test
docker run -d --name sshd-test -p 127.0.0.1:2222:22 mcp-ssh-test
SSH_TEST_HOST=127.0.0.1 SSH_TEST_PORT=2222 SSH_TEST_USER=root \
SSH_TEST_PASSWORD=rootpass SSH_TEST_SUDO_PASSWORD=rootpass \
uv run pytest tests/ --ignore=tests/test_mikrotik.py --ignore=tests/test_network_devices.py

test_mikrotik.py and test_network_devices.py need physical network gear.

.github/workflows/integration.yml runs the container-backed suite on every pull request; .github/workflows/ci.yml covers unit tests, pyright, ruff and packaging across Python 3.10-3.13.

Architecture

Types are declared in a single module (models.py); api_types.py and datastructures.py are backward-compatible re-export shims. All execution goes through one stack, CommandExecutor, which returns a structured ExecutionResult. See docs/ARCHITECTURE.md for the module map, the execution pipeline and the known gaps.

Docs

Doc

Topic

API-DOCS.md

Full API reference - types, SSHService methods, MCP tools, error model

docs/AGENT_GUIDE.md

Agent prompt - patterns for correct tool usage, async handling

docs/ASYNC_COMMANDS.md

Smart execution & async command lifecycle

docs/INTERACTIVE_MODE.md

Terminal emulation, screen snapshots, key sending

docs/SAFETY_PROTECTIONS.md

Limits, timeouts, session recovery, error handling

docs/DOCKER.md

Running via Docker

docs/ARCHITECTURE.md

Module map, execution pipeline, known gaps

License

MIT - see LICENSE.

Fork

Fork of devnullvoid/mcp-ssh-session with significant refactoring by AmritaConstant.

Available Tools

22 tools
close_all_sessionsB

Close all active SSH sessions.

Inputs: no named parameters. Returns: result

close_sessionB

Close a specific SSH session.

Inputs: host (required), port, username. Returns: result

execute_commandB

Execute a command on an SSH host using a persistent session.

Inputs: host (required), command (required), port, timeout, +6 more. Returns: result

execute_command_asyncC

Execute a command asynchronously. Returns a command ID.

Inputs: host (required), command (required), port, timeout, +3 more. Returns: result

execute_command_enhancedC

Execute a command with auto timeout extension and streaming.

Inputs: host (required), command (required), port, timeout, +10 more. Returns: result

get_command_statusC

Get the status and output of an async command.

Inputs: command_id (required). Returns: result

get_command_status_enhancedC

Get enhanced status with detailed metrics.

Inputs: command_id (required). Returns: result

get_connection_health_reportB

Get health report for all active SSH connections.

Inputs: no named parameters. Returns: result

get_performance_metricsC

Get performance metrics.

Inputs: no named parameters. Returns: result

get_session_diagnosticsC

Get comprehensive diagnostics for an SSH session.

Inputs: host (required), port, username. Returns: result

interrupt_command_by_idB

Interrupt a running async command by sending Ctrl+C.

Inputs: command_id (required). Returns: result

list_command_historyC

List recent command history.

Inputs: limit. Returns: result

list_running_commandsA

List all currently running async commands.

Inputs: no named parameters. Returns: result

list_sessionsA

List all active SSH sessions.

Inputs: no named parameters. Returns: result

probeD

Report what the target host is and what this tool is, without any address.

Inputs: host (required), port, password, username, +1 more. Returns: result

read_fileB

Read a remote file over SSH. Falls back to sudo cat if permission denied.

Returns at most max_bytes bytes, cut on a character (and line) boundary. A truncated result reports the line range and how to resume with start_line or offset.

Inputs: host (required), remote_path (required), port, errors, +9 more. Returns: result

read_screenC

Read the terminal screen state (requires MCP_SSH_INTERACTIVE_MODE=1).

Inputs: host (required), port, username, max_lines. Returns: result

reset_session_promptC

Reset and recapture prompt detection.

Inputs: host (required), port, username. Returns: result

send_inputC

Send input to a running async command.

Inputs: command_id (required), input_text (required). Returns: result

send_input_by_sessionC

Send input to the active shell for a session.

Inputs: host (required), input_text (required), port, username. Returns: result

send_keysC

Send special keys to a session.

Inputs: host (required), keys (required), port, username. Returns: result

write_fileC

Write content to a remote file over SSH.

Inputs: host (required), content (required), remote_path (required), port, +11 more. Returns: result

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    C2.5/5.0

    Scored across 22 tools

    Disambiguation2/5

    Several tools overlap: execute_command / execute_command_async / execute_command_enhanced all run commands, get_command_status / get_command_status_enhanced both report status, and diagnostics/health/performance metrics are easily confused. Descriptions add some distinction, but boundaries remain fuzzy for an agent choosing a tool.

    Naming Consistency4/5

    Nearly all tools use snake_case verb_noun phrasing (execute_command, read_file, list_sessions), with minor deviations like probe and multi-word qualifiers (by_session, enhanced). The convention is readable and predictable overall.

    Tool Count3/5

    22 tools is heavy for an SSH session server, with several diagnostic/status and enhanced-variant tools that could be consolidated. The count is not absurd given the async/interactive feature set, but it borders on over-scoped.

    Completeness4/5

    Core SSH operations are covered: command execution (sync/async), file read/write, session listing/closing, input, screen/key interaction, and diagnostics. Some gaps remain (e.g., file deletion/directory listing, explicit session creation/disconnection), but the main workflows are supported.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      B
      quality
      F
      maintenance
      An MCP server that allows AI models to execute system commands on local machines or remote hosts via SSH, supporting persistent sessions and environment variables.
      1
      45 npm
      28
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      An MCP server that gives AI assistants full SSH/SFTP remote operations — session management, command execution, interactive shells, file transfers, port forwarding, and system diagnostics.
      2
      MIT
    • A
      license
      A
      quality
      C
      maintenance
      MCP server giving AI agents full SSH access with persistent sessions, structured command output, SFTP file transfer, and port forwarding.
      18
      59 PyPI
      12
      MIT
    • A
      license
      A
      quality
      C
      maintenance
      An MCP server that gives AI agents SSH access to remote machines through your local OpenSSH client, enabling remote command execution, file transfer, persistent shell sessions, and port forwarding.
      17
      319 PyPI
      38
      MIT