sshmng
Gestor de sesiones SSH basado en MCP para equipos de backend de Linux
Documentación
sshmng
sshmng es un gestor SSH unificado que cubre todas las formas de conexión — directa, saltos transparentes ssh -J, bastiones interactivos, proxies de transporte — en un único binario sin dependencias que admite auto-actualización. Funciona como servidor MCP para agentes de IA (Claude Code / Hermes / etc.) y como CLI sshmng ssh para humanos, ambos respaldados por la misma configuración. Cuando algo falla, el Agente lee el rastro del fallo, corrige la configuración y reintenta — auto-reparación en bucle cerrado, sin intervención humana.
Características
- Bastiones interactivos que realmente funcionan: la mayoría de las herramientas SSH se rinden ante bastiones basados en menús. El árbol de decisión
LoginFlowde sshmng (enviar + esperar, glob o regexre:) maneja el menú para iniciar sesión en el objetivo — y cuando el texto del menú cambia, el rastro del fallo vuelve al Agente para que pueda corregir el patrón y reintentar - Bucle de configuración auto-reparable: el Agente lee
error/login_trace, llama aupdate_*para corregir el patrón LoginFlow dañado, reintentalogin— cierra el bucle de diagnóstico sin supervisión humana - Asistente de configuración con un solo comando:
sshmng installcrea el directorio de configuración + plantilla, detecta automáticamente los Agentes de IA instalados (Claude Code / Hermes / OpenCode) y se inyecta en sus configuraciones con copias de seguridad con marca de tiempo;sshmng doctorverifica que todo esté conectado - Una configuración, dos interfaces: servidor MCP para agentes de IA (Claude Code / Hermes / OpenCode / Claude Desktop / Cursor), CLI
sshmng sshpara humanos. Mismoconfig.json, mismos patrones directo / Patrón A (ssh -J) / Patrón B (bastión) — configura un servidor una vez, úsalo desde cualquier lado - Gestión explícita de sesiones: trío
login→run_in_session→close_session; los comandos consecutivos comparten cwd / env / trabajos en segundo plano, a diferencia dessh host cmdde un solo uso - Transferencia de archivos sftp:
upload/downloadarchivos individuales a través de un canal sftp dedicado, separado del canal de comandos PTY; degradación elegante cuando no está disponible.upload_dir/download_dirtransfieren árboles de directorios recursivamente, concurrente (predeterminado 4), política de conflictos sobrescribir / omitir / renombrar.relay_transfertransmite un archivo de una sesión a N otras vía sshmng (sin disco local, fanout 1:N, fuente leída una vez) - Diagnóstico de comandos:
run_in_sessiontiempo de espera auto Ctrl-C + drenaje, devuelvetimed_out/ctrl_c_sent;get_tracerecupera el historial de comandos (incluyendo raw_output, ctrl_c_sent) - Clave de host TOFU: la primera conexión registra la clave pública en
known_hosts; los cambios se rechazan ("host key changed, possible MITM") - CRUD de configuración: familias de herramientas
list_*/get_*/update_*gestionan SSHServer / Jumphost / Proxy, con semántica RFC 7396 JSON Merge Patch
Instalación y compilación
sshmng es un único binario sin dependencias de ejecución. Elige una opción:
# Option 0: one-click install — downloads release, places on PATH
# macOS / Linux:
curl -fsSL https://raw.githubusercontent.com/jim58246/sshmng/main/install.sh | bash
# Windows (PowerShell):
irm https://raw.githubusercontent.com/jim58246/sshmng/main/install.ps1 | iex
# Option 1: download release binary (recommended, no Go required)
# From https://github.com/jim58246/sshmng/releases, pick the binary for your OS/Arch
chmod +x sshmng
# Option 2: go install (requires Go 1.25+)
go install github.com/jim58246/sshmng/cmd/sshmng@latest
# Option 3: clone and build locally
git clone https://github.com/jim58246/sshmng.git
cd sshmng && go build -o sshmng ./cmd/sshmng
O deja que tu Agente de IA lo instale por ti: copia el prompt en docs/agent-install-prompt.md y pégalo en Claude Code / Cursor / Hermes / OpenCode — el Agente descargará el binario, lo colocará en PATH y ejecutará sshmng install por ti.
macOS: los binarios descargados desde el navegador llevan un atributo de cuarentena de Gatekeeper — ejecuta xattr -d com.apple.quarantine sshmng antes del primer uso. Los binarios go install / go build no lo necesitan (compilación local). Los binarios auto-actualizados tampoco lo necesitan (ver docs/auto-update.md).
Después de obtener el binario, ejecuta sshmng install para crear ~/.sshmng/ e inyectarlo en los Agentes de IA instalados (Claude Code / Hermes / OpenCode, etc.). Ver Quick Start.
Recomendado: antes de ejecutar install, mueve el binario a una ubicación estable en tu PATH (p. ej. mv sshmng /usr/local/bin/, o confía en ~/go/bin/ si usaste go install). sshmng install registra la ruta absoluta del binario en las configuraciones del Agente, y sshmng doctor verifica que coincida con el ejecutable en ejecución — elegir una ubicación estable de antemano evita re-ejecutar la instalación después de un movimiento posterior.
Compilar desde el código fuente
# Plain build (version.Version is "dev", self-update is disabled)
go build -o sshmng ./cmd/sshmng
# Inject version via ldflags (self-update needs a real version number)
go build -ldflags="-X github.com/jim58246/sshmng/internal/version.Version=v1.2.3" -o sshmng ./cmd/sshmng
Sin ldflags, version.Version por defecto es "dev", en cuyo caso tanto sshmng update como la gorutina de auto-actualización al inicio de mcp se omiten.
Ejecuta:
./sshmng # Print help
./sshmng mcp # Start MCP server (what Agent configs use)
./sshmng install # First-time setup wizard
./sshmng doctor # Verify setup
./sshmng version # Print version / commit / date
./sshmng version --check # Check latest version against source
./sshmng update # Self-update to latest release
./sshmng mcp --config /path/to/config.json # MCP server with custom config
SSHMNG_HOME=/custom/dir ./sshmng mcp # MCP server with custom home
./sshmng server list [keywords...] # List SSH servers (AND match on name/addr/tags)
./sshmng server get <name> # Show SSH server details (full auth)
./sshmng jumphost list|get ... # Same for jumphosts
./sshmng proxy list|get ... # Same for proxies
./sshmng ssh <name> [command] # Interactive login; <name> also resolves to a jumphost (bastion). Non-interactive command needs a shell — bastions (ssh_j=false) and raw devices (raw=true) reject it
./sshmng file upload <name> <local> <remote> # File transfer via sftp (also: download, upload-dir, download-dir, relay)
./sshmng file relay <src-name> <src-path> <dst-path> --to <dst1,dst2> # 1:N fanout to multiple servers
Inicio rápido
# 1. Build
go build -o sshmng ./cmd/sshmng
# 2. First-time install (creates ~/.sshmng/ + injects into installed AI Agents)
./sshmng install
# 3. Verify config
./sshmng doctor
# 4. Restart your Agent, have it call sshmng:
# "list_ssh_servers" → should return an empty array
# "add an SSH server named prod-web-01 at 10.0.0.1:22 with password ..."
# "login to prod-web-01 and run df -h"
No interactivo:
./sshmng install --yes --agents claude-code,hermes
Para configuración manual de respaldo y pasos de integración por Agente, ver docs/agents.md.
Resumen de herramientas MCP
21 herramientas en total:
| Categoría | Herramienta | Descripción |
|---|---|---|
| Consulta de configuración | list_ssh_servers / list_jumphosts / list_proxies | Coincidencia AND multi-palabra clave en nombre/dirección/etiquetas (separadas por espacios, sin distinción de mayúsculas, autenticación redactada) |
| Consulta de configuración | get_ssh_server / get_jumphost / get_proxy | Registro único por nombre (autenticación completa) |
| Actualización de configuración | update_ssh_server / update_jumphost / update_proxy | RFC 7396 JSON Merge Patch; null elimina, objeto fusiona/crea |
| Sesión | login(name) → {sid, sftp_available, mode, tags} | Dial + LoginFlow + inyección RC + configuración del canal sftp. mode: shell = shell unix (usa run_in_session); raw = sin shell unix, p. ej. switch de red (usa send_in_session/read_in_session). tags reflejan las etiquetas configuradas del servidor (pistas humano→IA) |
| Sesión | run_in_session(sid, cmd, timeout_ms?, max_output_bytes?) | Ejecuta comando, devuelve output/exit_code/timed_out/truncated/total_bytes. Rechazado en sesiones raw |
| Sesión | send_in_session(sid, input) | Primitiva de terminal: escribe en el PTY. El servidor interpreta escapes estilo C (\r=Enter, \n, \t, \e=ESC, \uXXXX=Ctrl-C etc., \\=barra invertida literal), el resto verbatim. Solo sesiones inactivas; funciona en todas las sesiones |
| Sesión | read_in_session(sid, wait_ms?, max_bytes?) | Primitiva de terminal: lee la nueva salida del PTY desde la última lectura (absorción silenciosa, la salida no leída permanece en cola). Devuelve output/more/idle_ms |
| Sesión | close_session(sid) | Forzar cierre, rastro conservado durante 10 minutos |
| Sesión | stat() | Lista todos los resúmenes de sesiones activas (incluyendo sftp_available, mode, tags) |
| Diagnóstico | get_trace(sid, last_n?, trunc_output?) | Recupera el historial de comandos (incluyendo ctrl_c_sent, salida raw) |
| Transferencia de archivos | upload(sid, src, dst, timeout_ms?) | Local → remoto, vía sftp |
| Transferencia de archivos | download(sid, src, dst, timeout_ms?) | Remoto → local, vía sftp |
| Transferencia de archivos | upload_dir(sid, src, dst, conflict?, concurrency?, timeout_ms?) | Árbol de directorios local → remoto, sftp recursivo, concurrente predeterminado 4, política de conflictos sobrescribir/omitir/renombrar |
| Transferencia de archivos | download_dir(sid, src, dst, conflict?, concurrency?, timeout_ms?) | Árbol de directorios remoto → local, sftp recursivo, concurrente predeterminado 4, política de conflictos sobrescribir/omitir/renombrar |
| Transferencia de archivos | relay_transfer(src_sid, src_path, dst_sids[], dst_path, timeout_ms?) | Transmite un archivo remoto de una sesión a N otras vía sshmng (sin disco local, fanout 1:N, fuente leída una vez); requiere sftp en la fuente + todos los destinos; fallos parciales devuelven ok:false (verifica el campo ok, no IsError) |
Los dispositivos raw (switches etc.,
raw: true) no tienen shell unix: el inicio de sesión omite la detección de shell / inyección RC, yrun_in_sessionse rechaza. Manéjalos con las primitivas de terminalsend_in_session+read_in_session: envía un comando (añade\r— el servidor interpreta escapes estilo C, así que Enter funciona ya sea que el cliente transmita un CR real o los dos caracteres\r), lee la salida, juzga la finalización por el contenido +idle_ms, maneja los prompts de paginador (---- More ----) según la convención del dispositivo — el servidor no incluye recetas de proveedor. Las mismas primitivas funcionan en sesiones unix para programas persistentes (tail -f,top,vim). Los clientes MCP serializan las llamadas a herramientas, así que las primitivas solo son utilizables mientras la sesión está inactiva (nunca durante unrun_in_sessionen ejecución).
Notas de seguridad
- Almacenamiento en texto plano: v1 almacena contraseña / frase de contraseña en texto plano en
config.json, documentado explícitamente; si es inaceptable, cifra todoconfig.jsonconage/gpgtú mismo, descifra antes de usar - Clave de host TOFU: habilitada por defecto; la primera conexión registra la clave pública en
~/.sshmng/known_hosts, los cambios se rechazan ("host key changed, possible MITM"). Se puede deshabilitar por entidad víahost_key_verify: false(omite completamente la lectura/escritura de known_hosts, pierde la protección MITM — solo para bastiones de intranet de confianza, etc.); eliminar una clave registrada aún requiere editar manualmente~/.sshmng/known_hosts, sin soporte de herramientas - El rastro contiene datos sensibles:
Send(etapa LoginFlow),Output(flujo raw PTY) pueden contener contraseñas; el rastro es solo en memoria, retenido durante 10 minutos después declose_sessiony luego auto-limpiado, nunca persistido en disco - stdout nunca debe registrar: JSON-RPC está dedicado a stdout; los registros de operación van al archivo rotativo especificado por
config.log_path(10MB / 5 archivos, permisos 0600), o sin registro si no está configurado; los errores de arranque van a stderr - Alcance de autenticación (v1): solo se admiten Password + PrivateKey; sin keyboard-interactive / agente SSH / certificado SSH / 2FA (si tu entorno lo requiere, extensión v2 o interacción codificada en LoginFlow)
Auto-actualización
sshmng verifica silenciosamente actualizaciones en una gorutina en segundo plano al inicio de mcp (escribe solo el registro log_path, nunca stdout). Deshabilita vía {"auto_update_enabled": false}. Actualización manual: sshmng update. ¿Limitado por GitHub? Descarga el recurso con tu navegador y ejecuta sshmng update --file <path> (omite la cuota de API; acepta .tar.gz, .tar o un directorio extraído). Verificación de versión: sshmng version --check. Fuente personalizada: establece update_url (ver docs/auto-update.md para el diseño de fuente auto-alojada, notas de macOS, modo --file y flujo de lanzamiento).
Pruebas y desarrollo
# Run all tests (with race detector)
go test -race ./...
Para cobertura de pruebas y detalles de desarrollo, ver docs/development.md (solo chino — traducciones bienvenidas).
Documentación
- Referencia de configuración — referencia completa de campos de config.json, restricciones de forma Patrón A/B, ejemplos
- Guía de integración de agentes — configuración detallada de Claude Code / Hermes Agent / OpenCode / Claude Desktop, depuración con MCP Inspector, flujo de configuración inicial, flujo de llamadas típico
- Prompt de instalación de agentes — prompt de copiar y pegar para que tu Agente de IA instale sshmng de principio a fin
- Auto-actualización — diseño de fuente HTTP auto-alojada, notas de macOS, flujo de lanzamiento
- Arquitectura y desarrollo — estructura de paquetes, diseños clave, despacho de subcomandos, cobertura de pruebas (solo chino — traducciones bienvenidas)
- Documento de diseño — especificación de diseño completa (centinela PTY, LoginFlow, máquina de estados de sesión, etc.) (solo chino — traducciones bienvenidas)
- Plan de implementación — progreso de implementación v1 (solo chino — traducciones bienvenidas)
Estado
Etapa v1: el cliente se ejecuta de forma independiente, stdio de un solo proceso, configuración almacenada localmente. Documento de diseño: docs/ssh-session-manager-design.md (solo chino — traducciones bienvenidas).
Contribuciones
Siéntete libre de abrir issues para errores y solicitudes de funciones.
Licencia
MIT — Copyright (c) 2026 jim58246