MCP Hub
Back to servers

SSH MCP Tool

Secure MCP SSH automation server with policy controls, resources, prompts, stdio, and HTTP.

Registry
Stars
1
Forks
2
Updated
May 10, 2026

Quick Install

npx -y mcp-ssh-tool

mcp-ssh-tool

npm version CI Security Official MCP Registry License: MIT npm downloads

Production-grade MCP SSH automation for operators, developers, and AI clients. mcp-ssh-tool opens persistent SSH sessions and exposes safe, structured tools for command execution, file operations, transfers, tunnels, package/service management, metrics, resources, and guided prompts.

v2 is secure by default: strict host-key verification is on, root login is off, raw sudo is policy-gated, destructive commands and filesystem mutations are denied unless policy allows them, and remote HTTP starts on loopback only unless bearer auth and allowed origins are configured.

Why This Server

  • Trust: central policy engine, structured audit events, redacted logs, strict host keys, and machine-readable errors.
  • MCP quality: stdio for local clients, Streamable HTTP for remote clients, legacy SSE only behind an explicit compatibility flag.
  • AI-friendly tools: stable output schemas, structuredContent, annotations for read-only/destructive/idempotent behavior, resources, and curated prompts.
  • Operations: session TTL/eviction, command timeouts, transfer checksum verification, real SSH forwarding, Prometheus metrics, and OpenTelemetry hooks.
  • Portability: SFTP first, POSIX/BusyBox-aware shell fallbacks for basic file operations, and explicit support boundaries.

Quick Start

Run without installing:

pnpm dlx mcp-ssh-tool --version

Or install globally:

pnpm add --global mcp-ssh-tool

Add a stdio MCP server to your client:

{
  "servers": {
    "ssh-mcp": {
      "type": "stdio",
      "command": "mcp-ssh-tool",
      "args": []
    }
  }
}

Use it from your MCP client:

Open a safe SSH session to prod-1 as deploy, inspect host capabilities, then show disk usage.

Requirements

  • Node.js 22.22.2+ or 24.15.0+ (LTS only)
  • SSH access to target hosts
  • A populated known_hosts file for strict host verification, or an explicit per-session host-key policy

Transports

ModeCommandUse When
stdiomcp-ssh-toolLocal desktop clients such as ChatGPT, Claude Desktop, VS Code, Cursor, or Codex.
Streamable HTTPmcp-ssh-tool --transport=http --host 127.0.0.1 --port 3000Remote MCP clients, reverse proxies, or Inspector sessions.
legacy SSEmcp-ssh-tool --transport=http --enable-legacy-sseTemporary v1 compatibility only. Prefer Streamable HTTP.

Non-loopback HTTP startup is refused unless --bearer-token-file, allowed origins, and SSH_MCP_HTTP_PUBLIC_URL are configured.

Secure Defaults

Areav2 Default
Host keyshostKeyPolicy=strict, knownHostsPath=~/.ssh/known_hosts
Root SSH logindenied
Raw proc_sudodenied unless allowRawSudo=true
Destructive commandsdenied unless allowDestructiveCommands=true
Destructive fs operationsallowed only under policy prefixes, denied elsewhere
Local transfer pathsfile_upload and file_download limited to OS temp unless policy allows more
HTTP bind127.0.0.1
Legacy SSEdisabled
File readssize-limited by SSH_MCP_MAX_FILE_SIZE
Command outputbounded by SSH_MCP_MAX_COMMAND_OUTPUT_BYTES
Transfersbounded by SSH_MCP_MAX_TRANSFER_BYTES

Per-session policyMode: "explain" returns a plan/verdict without executing. Use it before mutations when an AI client needs to summarize risk.

Policy Example

Set SSH_MCP_POLICY_FILE=/etc/mcp-ssh-tool/policy.json:

