Files

13 KiB
Raw Permalink Blame History

ssh-mcp-server logo

ssh-dynamic-mcp

MCP-сервер для управления удалёнными серверами по SSH с динамическими подключениями на лету и встроенной маскировкой секретов в логах и ошибках.

📝 О проекте

ssh-dynamic-mcp — это форк classfang/ssh-mcp-server (v1.9.0), расширенный поддержкой динамического режима: теперь сервер можно запустить без какой-либо конфигурации и подключаться к произвольному хосту прямо в каждом вызове инструмента, передавая host, username и пароль (или приватный ключ) в параметрах вызова.

Ключевые отличия от исходной версии:

  • 🔌 Динамический режим — запуск без аргументов и подключение «на лету» к любому хосту
  • 🛡️ Маскировка секретов — пароли, фразы-пароли и ключи автоматически заменяются на [REDACTED] в логах и сообщениях об ошибках
  • 🔑 --password-from-env — чтение пароля из переменной окружения вместо аргументов командной строки
  • 🚫 Новые стабильные коды ошибок, в том числе SSH_CONFIG_MISSING при неполных параметрах подключения

Остальной функционал исходной версии (статическая конфигурация, несколько серверов, прокси, shell-транспорт, команды-шаблоны, whitelist/blacklist, 2FA) сохранён и работает как раньше.

🛠️ Инструменты

Инструмент Назначение
execute-command Выполнить команду на удалённом сервере
upload Загрузить локальный файл на сервер
download Скачать файл с сервера
list-servers Показать список доступных SSH-подключений

🚀 Быстрый старт

Динамический режим (новое)

Запустите сервер вообще без аргументов — и подключайтесь к любому хосту прямо при вызове инструмента.

{
  "mcpServers": {
    "ssh-dynamic": {
      "command": "node",
      "args": ["C:/path/to/ssh-dynamic-mcp/build/index.js"]
    }
  }
}

Теперь в каждом вызове можно задать целевой хост и учётные данные:

{
  "tool": "execute-command",
  "params": {
    "cmdString": "df -h",
    "host": "192.168.1.10",
    "port": 22,
    "username": "max",
    "password": "пароль"
  }
}

То же относится к upload и download — передавайте host/username (+ password или privateKey) прямо в параметрах вызова, и для операции создастся одноразовое эфемерное подключение, которое будет закрыто после выполнения.

Как это устроено: когда в вызове присутствуют host и username, сервер открывает отдельное соединение только для этой операции (динамический режим). Если их нет — используется connectionName для подключения к предварительно настроенному (статическому) серверу.

Безопасность паролей

Пароли в аргументах командной строки видны в списке процессов и командной истории. Чтобы этого избежать, используйте --password-from-env:

{
  "mcpServers": {
    "ssh-dynamic": {
      "command": "node",
      "args": [
        "C:/path/to/ssh-dynamic-mcp/build/index.js",
        "--password-from-env", "SSH_MCP_PASSWORD"
      ]
    }
  }
}

Пароль будет прочитан из переменной окружения SSH_MCP_PASSWORD, заданной в среде, где запущен сервер.

Секреты (пароль, фраза-пароль приватного ключа) автоматически маскируются знаком [REDACTED] в любом логе и сообщении об ошибке, возвращаемом модели, — они не попадут в вывод сервера.

🔐 Статическая конфигурация (как в оригинале)

Весь функционал исходной версии поддерживается. Например, парольная аутентификация:

{
  "mcpServers": {
    "ssh-mcp-server": {
      "command": "node",
      "args": [
        "C:/path/to/ssh-dynamic-mcp/build/index.js",
        "--host", "192.168.1.1",
        "--port", "22",
        "--username", "root",
        "--password", "pwd123456"
      ]
    }
  }
}

Несколько серверов

{
  "mcpServers": {
    "ssh-mcp-server": {
      "command": "node",
      "args": [
        "C:/path/to/ssh-dynamic-mcp/build/index.js",
        "--config-file", "ssh-config.json"
      ]
    }
  }
}

Файл ssh-config.json (массив или объект):

[
  {
    "name": "dev",
    "host": "1.2.3.4",
    "port": 22,
    "username": "alice",
    "password": "secret"
  },
  {
    "name": "bastion",
    "host": "9.9.9.9",
    "port": 22,
    "username": "ops",
    "password": "pwd123456",
    "transportMode": "shell"
  }
]

