Skip to main content
ClaudeWave

MCP server exposing SSH control for Linux servers via Model Context Protocol.

MCP ServersRegistry oficial655 estrellas101 forksTypeScriptMITActualizado today
ClaudeWave Trust Score
94/100
Verified
Passed
  • Open-source license (MIT)
  • Actively maintained (<30d)
  • Healthy fork ratio
  • Clear description
  • Mature repo (>1y old)
  • Documented (README)
Flags
  • !Install pipes a remote script into a shell (curl | sh)
Last scanned: 8/25/2026
Install in Claude Code / Claude Desktop
Method: Manual
Claude Code CLI
git clone https://github.com/tufantunc/ssh-mcp
claude_desktop_config.json (Claude Desktop)
{
  "mcpServers": {
    "ssh-mcp": {
      "command": "node",
      "args": ["/path/to/ssh-mcp/dist/index.js"],
      "env": {
        "SSH_MCP_PASSWORD": "<ssh_mcp_password>"
      }
    }
  }
}
1. Run the command above in your terminal (Claude Code), or paste the JSON config into claude_desktop_config.json (Claude Desktop).
2. Replace any <placeholder> values with your API keys or paths.
3. Restart Claude. The MCP server and its tools appear automatically.
💡 Clone https://github.com/tufantunc/ssh-mcp and follow its README for install instructions.
Detected environment variables
SSH_MCP_PASSWORD
Casos de uso

Resumen de MCP Servers

# SSH MCP Server v2

