s

ssh-mcp

lingex/ssh-mcp
0 Stars 16 次浏览 更新于 2026-08-23

一个纯 Rust 的 SSH MCP 服务器,可以从命令行安全地管理身份验证凭据,并允许对多个 Linux 主机执行远程命令、交互式 shell 和 SFTP 文件传输。

MCP 服务配置

复制以下 JSON 到 OPClaw 或其他 MCP 客户端的配置文件中即可使用

{
  "mcpServers": {
    "ssh-mcp": {
      "command": "\u003cyour-path\u003e\\ssh-mcp.exe",
      "env": {
        "SSH_MCP_MASTER_PASSWORD": "${SSH_MCP_MASTER_PASSWORD}"
      },
      "type": "stdio"
    }
  }
}

该服务需要配置环境变量:SSH_MCP_MASTER_PASSWORD

服务介绍

ssh-mcp

使用 Rust 编写的 SSH MCP 服务器:通过命令行安全地加密管理认证凭据,再通过 MCP 工具对多台 Linux 主机执行远程命令、交互式 Shell 与 SFTP 文件传输。SSH 敏感信息(账号、密码、主密码)不会传给 MCP 客户端/agent。

English docs: README.md

下载

每个版本都会附带 Windows 与 Linux(x86_64)预编译二进制。直接到最新 Release 下载:

  • ssh-mcp-windows-x86_64.exe — Windows
  • ssh-mcp-linux-x86_64 — Linux(在 Linux 上编译)
# Windows
ssh-mcp-windows-x86_64.exe --version

# Linux
chmod +x ssh-mcp-linux-x86_64
./ssh-mcp-linux-x86_64 --version

每个 Release 说明里都附有 SHA-256 校验和。需要其他平台或架构请从源码构建。