{
  "mode": "enforce",
  "allowRootLogin": false,
  "allowRawSudo": false,
  "allowDestructiveCommands": false,
  "allowDestructiveFs": false,
  "allowedHosts": ["^prod-[0-9]+\\.example\\.com$"],
  "commandAllow": ["^(uname|df|uptime|systemctl status)\\b"],
  "commandDeny": ["rm\\s+-rf\\s+/", "shutdown", "reboot"],
  "pathAllowPrefixes": ["/tmp", "/var/tmp", "/home/deploy"],
  "pathDenyPrefixes": ["/etc/shadow", "/etc/sudoers", "/boot", "/dev", "/proc"],
  "localPathAllowPrefixes": ["/var/tmp/mcp-ssh-tool"],
  "localPathDenyPrefixes": []
}

Simple deploys can use environment overrides such as SSH_MCP_ALLOW_RAW_SUDO=true, SSH_MCP_ALLOWED_HOSTS=prod-1.example.com, SSH_MCP_PATH_ALLOW_PREFIXES=/tmp,/home/deploy, or SSH_MCP_LOCAL_PATH_ALLOW_PREFIXES=/var/tmp/mcp-ssh-tool.

Core Tools

  • ssh_open_session, ssh_close_session, ssh_list_sessions, ssh_ping, ssh_list_configured_hosts, ssh_resolve_host
  • proc_exec, proc_sudo, proc_exec_stream
  • fs_read, fs_write, fs_list, fs_stat, fs_mkdirp, fs_rmrf, fs_rename
  • file_upload, file_download
  • ensure_package, ensure_service, ensure_lines_in_file, patch_apply
  • os_detect, get_metrics
  • tunnel_local_forward, tunnel_remote_forward, tunnel_list, tunnel_close

All tools return text plus stable structuredContent. Tool metadata includes titles, output schemas, and annotations that disclose read-only, destructive, idempotent, and external side-effect behavior.

Resources And Prompts

Resources:

  • mcp-ssh-tool://sessions/active
  • mcp-ssh-tool://metrics/json
  • mcp-ssh-tool://metrics/prometheus
  • mcp-ssh-tool://ssh-config/hosts
  • mcp-ssh-tool://policy/effective
  • mcp-ssh-tool://audit/recent
  • mcp-ssh-tool://capabilities/support-matrix

Prompts:

  • safe-connect
  • inspect-host-capabilities
  • plan-mutation
  • managed-config-change

Support Matrix

TargetStatus
LinuxFull support.
macOS/BSDSession, process, fs, and transfer supported; package/service helpers only where tested.
BusyBox/dropbearExperimental for session, process, and basic fs fallbacks.
Windows SSH targetsExperimental for session, process, fs, and transfer; no proc_sudo or ensure_*.

Client Examples

ChatGPT or Claude Desktop:

{
  "mcpServers": {
    "ssh-mcp": {
      "command": "pnpm",
      "args": ["dlx", "mcp-ssh-tool"]
    }
  }
}

VS Code or Cursor:

{
  "servers": {
    "ssh-mcp": {
      "type": "stdio",
      "command": "mcp-ssh-tool"
    }
  }
}

MCP Inspector over HTTP:

printf '%s' 'super-secret-token' > .mcp-token
mcp-ssh-tool --transport=http --host 127.0.0.1 --port 3000 --bearer-token-file .mcp-token

Configuration

High-value environment variables:

