ssh-mcp
@txcxgzs/ssh-mcp
让 SSH 为 AI 工具所用。 MCP 服务器,管理你的 SSH 环境、诊断问题、修复故障,并让你的智能体远程访问任何内容。
Fork 关系: 本仓库是 YawLabs/ssh-mcp 的衍生 fork。它保留了上游的 SSH/MCP 实现,并通过
SSH_CREDENTIALS_JSON增加了服务端密码别名解析, 从 MCP 工具参数中移除了明文密码,并修复了当~/.ssh尚不存在时首次运行known_hosts创建的问题。上游仍是原始项目;fork 特有的改动在此单独维护。
上游项目由 Yaw Labs 构建和维护。
一键将其添加到你的本地 Yaw MCP 配置中,使其在每个 Yaw Terminal 会话中可用。或者按下面的说明手动安装。
问题所在
AI CLI 工具在子进程中运行,而 SSH 在那里经常出问题。智能体尝试 git pull 却得到 Permission denied (publickey)。它尝试 SSH 到服务器,但 agent socket 已过期。它尝试部署,但主机密钥因实例被重建而改变。每次 AI 都不知道哪里出了问题,然后陷入困境。
这种情况发生在所有需要 SSH 密钥的场景中:
Git — clone、pull、push、fetch、submodules、LFS
包管理器 — 从私有仓库执行
npm install、pip install、go get、cargo、composer服务器访问 — SSH、SCP、SFTP、rsync
隧道 — 端口转发到数据库、SOCKS 代理
部署 — Ansible、Terraform、Capistrano、部署脚本
云 — AWS EC2、GCP、Azure、DigitalOcean、任何 VPS
ssh-mcp 解决了这个问题。它管理 SSH agent、加载密钥、诊断故障并提供可操作的修复命令,以及远程操作——全部作为你的 AI 智能体可以调用的 MCP 工具。
Related MCP server: MCP SSH Server
快速开始
添加到你的 MCP 客户端配置:
{
"mcpServers": {
"ssh": {
"command": "npx",
"args": ["-y", "@txcxgzs/ssh-mcp@latest"],
"env": {
"SSH_CREDENTIALS_JSON": "{\"ssh1\":\"your-password\"}"
}
}
}
}在 Windows 上,用 cmd /c 包裹,因为 Node 20+ 无法直接生成 .cmd 文件:
{
"mcpServers": {
"ssh": {
"command": "cmd",
"args": ["/c", "npx", "-y", "@txcxgzs/ssh-mcp@latest"]
}
}
}@latest 标签使 npx 在每次生成时重新向 registry 解析,因此每个 MCP 会话都使用最新发布的版本。或者,如果你更想固定版本(不自动更新),可以全局安装:
npm install -g @txcxgzs/ssh-mcp
# then in client config: "command": "ssh-mcp"工具
SSH 环境管理
修复你本地 SSH 配置的工具,让其他一切——git、部署、隧道——不再出问题。
工具 | 描述 |
| 确保 ssh-agent 正在运行。如果需要则启动一个,并为会话设置环境变量。 |
| 列出 ~/.ssh/ 中的所有 SSH 密钥,包括类型、指纹和 agent 状态。 |
| 将密钥加载到正在运行的 agent 中。确保先启动 agent。 |
| 解析主机的有效 SSH 配置(主机名、用户、端口、代理、身份文件)。 |
| 移除过期的主机密钥并重新扫描。修复"主机密钥验证失败"错误。 |
| 测试通过 SSH 的 Git 认证,支持 GitHub、GitLab、Bitbucket 等。 |
| 快速连通性测试,带计时和可操作的错误详情。 |
诊断
工具 | 描述 |
| 完整的 SSH 环境诊断。检查 agent、密钥、配置、known_hosts 和连通性。对每个故障返回精确的修复命令。 |
远程操作
工具 | 描述 |
| 在远程主机上执行命令。返回 stdout、stderr 和退出码(当通道以仅信号方式关闭时返回 |
| 通过 SFTP 从远程主机读取文件。 |
| 通过 SFTP 将内容写入远程主机上的文件。 |
| 通过 SFTP 将本地文件上传到远程主机。 |
| 将文件从远程主机下载到本地文件系统。 |
| 列出远程主机上目录中的文件。 |
| 获取文件或目录的元数据(大小、八进制模式、uid/gid、mtime/atime、isFile/isDirectory/isSymbolicLink)。用它代替解析 |
| 通过 SFTP 创建目录。设置 |
| 通过 SFTP 删除文件或空目录。根据路径类型自动分派 unlink 或 rmdir。有意不支持递归删除目录——如果需要,请使用 |
高级操作
封装智能体常用 ssh_exec 模式的工具——更快且更不易出错。
工具 | 描述 |
| 在多个主机上并行运行命令。按主机返回结果。如果配置了命令策略,则受其约束(策略在扇出前检查一次)。 |
| 使用结构化参数远程搜索文件( |
| 读取文件最后 N 行,可选地按 grep 模式过滤。 |
| 检查 systemd 服务状态(active、PID、运行时间、描述)。仅当无法找到/查询单元时标记 |
自动诊断
当任何远程操作失败时,ssh-mcp 会自动运行诊断并将结果包含在错误响应中。你的智能体不需要单独调用 ssh_diagnose——它会在错误消息中直接被告知问题所在以及如何修复。
连接池
远程操作自动复用 SSH 连接。当你的智能体对同一主机进行多次调用时,第一次调用打开连接,后续调用复用该连接。连接在最后一次使用后保持 60 秒,然后自动关闭。
连接池默认上限为 100 个活动连接。设置 SSH_MCP_MAX_POOL_SIZE=<n> 可提高上限,以应对针对大量不同主机的扇出工作负载(例如跨大型机群的 ssh_multi_exec)。达到上限时,连接池会驱逐一个空闲条目以腾出空间;如果所有条目都在使用中,则拒绝并返回 Connection pool is full。
SSH 配置支持
所有连接都遵循你的 ~/.ssh/config。主机别名、自定义端口、用户名、身份文件和 ProxyJump 设置都会自动使用。如果你在 SSH 配置中配置了 Host myserver,只需传入 host: "myserver"——ssh-mcp 会解析一切。
ProxyJump / 堡垒主机 自动支持。如果你的 SSH 配置中某个主机有 ProxyJump bastion,ssh-mcp 会透明地通过堡垒机连接。链式代理也可以工作。
主机密钥验证
所有远程操作都会根据 ~/.ssh/known_hosts 验证服务器的主机密钥:
已知主机,密钥匹配 — 接受。
已知主机,密钥已更改 — 拒绝(MITM 防护)。
未知主机 — 首次连接时接受(TOFU)。使用
ssh_known_hosts_fix固定密钥,以便将来检测不匹配。
对于更严格的环境,设置 SSH_MCP_STRICT_HOST_KEY=1 以拒绝未知主机。先用 ssh_known_hosts_fix 显式添加它们。
诊断工具(ssh_test、ssh_diagnose)对其探测命令使用 StrictHostKeyChecking=no。这些探测只运行 echo SSH_OK——不传递凭据或数据——因此宽松设置对连通性测试是安全的。实际操作始终通过 hostVerifier 进行。
命令策略
ssh_exec 和 ssh_multi_exec 接受来自代理的自由格式 shell 命令。对于注重安全性的部署,你可以通过两个环境变量限制允许执行的命令,每个变量接受一个以逗号分隔的正则表达式模式列表:
SSH_MCP_COMMAND_WHITELIST— 如果设置,命令必须至少匹配一个模式,否则会被阻止。SSH_MCP_COMMAND_BLACKLIST— 如果设置,命令不得匹配任何模式,否则会被阻止。
当两者都设置时,命令必须通过两项检查(先白名单,后黑名单)。当两者都未设置时(默认情况),所有命令都被允许。
模式是 JavaScript 正则表达式。使用 ^ 和 $ 进行锚定匹配;否则模式被视为子字符串匹配。逗号是分隔符,因此模式中的字面逗号需要用 \x2c 或字符类来表示。
# Read-only allowlist: only ls / df / cat / find / tail
SSH_MCP_COMMAND_WHITELIST="^ls( .*)?,^df( .*)?,^cat ,^find ,^tail "
# Block destructive ops even if your agent goes off-script
SSH_MCP_COMMAND_BLACKLIST="^rm ,^shutdown,^reboot,^mkfs,^dd if=,>\s*/dev/"被阻止的命令会显示为清晰的错误信息,指出哪个模式(或哪个环境变量)拒绝了该调用,以便代理能够调整而不是猜测。策略在 SSH 连接打开之前就执行——被阻止的命令不会启动任何远程进程。
结构化的高级工具(ssh_find、ssh_tail、ssh_service_status、SFTP 操作)不受策略限制。它们从类型化参数构建命令,因此严格的白名单 ^ls 会迫使你为了保持这些工具可用而允许 ^find、^tail、^systemctl——这反而使严格白名单失去意义。
与 ssh_exec 的 env 参数之间的策略交互
当使用 env: { KEY: "value" } 调用 ssh_exec 时,这些值会以 KEY='value' ... 的 shell 前缀形式注入到命令之前(参见 ssh_exec 的描述)。策略检查的是完整的带前缀命令,而不是裸的 command 参数。这是在协议层更安全的排序——但这意味着白名单模式需要预料到前缀,并且必须是锚定的,而不是子字符串匹配:
# WRONG -- blocks any ssh_exec call that uses `env`, because the final command
# starts with `KEY='value' ` and never matches `^ls`.
SSH_MCP_COMMAND_WHITELIST="^ls "
# RIGHT -- allow zero or more `KEY='value' ` prefixes before the real command.
SSH_MCP_COMMAND_WHITELIST="^([A-Za-z_][A-Za-z0-9_]*='[^']*' )*ls( |$)"避免使用子字符串匹配模式,例如 ls,如果你担心恶意代理的话。代理可以传入 env: { ATTACK: " ls " } 使最终命令变成 ATTACK=' ls ' rm -rf /,这会匹配子字符串 ls 并绕过白名单。上述形式的锚定模式没有这个弱点,因为它们要求真正的命令名跟在环境变量前缀块之后,而不是出现在带引号的环境变量值内部。
黑名单需要同样的注意。^rm 会阻止裸的 rm 调用,但不会阻止 FOO='bar' rm。使用同样的环境变量前缀容错锚定:
SSH_MCP_COMMAND_BLACKLIST="^([A-Za-z_][A-Za-z0-9_]*='[^']*' )*rm( |$)"如果你完全不信任代理的 env 值,最简单的缓解措施是在客户端配置中不使用 env,并自己通过 command 字符串传递所有内容。
Windows 支持
在 Windows 上,ssh-mcp 会自动检测 OpenSSH 认证代理服务(通过 \\.\pipe\openssh-ssh-agent 命名管道)。无需 SSH_AUTH_SOCK——只需确保 OpenSSH 代理服务正在运行即可。
身份认证
所有远程操作都接受连接参数:
参数 | 描述 | 默认值 |
| SSH 主机名或 IP(必填) | — |
| SSH 端口 | 来自 SSH 配置或 |
| SSH 用户名 | 来自 SSH 配置或当前用户 |
| SSH 私钥路径 | 自动检测 |
| 仅在服务器端 | — |
认证解析顺序: ssh-mcp 从以下列表中选择第一个匹配项,并且不会回退到后面的条目——这使得认证方法具有确定性和可预测性。
显式的
privateKeyPath从
credential_id解析出的密码ssh-agent(Unix 上是
SSH_AUTH_SOCK,Windows 上是\\.\pipe\openssh-ssh-agent)来自
~/.ssh/config中该主机的身份文件默认密钥路径(
~/.ssh/id_ed25519、id_rsa、id_ecdsa)
真实密码永远不会作为 MCP 工具参数。仅在 MCP 服务器环境中配置别名到密码的映射,然后让代理动态选择 host、port、username 和 credential_id:
SSH_CREDENTIALS_JSON={"ssh1":"password1","ssh2":"password2"}{
"host": "bore.pub",
"port": 45201,
"username": "root",
"credential_id": "ssh1",
"command": "hostname"
}如果省略 credential_id,密钥和 ssh-agent 认证仍然可以工作。未知的别名会失败,但错误信息中不会包含任何已配置的密码。
示例工作流
代理无法执行 git pull
Agent calls ssh_git_check → "Permission denied. Your SSH key is not registered with github.com."
Agent calls ssh_key_list → finds id_ed25519 exists but is not loaded
Agent calls ssh_key_load("~/.ssh/id_ed25519") → "Key loaded"
Agent calls ssh_git_check → "Git SSH authentication to github.com succeeded as username"
Agent runs git pull → works实例重建后主机密钥变更
Agent calls ssh_exec on server → error: "Host key verification failed"
(auto-diagnostics included in error: "Fix with ssh_known_hosts_fix")
Agent calls ssh_known_hosts_fix("my-server") → "Host key refreshed"
Agent calls ssh_exec → works首次连接到新服务器
Agent calls ssh_test("new-server") → "Connection refused at new-server:22"
Agent calls ssh_diagnose("new-server") → full report showing agent running, keys loaded, but host unreachable
Agent reports: "SSH server isn't running on new-server or port 22 is blocked"程序化使用
import { connect, exec, diagnose, ensureAgent, listSshKeys, checkGitSsh, ConnectionPool } from '@txcxgzs/ssh-mcp';
// Fix SSH environment
const agent = ensureAgent();
console.log(agent.message);
// Check git access
const git = checkGitSsh('github.com');
console.log(git.message);
// List available keys
const keys = listSshKeys();
for (const key of keys) {
console.log(`${key.name} (${key.type}) - ${key.loadedInAgent ? 'loaded' : 'not loaded'}`);
}
// Run a remote command (one-off)
const client = await connect({ host: 'my-server', username: 'deploy' });
const result = await exec(client, 'uptime');
console.log(result.stdout);
client.end();
// Run multiple commands with connection pooling
const pool = new ConnectionPool();
await pool.withConnection({ host: 'my-server' }, async (client) => {
const r1 = await exec(client, 'uptime');
console.log(r1.stdout);
});
// Connection stays open for 60s — next call reuses it
await pool.withConnection({ host: 'my-server' }, async (client) => {
const r2 = await exec(client, 'df -h');
console.log(r2.stdout);
});
pool.drain(); // close all connections when done
// Diagnose issues
const report = diagnose('my-server');
console.log(report.overall); // "ok" | "warning" | "error"
for (const check of report.checks) {
console.log(`[${check.status}] ${check.name}: ${check.message}`);
}要求
Node.js 18+
已安装 SSH 客户端(用于诊断和环境管理)
许可证
MIT
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityCmaintenanceEnables AI assistants to securely connect to and manage remote servers via SSH, supporting command execution, file transfers via SFTP, and multi-server management with both password and SSH key authentication.9802MIT
- AlicenseNot gradedqualityFmaintenanceEnables AI assistants to execute commands and transfer files on remote servers over SSH connections.1MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI assistants to securely execute commands, transfer files, and manage port forwarding on remote servers via SSH.9836Apache 2.0
- AlicenseAqualityCmaintenanceEnables AI assistants to manage remote servers via SSH with agentless command execution, file operations, and service management.9MIT
Related MCP Connectors
Let AI operate servers without SSH. Choose actions, approve risky changes, and audit every step.
Operate Linux, macOS and Windows from your LLM. Every action runs through an auditable allowlist.
Provides cloud browser automation capabilities using Stagehand and Browserbase, enabling LLMs to i…
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/txcxgzs/ssh-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server