ssh-chat-mcp: SSH/SFTP для ИИ-агентов без конфигов и постоянных секретов
MCP-сервер от AI Platforms под лицензией MIT. Временные SSH/SFTP-сессии через чат: модель подключается, выполняет команды и файловые операции, отключается - и секреты стираются из памяти. Без конфигов, без env-переменных, без дискового хранения кредов.
Зачем агенту SSH без конфигов
Когда ИИ-агенту нужно не просто ответить текстом, а реально зайти на сервер, проверить состояние, залить файлы, перезапустить сервис и выйти - обычного prompt-а уже недостаточно. Нужен инструментальный слой.
У SSH-автоматизации обычно одна и та же боль: всё завязано на конфиги, inventory-файлы, переменные окружения и сохранённые ключи. Для стабильного production-хоста это иногда нормально. Для агентного сценария - уже нет. LLM-клиент не должен помнить инфраструктуру после окончания чата. MCP-сервер не должен хранить хосты и ключи на диске.
ssh-chat-mcp делает ставку на другой режим: zero-config по-настоящему. Вы запускаете сервер без аргументов. В чате передаёте модели host и креды. Она вызывает connect, работает, вызывает disconnect - и секреты стираются из RAM. Никакого предзаданного конфига, никакого хранения на диске, никакой миграции секретов между сессиями.
Публичный репозиторий: github.com/aiplatforms-ru/ssh-chat-mcp. npm: ssh-chat-mcp.
Ключевые архитектурные решения
In-memory connections
Все соединения хранятся в RAM в Map<string, ConnectionDescriptor>. На disconnect секреты очищаются, объект удаляется - никакого дискового следа.
Redaction выходных данных
Закрываются поля password, passphrase, privateKey, sudoPassword, token, apiKey, Authorization, secret, PEM-блоки и text patterns.
POSIX shell quoting
Каждая cwd/command-интерполяция обёрнута в безопасное quoting. Валидация Linux-username строго по ^[a-z_][a-z0-9_-]{0,31}$.
exec_as через sudo -iu
Привилегированные действия - строго ограниченный путь: sudo -S -p '' -iu <user> -- bash -lc <command>. Пароль через stdin, не в командной строке.
SFTP напрямую, без scp
upload_file, upload_directory, download_file, read_remote_file, write_remote_file - всё через встроенный SFTP, без внешних утилит.
Долгие команды без таймаута
exec_start/exec_as_start возвращают jobId немедленно. exec_status читает stdout/stderr инкрементально. exec_cancel останавливает процесс.
Как устроен сервер: разбор кода
index.ts - MCP stdio и молчание на старте
Сервер регистрирует инструменты MCP, поднимает stdio transport и не пишет ничего в stdout до получения JSON-RPC. Это важная дисциплина: stdout зарезервирован для протокола. Если сервер печатает «добро пожаловать» - он сломан по стандарту MCP.
В CI это тоже закреплено: GitHub Actions гоняет build-and-test на Ubuntu и Windows под Node 20 и 22, а на Linux есть smoke-start, который проверяет, что сервер стартует молча.
connectionManager.ts - жизненный цикл соединения
Все соединения живут в in-memory Map<connectionName, ConnectionDescriptor>. У каждого - статус, metadata и блок secrets. На disconnect секреты не просто забываются логически - на них вызывается очистка, и сам объект удаляется из менеджера.
exec.ts - выполнение команд
exec- обычное выполнение с опциональнымcwd, обёрнутое вcd <quoted cwd> && <command>.exec_as- запуск черезsudo -S -p '' -iu <runAs> -- bash -lc <command>, гдеrunAsстрого валидирован.sudoPasswordпередаётся через stdin и никогда не логируется.- Сбор
stdoutиstderrв буферы, таймаут с принудительным завершением канала. - Возврат
exitCodeиsignal. - Redaction выходных данных перед отправкой в MCP-клиент.
Долгие команды: exec_start / exec_as_start
Для команд, которые могут превысить tool timeout клиента (деплой, установка пакетов, сборка), используется паттерн start → status:
exec_startоткрывает SSH-канал и немедленно возвращаетjobId.exec_statusчитает stdout/stderr инкрементально черезstdoutOffset/stderrOffset.exec_cancelшлёт сигнал удалённой группе процессов и закрывает канал.exec_removeочищает in-memory буферы после завершения.
Это держит MCP-транспорт отзывчивым: первый вызов только открывает канал, логи читаются по jobId позже.
sftp.ts - файловые операции
upload_directory - рекурсивная загрузка с исключениями по basename. Symlink-ы не следуются по умолчанию. Родительские директории создаются только при явном mkdirParents. write_remote_file - удобный способ залить текстовый конфиг в /tmp, а потом sudo mv на место.
redact.ts и shellQuote.ts - сердцевина безопасности
Redaction не декларативный, а практический. В коде и тестах закрываются поля password, passphrase, privateKey, sudoPassword, token, apiKey, Authorization, secret, PEM-блоки и text patterns вроде password= и Authorization: Bearer .... POSIX quoting защищает от shell injection в каждом вызове.
Честные ограничения безопасности
Host-key checking выключен по дизайну - цена zero-config (нет on-disk known_hosts). Ответственность за доверие хосту - на пользователе. Нет blacklist-а деструктивных команд - сервер не песочница, контроль остаётся на стороне MCP-клиента. Пароль или приватный ключ, переданные в чат, видны в транскрипте - предпочитайте локальные и приватные клиенты. Сервер не заменяет Ansible и fleet management; это инструмент для точечных, временных операций.
Сценарии, где это реально нужно
Deploy-агент
Залить проект через upload_directory, собрать, написать systemd-unit, перезапустить сервис и отключиться - полный цикл за один чат-сеанс.
Incident-response агент
Диагностика через exec, чтение логов, правка конфига через write_remote_file, перезапуск сервиса - без ручного захода по SSH.
Infra-ассистент
Поднять новый хост: залить nginx-конфиг в /tmp, перенести sudo mv, проверить nginx -t, reload. Всё через инструменты.
Аудит и проверка
Быстро проверить состояние нового сервера: whoami, hostname, pwd, systemctl status, journalctl, ls, read_remote_file - и уйти.
Привилегированные шаги
exec_as для установки systemd-unit или правки конфигов от root, строго через sudo -iu с валидированным runAs.
Приватный контур
С локальными LLM-клиентами (LM Studio, Claude Code локально) данные и команды не выходят из периметра - идеально для on-premise.
Практическая интеграция в агентный цикл
Типовой рабочий цикл
Самая полезная часть проекта начинается там, где ssh-chat-mcp становится не отдельным инструментом, а частью agent loop:
1. Агент уточняет, на какой хост нужно зайти, под каким пользователем и с каким типом доступа.
2. Вызывает connect - получает временную сессию.
3. Проводит короткую разведку: diagnose, whoami, hostname, pwd, systemctl status, journalctl, ls, read_remote_file.
4. Делает точечное действие: загружает файлы, пишет конфиг, запускает команду, переключается на exec_as.
5. Проверяет результат: тест конфига, статус процесса, повторное чтение логов, smoke-check.
6. Вызывает disconnect - даже если задача завершилась с ошибкой.
Хорошее правило: один хост = один краткий цикл = один disconnect в конце. Не держите соединение дольше, чем нужно.
Конкретные паттерны
Deploy-агент: connect → upload_directory → exec (сборка) → exec_as (привилегированный шаг) → read_remote_file (проверка) → disconnect.
Incident-response: connect → exec (диагностика) → read_remote_file (логи) → exec_as (правка конфига) → exec (проверка) → disconnect.
Infra-ассистент: залить systemd/nginx/cron-конфиг в /tmp через write_remote_file, потом sudo mv на место и перезагрузить сервис.
Важный момент: агенту не нужно «знать SSH». Ему нужно уметь пользоваться инструментами. ssh-chat-mcp делает этот слой явным и контролируемым. Этот подход мы разбирали в статье ИИ-агенты с tool-use: как модель сама ищет данные и добирает контекст.
Интеграция с MCP-клиентами
Сервер работает с любым stdio MCP-клиентом: Claude Code, Codex, Kilo, LM Studio, Cursor. Регистрация везде одна и та же:
{
"mcpServers": {
"ssh-chat": {
"command": "node",
"args": ["/absolute/path/to/ssh-chat-mcp/build/index.js"]
}
}
}
Больше ничего настраивать не нужно - это осознанная позиция проекта.
Инструменты сервера
| Инструмент | Что делает | Особенности |
|---|---|---|
| connect | Открыть SSH-сессию | host, username, password или privateKey, port, passphrase, keepalive. Креды только в RAM. |
| disconnect | Закрыть SSH+SFTP и стереть креды | Секреты очищаются, объект удаляется из менеджера. |
| list_connections | Метаданные активных соединений | Не содержит секретов - только статус и нечувствительные поля. |
| diagnose | Локальная MCP/SSH диагностика | Без аргументов - проверка живости сервера. С connectionName - SSH probe: ok / ssh_unresponsive / ssh_error. |
| exec | Выполнить shell-команду | cwd оборачивается в cd <quoted cwd> && <command>. Возвращает stdout, stderr, exitCode, signal. |
| exec_as | Команда от другого пользователя | sudo -S -p '' -iu <runAs> -- bash -lc <command>. runAs валидирован. Пароль через stdin. |
| exec_start / exec_as_start | Долгая команда - немедленный jobId | Для деплоя, сборки, установки пакетов. Не блокирует MCP-транспорт. |
| exec_status | Чтение stdout/stderr по jobId | Инкрементально через stdoutOffset / stderrOffset. |
| exec_cancel / exec_remove | Остановка / очистка job | Сигнал удалённой группе процессов, закрытие канала, очистка буферов. |
| upload_file / upload_directory | SFTP-загрузка | Рекурсивно, exclude по basename, symlink-ы не следуются, mkdirParents опционально. |
| download_file | SFTP-скачивание на локальный диск | Прямой SFTP, без внешних утилит. |
| read_remote_file / write_remote_file | Чтение/запись текстовых файлов | read с redaction и лимитом maxBytes. write - удобно для конфигов в /tmp. |
Внедряем агентов с tool-use под ваш контур
ssh-chat-mcp - один из кирпичиков в нашем подходе к агентным системам. Если вам нужен ИИ-агент, который не только советует, но и действует - с RAG, MCP, приватными LLM и on-premise безопасностью - опишите задачу. Предложим архитектуру и план пилота.