This repository has been archived on 2026-06-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
wiki/ssh-mcp/ARCHITECTURE.md
T
2026-05-09 19:09:43 -05:00

166 lines
8.6 KiB
Markdown

← [Home](Home)
# Architecture
ssh-mcp is a plain JavaScript (ESM) MCP server built on the `@modelcontextprotocol/sdk`. It exposes 37 tools organized into 6 groups that operate on remote servers over SSH.
---
## Source Files
The `src/` directory contains 19 modules:
| File | Responsibility |
|------|----------------|
| `index.js` | MCP server entry point. Registers all 37 tools, manages the connection pool, and wires modules together. |
| `ssh-manager.js` | Thin wrapper around the `ssh2` library. Handles connect, exec, file transfer, and stream operations. |
| `config.js` | Constants for output limits, timeouts, and helper functions (`truncateOutput`, `formatJSONResponse`). |
| `config-loader.js` | Loads server definitions from `.env`, TOML, and environment variables with a priority chain. |
| `backup-manager.js` | Builds shell commands for MySQL, PostgreSQL, MongoDB, and file backups. Manages metadata and retention. |
| `database-manager.js` | Builds shell commands for database dump, import, list, and read-only query operations. Includes query safety validation. |
| `health-monitor.js` | Builds shell commands for CPU, memory, disk, network, and load average checks. Parses results and determines overall health status. |
| `deploy-helper.js` | Deployment strategy builder. Detects permission issues and generates sudo scripts when needed. |
| `session-manager.js` | Persistent SSH session lifecycle (create, send, list, close). Sessions maintain working directory state across commands. |
| `tunnel-manager.js` | SSH tunnel creation and management (local, remote, dynamic/SOCKS). Tracks active tunnels and connection statistics. |
| `server-aliases.js` | Maps short alias names to full server names. Persisted to `~/.ssh-manager/aliases.json`. |
| `command-aliases.js` | Maps short command strings to full commands. Supports suggestion of aliases for frequently typed commands. |
| `server-groups.js` | Server group CRUD and multi-server command execution with parallel, sequential, and rolling strategies. |
| `hooks-system.js` | Automation hooks that run before/after operations (e.g., `pre-backup`, `post-bench-update`). |
| `profile-loader.js` | Profile management for switching between project-specific tool/configuration sets. |
| `ssh-key-manager.js` | Host key verification, fingerprint comparison, and `known_hosts` management. |
| `tool-registry.js` | Centralized registry of all 37 tools and their group assignments. Provides validation and statistics. |
| `tool-config-manager.js` | Reads `~/.ssh-manager/tools-config.json` to determine which tool groups are enabled. |
| `logger.js` | Structured logging with levels, command history tracking, and transfer logging. |
---
## Component Diagram
```
Claude Code / MCP Client
|
| stdio (JSON-RPC)
v
+-----------+
| index.js | <-- MCP Server (tool registration + dispatch)
+-----------+
|
+---> ssh-manager.js ---> ssh2 library ---> Remote Server
|
+---> config-loader.js ----> .env / TOML / env vars
|
+---> tool-config-manager.js ---> tools-config.json
|
+---> session-manager.js (persistent sessions)
+---> tunnel-manager.js (port forwarding)
+---> backup-manager.js (backup commands)
+---> database-manager.js (db commands)
+---> health-monitor.js (monitoring commands)
+---> deploy-helper.js (deployment logic)
+---> server-groups.js (multi-server ops)
+---> hooks-system.js (pre/post hooks)
+---> server-aliases.js (alias resolution)
+---> command-aliases.js (command shortcuts)
+---> profile-loader.js (profiles)
+---> ssh-key-manager.js (host key mgmt)
+---> logger.js (logging + history)
```
---
## Tool Activation System
Not every user needs all 37 tools. Unused tools consume context tokens in Claude Code without providing value. The tool activation system solves this.
### How It Works
1. On startup, `tool-config-manager.js` loads `~/.ssh-manager/tools-config.json`.
2. The config specifies a mode (`all`, `minimal`, or `custom`) and per-group enabled/disabled flags.
3. In `index.js`, every tool is registered through `registerToolConditional()`, which checks `isToolEnabled(toolName)` before calling `server.registerTool()`.
4. Disabled tools are silently skipped -- the MCP client never sees them.
### Configuration Modes
| Mode | Tools | Context Usage |
|------|-------|---------------|
| `all` | 37 | ~43.5k tokens |
| `minimal` | 5 (core only) | ~3.5k tokens |
| `custom` | Variable | Variable |
The CLI (`ssh-manager tools configure`) provides an interactive wizard for selecting groups.
### Tool Groups
| Group | Count | Tools |
|-------|-------|-------|
| core | 5 | `ssh_execute`, `ssh_upload`, `ssh_download`, `ssh_sync`, `ssh_list_servers` |
| sessions | 4 | `ssh_session_start`, `ssh_session_send`, `ssh_session_list`, `ssh_session_close` |
| monitoring | 6 | `ssh_health_check`, `ssh_service_status`, `ssh_process_manager`, `ssh_monitor`, `ssh_tail`, `ssh_alert_setup` |
| backup | 4 | `ssh_backup_create`, `ssh_backup_list`, `ssh_backup_restore`, `ssh_backup_schedule` |
| database | 4 | `ssh_db_dump`, `ssh_db_import`, `ssh_db_list`, `ssh_db_query` |
| advanced | 14 | `ssh_deploy`, `ssh_execute_sudo`, `ssh_alias`, `ssh_command_alias`, `ssh_hooks`, `ssh_profile`, `ssh_connection_status`, `ssh_tunnel_create`, `ssh_tunnel_list`, `ssh_tunnel_close`, `ssh_key_manage`, `ssh_execute_group`, `ssh_group_manage`, `ssh_history` |
---
## Connection Pooling
ssh-mcp maintains a pool of SSH connections to avoid the overhead of re-authenticating on every tool call.
### Pool Mechanics
| Aspect | Behavior |
|--------|----------|
| **Storage** | Active connections are held in a `Map<serverName, SSHClient>`. |
| **Reuse** | `getConnection(serverName)` returns an existing connection if it is still valid (tested via ping), or creates a new one. |
| **Timeout** | Connections idle for more than 30 minutes are closed by a periodic cleanup sweep. |
| **Keepalive** | Every 5 minutes, a ping is sent to each connection. If the ping fails, the connection is removed from the pool and will be re-established on the next call. |
| **Cleanup on error** | If a command times out, the connection is disposed of immediately so subsequent calls get a fresh channel. |
### Proxy Jump Support
When `PROXYJUMP` is set, the server first connects to the jump host, then tunnels through it to reach the target. Jump host connections are also pooled. Dependency tracking ensures that closing a jump host also closes all connections that depend on it.
`PROXYCOMMAND` provides an alternative mechanism. The configured command (e.g., `ncat`, `ssh -W`) is spawned as a local child process, and its stdin/stdout are used as the transport socket.
---
## Command Execution
Commands are executed via `execCommandWithTimeout()`:
1. **Windows targets** are detected by the `platform` config field. Commands are UTF-16LE base64-encoded and passed to PowerShell via `-EncodedCommand`, avoiding quoting issues.
2. **Linux/macOS targets** wrap commands in the system `timeout` utility for reliable kill semantics on long-running operations.
3. Output is truncated to configurable limits to prevent Claude Code crashes from extremely large command output.
---
## Design Decisions
### Plain JavaScript (no TypeScript)
The project uses plain JavaScript with ES modules. This keeps the build step to zero -- `node src/index.js` is all that is needed. JSDoc comments provide type hints where useful.
### Command Building vs. Direct Execution
Manager modules (`backup-manager.js`, `database-manager.js`, `health-monitor.js`) build shell command strings rather than using database client libraries. This design means:
- No database drivers need to be installed on the MCP host.
- The remote server only needs standard tools (`mysqldump`, `pg_dump`, `mongodump`, `tar`, etc.).
- Commands run in the same security context as the SSH user.
### Read-Only Query Safety
`ssh_db_query` validates that the query is a `SELECT` statement before execution. The `isSafeQuery()` function in `database-manager.js` rejects `INSERT`, `UPDATE`, `DELETE`, `DROP`, and other mutating statements.
### Hooks System
Hooks run at defined lifecycle points (e.g., `pre-backup`, `post-bench-update`). They are shell scripts stored in `~/.ssh-manager/hooks/` and are opt-in -- disabled by default until explicitly enabled via `ssh_hooks`.
---
*Repo: [ssh-mcp](https://git.mokoconsulting.tech/MokoConsulting/ssh-mcp) · [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
| Revision | Date | Author | Description |
|---|---|---|---|
| 1.0 | 2026-05-09 | Moko Consulting | Initial version |