关于 ssh-mcp
ssh-mcp 是集中式 MCP 网关,供需要让 AI Agent 访问 SSH 目标的团队使用。它通过一个 Streamable HTTP 服务统一执行授权、速率限制、连接池管理和审计日志记录。
主要功能
- 01按客户端和网络制定命令策略
- 02执行 SSH 命令并检查连接
- 03单文件 SFTP 传输
- 04速率限制与连接池
- 05结构化审计日志
适用场景
- 01管理多个 AI Agent 的 SSH 访问
- 02按客户端或网络限制命令
- 03审查命令和授权活动
MCP 相关
通过 Streamable HTTP 提供六种 SSH 和 SFTP 工具,包括目标列表、命令执行、连接检查及文件传输。MCP 客户端连接 `/mcp`,并使用 API 密钥进行身份验证。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
docker run -i --rm -e CONFIG_DIR -e LOG_DIR -e CONFIG_API_ENABLED -e CONFIG_API_TOKEN ghcr.io/gelse/ssh-mcp:0.3.0CONFIG_DIRDirectory containing ssh-mcp-config.jsonLOG_DIRDirectory for JSONL audit logsCONFIG_API_ENABLEDEnable the configuration REST API and web dashboardCONFIG_API_TOKEN密钥Bearer token for the configuration API本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
ghcr.io/gelse/ssh-mcp:0.3.0Streamable HTTP工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
ssh-mcp
一个集中式 MCP 网关,通过 Streamable HTTP 为 AI Agent 提供受控的 SSH 访问。
这个项目解决什么问题?
大多数 MCP SSH 服务以本地 stdio 进程的形式运行——每个 客户端一个,既没有共享状态,也没有集中式授权, 更没有审计追踪。当多个 AI Agent 需要 SSH 访问时,每个 Agent 都要管理自己的 SSH 密钥并运行自己的进程。这会导致:
- 没有集中式访问控制 — 每个客户端自行决定 可以运行什么
- 没有审计追踪 — 运维团队看不到执行的命令
- SSH 密钥泛滥 — 密钥散落在每台 Agent 机器上
- 没有速率限制 — 失控的 Agent 可能会压垮目标主机
ssh-mcp 通过部署单个 HTTP 网关来解决这个问题。所有 客户端都连接到网关;网关再连接到 SSH 目标主机。 授权、速率限制、连接池和审计日志都在一个地方处理。
快速开始
使用预构建镜像(推荐)
docker compose pull
docker compose up -d
镜像发布于 ghcr.io/gelse/ssh-mcp:latest。
compose 文件将主机端口 9080 映射到容器端口 8080。
验证服务是否正在运行:
curl http://localhost:9080/health
# → {"status": "ok"}
在 config/ssh-mcp-config.json 中创建最简配置:
{
"version": 1,
"ssh_targets": {
"my-server": {
"host": "10.0.1.10",
"username": "deploy"
}
},
"allowed_commands": {
"default": [
{
"targets": ["*"],
"commands": ["hostname", "uptime", "free", "df"]
}
]
}
}
生成 API 密钥哈希,并将其添加到配置文件或
secrets.json 中(参见配置)。
改为在本地构建
make build
docker compose up -d --build
可用功能(工具)
通过 Streamable HTTP 可使用六个 MCP 工具:
| 工具 | 描述 |
|---|---|
ssh_list_servers | 列出已配置的 SSH 目标主机 |
ssh_list_allowed_commands | 显示目标主机允许执行的命令 |
ssh_execute_command | 在远程服务上执行命令 |
ssh_check_connection | 测试与目标主机的 SSH 连接 |
ssh_download_file | 通过 SFTP 下载文件 |
ssh_upload_file | 通过 SFTP 上传文件 |
工具命名约定
所有工具都遵循 ssh_<verb>_<noun> 模式:
ssh_list_servers— 列出资源ssh_list_allowed_commands— 列出权限ssh_execute_command— 执行操作ssh_check_connection— 验证连接ssh_download_file/ssh_upload_file— 文件传输
参见 examples/README.md,其中包含使用示例,
包括 curl 命令和 Python 客户端代码。
可配置项
ssh-mcp 通过 JSON 文件配置,并支持热重载 (每 15 s 轮询一次,2 s 防抖)。主要配置项:
| 类别 | 详情 |
|---|---|
| SSH 目标 | 主机、端口、用户名、密钥、密码 |
| 命令策略 | 屏蔽模式、按密钥/网络划分的允许列表 |
| 连接池 | 最大连接数、空闲超时、并发数 |
| 速率限制 | 按 IP 限制的滑动窗口(默认每分钟 60 次请求) |
| 日志记录 | 支持轮转、gzip 和多个目标的 JSONL |
| SFTP | 沙箱根目录、路径长度限制 |
完整参考文档:docs/CONFIGURATION.md
| 文件 | 用途 |
|---|---|
ssh-mcp-config.json | 主配置文件 |
config.schema.json | 用于验证的 JSON Schema |
secrets.json | 密码和 API 密钥哈希 |
MCP_SSH_* 环境变量 | 覆盖任意设置 |
为什么不直接使用原始 SSH/其他 MCP 服务?
ssh-mcp 在每个客户端请求与每条 SSH 命令之间,添加了一条由 9 个有序层组成的分层授权链。针对不同 API 密钥和网络的规则,让不同 Agent 在不同服务器上拥有不同权限,而无需改动底层 SSH 账户。
其他防护措施:
- 熔断器通过指数退避隔离故障目标
- 速率限制防止失控的 Agent 给主机造成过大负载
- 结构化审计日志追踪每条命令、客户端、IP 和授权决策
- 连接池可在多个请求之间复用 SSH 会话
- 输入清理和危险模式检测可阻止 Shell 注入尝试
架构:ARCHITECTURE.md
安全模型:docs/SECURITY.md
它不是什么
- 不是交互式 Shell — 每条命令单独执行,并返回结构化输出
- 不是文件管理器 — SFTP 仅支持单文件下载和上传(不支持目录列表或递归传输)
- 不是防火墙/网络 ACL — 授权针对命令级别,而不是网络级别
- 不会降低 SSH 账户的权限 — 如果允许执行某条命令,SSH 用户就会以该账户拥有的权限执行它
尚未实现/已知缺陷
可通过贡献修复:
- SFTP 仅支持单文件 — 不支持目录列表或递归传输
- 不支持 TLS 终止 — 请在前面运行 Traefik 或 nginx
- 不支持 OAuth 或 mTLS 应用层身份验证
- 速率限制器设置无法热重载(启动时设置)
架构限制:
- 配置 API 仪表板的登录会话仅保存在内存中 — 重启后会丢失,且 API 仅支持单实例(配置更改本身仍会正常写入配置文件)
- 审计日志没有防篡改保护
可观测性
- 健康状态:
GET /health— 返回{"status": "ok"} - 指标:
GET /metrics— Prometheus 展示格式 - 日志: 带有请求关联信息的结构化 JSONL
配置 API 与仪表板
可选的 Web 仪表板,无需编辑 JSON 文件即可管理配置。通过 CONFIG_API_ENABLED=true 启用。
完整参考:docs/CONFIG-API.md
常见问题
通过 HTTP 访问仪表板时返回 401
会话 Cookie 默认启用 Secure(仅限 HTTPS)。如需在本地通过 HTTP 测试,请设置:
environment:
- CONFIG_API_SESSION_COOKIE_SECURE=false
然后重启容器。
MCP 客户端如何连接?
使用 Streamable HTTP 传输连接到 http://host:9080/mcp。通过 X-API-Key 或 Authorization: Bearer 请求头传递 API 密钥。
如何生成 API 密钥哈希?
docker compose exec mcp-ssh python -c \
"from lib.crypto import hash_api_key; print(hash_api_key('your-key'))"
# → pbkdf2:sha256:100000$<salt>$<hash>
也可以使用配置 API 仪表板中的哈希工具。
热重载如何工作?
配置文件每 15 秒轮询一次,并进行 2 秒防抖。目标、命令和设置的更改无需重启即可生效。速率限制器和日志目标设置需要重启。
为什么我的命令被拒绝?
命令会经过一条由 9 层组成的授权链进行评估。日志中的 matched_via 字段会显示是哪一层拒绝了命令。完整链条请参阅安全模型。
速率限制如何工作?
按 IP 进行滑动窗口限流,默认每 60 秒最多 60 个请求。超出限制时返回 HTTP 503。通过配置文件中的 settings.rate_limit 进行配置。
日志保存在哪里?
日志写入 /logs 卷(映射自 ./logs)。当前日志文件为 ssh-mcp.log,采用 JSONL 格式,并可选择启用 gzip 轮转。
基础故障排查
# Check server health
curl http://localhost:9080/health
# Validate config
make config-test
# Check logs
docker compose logs mcp-ssh
文档
| 文档 | 描述 |
|---|---|
ARCHITECTURE.md | 系统设计与数据流 |
docs/SECURITY.md | 安全模型与威胁分析 |
docs/CONFIGURATION.md | 完整配置参考 |
docs/CONFIG-API.md | 配置 API 与仪表盘 |
docs/OBSERVABILITY.md | 健康状态、指标与日志记录 |
CONTRIBUTING.md | 开发与贡献指南 |
CHANGELOG.md | 发布历史 |
examples/ | 配置示例与客户端代码 |
开发
# Unit tests
make test
# Integration tests (builds Docker image)
make integrationtest
完整的开发指南、编码规范和 PR 工作流,请参阅 CONTRIBUTING.md。
路线图
暂无公开路线图。当前的限制和机会请参阅 尚未实现 / 已知缺陷。
许可证
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。