Skip to main content
Glama
perhamm

ssh-mcp-server

by perhamm

ssh-mcp-server

CI npm

Servidor MCP sobre SSH: el agente ejecuta comandos en máquinas remotas, mientras que las claves, contraseñas y sudo permanecen de nuestro lado.

Fork de classfang/ssh-mcp-server bajo ISC.

Русский | English

Qué es

ssh-mcp-server es un puente entre un cliente MCP (Claude Code, Cursor, Cline) y SSH. El agente invoca herramientas, el servidor se conecta a la máquina y devuelve la salida. El modelo no ve ni la clave privada, ni la contraseña, ni la contraseña de sudo: todo esto se lee desde la configuración local y las variables de entorno del proceso.

Un solo servidor atiende cualquier número de hosts. El host se selecciona sobre la marcha mediante un alias de ~/.ssh/config, por lo que no es necesario escribir cada máquina en la configuración del cliente MCP.

Related MCP server: ssh-mcp-server

Qué se ha añadido en este fork

Funcionalidad

Para qué

Hosts de ~/.ssh/config sobre la marcha

Un solo MCP para todo el parque. El alias se pasa en connectionName, la conexión se establece en la primera solicitud

ProxyJump

El host detrás de un bastión es accesible por alias, la cadena ProxyJump se resuelve desde la configuración SSH

sudo desde variable de entorno

El agente solicita sudo: true, el servidor introduce la contraseña y la elimina de la salida

Núcleo prohibido

Lista de operaciones que nunca se ejecutan: ni con sudo, ni en ningún perfil, ni a través de SFTP

Perfiles de guardias

Conjunto listo de prohibiciones safe y lista blanca readonly, versionado y actualizable

Túneles

SOCKS5 (equivalente a ssh -D) y reenvío de puerto (equivalente a ssh -L) a cualquier puerto local

Verificación de claves de host

known_hosts se verifica por defecto; una clave que no esté en la lista significa rechazo de conexión

Criptografía moderna

Ed25519 primero en la lista, sin SHA-1, CBC ni DSA

Registro de auditoría

Cada llamada se escribe en JSONL con rotación y archivos gzip

Sin carga de archivos

upload no se publica por defecto: un archivo que los guardias no leerán es una forma de introducir código en el host

Herramientas

Herramienta

Qué hace

execute-command

Ejecuta un comando, admite sudo y un connectionName arbitrario

download

Descarga un archivo del servidor

list-servers

Muestra las conexiones configuradas, su estado y el perfil de guardias activo

list-ssh-hosts

Muestra los alias de la configuración SSH disponibles como connectionName

open-tunnel

Levanta un proxy SOCKS5 o un reenvío de puerto a través de la conexión

close-tunnel

Cierra un túnel

list-tunnels

Muestra los túneles abiertos y los contadores de conexiones

list-ssh-hosts solo aparece con la bandera --ssh-config-hosts; las herramientas de túnel se eliminan con la bandera --disable-tunnels. La herramienta upload no está en la lista: solo se publica con la bandera --enable-upload.

Datos del host sin comandos adicionales

Al conectarse, el servidor captura una vez el estado de la máquina: nombre, direcciones, SO, kernel, uptime, disco, memoria, número de procesos. Todas las sondas se combinan con marcadores en un solo comando, de modo que es una sola sesión ssh, no seis.

El servidor mantiene el resultado en caché y lo entrega en list-servers:

[connected] prod-1 | deploy@10.0.0.5:22 | hostname=prod-1 | os=Linux | updated=2026-08-19T18:14:23Z

Raw JSON:
[{"name":"prod-1","connected":true,"guards":"guards=safe ruleset=2026.08.19 ...",
  "status":{"reachable":true,"osVersion":"Ubuntu 24.04.1 LTS","kernelVersion":"6.8.0-51-generic",
  "uptime":"12 days","diskSpace":{"free":"9.8G","total":"229.6G"},
  "memory":{"free":"5.6G","total":"15.5G"},"processes":{"running":214}}}]

