Skip to main content
Glama
the-nine-nation

Remote SSH MCP

Remote SSH MCP

English | 简体中文

A local MCP server that exposes persistent, stateful remote Bash sessions to AI agents. Reusing the same session ID preserves the working directory, environment variables, and shell side effects. Open a new session whenever a clean environment is required.

Remote SSH MCP uses the system OpenSSH client instead of reimplementing SSH. Your existing ~/.ssh/config, known hosts, SSH agent, ProxyJump routes, and hardware-key policies continue to work.

Why

Running ssh host "command" for every remote action repeatedly reconnects, loses shell state, reproduces banners and environment probes, and wastes model context. Remote SSH MCP keeps one remote shell alive behind a small, explicit tool interface:

ssh_open(host) → session id
ssh_run(id, command) → same cwd and environment
ssh_peek(id) / ssh_interrupt(id) → observe or recover a stuck command
ssh_close(id) → release the shell and connection

Related MCP server: TerminusAI

Features

  • Persistent remote Bash sessions with stable IDs

  • Working-directory and environment persistence within each session

  • Separate stdout and stderr in tool results

  • Non-blocking observation of long commands with a separate hard timeout

  • Safe fail-closed behavior when shell recovery cannot be confirmed

  • Head-and-tail output truncation with valid UTF-8 boundaries

  • Exact SSH Host alias allowlist from ssh_config and explicit configuration

  • Session limits, idle reaping, command auditing, and a minimal safety denylist

  • MCP stdio support for both legacy and current protocol handshakes

  • No password, private-key text, or arbitrary SSH option arguments

MCP tools

Tool

Purpose

ssh_open

Open a clean persistent shell for an allowed SSH Host alias

ssh_run

Run a non-interactive command in an existing session

ssh_peek

Inspect status and the latest N output lines; optional wait_sec long-polls while running

ssh_interrupt

Send Ctrl-C and wait for confirmed shell recovery

ssh_list

List sessions, cwd, state, idle countdown, and capacity

ssh_close

Clean up and close a session

Requirements

  • Node.js 20 or newer

  • An OpenSSH client

  • A remote host with Bash, base64, stty, mkdir, cat, and rm

  • A configured SSH Host alias and a known host key

The server enforces BatchMode=yes and StrictHostKeyChecking=yes. Complete first-connection host-key confirmation and authentication setup in a normal terminal before using the MCP server. It never opens password or confirmation prompts.

Install

git clone https://github.com/the-nine-nation/remote-ssh-mcp.git
cd remote-ssh-mcp
npm install
npm run build
npm test

Run the server directly:

node /absolute/path/to/remote-ssh-mcp/dist/index.js

Or, after installing it as a package, use the remote-ssh-mcp executable.

MCP host configuration

Most stdio MCP hosts accept a configuration shaped like this; the outer key may differ by host:

{
  "mcpServers": {
    "remote-ssh": {
      "command": "node",
      "args": [
        "/absolute/path/to/remote-ssh-mcp/dist/index.js"
      ],
      "env": {
        "SSH_MCP_ALLOWED_HOSTS": "prod,staging"
      }
    }
  }
}

SSH_MCP_ALLOWED_HOSTS adds explicit aliases to the allowlist. By default, the server also discovers exact Host aliases from ~/.ssh/config and its Include files. Patterns containing *, ?, or ! are ignored. Tool inputs accept only safe aliases, not user@host, ports, or extra SSH options.

Configuration

The optional configuration file defaults to:

~/.config/remote-ssh-mcp/config.json

Example:

{
  "allowedHosts": ["prod", "staging"],
  "sshConfigPath": "~/.ssh/config",
  "sshPath": "ssh",
  "maxTimeoutSec": 1800,
  "defaultWaitSec": 10,
  "maxWaitSec": 30,
  "openTimeoutSec": 20,
  "idleTimeoutSec": 1800,
  "interruptGraceSec": 5,
  "maxSessions": 8,
  "outputMaxBytes": 32768,
  "outputHeadBytes": 4096,
  "auditLogPath": "~/.local/state/remote-ssh-mcp/audit.jsonl"
}

Environment variables override file settings:

Environment variable

Purpose

SSH_MCP_CONFIG

Configuration file path

SSH_MCP_ALLOWED_HOSTS

Comma-separated additional Host aliases

SSH_MCP_SSH_CONFIG

SSH config path

SSH_MCP_SSH_PATH

OpenSSH executable

SSH_MCP_MAX_TIMEOUT_SEC

Maximum explicitly requested command timeout

SSH_MCP_DEFAULT_WAIT_SEC

How long ssh_run waits before returning running

SSH_MCP_MAX_WAIT_SEC