功能

  • 认证凭据使用 AES-256-GCM 加密保存(密钥由主密码经 Argon2id 派生),凭据只能通过 CLI 添加,MCP 接口无法添加
  • SSH 敏感信息(密码/主密码)与 agent 完全隔离:凭据加密保存在本地 vault,仅能通过 CLI 管理;MCP 客户端/agent 只能看到 alias、session_id 和非敏感元数据(用户名/主机/端口),既不能读取也不能修改任何凭据
  • 每台主机可同时建立多个会话,每个会话有唯一 session_id
  • MCP 双传输:stdio(默认)与 Streamable HTTP(actix-web),可同时运行
  • 远程命令执行、交互式 PTY Shell、SFTP 上传/下载
  • 主机密钥 TOFU 校验(首次连接记录指纹,之后指纹不符拒绝连接)
  • 内置命令安全闸门:灾难性命令(如 rm -rf /)硬拦截,高风险命令需 CLI 人工审批(ssh-mcp pending/approve/deny
  • 所有操作写入日志文件,带进程 ID,超过 10MB 自动轮转
  • HTTP 请求头鉴权(SSH_MCP_HTTP_TOKEN,Bearer Token)
  • 内置 Codex / Claude Code / Cursor / VS Code / Claude Desktop / Cherry Studio 客户端接入配置

构建

cargo build --release

产物位于 target/release/ssh-mcp(.exe)

主密码

凭据库由主密码加密。主密码通过环境变量 SSH_MCP_MASTER_PASSWORD 提供;未设置时仅当 stdin 是终端才会交互式输入,否则报错退出(MCP stdio 模式下必须使用环境变量)。空值视为错误。

CLI 参考

ssh-mcp 是单一二进制。运行 ssh-mcp --helpssh-mcp <命令> --help 可查看内置帮助。

全局选项

选项 说明
-h, --help 打印帮助
-V, --version 打印版本
--data-dir <path> 数据目录(默认 ~/.ssh-mcp,Windows 为 %USERPROFILE%\.ssh-mcp)。对每个子命令都有效,可放在子命令前或后。pending / approve / deny 需要与运行中的服务器使用相同的数据目录。

命令

命令 参数 说明
add <alias> <user@host> <password> [--port <port>] 添加凭据。<alias> 是后续 MCP 使用的唯一名称;<user@host> 必须严格是 user@host 形式;--port 默认 22
list 列出已保存凭据(alias user@host:port),不显示密码。
remove <alias> 删除凭据。
pending 列出等待人工审批的命令(ID、alias、创建时间、剩余有效期),并打印当前策略。
approve <id> 批准一条待审批命令,使下一次相同命令的重试被放行。需要主密码;审批人记录为 USERNAME
deny <id> 删除一条待审批命令,不批准。
serve [--http <addr:port>] 启动 MCP 服务器(不写子命令时默认执行此命令)。不带 --http:仅 stdio;带 --http:在 http://<addr>/mcp 提供 Streamable HTTP 并且同时保留 stdio;stdin 关闭时 stdio 侧退出,HTTP 继续服务。

示例

# 添加凭据(密码只进入加密 vault)
ssh-mcp add web root@192.168.1.10 'password'
ssh-mcp add db root@10.0.0.5 'password' --port 2222

# 查看与删除
ssh-mcp list
ssh-mcp remove web

# 审批流程
ssh-mcp pending
ssh-mcp approve <id>
ssh-mcp deny <id>

# 仅 stdio 的服务器(由 MCP 客户端拉起进程)
SSH_MCP_MASTER_PASSWORD='...' ssh-mcp

# 在 127.0.0.1:8787 提供 Streamable HTTP
SSH_MCP_MASTER_PASSWORD='...' ssh-mcp serve --http 127.0.0.1:8787

# --data-dir 是全局参数,两种写法都可以
ssh-mcp --data-dir /srv/ssh-mcp serve --http 0.0.0.0:8787
ssh-mcp serve --data-dir /srv/ssh-mcp --http 0.0.0.0:8787

成功退出码为 0,出错为 1(错误信息输出到 stderr)。

数据目录内容

  • vault.bin — AES-256-GCM 加密的凭据库
  • known_hosts — 已信任主机指纹
  • pending/ — 待审批队列(每条待审批命令一个文件)
  • approved/ — 已消费的审批记录
  • ssh-mcp.log — 操作日志(见「日志」)

环境变量

变量 默认值 说明
SSH_MCP_MASTER_PASSWORD 交互式输入(仅终端) 解锁凭据库的主密码。只要 stdin 不是终端就必须设置(MCP stdio 模式必然如此)。空值视为错误。永不写入日志。
SSH_MCP_HTTP_TOKEN 未设置(不鉴权) 设置后,每个 HTTP 请求必须携带 Authorization: Bearer <token>X-SSH-MCP-Token: <token>,否则返回 401。仅对 serve --http 生效。永不写入日志。
SSH_MCP_COMMAND_POLICY block block:硬拦截灾难命令 + 高风险命令需审批;warn:仅硬拦截,高风险命令放行并记录警告;allow:关闭过滤(不推荐)。未知值回退为 block
SSH_MCP_APPROVAL_TTL 300 审批有效期(秒)。超过该时间审批失效;审批只对同一 alias 的同一命令生效,且使用一次后即失效。
SSH_MCP_LOG_FILE <data_dir>/ssh-mcp.log 覆盖日志文件路径;父目录会自动创建。
SSH_MCP_LOG_LEVEL info trace / debug / info / warn / error。未知值回退为 info
USERNAME cli 执行 ssh-mcp approve 时记录的审批人(Windows 通常自动设置;未设置时回退为 cli)。

所有变量都在进程启动时读取一次。

MCP 服务

stdio(默认)

本地 MCP 客户端(Claude Desktop、Cursor 等)直接拉起进程:

SSH_MCP_MASTER_PASSWORD='...' ssh-mcp

Streamable HTTP(actix-web)

SSH_MCP_MASTER_PASSWORD='...' ssh-mcp serve --http 127.0.0.1:8787

端点为 http://127.0.0.1:8787/mcp(MCP Streamable HTTP 规范,stateful 会话)。带 --http 时 stdio 传输仍会保留;stdin 关闭后 stdio 侧退出,HTTP 继续服务。

设置 SSH_MCP_HTTP_TOKEN 后,每个 HTTP 请求都必须携带 Authorization: Bearer <token>(或 X-SSH-MCP-Token: <token>):

SSH_MCP_MASTER_PASSWORD='...' SSH_MCP_HTTP_TOKEN='你的token' ssh-mcp serve --http 0.0.0.0:8787

绑定 0.0.0.0 会把服务暴露到网络——此时务必设置 SSH_MCP_HTTP_TOKEN,并让防火墙只放行可信客户端。

工具

工具 说明
ssh_connect 按 alias 建立 SSH 会话,返回 session_id
ssh_disconnect 关闭会话
ssh_exec 执行命令,返回 stdout/stderr/退出码(可设超时)
ssh_shell_start 打开交互式 PTY Shell
ssh_shell_write 向 Shell 发送输入
ssh_shell_read 读取 Shell 输出(可设等待毫秒数)
ssh_shell_close 关闭 Shell
ssh_upload SFTP 上传本地文件到远程
ssh_download SFTP 下载远程文件到本地
ssh_list_sessions 列出当前所有会话
ssh_list_credentials 列出已保存凭据(alias、用户名、主机、端口);绝不返回密码

凭据只能通过 CLI 添加/删除;MCP 无法修改凭据,也永远读不到任何密码。ssh_list_credentials 只返回非敏感元数据。

命令安全防护(内置安全闸门)

服务器内置命令安全闸门(src/guard.rs):无论哪个 MCP 客户端调用,ssh_execssh_shell_start(带命令)、ssh_shell_write 都会先经过检查,命令在发往远端之前就会被放行或拦截。

分级规则

  • 硬拦截(永远禁止,无法审批绕过):对系统根目录的递归强制删除(rm -rf /rm -rf /*rm -rf /etcrm -rf /boot 等);向磁盘设备写入(dd ... of=/dev/sdXmkfs ... /dev/sdX> /dev/sdX 等);fork bomb(:(){ :|:& };:);对系统根目录的递归 chmod / chown
  • 需人工审批(默认)rm -rf 删除任意路径、rm -r 删除系统目录、mkfsdd、关机/重启(shutdown/reboot/halt/poweroff/init 0|6)、kill -9 1、移动系统根目录、curl|wget ... | sh|bash、递归 chmod / chown

审批流程

高风险命令首次执行时,MCP 调用会返回错误并附带审批 ID:

command requires approval: run `ssh-mcp approve <id>` (or `ssh-mcp deny <id>`), then retry the same command
  1. 查看待审批队列:ssh-mcp pending
  2. 批准:ssh-mcp approve <id>(会要求主密码,且需与服务器使用相同的 --data-dir
  3. 让 MCP 客户端重试完全相同的命令,即可放行
  4. 审批默认 5 分钟内有效(SSH_MCP_APPROVAL_TTL 可调),仅对同一 alias 的同一命令生效,放行一次后即失效

拒绝:ssh-mcp deny <id>

策略与审批有效期通过 SSH_MCP_COMMAND_POLICYSSH_MCP_APPROVAL_TTL 配置(见环境变量)。

日志

所有操作都会写入日志文件,默认位置为 <data_dir>/ssh-mcp.log(默认 ~/.ssh-mcp/ssh-mcp.log),包括:

  • CLI 操作:添加/删除凭据(不记录密码)、查询凭据、审批/拒绝/查看待审批命令
  • MCP 工具调用:每个工具的入参(会话 ID、命令、路径等)与成功/失败结果
  • 安全闸门:硬拦截、审批生成/批准/放行执行
  • HTTP 请求:方法、路径、状态码、耗时

日志路径与级别通过 SSH_MCP_LOG_FILESSH_MCP_LOG_LEVEL 配置(见环境变量)。

日志文件超过 10MB 会自动轮转为 ssh-mcp.log.1。日志中不包含任何密码或主密码;时间戳为 UTC。日志初始化失败(如文件不可写)只输出警告,不会阻断正常操作。每一行都带进程 ID([pid=12345]),多个 Codex 实例各拉起一个 ssh-mcp 时,可以区分是哪条进程写的。

接入主流 MCP 客户端

以下配置均以 Windows 上的 ssh-mcp.exe 为例。请把 <你的路径> 替换为你实际的绝对路径:

<你的路径>\ssh-mcp.exe

两种接入方式:

  • stdio(推荐):由 MCP 客户端拉起进程。客户端需要给子进程设置环境变量 SSH_MCP_MASTER_PASSWORD(解锁加密凭据库)。
  • HTTP:先手动启动服务(ssh-mcp serve --http 127.0.0.1:8787),客户端只填 URL。此方式客户端配置中不需要主密码。

Codex

命令行添加(stdio):

codex mcp add ssh-mcp --env SSH_MCP_MASTER_PASSWORD=你的主密码 -- <你的路径>\ssh-mcp.exe

或直接编辑 ~/.codex/config.toml

[mcp_servers.ssh-mcp]
command = "<你的路径>\\ssh-mcp.exe"
enabled = true

[mcp_servers.ssh-mcp.env]
SSH_MCP_MASTER_PASSWORD = "${SSH_MCP_MASTER_PASSWORD}"

使用 ${SSH_MCP_MASTER_PASSWORD} 时,需先在系统中设置该环境变量(如 Windows 的「系统属性 → 环境变量」),再启动 Codex;否则会按字面值传递导致解锁失败。

HTTP 方式(token 以请求头形式发送;部分 Codex 版本不接受直接写 bearer token,可以用字面请求头或引用环境变量两种方式):

codex mcp add ssh-mcp --url http://127.0.0.1:8787/mcp --bearer-token-env-var SSH_MCP_HTTP_TOKEN
[mcp_servers.ssh-mcp]
url = "http://127.0.0.1:8787/mcp"
enabled = true
startup_timeout_sec = 3600
tool_timeout_sec = 3600
http_headers = { Authorization = "Bearer 你的token" }   # 字面请求头,或:
# bearer_token_env_var = "SSH_MCP_HTTP_TOKEN"

配置后可运行 codex mcp list 确认,重启 Codex 后生效。参考官方文档:https://developers.openai.com/codex/mcp

让 Codex 在调用 ssh-mcp 工具前询问codex mcp add 暂无审批参数,需手动编辑 ~/.codex/config.toml):

[mcp_servers.ssh-mcp]
command = "<你的路径>\\ssh-mcp.exe"
enabled = true
default_tools_approval_mode = "prompt"   # auto | prompt | approve

# 也可以只对个别高风险工具强制询问
[mcp_servers.ssh-mcp.tools.ssh_exec]
approval_mode = "prompt"
[mcp_servers.ssh-mcp.tools.ssh_shell_write]
approval_mode = "prompt"

Claude Code

命令行添加(stdio):

claude mcp add --transport stdio --scope user ssh-mcp --env SSH_MCP_MASTER_PASSWORD=你的主密码 -- <你的路径>\ssh-mcp.exe

或项目级 .mcp.json(放在项目根目录,跟随仓库共享):

{
  "mcpServers": {
    "ssh-mcp": {
      "type": "stdio",
      "command": "<你的路径>\\ssh-mcp.exe",
      "env": {
        "SSH_MCP_MASTER_PASSWORD": "${SSH_MCP_MASTER_PASSWORD}"
      }
    }
  }
}

同样,${SSH_MCP_MASTER_PASSWORD} 需要先在本机设置好环境变量再启动 Claude Code,否则会原样传字面值导致解锁失败。

HTTP 方式:

claude mcp add --transport http ssh-mcp http://127.0.0.1:8787/mcp

在 Claude Code 中运行 /mcp 查看连接状态。参考官方文档:https://code.claude.com/docs/en/mcp

让 Claude Code 在调用 ssh-mcp 工具前询问(项目级 .claude/settings.json):

{
  "permissions": {
    "ask": [
      "MCPTool(ssh-mcp:*)"
    ]
  }
}

也可以只针对指定工具询问,如 "MCPTool(ssh-mcp:ssh_exec)""MCPTool(ssh-mcp:ssh_shell_write)";放到 deny 列表则直接禁止。

Cursor

项目级 .cursor/mcp.json(或全局 ~/.cursor/mcp.json):

{
  "mcpServers": {
    "ssh-mcp": {
      "type": "stdio",
      "command": "<你的路径>\\ssh-mcp.exe",
      "env": {
        "SSH_MCP_MASTER_PASSWORD": "你的主密码"
      }
    }
  }
}

也可以走界面:Settings → MCP → Add new MCP server → 填入命令、参数与环境变量。参考官方文档:https://cursor.com/help/customization/mcp

VS Code(GitHub Copilot / Agent 模式)

工作区 .vscode/mcp.json

{
  "servers": {
    "ssh-mcp": {
      "type": "stdio",
      "command": "<你的路径>\\ssh-mcp.exe",
      "env": {
        "SSH_MCP_MASTER_PASSWORD": "${input:ssh-mcp-master-password}"
      }
    }
  },
  "inputs": [
    {
      "type": "promptString",
      "id": "ssh-mcp-master-password",
      "description": "ssh-mcp 主密码",
      "password": true
    }
  ]
}

使用 ${input:...} 变量时 VS Code 会在首次启动时安全提示输入主密码,避免明文写入配置。HTTP 方式改为:

{
  "servers": {
    "ssh-mcp": {
      "type": "http",
      "url": "http://127.0.0.1:8787/mcp"
    }
  }
}

参考官方文档:https://code.visualstudio.com/docs/copilot/customization/mcp-servers

Claude Desktop

编辑 %APPDATA%\Claude\claude_desktop_config.json(Windows):

{
  "mcpServers": {
    "ssh-mcp": {
      "command": "<你的路径>\\ssh-mcp.exe",
      "env": {
        "SSH_MCP_MASTER_PASSWORD": "你的主密码"
      }
    }
  }
}

修改后完全退出并重启 Claude Desktop。

Cherry Studio

设置 → MCP 服务器 → 添加服务器:

  • 名称:ssh-mcp
  • 命令:<你的路径>\ssh-mcp.exe
  • 环境变量:SSH_MCP_MASTER_PASSWORD=你的主密码

也可以选择 Streamable HTTP 类型并填写 http://127.0.0.1:8787/mcp(无需主密码)。

通用注意事项

  • 修改配置后需要重启客户端或重新打开会话,工具列表才会加载。
  • stdio 模式下客户端配置中的主密码为明文(或引用环境变量),请勿把含密码的配置提交到公开仓库;.mcp.json 若提交建议用 ${VAR} 形式。
  • Windows 路径在 JSON/TOML 中反斜杠需写成 \\,也可以统一使用正斜杠 <你的路径>/ssh-mcp.exe
  • 客户端审批(如 Codex 的 approval_mode = "prompt"、Claude Code 的 permissions.ask)只约束单个客户端;服务器内置的命令安全闸门对所有客户端生效,是最终的防线。

测试

cargo test

包含凭据库加解密单元测试,以及 stdio 与 HTTP 两种传输的 MCP 握手集成测试。

相关 MCP 服务