Es decir, no hace falta preguntar por uname -a, df -h, free -h ni uptime: las respuestas ya han llegado. El agente llama a list-servers una vez y lee el estado desde allí.

Las sondas pasan por los guardias una a una. Con la lista blanca, en el estado solo quedarán los campos permitidos. Un estado incompleto no significa que el host esté inaccesible.

Un comando exitoso sin salida devuelve [exit code] 0, no una cadena vacía. Una respuesta vacía el modelo la lee como un resultado poco claro y va a verificar de nuevo con echo $?, lo que supone una sesión extra al servidor y tokens adicionales.

Inicio rápido: un servidor para todo el parque

Configuración del cliente MCP:

{
  "mcpServers": {
    "ssh": {
      "command": "npx",
      "args": [
        "-y",
        "@perhamm/ssh-mcp-server",
        "--ssh-config-hosts",
        "--guards-profile", "safe"
      ],
      "env": {
        "SSH_MCP_SUDO_PASSWORD": "..."
      }
    }
  }
}

A partir de ahí, el agente funciona así:

  1. Llama a list-ssh-hosts y encuentra el alias necesario, por ejemplo r-ulybka-prod-master. En configuraciones grandes la lista se recorta, por lo que el agente pasa filter: una subcadena o un patrón del tipo r-ulybka-*.

  2. Llama a execute-command con connectionName: "r-ulybka-prod-master".

  3. El servidor lee el alias de ~/.ssh/config, toma de allí HostName, User, Port, IdentityFile y ProxyJump, establece la conexión y ejecuta el comando.

La clave no abandona la máquina: el servidor lee el archivo por sí mismo; en el diálogo solo aparece la ruta de la configuración SSH. Si no se especifica IdentityFile, se toma el ssh-agent de SSH_AUTH_SOCK. Un alias sin HostName se conecta por su propio nombre, como hace ssh.

Solo es alcanzable el alias que esté declarado en la configuración como bloque Host independiente. El bloque Host * proporciona valores por defecto, pero no convierte un nombre arbitrario en un host alcanzable.

La lista de alias se puede acotar:

"args": [
  "-y", "@perhamm/ssh-mcp-server",
  "--ssh-config-hosts",
  "--allowed-hosts", "r-ulybka-*,*-stage-*",
  "--ssh-config-file", "/home/user/.ssh/config_work"
]

Los patrones admiten * y ?. Si el alias no coincide con ningún patrón, la conexión no se establece y el agente recibe el error SSH_HOST_NOT_ALLOWED.

Modo seguro y guardias

Los guardias son un conjunto versionado de reglas que verifica cada comando antes de enviarlo al servidor. Las reglas están en guards/default-guards.json y se actualizan junto con el repositorio.

Perfiles

Perfil

Comportamiento

off

Las reglas del perfil están desactivadas; solo funciona el núcleo prohibido. Valor por defecto

safe

Además prohíbe comandos destructivos; el resto lo permite

readonly

Solo permite lectura y diagnóstico; hereda todas las prohibiciones de safe

"args": ["-y", "@perhamm/ssh-mcp-server", "--ssh-config-hosts", "--guards-profile", "safe"]

Lo que safe detecta además del núcleo: shutdown y reboot, reinicio del firewall, detención de sshd y kubelet, kubectl delete, helm uninstall, docker system prune, eliminación de paquetes, DROP DATABASE, curl | sh, git push --force, limpieza de logs, descarga de módulos del kernel, editores interactivos. La lista completa con motivos está en el JSON.

readonly además exige que cada parte del comando esté en la lista blanca: ls, cat, grep, find, ps, ss, df, journalctl, systemctl status, kubectl get/describe/logs, docker ps/logs y similares. En este perfil sudo está completamente prohibido, junto con su, doas y pkexec.