Maximum permitted wait_sec on ssh_run and ssh_peek

SSH_MCP_OPEN_TIMEOUT_SEC

Connection and handshake timeout

SSH_MCP_IDLE_TIMEOUT_SEC

Idle session lifetime

SSH_MCP_INTERRUPT_GRACE_SEC

Marker recovery grace period after Ctrl-C

SSH_MCP_MAX_SESSIONS

Maximum live sessions

SSH_MCP_OUTPUT_MAX_BYTES

Per-stream retained output limit

SSH_MCP_OUTPUT_HEAD_BYTES

Retained head bytes when truncating

SSH_MCP_AUDIT_LOG

JSONL audit-log path

The audit log is created with mode 0600. It records the session, host, result, duration, command length, command name, and SHA-256 hash. Full command arguments are intentionally omitted to reduce the chance of logging secrets.

Execution semantics

  • One session accepts only one foreground command at a time. Concurrent ssh_run calls return busy instead of being queued.

  • wait_sec limits only how long the MCP call waits. If it expires, ssh_run returns status: "running" while the remote command continues. Do not start the command again. Poll with ssh_peek(wait_sec=...) so the call blocks until the command finishes or the wait expires; do not busy-loop with wait_sec: 0. Stop it with ssh_interrupt, or open another session for concurrent work.

  • Commands have no automatic execution timeout by default. The model owns their lifecycle. Only an explicitly supplied timeout_sec creates a hard deadline that sends Ctrl-C.

  • ssh_peek returns the newest 50 lines from stdout and stderr by default. Pass lines (maximum 1,000) when a different tail length is needed. Byte limits still apply, so a very long individual line remains bounded. Optional wait_sec (default 0, capped by maxWaitSec) long-polls while the session is running and returns immediately when idle.

  • User-command stdin is /dev/null. Do not run vim, top, interactive installers, or other TUI/input-driven programs.

  • A timeout sends Ctrl-C. If a complete protocol marker arrives during the grace period, the session returns to idle. Otherwise, the session is closed to prevent an unknown foreground process from corrupting the next command.

  • stdout and stderr independently retain their beginning and end. Responses always end on valid UTF-8 boundaries.

  • The built-in denylist blocks only a few obviously destructive patterns. It is not a complete policy engine.

  • This project targets a trusted local developer environment. It is not a multi-tenant remote execution service.

  • If the MCP host exits or its stdio/parent connection disappears, the server closes every tracked SSH connection, including connections still opening. Normal foreground processes end with their PTY; deliberately detached processes such as nohup, setsid, services, and containers may continue.

For example, start a docker pull with wait_sec: 10 and omit timeout_sec. A running result means the original pull remains active—not that it should be retried. Call ssh_peek with the same session ID and a positive wait_sec until it becomes idle, interrupt it explicitly, or open another session for parallel work.

Development

npm run typecheck
npm test
npm run build
npm audit --omit=dev

The test suite covers MCP stdio discovery and calls, persistent cwd/environment state, stream separation, framing across arbitrary chunk boundaries, timeout fail-closed behavior, shell death, allowlist discovery, output truncation, and the safety denylist.

Security

Please do not report security vulnerabilities through public GitHub issues. Until a private security-advisory workflow is configured, contact the maintainer through the email listed on their GitHub profile.

Remote commands can have irreversible side effects even when the MCP transport works correctly. Review host permissions, use least-privilege accounts, and keep the allowlist narrow.

License

MIT

The wire protocol and detailed design decisions are documented in 远程SSH-MCP设计.md.

A
license - permissive license
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    Execute terminal commands locally or remotely via SSH with session persistence and environment variable support. Manage terminal sessions that maintain state for up to 20 minutes, enabling efficient command execution workflows. Connect using stdio or SSE for flexible integration with AI models and a
    Last updated
    1
    1
    MIT
  • A
    license
    -
    quality
    D
    maintenance
    Provides LLM clients with safe, persistent SSH access to remote machines through the Model Context Protocol. Maintains shell sessions that preserve environment state between commands, enabling multi-step workflows and interactive diagnostics on remote systems.
    Last updated
    71
    16
    MIT
  • F
    license
    -
    quality
    C
    maintenance
    Enables AI assistants to run commands on remote SSH-accessible devices via persistent sessions, supporting both POSIX and CLI shells with safety filters.
    Last updated

View all related MCP servers

Related MCP Connectors

  • Operate your own Linux servers from your LLM. Requires the SentinelX agent installed per host.

  • Let AI operate servers without SSH. Choose actions, approve risky changes, and audit every step.

  • Persistent memory and cross-session learning for AI coding assistants (hosted remote MCP).

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/the-nine-nation/remote-ssh-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server