VariableDefaultPurpose
SSH_MCP_POLICY_FILEunsetCanonical JSON policy source.
SSH_MCP_HOST_KEY_POLICYstrictstrict, accept-new, or insecure.
SSH_MCP_KNOWN_HOSTS_PATH~/.ssh/known_hostsKnown-hosts file for strict verification.
SSH_MCP_MAX_FILE_SIZE10485760Max bytes for fs_read.
SSH_MCP_MAX_FILE_WRITE_BYTES10485760Max text payload bytes accepted by fs_write before buffering.
SSH_MCP_MAX_COMMAND_OUTPUT_BYTES1048576Max retained stdout/stderr bytes per command or stream.
SSH_MCP_MAX_STREAM_CHUNKS4096Max retained streaming chunks before truncation metadata is returned.
SSH_MCP_MAX_TRANSFER_BYTES52428800Max bytes for file_upload and file_download.
SSH_MCP_COMMAND_TIMEOUT30000Default command timeout.
SSH_MCP_HTTP_HOST127.0.0.1Streamable HTTP bind host.
SSH_MCP_HTTP_PORT / PORT3000Streamable HTTP port.
SSH_MCP_HTTP_MAX_REQUEST_BODY_BYTES1048576Max JSON request bytes accepted by Streamable HTTP.
SSH_MCP_HTTP_MAX_SESSIONS20Max concurrent Streamable HTTP/SSE MCP sessions.
SSH_MCP_HTTP_SESSION_IDLE_TTL_MS900000Idle TTL before abandoned HTTP sessions are closed.
SSH_MCP_HTTP_PUBLIC_URLunsetRequired for non-loopback HTTP to publish stable protected-resource metadata.
SSH_MCP_HTTP_TRUST_PROXYfalseTrust X-Forwarded-Proto only when explicitly set.
SSH_MCP_LOCAL_PATH_ALLOW_PREFIXESOS temp directoryLocal transfer allow-list for file_upload and file_download.
SSH_MCP_TUNNEL_ALLOW_BIND_HOSTS127.0.0.1,localhost,::1Tunnel bind-host allow-list.
SSH_MCP_TUNNEL_DENY_BIND_HOSTS0.0.0.0,::Tunnel bind-host deny-list.
SSH_MCP_TUNNEL_ALLOW_REMOTE_HOSTSunsetOptional tunnel destination host allow-list.
SSH_MCP_TUNNEL_DENY_REMOTE_HOSTSunsetTunnel destination host deny-list.
SSH_MCP_TUNNEL_ALLOW_PORTSunsetOptional tunnel port allow-list, including ranges such as 1024-65535.
SSH_MCP_TUNNEL_DENY_PORTSunsetTunnel port deny-list.
SSH_MCP_HTTP_BEARER_TOKEN_FILEunsetRequired for non-loopback HTTP.
SSH_MCP_HTTP_ALLOWED_ORIGINSloopback originsComma-separated allowed origins.

Deprecated aliases STRICT_HOST_KEY_CHECKING and SSH_MCP_STRICT_HOST_KEY are still accepted for one v2 compatibility cycle. Prefer SSH_MCP_HOST_KEY_POLICY.

Development

Use the exact local runtime from .nvmrc / .node-version, then run:

pnpm install --frozen-lockfile
pnpm run check

Live SSH suites are opt-in:

RUN_SSH_INTEGRATION=1 pnpm run test:integration
RUN_SSH_E2E=1 pnpm run test:e2e

Local quality gates are layered:

  • pre-commit: formats staged files and lints staged TypeScript only
  • pre-push: runs pnpm run check:push
  • task hooks: runs tracked pnpm hooks plus .pre-commit-config.yaml hooks when pre-commit is installed
  • manual/full parity: task ci or pnpm run check

CI/CD Ownership

The personal repository https://github.com/oaslananka/mcp-ssh-tool is the source repository. The organization repository https://github.com/oaslananka-lab/mcp-ssh-tool is the GitHub Actions, CI/CD, release, security, and provenance boundary.

Automatic CI/CD, supply-chain security checks, trusted npm publishing, MCP Registry publishing, GitHub Releases, Docker image validation, SBOMs, attestations, and release decisions run only from the org repository. Personal-repo Actions are intentionally not required gates.

The two repositories must stay content-identical for main, release tags, releases, labels, milestones, and active collaboration state. Org release-generated refs are backfilled to the personal source repository.

The npm package repository.url intentionally points at the org automation repository so npm provenance can verify that the published artifact came from the same GitHub Actions repository that built it. The MCP Registry server name remains io.github.oaslananka/mcp-ssh-tool because it is already published and changing it would break existing users.

See docs/ci-cd-topology.md for mirror, release, dry-run, and manual fallback guidance.

Documentation

License

MIT License. See LICENSE.

Reviews

No reviews yet

Sign in to write a review