Files
ssh-dynamic-mcp/README.md
T

249 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<div align="center">
<img src="images/ssh-mcp-server-logo-v2.png" alt="ssh-mcp-server logo" width="220">
# ssh-dynamic-mcp
MCP-сервер для управления удалёнными серверами по SSH с **динамическими подключениями на лету** и встроенной **маскировкой секретов** в логах и ошибках.
</div>
## 📝 О проекте
`ssh-dynamic-mcp` — это форк [classfang/ssh-mcp-server](https://github.com/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-подключений |
## 🚀 Быстрый старт
### Динамический режим (новое)
Запустите сервер вообще **без аргументов** — и подключайтесь к любому хосту прямо при вызове инструмента.
```json
{
"mcpServers": {
"ssh-dynamic": {
"command": "node",
"args": ["C:/path/to/ssh-dynamic-mcp/build/index.js"]
}
}
}
```
Теперь в каждом вызове можно задать целевой хост и учётные данные:
```json
{
"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`:
```json
{
"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]` в любом логе и сообщении об ошибке, возвращаемом модели, — они **не** попадут в вывод сервера.
## 🔐 Статическая конфигурация (как в оригинале)
Весь функционал исходной версии поддерживается. Например, парольная аутентификация:
```json
{
"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"
]
}
}
}
```
### Несколько серверов
```json
{
"mcpServers": {
"ssh-mcp-server": {
"command": "node",
"args": [
"C:/path/to/ssh-dynamic-mcp/build/index.js",
"--config-file", "ssh-config.json"
]
}
}
}
```
Файл `ssh-config.json` (массив или объект):
```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`:
```json
{
"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`
## ⚙️ Справка по командной строке
```text
Опции:
--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) не читала и не писала чувствительные файлы.
## 📦 Сборка и тесты
```bash
npm install
npm run build # компиляция TypeScript → build/
npm test # запуск тестов
```
Код: [gitea.wtnet.ru/mshcheglov/ssh-dynamic-mcp](https://gitea.wtnet.ru/mshcheglov/ssh-dynamic-mcp)
Оригинал: [github.com/classfang/ssh-mcp-server](https://github.com/classfang/ssh-mcp-server)
## 📄 Лицензия
ISC — см. файл [LICENSE](LICENSE).