Núcleo prohibido

Parte de las operaciones nunca se ejecutan: ni en el perfil off, ni con sudo, ni mediante un archivo de guardias propio, ni a través de SFTP para eludir los comandos. La lista vive en el bloque forbidden.

Categoría

Qué queda cerrado

Cuentas

useradd, usermod, userdel, groupadd, passwd, chpasswd, chage, vipw y escritura en /etc/passwd, /etc/shadow, /etc/group

sudo

Escritura en /etc/sudoers y /etc/sudoers.d, visudo

Programaciones

crontab salvo crontab -l, escritura en /etc/cron*, /var/spool/cron, /etc/anacrontab, comandos at y batch

systemd

Escritura de unidades y temporizadores en /etc/systemd, /lib/systemd, /usr/lib/systemd, systemctl edit, systemd-run

SSH

Edición de /etc/ssh/*, ~/.ssh/*, authorized_keys, sshd_config, así como ssh-keygen, ssh-copy-id, ssh-add

Intérpretes

python, perl, ruby, node, php, lua, Rscript y ejecución de un script como archivo: bash /tmp/x.sh, sh -s, source. Los guardias no leen código ajeno, por lo que esa ejecución queda cerrada por completo

Borrado masivo

rm -r de un directorio de primer nivel o de un subdirectorio del sistema, rm -r con máscara, find -delete, borrado mediante xargs rm, bandera --no-preserve-root

Discos y secretos

mkfs, wipefs, dd of=/dev/, escritura en /dev/sd*, fork bomb, lectura de /etc/shadow y de claves privadas

El trabajo habitual sigue funcionando: crontab -l, cat /etc/ssh/sshd_config, systemctl restart nginx, rm -rf /var/lib/myapp/cache/tmp pasan. Un bash -c "..." analizable también funciona: su contenido se verifica con las mismas reglas.

El núcleo también cierra las herramientas de archivos. download no tomará /etc/shadow ni el contenido de ~/.ssh, y allowedRemotePaths no puede revertir eso. El lado local también está protegido: download no colocará un archivo en nuestro propio ~/.ssh.

La carga de archivos está completamente desactivada. La herramienta upload no se publica hasta que se pasa --enable-upload, y el perfil readonly rechaza la carga incluso con esa bandera.

Si el servidor se necesita precisamente para crear usuarios o editar el cron, el núcleo habrá que modificarlo en el fork de forma consciente: no existe una bandera que lo desactive.

Por qué no se elude con un punto y coma

El comando se divide en partes por ;, |, &&, ||, &, saltos de línea y sustituciones $(...), y cada parte se verifica por separado. Las comillas se tienen en cuenta al analizar. Así, ls; rm -rf / no pasa en ningún perfil, aunque la línea completa empiece por el permitido ls.

Los envoltorios se eliminan antes de la verificación: sudo, env, timeout 5, nohup y asignaciones del tipo LC_ALL=C no ocultan el comando a las reglas. El script dentro de bash -c "..." se analiza por separado y se verifica con las mismas reglas. La longitud del comando está limitada a 5000 caracteres.

Los guardias cubren errores del agente, no una evasión intencionada. Un intérprete con código arbitrario dentro, como python -c, las reglas no lo analizarán. Allí donde la evasión sea inaceptable, limitamos los permisos del propio usuario SSH.

Actualización de reglas

Tres formas de mantener las reglas al día:

  1. Fusionamos el upstream en nuestro fork. El archivo de reglas está versionado con el campo version; la versión se ve en list-servers y en el texto de rechazo.

  2. Mantenemos nuestro propio archivo y lo indicamos con --guards-file /etc/ssh-mcp/guards.json. Las reglas de ese archivo se añaden a las integradas; la versión pasa a ser 2026.08.19+local-1.

  3. Actualizamos el archivo según un horario:

node scripts/update-guards.js https://example.com/guards.json /etc/ssh-mcp/guards.json

El script verifica el JSON y compila cada expresión regular, y solo entonces reemplaza el archivo. Una descarga corrupta no rompe el conjunto de reglas en funcionamiento.

Formato de nuestro propio archivo:

{
  "version": "local-1",
  "profiles": {
    "safe": {
      "deny": [
        { "id": "no-ansible", "pattern": "^ansible-playbook\\b", "reason": "выкат идёт из CI" }
      ]
    }
  }
}

El campo scope: "command" obliga a la regla a verificar el comando completo, no por partes. Así funcionan las reglas sobre curl | sh y SQL. En el bloque forbidden de nuestro propio archivo se pueden añadir prohibiciones propias, pero las integradas no se pueden quitar: las listas se suman.

Los antiguos --whitelist y --blacklist no han desaparecido y se verifican antes que los guardias.

La contraseña de sudo está en la variable de entorno del proceso del servidor. El agente envía sudo: true, pero no ve la contraseña ni en los argumentos de la llamada ni en la salida.

{
  "mcpServers": {
    "ssh": {
      "command": "npx",
      "args": ["-y", "@perhamm/ssh-mcp-server", "--ssh-config-hosts", "--guards-profile", "safe"],
      "env": {
        "SSH_MCP_SUDO_PASSWORD": "..."
      }
    }
  }
}

Llamada a la herramienta:

{
  "tool": "execute-command",
  "params": {
    "cmdString": "systemctl restart nginx",
    "connectionName": "r-ulybka-prod-master",
    "sudo": true
  }
}

El comando viaja al servidor como sudo -S -k -p '' -u root -- /bin/sh -c '<команда>' y la contraseña se escribe en el stdin del canal. No aparece en la línea de comandos, por lo que no llega a ps ni al historial. El pseudoterminal se desactiva para estos comandos; de lo contrario, la tty haría eco de la entrada en la salida. Por si acaso, la contraseña se elimina de la salida y del texto de los errores.

El nombre de la variable y del usuario de destino se cambian con las opciones --sudo-password-env y --sudo-user. Si la variable está vacía, la llamada falla con SUDO_PASSWORD_MISSING incluso antes de conectarse. El perfil readonly prohíbe sudo por completo.

En el modo shell, la contraseña se añade en una línea aparte justo después del comando, porque sudo lee el mismo stdin que el propio shell. La opción -k garantiza que la contraseña se pida siempre y que la línea no se ejecute como comando. Para sudo es mejor el modo exec.

Túneles

open-tunnel levanta un listener local y envía el tráfico a través de la conexión SSH. Resulta útil cuando no hay acceso directo a los servicios del clúster, pero sí al nodo.

SOCKS5 en el puerto 8777:

{
  "tool": "open-tunnel",
  "params": {
    "type": "socks5",
    "localPort": 8777,
    "connectionName": "r-ulybka-prod-master"
  }
}

A partir de ahí, cualquier cliente pasa por el proxy; los nombres se resuelven en el lado remoto:

curl --socks5-hostname 127.0.0.1:8777 http://prometheus.monitoring.svc:9090/api/v1/query?query=up
kubectl --request-timeout=30s ... # через HTTPS_PROXY=socks5h://127.0.0.1:8777

Reenvío de un puerto, equivalente a ssh -L:

{
  "tool": "open-tunnel",
  "params": {
    "type": "local",
    "localPort": 15432,
    "remoteHost": "pg-master.internal",
    "remotePort": 5432
  }
}

Si no se indica localPort, el sistema elige un puerto y lo devuelve en la respuesta. Los túneles viven hasta close-tunnel, hasta que se interrumpe la conexión SSH o hasta que se detiene el servidor.

Las restricciones se definen con las opciones:

Opción

Valor por defecto

Qué hace

--tunnel-bind-address

127.0.0.1

Dirección en la que escuchan los túneles

--allowed-tunnel-ports

sin restricciones

Lista de puertos que se pueden ocupar

--max-tunnels

8

Cuántos túneles mantenemos a la vez

--disable-tunnels

desactivado

Quita las herramientas de túnel de la lista

El listener se levanta en loopback por defecto. Una dirección más amplia que loopback expone el proxy a tu red, así que debe cambiarse con conocimiento de causa.

Verificación de claves de host

La clave del servidor se comprueba contra known_hosts en cada conexión, incluidos los hosts intermedios de la cadena ProxyJump. Por defecto el modo es strict: que el host no esté en known_hosts significa rechazo.

Modo

Comportamiento

strict

Por defecto. Solo nos conectamos a hosts de known_hosts

accept-new

Un host desconocido se registra en la primera conexión; la discrepancia de clave sigue siendo un rechazo

off

No hay comprobación; comportamiento del upstream

Se comprueban ~/.ssh/known_hosts, ~/.ssh/known_hosts2 y /etc/ssh/ssh_known_hosts; para un alias con UserKnownHostsFile, se comprueba el archivo indicado en la configuración SSH. La lista propia se define con la opción --known-hosts-file. Se admiten registros con hash, patrones, el formato [host]:port y la marca @revoked.

El rechazo llega con el código SSH_HOST_KEY_REJECTED y un texto con la huella:

Host key of prod.example.com is not in known_hosts (~/.ssh/known_hosts): ssh-ed25519 SHA256:xxxx.
Verify that fingerprint, add the host to known_hosts, or start the server with --host-key-checking accept-new.

La discrepancia de clave no se acepta nunca, en ningún modo: el servidor se niega a conectar y escribe que el host ha sido recreado o que alguien se ha interpuesto en medio.

Para la primera toma de contacto con el parque de máquinas, conviene pasar una vez con --host-key-checking accept-new y luego volver a strict.

Log de auditoría

Cada llamada se escribe como una línea JSON: comando, conexión, opción sudo, veredicto de la guarda, duración y volumen de salida. El contenido de la salida no entra en el log; la contraseña de sudo se elimina.

{"time":"2026-08-19T08:12:44.101Z","pid":8123,"event":"command","result":"blocked","connection":"r-ulybka-prod-master","command":"useradd deploy","sudo":true,"code":"COMMAND_VALIDATION_FAILED","reason":"Blocked by the forbidden core ..."}
{"time":"2026-08-19T08:12:51.880Z","pid":8123,"event":"command","result":"ok","connection":"r-ulybka-prod-master","command":"systemctl status nginx","sudo":false,"durationMs":412,"bytes":1840}

Se registran los eventos connect, command, download, upload, tunnel-open, tunnel-close y host-key.

Por defecto, el archivo se encuentra en $XDG_STATE_HOME/ssh-mcp-server/audit.jsonl, es decir, normalmente ~/.local/state/ssh-mcp-server/audit.jsonl, con permisos 0600.

Opción

Por defecto

Qué hace

--audit-log <path>

directorio de estado XDG

Ruta al log; el valor off desactiva la escritura

--audit-max-size <bytes>

10485760

Tamaño tras el cual el archivo se rota. 0 desactiva la rotación integrada

--audit-keep <count>

10

Cuántos archivos gzip conservamos

La rotación está integrada: al alcanzar el límite, el archivo actual pasa a audit.jsonl.1.gz, los archivos antiguos se desplazan y se elimina todo lo que quede fuera de --audit-keep. Diez archivos de 10 MiB suponen unos cien megabytes sin comprimir y bastante menos después de gzip.

Si los logs ya los gestiona logrotate, ponemos --audit-max-size 0 y configuramos la rotación con el modo copytruncate.

Un error de escritura no hace fallar el comando: el servidor lo escribe una vez en stderr y sigue funcionando.

Métodos de conexión

A continuación, escenarios de menor a mayor complejidad. En args, cada opción y su valor son dos elementos separados del array: "--host", "192.168.1.1", no "--host 192.168.1.1".

Usuario y contraseña

{
  "mcpServers": {
    "ssh-mcp-server": {
      "command": "npx",
      "args": [
        "-y",
        "@perhamm/ssh-mcp-server",
        "--host", "192.168.1.1",
        "--port", "22",
        "--username", "root",
        "--password", "pwd123456"
      ]
    }
  }
}

Clave privada

"args": [
  "-y", "@perhamm/ssh-mcp-server",
  "--host", "192.168.1.1",
  "--username", "root",
  "--privateKey", "~/.ssh/id_rsa",
  "--passphrase", "pwd123456"
]

La contraseña de la clave no es necesario escribirla en la configuración; se puede poner en la variable SSH_MCP_PASSPHRASE.

Un alias de ~/.ssh/config

"args": ["-y", "@perhamm/ssh-mcp-server", "--host", "myserver"]

El servidor lee HostName, Port, User, IdentityFile y ProxyJump del bloque Host myserver, incluidas las directivas Include y los patrones. Las opciones de línea de comandos tienen prioridad: --port 2222 anula el puerto de la configuración.

Bastión y ProxyJump

Si el alias tiene ProxyJump, la cadena se levanta sola:

Host r-ulybka-prod-master
    HostName 10.20.30.40
    User ops
    ProxyJump bastion
    IdentityFile ~/.ssh/prod_key

Cada salto siguiente se conecta a través del canal del anterior, como hace ssh -J. La cadena también se puede indicar manualmente: --proxy-jump "bastion,gateway:2222". La profundidad de la cadena está limitada a cinco saltos.

Proxy

"args": [
  "-y", "@perhamm/ssh-mcp-server",
  "--host", "192.168.1.1",
  "--username", "root",
  "--password", "pwd123456",
  "--proxy", "socks5://user:pwd@proxy-host:1080"
]

Se admiten socks://, socks5://, http:// y https://. HTTP y HTTPS usan el método CONNECT con autenticación Basic; el puerto por defecto es 80 y 443. Para SOCKS5, el puerto es obligatorio. La antigua opción --socksProxy sigue funcionando, pero solo acepta SOCKS. --proxy y --proxy-jump no se usan juntos.

Host de salto con shell interactivo

transportMode por defecto es exec. Cambiamos a shell si, tras un inicio de sesión correcto, los comandos no se ejecutan o el dispositivo solo ofrece una sesión interactiva:

"args": [
  "-y", "@perhamm/ssh-mcp-server",
  "--host", "bastion.example.com",
  "--username", "ops",
  "--password", "pwd123456",
  "--transport-mode", "shell",
  "--shell-ready-timeout", "15000"
]

En el modo shell, los comandos pasan en cola por una única sesión persistente, y upload y download no funcionan: en ese modo SFTP está desactivado.

Autenticación de dos factores

La opción --try-keyboard activa keyboard-interactive. La contraseña y la clave se rellenan automáticamente; el código del segundo factor se lee de la variable SSH_MCP_2FA_CODE.

Varias conexiones en un mismo servidor

Además de los alias de la configuración SSH, queda el método antiguo: un archivo con la descripción de las conexiones.

[
  {
    "name": "dev",
    "host": "1.2.3.4",
    "port": 22,
    "username": "alice",
    "privateKey": "~/.ssh/dev_key",
    "guardProfile": "safe",
    "commandTimeoutMs": 120000
  },
  {
    "name": "prod",
    "host": "5.6.7.8",
    "port": 22,
    "username": "bob",
    "privateKey": "~/.ssh/prod_key",
    "guardProfile": "readonly",
    "allowedRemotePaths": ["/var/log", "/tmp"]
  }
]
"args": ["-y", "@perhamm/ssh-mcp-server", "--config-file", "/abs/path/ssh-config.json"]

También se admite el formato de objeto en el que la clave es el nombre de la conexión. La conexión se selecciona con el parámetro connectionName; sin él, se toma la primera.

Restricciones de comandos y rutas

Listas blanca y negra

"args": [
  "-y", "@perhamm/ssh-mcp-server",
  "--host", "192.168.1.1",
  "--username", "root",
  "--privateKey", "~/.ssh/id_rsa",
  "--whitelist", "^ls( .*)?,^cat .*,^df.*",
  "--blacklist", "^rm .*,^shutdown.*"
]

Los patrones son expresiones regulares separadas por comas. El comando se comprueba primero contra la lista blanca, luego contra la negra y después contra el perfil de guardas, y debe superar las tres comprobaciones.

Plantilla de comando

--command-template envuelve cada comando. <quotedCommand> sustituye el comando como un argumento escapado; <command> lo inserta tal cual. La plantilla se aplica después de la sustitución del directorio de trabajo.

su root -c <quotedCommand>
docker exec -i mycontainer sh -c <quotedCommand>

Rutas para operaciones con archivos

--allowed-local-paths amplía la lista de directorios locales disponibles para upload y download (por defecto, solo el directorio actual). --allowed-remote-paths limita las rutas remotas; ahí se escriben rutas POSIX absolutas separadas por comas. Sin esta opción, SFTP ve todo el sistema de archivos del host; el servidor lo advierte al arrancar.

Timeouts y límite de salida

Parámetro

Por defecto

Qué limita

timeout en la llamada a la herramienta

no

Un solo comando; anula la configuración de la conexión

commandTimeoutMs

30000

El comando en modo exec

shellCommandTimeoutMs

30000

El comando en modo shell

connectionTimeoutMs

30000

El establecimiento de la conexión y el handshake

sftpTimeoutMs

300000

Las operaciones SFTP

maxOutputBytes

10485760

La salida capturada de un comando

keepaliveIntervalMs

10000

El intervalo de keepalive

Al superar el límite de salida, el comando se interrumpe y la herramienta devuelve OUTPUT_LIMIT_EXCEEDED junto con el fragmento ya recopilado. Los errores llegan con una estructura formada por code, message y retriable.

Opciones de línea de comandos

  --config-file <path>             Файл с описанием соединений
  --ssh-config-file <path>         Путь к SSH-конфигу (по умолчанию ~/.ssh/config)
  --ssh <config>                   Соединение как JSON или пары key=value
  -h, --host <host>                Хост или алиас из SSH-конфига
  -p, --port <port>                Порт
  -u, --username <name>            Пользователь
  -w, --password <password>        Пароль
  -k, --privateKey <path>          Путь к приватному ключу
  -P, --passphrase <passphrase>    Пароль от ключа
  -a, --agent <path>               Сокет ssh-agent
  -W, --whitelist <patterns>       Белый список команд, через запятую
  -B, --blacklist <patterns>       Чёрный список команд, через запятую
  --proxy <url>                    Прокси SOCKS5, HTTP или HTTPS
  -s, --socksProxy <url>           Старый флаг только для SOCKS5
  --allowed-local-paths <paths>    Локальные каталоги для upload и download
  --allowed-remote-paths <paths>   Удалённые каталоги для SFTP
  --transport-mode <mode>          exec или shell (по умолчанию exec)
  --shell-ready-timeout <ms>       Таймаут готовности shell (по умолчанию 10000)
  --command-template <template>    Шаблон с <command> или <quotedCommand>
  --pty                            Псевдотерминал для exec (по умолчанию включён)
  --try-keyboard                   Keyboard-interactive для 2FA
  --pre-connect                    Подключиться ко всем хостам при старте
  --ssh-config-hosts               Разрешить хосты из SSH-конфига на лету
  --allowed-hosts <patterns>       Шаблоны разрешённых алиасов, через запятую
  --proxy-jump <chain>             Цепочка ProxyJump, через запятую
  --guards-profile <name>          off, safe или readonly (по умолчанию off)
  --guards-file <path>             Свой набор правил поверх встроенного
  --sudo-password-env <var>        Переменная с паролем sudo
  --sudo-user <user>               Пользователь для sudo (по умолчанию root)
  --host-key-checking <mode>       strict, accept-new или off (по умолчанию strict)
  --known-hosts-file <paths>       Свои файлы known_hosts, через запятую
  --host-key-algorithms <list>     Алгоритмы хост-ключа, через запятую
  --enable-upload                  Опубликовать инструмент upload (по умолчанию выключен)
  --audit-log <path|off>           Путь к аудит-логу (по умолчанию каталог состояния XDG)
  --audit-max-size <bytes>         Порог ротации, 0 отключает (по умолчанию 10485760)
  --audit-keep <count>             Сколько архивов держим (по умолчанию 10)
  --disable-tunnels                Убрать туннельные инструменты
  --tunnel-bind-address <addr>     Адрес для туннелей (по умолчанию 127.0.0.1)
  --allowed-tunnel-ports <ports>   Разрешённые порты туннелей, через запятую
  --max-tunnels <count>            Лимит одновременных туннелей (по умолчанию 8)
  --version, -v                    Версия пакета
  --help                           Справка

Seguridad

  • Para producción activamos --guards-profile safe; para el análisis de incidentes de guardia sirve readonly. Con off, solo permanece un núcleo de comandos prohibidos; todo lo demás se ejecutará, algo que el servidor advierte en el log.

  • La clave, su contraseña y la contraseña de sudo se leen de archivos y variables de entorno. En la configuración del cliente MCP guardamos la ruta a la clave, no la clave en sí.

  • Los túneles escuchan en loopback. SOCKS5 no tiene autenticación, por lo que un proxy en 0.0.0.0 abre la red interna a cualquiera que pueda alcanzar el puerto; el servidor escribe una advertencia al respecto al arrancar.

  • Sin --allowed-remote-paths, a través de SFTP se lee y se escribe cualquier ruta del host, incluida ~/.ssh/authorized_keys.

  • La clave del host se comprueba contra known_hosts en modo strict. Solo merece la pena desactivar la comprobación con --host-key-checking off en un laboratorio.

  • No hay límites de frecuencia de llamadas.

Desarrollo

npm install
npm run build
npm test

Los tests se ejecutan con el runner integrado de Node.js y están en test/.

Upstream y licencia

El proyecto surgió de classfang/ssh-mcp-server (autor junki.cn), con licencia ISC. El copyright del upstream se conserva en LICENSE, donde también está el enlace al repositorio original.

El conjunto de guardas está parcialmente inspirado en las ideas de tufantunc/ssh-mcp (MIT).

El paquete en NPM: @perhamm/ssh-mcp-server.

F
license - not found
Not graded
quality - not tested
A
maintenance

Maintenance

Maintainers
Response time
0dRelease cycle
6Releases (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
    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
    32
    28
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    An MCP server that enables remote SSH command execution and bidirectional file transfers through a standardized interface. It allows AI assistants to securely manage remote servers while keeping credentials isolated and applying command-level security controls.
    ISC
  • A
    license
    A
    quality
    B
    maintenance
    MCP server for managing multiple SSH servers via AI assistants, offering tools for remote command execution, file operations, and system monitoring.
    11
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    An MCP server that gives AI agents SSH capabilities to execute commands, transfer files, and inspect remote systems through a preconfigured host list.
    43
    MIT

View all related MCP servers

Related MCP Connectors

  • MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.

  • MCP server for secureFlows: token-free URL builders and integration-linting tools for AI agents.

  • MCP server connecting AI agents to non-custodial staking data across 130+ networks.

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/perhamm/ssh-mcp-server'

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