内容
# SSH MCP 服务器
**通用 SSH MCP 服务器**,用于通过 AI 助手(Cursor、Claude Desktop)管理远程服务器。
[](https://opensource.org/licenses/MIT)
[](https://nodejs.org/)
**GitHub:** [@hypnosis](https://github.com/hypnosis) | **许可证:** MIT | **npm:** [@hypnosis/ssh-mcp-server](https://www.npmjs.com/package/@hypnosis/ssh-mcp-server)
> **⚠️ 重要提示:** 对于二进制文件和大文件,请使用 `ssh_upload` / `ssh_download`(SFTP,支持二进制文件,sha256 验证,原子重命名)—— **不要** 通过 `ssh_exec` 或 `ssh_file_write` 使用 base64 分段。 Heredoc 写入会损坏二进制文件,并且没有原子性 / 完整性保证。参见 [传输工具](#-传输工具-v130) 和 [docs/transfer.md](docs/transfer.md)。
## ✨ 功能
### 14 个强大的命令:
**核心(8):**
1. **ssh_exec** - 通用命令执行(单个或批量)
2. **ssh_file_read** - 读取文件(单个或多个);`binary: true` 表示 base64
3. **ssh_file_write** - 写入文件(单个或多个);`verify` / `atomic` / `binary`
4. **ssh_file_list** - 列出目录中的文件
5. **ssh_log_tail** - 日志的最后 N 行(单个或多个)
6. **ssh_log_search** - 使用 grep 搜索日志(单个或多个)
7. **ssh_snapshot** - 即时系统健康检查
8. **ssh_monitor** - 监控连接、重新加载配置文件、测试连接
**传输 - SFTP(2,v1.3.0+):**
9. **ssh_upload** - 安全的二进制文件/目录上传(sha256 验证,原子重命名,sudo via `install`)
10. **ssh_download** - 安全的二进制文件/目录下载(sha256 验证)
**审计 - 只读深度检查(4,v1.3.0+):**
11. **ssh_audit_baseline** - 一次系统审计(取代 5+ 次 ssh_exec 调用)
12. **ssh_tls_check** - TLS 过期 + SAN + 颁发者 + Let's Encrypt renew_hook
13. **ssh_disk_breakdown** - df + top-N du + docker df + journald + 缓存
14. **ssh_service_status** - systemctl status + journalctl tail 合并在一个调用中
### 主要功能:
- ✅ **REST 方法** - 数组在逻辑上
- ✅ **安全性** - 危险命令的警告,路径验证,安全引用
- ✅ **波浪号展开** - `~/file` 自动展开为 `$HOME/file`
- ✅ **路径安全性** - 按配置文件可选的白名单/黑名单
- ✅ **sudo 支持** - 每个命令的参数
- ✅ **配置文件** - 多个 SSH 配置
- ✅ **重试逻辑** - 网络错误时的自动重试
- ✅ **连接池** - 重用 SSH 连接以提高性能
## 📦 安装
```bash
# 全局安装
npm install -g @hypnosis/ssh-mcp-server
# 或无需安装直接运行
npx @hypnosis/ssh-mcp-server
```
最新发布的版本:请参阅 [npmjs.com/@hypnosis/ssh-mcp-server](https://www.npmjs.com/package/@hypnosis/ssh-mcp-server)。
## 🚀 快速开始
### 1. 创建配置文件
创建文件 `~/.cursor/ssh-profiles.json`:
```json
{
"default": "production",
"profiles": {
"production": {
"host": "server.example.com",
"username": "admin",
"port": 22,
"privateKeyPath": "~/.ssh/your_private_key"
},
"staging": {
"host": "staging.example.com",
"username": "deploy",
"port": 22,
"privateKeyPath": "~/.ssh/your_private_key"
}
}
}
```
**注意:** 您可以使用与 Docker MCP 服务器相同的配置文件。SSH MCP 服务器将自动跳过具有 `mode: "local"` 的配置文件,并使用具有 `host` 和 `username` 的配置文件。
### 1.1. 可选:路径安全配置
您可以添加可选的安全规则以限制每个配置文件的路径访问:
```json
{
"default": "production",
"profiles": {
"production": {
"host": "prod.example.com",
"username": "admin",
"port": 22,
"privateKeyPath": "~/.ssh/id_rsa_prod",
"pathSecurity": {
"allowedPaths": ["/home/admin", "/var/www", "/var/log"],
"deniedPaths": ["/etc/shadow", "/root", "/etc/ssh"],
"allowTraversal": false,
"maxPathLength": 1000
}
}
}
}
```
**路径安全选项:
- **`allowedPaths`** (可选):允许的目录白名单。如果指定,只有以这些前缀开头的路径被允许。
- 示例:`["/home/admin", "/var/www"]`
- 子目录被允许:`/home/admin/subdir/file.txt` ✅
- **`deniedPaths`** (可选):禁止路径的黑名单。以这些前缀开头的路径将被拒绝。
- 示例:`["/etc/shadow", "/root", "/etc/ssh"]`
- 优先级高于 `allowedPaths`
- **`allowTraversal`** (可选):允许路径遍历(`../`)在路径中。默认值:`true`
- 设置为 `false` 以防止目录遍历攻击
- 示例:`../../../etc/passwd` ❌ 已拒绝
- **`maxPathLength`** (可选):允许的最大路径长度。默认值:无限制
- 示例:`1000` (长度超过 1000 个字符的路径被拒绝)
**安全注意事项:
- 路径安全是**可选的**。如果未配置,则允许所有路径。
- 黑名单(`deniedPaths`)在白名单(`allowedPaths`)之前检查
- 这些规则适用于:`ssh_file_read`、`ssh_file_write`、`ssh_file_list`、`ssh_log_tail`、`ssh_log_search`
- 波浪号(`~`)路径受支持并自动展开为 `$HOME`
### 2. 配置 Cursor
添加到 `~/.cursor/mcp.json` (示例):
```json
{
"mcpServers": {
"ssh": {
"command": "node",
"args": ["/path/to/ssh-mcp-server/dist/index.js"],
"env": {
"SSH_PROFILES_FILE": "~/.cursor/ssh-profiles.json"
}
}
}
}
```
### 3. 重启 Cursor
完成!AI 现在可以管理您的服务器。
## 📚 使用示例
### ssh_exec - 执行命令
**⚠️ 重要提示:数组语法**
对于批量命令,请使用 **双引号** JSON 格式:
- ✅ 正确:`command: ["cmd1", "cmd2"]`
- ❌ 错误:`command: ['cmd1', 'cmd2']`
MCP 工具需要有效的 JSON 语法。单引号会导致错误。
```typescript
// 单个命令
ssh_exec({
profile: "production",
command: "systemctl status nginx"
})
// 批量命令(使用双引号!)
ssh_exec({
profile: "production",
command: [
"systemctl status nginx",
"docker ps",
"df -h"
]
})
// 使用 sudo
ssh_exec({
profile: "production",
command: "systemctl restart nginx",
sudo: true
})
// 使用工作目录
ssh_exec({
profile: "production",
command: "npm install",
cwd: "/var/www/app"
})
```
### ssh_file_read - 读取文件
**注意:** 对于多个文件,请使用双引号:`path: ["file1", "file2"]`
**波浪号支持:** 路径中的 `~` 会自动展开为 `$HOME`
```typescript
// 单个文件
ssh_file_read({
profile: "production",
path: "/etc/nginx/nginx.conf"
})
// 波浪号路径(自动展开)
ssh_file_read({
profile: "production",
path: "~/.bashrc" // 展开为 $HOME/.bashrc ✅
})
// 多个文件(使用双引号!)
ssh_file_read({
profile: "production",
path: [
"/etc/nginx/nginx.conf",
"~/.ssh/config", // 波浪号支持!✅
"/etc/hosts"
]
})
// 使用 sudo
ssh_file_read({
profile: "production",
path: "/root/.ssh/config",
sudo: true
})
```
### ssh_file_write - 写入文件
```typescript
// 单个文件
ssh_file_write({
profile: "production",
files: {
path: "/var/www/app/.env",
content: "APP_ENV=production\nDB_HOST=localhost",
mode: "600"
}
})
// 多个文件
ssh_file_write({
profile: "production",
files: [
{
path: "/etc/nginx/sites-available/app.conf",
content: "server { ... }",
mode: "644",
sudo: true
},
{
path: "/var/www/app/.env",
content: "APP_ENV=production",
mode: "600"
}
]
})
```
#### v1.3.0+ 每个文件的标志:`verify`、`atomic`、`binary`
`ssh_file_write` 默认情况下是向后兼容的,但现在支持三个新的每个文件的标志。内部,任何这些 - 或内容大小> 256KB - 将写入路由到 SFTP 而不是遗留的 heredoc 快速路径。
| 标志 | 默认值 | 功能 |
|------|---------|--------------|
| `verify` | `false` | 计算本地 sha256,与写入后远程 `sha256sum` 进行比较(回退 `openssl dgst -sha256`) |
| `atomic` | `false` | 写入 `<path>.tmp.<rand>` 旁边,然后 `mv`(在同一 FS 上原子) |
| `binary` | `false` | `content` 是 base64;解码并通过 SFTP 上传。使用此选项进行非文本有效负载 |
```typescript
// 验证原子配置写入(文本)
ssh_file_write({
profile: "production",
files: {
path: "/etc/nginx/conf.d/app.conf",
content: "server { listen 80; }\n",
mode: "644",
sudo: true,
atomic: true,
verify: true
}
})
// 二进制有效负载(例如小图像,证书,.pem)
ssh_file_write({
profile: "production",
files: {
path: "/etc/ssl/private/app.pem",
content: "<base64-encoded-bytes>",
binary: true,
mode: "600",
sudo: true,
atomic: true,
verify: true
}
})
```
> 对于大于 ~1 MB 的文件,请使用 `ssh_upload` - 它直接流式传输块,避免将内容加载到 LLM 上下文中。
#### v1.3.0+ ssh_file_read - `binary: true`
通过 SFTP 读取并返回 base64 编码的字节,字节安全(旧版 `cat` 通过 PTY 损坏二进制文件,因为编码/CR-LF 转换)。
```typescript
ssh_file_read({
profile: "production",
path: "/etc/ssl/certs/app.crt",
binary: true // 返回 base64
})
```
### ssh_file_list - 列出文件
```typescript
// 列出目录
ssh_file_list({
profile: "production",
path: "/var/log/nginx"
})
// 带有模式过滤
ssh_file_list({
profile: "production",
path: "/var/log",
pattern: "*.log"
})
// 递归
ssh_file_list({
profile: "production",
path: "/etc/nginx",
recursive: true
})
```
### ssh_log_tail - 日志的最后几行
**注意:** 对于多个日志,请使用双引号:`path: ["log1", "log2"]`
```typescript
// 单个日志
ssh_log_tail({
profile: "production",
path: "/var/log/nginx/error.log",
lines: 100
})
// 多个日志(使用双引号!)
ssh_log_tail({
profile: "production",
path: [
"/var/log/nginx/error.log",
"/var/log/nginx/access.log"
],
lines: 50
})
```
### ssh_log_search - 搜索日志
```typescript
// 搜索错误
ssh_log_search({
profile: "production",
path: "/var/log/nginx/error.log",
query: "error|fatal"
// 上下文行
ssh_log_search({
profile: "production",
path: "/var/log/syslog",
query: "docker",
context: 3
})
// 多个日志
ssh_log_search({
profile: "production",
path: [
"/var/log/nginx/*.log",
"/var/log/syslog"
],
query: "500|502|503"
})
```
### ssh_snapshot - 系统健康检查
```typescript
// 完整的系统快照
ssh_snapshot({
profile: "production"
})
// 返回:
- 主机名,正常运行时间
- 服务状态(nginx,docker,postgresql等)
- 资源(CPU,内存,磁盘)
- Docker 容器(如果可用)
- 开放端口和连接
- 日志中的最近错误
```
### ssh_monitor - 监控和诊断
```typescript
// 获取连接池统计信息
ssh_monitor({
action: "stats")
// 返回:缓存命中率,活动连接,会话指标
// 注意:当所有连接关闭时,指标自动重置(基于会话)
// 重新加载 SSH 配置文件(无需重启服务器)
ssh_monitor({
action: "reload"
// 重新加载 SSH_PROFILES_FILE 并显示新配置文件
// 测试配置文件
ssh_monitor({
action: "test",
profile: "production"
// 测试连接并显示连接/命令计时
// 列出可用配置文件
ssh_monitor({
action: "list"
// 显示所有可用的配置文件,默认标记
})
```
---
## 📦 传输工具(v1.3.0+)
二进制安全的 SFTP 传输,依赖于其他工具使用的相同连接池。**使用这些代替 base64 分段通过 `ssh_exec`** - heredoc / `cat > file` 损坏二进制文件,没有原子语义,没有完整性验证,并将整个有效负载 Node 内存。
默认:`atomic=true`(写入 `<path>.tmp.<rand>`,然后 `mv`),`verify=true`(本地 sha256 与远程 `sha256sum` / `openssl dgst -sha256` 回退)。
**文件大小指南:
- ≤ 256 KB,文本 -> `ssh_file_write`(遗留 heredoc,略快 - 没有第二个 sha256 往行程)
- 256 KB – 1 MB,文本 -> `ssh_file_write` 带有 `atomic: true, verify: true`(自动路由到 SFTP)
- 任意二进制文件,或 > 1 MB -> `ssh_upload`(流式传输块,从不将文件加载到 LLM 上下文)
对于完整的 API 和架构,请参阅 [docs/transfer.md](docs/transfer.md)。
### ssh_upload - 基于二进制的安全上传
| 参数 | 类型 | 默认值 | 描述 |
|-----------|------|---------|-------------|
| `profile` | 字符串 | `"default"` | SSH 配置文件名称 |
| `local_path` | 字符串 | **必填** | 本地文件或目录路径 |
| `remote_path` | 字符串 | **必填** | 远程目标路径 |
| `mode` | 字符串 | - | 八进制文件模式,例如 `"644"` |
| `recursive` | 布尔值 | 自动检测 | 强制目录模式(自动通过本地 `stat()` 检测) |
| `atomic` | 布尔值 | `true` | 写入 `<path>.tmp.<rand>`,然后 `mv` |
| `verify` | 布尔值 | `true` | 比较本地和远程 sha256 之后上传 |
| `sudo` | 布尔值 | `false` | 暂存到 `/tmp`,然后使用 `sudo install` 到目标 |
| `owner` | 字符串 | - | 当 `sudo=true` 时:`"user:group"` 用于 `install -o/-g` |
| `overwrite` | 布尔值 | `true` | 允许覆盖现有的远程文件 |
| `concurrency` | 数字 | `4` | `fastPut` 的并行 SFTP 块并发 |
```typescript
// 1)单个文件,带有 sha256 验证和原子重命名(默认值)
ssh_upload({
profile: "production",
local_path: "./build/app.tar.gz",
remote_path: "/srv/releases/app-2026-05.tar.gz",
mode: "644"
})
// 2)递归目录上传(自动从本地 stat 检测)
ssh_upload({
profile: "production",
local_path: "./dist",
remote_path: "/var/www/app/current",
mode: "755",
concurrency: 8
})
// 3)sudo 写入 /etc - 暂存到 /tmp,然后 `sudo install -m 644 -o root:root`
ssh_upload({
profile: "production",
local_path: "./nginx-site.conf",
remote_path: "/etc/nginx/conf.d/site.conf",
mode: "644",
owner: "root:root",
sudo: true
})
// 注意:递归 + sudo 不支持一步操作 - 解决方法:
// 1)上传到用户可写的暂存路径(不需要 sudo)
// 2)通过 ssh_exec 使用 sudo cp -r
// 4)下载二进制文件(默认开启验证)
ssh_download({
profile: "production",
remote_path: "/var/backups/db",
local_path: "./backups/db"
})
```
### ssh_download - 基于二进制的安全下载
| 参数 | 类型 | 默认值 | 描述 |
|-----------|------|---------|-------------|
| `profile` | 字符串 | `"default"` | SSH 配置文件名称 |
| `remote_path` | 字符串 | **必填** | 远程源路径 |
| `local_path` | 字符串 | **必填** | 本地目标路径 |
| `recursive` | 布尔值 | 自动检测 | 强制目录模式(自动通过远程 `test -d` 检测) |
| `verify` | 布尔值 | `true` | 下载后比较本地和远程 sha256 |
| `concurrency` | 数字 | `4` | `fastGet` 的并行 SFTP 块并发 |
```typescript
ssh_download({
profile: "production",
remote_path: "/var/backups/db",
local_path: "./backups/db",
recursive: true,
concurrency:
})
```
---
## 🔍 审计工具(v1.3.0+)
专门的只读审计原语,收集 **每个单程** 的证据。最大的好处是 `ssh_audit_baseline`:**一个调用取代 5+ 个单独的 ssh_exec 调用**(df,free,ss,docker ps,systemctl,sshd -T,ufw,...)- 延迟和结果合并成本都消失了。
有关管道指南和完整章节描述,请参阅 [docs/audit.md](docs/audit.md)。
### ssh_audit_baseline
单个批处理 shell 命令,结果通过哨兵标记分割,解析为结构化 JSON + 关键短语列表。取代 5-10 个单独的 `ssh_exec` 调用(df,free,ss,docker,systemctl,sshd -T,ufw,apt ...),**一次往返**。
部分(通过 `include` 开启):`system, disk, mem, net, ssh, services, docker, firewall, updates`。默认情况下,除 `ssh` 之外的所有部分(sudo)。
| 标志 | 默认值 | 用途 |
|------|---------|---------|
| `include` | 除 `ssh` 之外的所有部分 | 限制为子集,例如 `["disk", "services"]` |
| `include_sudo_sections` | `false` | 启用 `sshd -T`(整个复合命令在 sudo 下运行) |
| `compact` | `true` | 修剪长部分(侦听器,接口,docker 行)以获得更小的 LLM 负载 |
输出格式:主机标头 → 关键短语列表 → 磁盘表 → 侦听器 → sshd → 服务 → docker → 防火墙 → 更新)后跟 `--- raw JSON ---` 和完整的结构化结果。
自动红旗规则:
- **严重**:文件系统 ≥ 90%,`PermitRootLogin yes`,`PasswordAuthentication yes` 在端口 22
- **警告**:文件系统 70-90%,退出容器,失败的 systemd 单元,重启待处理,> 50 个可升级的软件包
- **正常**:文件系统 < 70%,一切正常
```typescript
ssh_audit_baseline({
profile: "production",
include_sudo_sections: true // 启用 sshd -T 部分
})
// 限制为子集
ssh_audit_baseline({
profile: "production",
include: ["disk", "services", "docker"]
})
```
### ssh_tls_check
将 `openssl s_client -connect <domain>:<port> -servername <domain>` 传输到 `openssl x509`,解析 `notAfter`,SAN 条目(X509v3 替代名称),颁发者;计算 `days_until_expiry`。还扫描 `/etc/letsencrypt/renewal/*.conf` 以获取 `renew_hook` 和 `/etc/letsencrypt/renewal-hooks/deploy/`。
- **严重**:已过期,≤ 7 天,或 SAN 不包括请求的域
- **警告**:≤ 30 天,或未配置 Let's Encrypt 部署钩
```typescript
ssh_tls_check({
profile: "production",
domain: "app.example.com",
port: 443,
check_renew_hook: true
})
```
### ssh_disk_breakdown
单个批量调用。当 `ssh_audit_baseline` 标记磁盘使用率超过 70% 时使用。比基准(多个 `du -shx` 遍历)更重量级,因此不要无条件运行。
| 章节 | 命令 |
|---------|---------|
| `df` | `df -hT` |
| `du_<path>` | `du -shx <path>/* \| sort -rh \| head -<top_n>`,适用于每个 `paths[]` |
| `docker` | `docker system df -v`(或 `NO_DOCKER`) |
| `journald` | `journalctl --disk-usage`(或 `NO_JOURNALD`) |
| `var_log` | `du -sh /var/log/* \| sort -rh \| head -<top_n>` |
| `cache` | `du -sh "$HOME"/.cache/* \| sort -rh \| head -<top_n>` |
默认值:`top_n: 20`,`paths: ["/"]`。`paths` 在插值前进行 shell 转义。
```typescript
ssh_disk_breakdown({
profile: "production",
top_n: 20,
paths: ["/", "/var", "/home"]
})
```
### ssh_service_status
替换 `systemctl status` + `journalctl -u`,适用于一个 systemd 单元。所有操作在一个批量调用中,解析为结构化的 `enabled / active / restart / status_head / log_tail`。
| 章节 | 命令 |
|---------|---------|
| `status` | `systemctl status <unit> --no-pager \| head -40` |
| `is_enabled` | `systemctl is-enabled <unit>` |
| `show` | `systemctl show <unit> --property=Restart,RestartSec,LoadState,ActiveState,SubState` |
| `log` | `journalctl -u <unit> -n <log_lines> --no-pager [--since <since>]` |
默认值:`log_lines: 50`。`since` 接受任何 `journalctl --since` 值(`"1h ago"`,`"2026-05-03"`)。单元名称针对 `^[a-zA-Z0-9@._-]+$` 进行验证,以防止 shell 注入。
```typescript
ssh_service_status({
profile: "production",
unit: "nginx.service",
log_lines: 50,
since: "1h ago"
})
```
### 推荐的审计管道
```typescript
// 1) 一次性基准 → 关键/警告短列表
const baseline = ssh_audit_baseline({ profile: "production", include_sudo_sections: true });
// 2) 如果有磁盘警告/关键 → 深入检查
ssh_disk_breakdown({ profile: "production", top_n: 20 });
// 3) 适用于每个公共 FQDN
ssh_tls_check({ profile: "production", domain: "app.example.com" });
// 4) 适用于每个失败的 systemd 单元
ssh_service_status({ profile: "production", unit: "nginx.service" });
```
此管道涵盖了约 80% 的典型服务器审计,无需使用 `ssh_exec`。
---
## 🔧 环境变量
### 必需
- `SSH_PROFILES_FILE` - SSH 配置文件 JSON 文件的路径
### 可选(日志记录)
- `SSH_MCP_LOG_LEVEL` - 日志级别:`debug`、`info`、`warn`、`error`(默认值:`info`)
- `SSH_MCP_LOG_TIMESTAMP` - 在日志中显示时间戳:`true`、`false`(默认值:`true`)
- `SSH_MCP_LOG_COLORS` - 在日志中启用颜色:`true`、`false`(默认值:`false`)
### 可选(连接池)
- `SSH_MCP_POOL_IDLE_TIMEOUT` - 连接空闲超时时间(毫秒)(默认值:`30000`)
- `SSH_MCP_POOL_KEEPALIVE_INTERVAL` - 连接保持活动间隔(毫秒)(默认值:`10000`)
### 可选(配置文件)
- `SSH_MCP_PROFILES_CACHE_TTL` - 配置文件缓存 TTL(毫秒)(默认值:`60000`)
- `SSH_MCP_PROFILES_WATCH` - 监视配置文件更改:`true`、`false`(默认值:`true`)
### 示例配置
```bash
# 必需
export SSH_PROFILES_FILE="$HOME/.ssh/mcp-profiles.json"
# 可选 - 日志记录
export SSH_MCP_LOG_LEVEL="debug"
export SSH_MCP_LOG_TIMESTAMP="true"
# 可选 - 连接池
export SSH_MCP_POOL_IDLE_TIMEOUT="60000"
# 可选 - 配置文件
export SSH_MCP_PROFILES_WATCH="true"
export SSH_MCP_PROFILES_CACHE_TTL="60000"
```
**注意:** 当 `SSH_PROFILES_FILE` 更改时,配置文件会自动重新加载(如果 `SSH_MCP_PROFILES_WATCH=true`)。您也可以使用 `ssh_monitor(action="reload")` 手动重新加载配置文件。
---
## 🔒 安全
### 危险命令警告
服务器会自动检测危险命令:
```typescript
ssh_exec({
command: "rm -rf /"
})
// ⚠️ 危险命令:rm -rf / 检测到
// 命令将执行,但会带有警告
```
检测到的危险模式:
- `rm -rf /`、`rm -rf ~`、`rm -rf *`
- `chmod 777`
- `reboot`、`shutdown`、`halt`
- `docker system prune -a`
- `DROP DATABASE`、`TRUNCATE`
### 建议
1. **使用 SSH 密钥** 而不是密码
2. **限制用户权限** (使用非 root 用户和 sudo)
3. **定期轮换密钥**
4. **检查 MCP 服务器日志**
## 🏗️ 架构
```
~/.cursor/mcp.json
↓
SSH MCP 服务器
↓
配置文件解析器 → ~/.cursor/ssh-profiles.json
↓
连接池(重用连接)
↓
SSH 执行器
↓
14 种工具(exec、file、log、snapshot、monitor、transfer、audit)
↓
远程服务器(s)
```
### 关键原则:
- **连接池** - 重用 SSH 连接以提高性能(6-10 倍更快)
- **基于会话的指标** - 指标在所有连接关闭时自动重置
- **无流式传输** - 仅快照结果
- **REST 方法** - 数组在逻辑上
- **重试逻辑** - 带有指数退避的自动重试
- **自动重新连接** - 连接丢失时的自动重新连接
## 🛠️ 开发
### 要求
- Node.js 18+
- TypeScript 5+
- SSH 访问远程服务器
### 开发设置
```bash
git clone https://github.com/hypnosis/ssh-mcp-server.git
cd ssh-mcp-server
npm install
npm run build
```
### 在开发模式下运行
```bash
npm run dev
```
### 项目结构
```
src/
├── index.ts # 入口点 + 路由
├── managers/
│ ├── ssh-executor.ts # SSH 命令
│ └── connection-pool.ts # 连接池 + getSftp()
├── tools/
│ ├── exec-tool.ts # ssh_exec
│ ├── file-tools.ts # ssh_file_read/write/list(验证/原子/二进制)
│ ├── log-tools.ts # ssh_log_tail/search
│ ├── snapshot-tool.ts # ssh_snapshot
│ ├── monitoring-tool.ts # ssh_monitor
│ ├── transfer-tool.ts # ssh_upload、ssh_download(v1.3.0)
│ └── audit-tool.ts # ssh_audit_baseline、ssh_tls_check、
│ # ssh_disk_breakdown、ssh_service_status(v1.3.0)
└── utils/
├── logger.ts # 日志记录
├── ssh-config.ts # SSH 配置
├── profile-resolver.ts # 加载配置文件
├── profiles-file.ts # 解析配置文件
├── path-validator.ts # 路径安全
├── retry.ts # 重试逻辑
├── sha256.ts # 本地 + 远程 sha256 助手(v1.3.0)
└── tmp-name.ts # 原子临时/暂存路径生成器(v1.3.0)
```
## 📝 路线图
### v1.0(MVP) ✅
- ✅ 7 个核心命令
- ✅ 来自文件的配置文件
- ✅ 重试逻辑
- ✅ 安全(警告)
### v1.1 - v1.2.2(已发布) ✅
- ✅ 连接池(6-10 倍更快)
- ✅ 路径安全和波浪号展开
- ✅ 带有指数退避的重试机制
- ✅ 增强的错误消息
- ✅ 配置文件重新加载和监视
- ✅ 基于会话的指标
### v1.3.0(已发布) ✅
- ✅ SFTP 传输工具 — `ssh_upload`、`ssh_download`(二进制安全、原子、sha256 验证)
- ✅ `ssh_file_write` / `ssh_file_read` 扩展为 `verify`、`atomic`、`binary`
- ✅ 审计工具 — `ssh_audit_baseline`、`ssh_tls_check`、`ssh_disk_breakdown`、`ssh_service_status`
- ✅ 工具数量:8 → 14
### 未来(计划中)
- 📋 递归 sudo 上传(一次性,无需临时解决方法)
- 📋 扩展快照(自定义检查)
- 📋 连接指标仪表盘
## 🤝 贡献
1. 复刻仓库
2. 创建功能分支(`git checkout -b feature/amazing-feature`)
3. 提交更改(`git commit -m 'Add amazing feature'`)
4. 推送到分支(`git push origin feature/amazing-feature`)
5. 打开拉取请求
## 🔒 安全
### 路径处理和引用
SSH MCP 服务器使用安全的引用策略来防止注入攻击:
**单引号(默认):**
- 用于没有波浪号的常规路径
- 防止所有扩展(变量、命令、通配符)
- 示例:`cat '/etc/hosts'` - 最安全选项
**双引号(适用于波浪号):**
- 仅在路径包含 `~` 时使用(扩展为 `$HOME`)
- 除 `$HOME` 外,所有内容都已转义
- 防止:变量扩展( `$VAR` )、命令替换( `` `cmd` `` )、历史记录扩展( `!` )
- 示例:`cat "$HOME/.bashrc"` - `$HOME` 扩展,但文件名中的 `$VAR` 不会扩展
**保护内容:**
- ✅ 通过 `;`、`&&`、`||` 进行命令注入
- ✅ 变量扩展( `$VAR` )
- ✅ 命令替换( `` `cmd` ``、`$(cmd)` )
- ✅ 历史记录扩展( `!` )
- ✅ 通配符扩展( `*`、`?` )
**波浪号扩展:**
- `~/file` → `$HOME/file` (自动)
- `~user/file` → shell 扩展 `~user` (自动)
- 适用于:`ssh_file_read`、`ssh_file_write`、`ssh_file_list`、`ssh_log_tail`、`ssh_log_search`
### 路径安全(可选)
在配置文件中添加 `pathSecurity` 以获得额外保护:
```json
{
"pathSecurity": {
"allowedPaths": ["/home/admin", "/var/www"],
"deniedPaths": ["/etc/shadow", "/root"],
"allowTraversal": false,
"maxPathLength": 1000
}
}
```
有关详细信息,请参见 [快速入门](#11-optional-path-security-configuration)。
## 📄 许可证
MIT 许可证 - Copyright (c) 2026 hypnosis
有关详细信息,请参见 [LICENSE](LICENSE) 文件。
---
**Made with ❤️ for AI-powered development**
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器