Выбор подключения при вызове — через connectionName:

{
  "tool": "execute-command",
  "params": {
    "cmdString": "ls -al",
    "connectionName": "dev"
  }
}

⚙️ Динамические параметры инструментов

Для execute-command, upload и download в динамическом режиме доступны:

Параметр Тип Описание
host string Целевой хост (IP или hostname)
port number SSH-порт (по умолчанию 22)
username string SSH-пользователь
password string Пароль
privateKey string Путь к приватному ключу или его содержимое
passphrase string Фраза-пароль для зашифрованного ключа

host и username обязательны для запуска динамического подключения. Если их не передать — будет использован connectionName (статический сервер).

⏱️ Тайм-ауты и лимиты

  • timeout — тайм-аут одной команды (мс, опционально; по умолчанию 30000 мс)
  • commandTimeoutMs / shellCommandTimeoutMs — настраиваемые значения по умолчанию в конфигурации
  • connectionTimeoutMs — лимит установления SSH-соединения (по умолчанию 30000 мс)
  • sftpTimeoutMs — тайм-аут SFTP-операций (по умолчанию 300000 мс)
  • maxOutputBytes — ограничение общего объёма stdout+stderr одной команды (по умолчанию 10 MiB; 0 отключает)

🛡️ Продвинутые возможности (из оригинала)

  • Прокси: --proxy поддерживает SOCKS5, HTTP и HTTPS
  • Whitelist / blacklist: --whitelist, --blacklist ограничивают допустимые команды
  • Shell-транспорт: --transport-mode shell для 堡垒机/跳板机 и интерактивных оболочек
  • Командные шаблоны: --command-template с <quotedCommand> / <command>
  • SSH config: переиспользование ~/.ssh/config через --host <alias>
  • 2FA / MFA: --try-keyboard + переменная SSH_MCP_2FA_CODE для одноразовых кодов
  • Ограничение путей: --allowed-local-paths и --allowed-remote-paths

⚙️ Справка по командной строке

Опции:
  --config-file <path>           Загрузить конфигурации из JSON-файла
  --ssh-config-file <path>       SSH-конфиг (по умолчанию: ~/.ssh/config)
  --ssh <config>                 Добавить конфигурацию (JSON или key=value)
  -h, --host <host>              Хост или алиас из SSH config
  -p, --port <port>              Порт (по умолчанию: 22)
  -u, --username <name>          SSH-пользователь
  -w, --password <pw>            SSH-пароль
  --password-from-env <name>     Читать пароль из переменной окружения (безопаснее, чем -w)
  -k, --privateKey <path>        Приватный ключ
  -P, --passphrase <pass>        Фраза-пароль ключа
  -a, --agent <path>             SSH agent socket
  -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> Разрешённые удалённые пути (POSIX абсолютные)
  --transport-mode <mode>        exec | shell (по умолчанию: exec)
  --shell-ready-timeout <ms>     Тайм-аут готовности shell (по умолчанию: 10000)
  --command-template <tpl>       Шаблон обёртки команд
  --pty                          Выделять псевдо-TTY (по умолчанию: включено)
  --pre-connect                  Предподключение ко всем серверам при старте
  --version, -v                  Версия
  --help                         Справка

🛡️ Безопасность

  • Динамический режим не имеет белого списка команд — при подключении к произвольным хостам следите за тем, какой команды вы позволяете модели выполнять.
  • Редокция активна всегда: значения паролей и фраз-паролей, переданные в инструменты, автоматически заменяются на [REDACTED] в логах и сообщениях об ошибках.
  • --password-from-env рекомендован везде, где пароль задаётся через CLI, чтобы он не мелькал в списке процессов и истории команд.
  • Приватные ключи загружаются в память процесса — запускайте сервер в защищённой среде.
  • Ограничивайте команды через --whitelist / черный список для статических серверов.
  • Пути upload/download ограничивайте через --allowed-local-paths и --allowed-remote-paths, чтобы модель (или отправленный в неё prompt-injection) не читала и не писала чувствительные файлы.

📦 Сборка и тесты

npm install
npm run build     # компиляция TypeScript → build/
npm test          # запуск тестов

Код: gitea.wtnet.ru/mshcheglov/ssh-dynamic-mcp

Оригинал: github.com/classfang/ssh-mcp-server

📄 Лицензия

ISC — см. файл LICENSE.