[![NPM Version](https://img.shields.io/npm/v/ssh-mcp)](https://www.npmjs.com/package/ssh-mcp)
[![Downloads](https://img.shields.io/npm/dm/ssh-mcp)](https://www.npmjs.com/package/ssh-mcp)
[![CI](https://github.com/tufantunc/ssh-mcp/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/tufantunc/ssh-mcp/actions/workflows/ci.yml)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/tufantunc/ssh-mcp/badge)](https://scorecard.dev/viewer/?uri=github.com/tufantunc/ssh-mcp)
[![codecov](https://codecov.io/gh/tufantunc/ssh-mcp/graph/badge.svg?branch=main)](https://codecov.io/gh/tufantunc/ssh-mcp)
[![License](https://img.shields.io/github/license/tufantunc/ssh-mcp)](./LICENSE)
[![GitHub issues](https://img.shields.io/github/issues/tufantunc/ssh-mcp)](https://github.com/tufantunc/ssh-mcp/issues)

**SSH MCP Server** is a security-first Model Context Protocol server that gives LLM agents controlled SSH access to remote hosts — with command classification, policy-based authorization, human-in-the-loop approval, and full audit logging.

> **The risk this server exists to manage.** Giving an LLM shell access on a remote host puts private data, untrusted input and network egress in one place — Simon Willison's ["lethal trifecta"](https://simonwillison.net/2025/Jun/16/the-lethal-trifecta/). Prompt injection has no general fix, so ssh-mcp assumes any command may be attacker-influenced: it classifies before executing, authorizes against a role × host-group matrix, gates destructive work behind approval, and records the decision either way. That narrows the blast radius; it does not remove the risk. Two things stay yours: **never point it at a root account**, and **never set `auto` approval on a production profile**. [SECURITY.md](./SECURITY.md) has the full threat model.

---

## Quick Start

### 1. Install

```bash
npm install -g ssh-mcp
```

### 2. Configure

Without a config the server still starts, so a client or directory can complete the MCP
handshake and read `tools/list` — but **every tool call is refused** until you configure it,
with a message naming the path below. Nothing runs on a host until this step is done.

Create the config file at the path for your platform:

| Platform | Path |
|---|---|
| Linux | `~/.config/ssh-mcp/config.toml` (or `$XDG_CONFIG_HOME/ssh-mcp/config.toml`) |
| macOS | `~/Library/Application Support/ssh-mcp/config.toml` |
| Windows | `%APPDATA%\ssh-mcp\config.toml` |

```toml
[defaults]
defaultProfile = "dev"
approvalMode = "ask-destructive"

[[profiles]]
name = "dev"
host = "192.168.1.100"
port = 22
user = "deploy"           # NOT root!
auth = "key"
keyRef = "~/.ssh/id_ed25519"
role = "admin"
approvalPolicy = "auto"    # dev is permissive
```

```bash
chmod 700 ~/.config/ssh-mcp && chmod 600 ~/.config/ssh-mcp/config.toml
```

The config decides which hosts, roles and policy rules this server honours, so it checks
that nobody but you can read it — and treats the two platforms differently, because the
question has a much clearer answer on one of them.

**Linux and macOS: enforced.** The mode check above, on the file *and* the directory —
which is why `chmod 700` is in that command, since `mkdir -p` under the default umask
leaves the directory 0755. The server refuses to start otherwise. "Only the owner" is
unambiguous here and `chmod` is a one-line fix.

**Windows: split by what the ACL actually allows.** There are no mode bits, so the ACL is
read instead — and read exposure and write exposure are not treated alike, because Windows
is much clearer about one of them than the other.

| The ACL lets another account… | Default |
|---|---|
| only **read** the config | reported, and the server starts |
| **change** the config | refused |
| nothing (no ACL at all) | refused — that is full control for everyone |
| …and if the ACL could not be read | refused, except when `icacls` is absent or the check timed out |

A config under `%APPDATA%` inherits access for you, `SYSTEM` and `Administrators` and needs
nothing done to it. One created elsewhere does not: a file under `C:\` inherits *read* for
every local account and *modify* for every authenticated one. The message names the two
`icacls` commands that fix it either way.

Read exposure is reported rather than refused because that is where Windows is genuinely
muddier than POSIX, and refusing over it blocked a config at the documented location
([#138](https://github.com/tufantunc/ssh-mcp/issues/138)). Write exposure is refused
because it is not muddy at all: another account being able to rewrite the file that decides
which hosts, roles and approval policy this server honours is an authorization bypass, not
a disclosure.

Two flags move the whole thing: `--strictConfigAcl` refuses everything the check objects
to, read-only grants included; `--allowUncheckedConfigAcl` reports everything and refuses
nothing. Neither combination leaves you without an exit, which is the lesson of #138.

### Exit statuses

| Status | Meaning |
|---|---|
| `0` | Clean shutdown |
| `1` | A defect in the server — printed with a stack trace; please report it |
| `2` | How it was invoked or configured — printed as a message, no stack |

A supervisor that treats any non-zero status as a failure needs no change. One
that matched on `1` to detect a startup problem should match on `2` as well.

Starting with nothing configured is **not** an exit-2 condition, as of the release that
added introspection without a config: the server starts so it can be described, and
refuses each tool call instead. A supervisor that used a non-zero exit to catch an
unconfigured deployment should watch for `starting unconfigured` on stderr, or read
`configured` from `GET /health` when running the HTTP transport.

### 3. Set credentials via environment variables

```bash
export SSH_MCP_PASSWORD="your-password"        # if using auth=password
# OR use SSH agent (recommended):
export SSH_AUTH_SOCK="$SSH_AUTH_SOCK"           # already set if agent running
```

### 4. Connect from your MCP client

**Claude Code:**
```bash
claude mcp add --transport stdio ssh-mcp -- ssh-mcp
```

**Claude Desktop / Cursor / Windsurf:**
```json
{
  "mcpServers": {
    "ssh-mcp": {
      "command": "ssh-mcp",
      "env": {
        "SSH_MCP_PASSWORD": "your-password"
      }
    }
  }
}
```

**Never pass passwords as CLI arguments** — they're visible via `ps aux`. Use env vars, config files, SSH agent, or OS keychain.

---

## Tools (11)

| Tool | Purpose | readOnly | destructive |
|------|---------|:--------:|:----------:|
| `list-connections` | Discover available hosts and connection status | ✅ | — |
| `list-sessions` | List active sessions per host | ✅ | — |
| `open-session` | Create a named interactive (stateful) or background session | — | — |
| `close-session` | Close a session. A background session's command is signalled (INT/TERM/KILL) before its channel is dropped | — | ✅ |
| `read-session-output` | Read output from background sessions (e.g., `tail -f`) | ✅ | — |
| `read-command` | Execute allowlisted read-only commands (`ls`, `cat`, `grep`, ...) | ✅ | — |
| `run-command` | Execute arbitrary commands (destructive ones need approval) | — | — |
| `privileged-command` | Execute with sudo (always requires approval) | — | ✅ |
| `sftp-upload` | Upload a file via SFTP | — | ✅ |
| `sftp-download` | Download a file via SFTP | ✅ | — |
| `signal-process` | Send INT/TERM/KILL to a remote PID | — | ✅ |

### Interactive Sessions

Sessions maintain state (CWD, environment variables) between commands:

```
Agent: open-session(name="deploy", type="interactive")
Agent: run-command(session="deploy", command="cd /opt/myapp")
Agent: run-command(session="deploy", command="git pull")    # runs in /opt/myapp
Agent: run-command(session="deploy", command="npm ci")      # CWD persists
Agent: close-session(name="deploy")
```

### Background Sessions

Long-running processes (logs, builds):

```
Agent: open-session(name="logs", type="background", command="tail -f /var/log/syslog")
Agent: read-session-output(name="logs", lines=20)   # poll
Agent: close-session(name="logs")
```

### Remote host support

Tested against Linux (Debian/bash, Alpine/busybox ash), Dropbear, and Windows
OpenSSH on Windows 11.

| | Linux / BSD / macOS | Windows OpenSSH |
|---|:---:|:---:|
| `read-command`, `run-command`, `privileged-command`, `signal-process` | ✅ | ✅ |
| `sftp-upload`, `sftp-download` | ✅ | ✅ |
| Background sessions | ✅ | ✅ |
| **Interactive sessions** | ✅ | ❌ |

**Interactive sessions require a POSIX shell** (sh, bash, ash, zsh). They work by
bracketing each command with `printf` markers and reading `$?` and `$PWD` from a
trailer — none of which exist in `cmd.exe`, the default shell for Windows
OpenSSH. Opening one against such a host fails immediately with an explicit
error rather than timing out; everything else works normally.

Setting PowerShell as the OpenSSH `DefaultShell` does not help: the protocol is
POSIX-specific, not merely non-`cmd`.

---

## Configuration

### Profile options

```toml
[defaults]
defaultProfile = "dev"
sessionMaxPerConnection = 5
sessionIdleTimeoutMs = 600000       # 10min
sessionBackgroundMaxMs = 3600000    # 1hr
commandTimeoutMs = 60000
commandMaxChars = 5000              # 0 = unlimited, the config spelling of --maxChars=none
commandMaxOutputBytes = 1048576     # 1MB
connectionIdleReapMs = 900000       # 15min
commandQuotaPerDay = 0              # 0 = unlimited; circuit breaker for runaway agents
approvalGrantTtlMs = 0              # 0 = always prompt; see "Approval Grants"
approvalMode = "ask-destructive"    # auto | ask-destructive | ask-all | deny

[[profiles]]
name = "prod-web-1"
host = "10.0.1.50"
port = 22
user = "deploy"
auth = "agent"                      # agent | key | password | keychain
keyRef = "~/.ssh/id_ed25519"        # for auth=key
keychainEntry = "ssh-mcp/prod"      # for auth=keychain (requires @napi-rs/keyring)
via = "bastion"                     # Pro

Lo que la gente pregunta sobre ssh-mcp

¿Qué es tufantunc/ssh-mcp?

+

tufantunc/ssh-mcp es mcp servers para el ecosistema de Claude AI. MCP server exposing SSH control for Linux servers via Model Context Protocol. Tiene 655 estrellas en GitHub y su última actualización registrada es del 2026-08-24.

¿Cómo se instala ssh-mcp?

+

Puedes instalar ssh-mcp clonando el repositorio (https://github.com/tufantunc/ssh-mcp) o siguiendo las instrucciones del README en GitHub. ClaudeWave también te ofrece bloques de instalación rápida en esta misma página.

¿Es seguro usar tufantunc/ssh-mcp?

+

Nuestro agente de seguridad ha analizado tufantunc/ssh-mcp y le ha asignado un Trust Score de 94/100 (tier: Verified). Revisa el desglose completo de comprobaciones superadas y flags en esta página.

¿Quién mantiene tufantunc/ssh-mcp?

+

tufantunc/ssh-mcp es mantenido por tufantunc. La última actividad registrada en GitHub es del 2026-08-24, con 5 issues abiertos.

¿Hay alternativas a ssh-mcp?

+

Sí. En ClaudeWave puedes explorar mcp servers similares en /categories/mcp, ordenados por popularidad o actividad reciente.

Despliega ssh-mcp en tu cloud

Lleva este repo a producción en minutos. Cada plataforma genera su propio entorno con variables de entorno editables.

¿Mantienes este repo? Añade un badge a tu README

Pega el badge en tu README de GitHub para mostrar que está auditado por ClaudeWave. Cada badge enlaza de vuelta a esta página y muestra el Trust Score actual.

Featured on ClaudeWave: tufantunc/ssh-mcp
[![Featured on ClaudeWave](https://claudewave.com/api/badge/tufantunc-ssh-mcp)](https://claudewave.com/repo/tufantunc-ssh-mcp)
<a href="https://claudewave.com/repo/tufantunc-ssh-mcp"><img src="https://claudewave.com/api/badge/tufantunc-ssh-mcp" alt="Featured on ClaudeWave: tufantunc/ssh-mcp" width="320" height="64" /></a>

Más MCP Servers

Alternativas a ssh-mcp