remotessh-mcp
v0.7.0
Published
A local and remote command execution MCP server with safer shell wrappers, remote profiles, terminal sessions, paged output, and audit logging.
Downloads
169
Maintainers
Readme
remotessh-mcp
remotessh-mcp 是一个通过 stdio 运行的 MCP Server,为 Codex 等 AI 客户端提供本地命令、远程 SSH、交互终端、文件读写、源码搜索和大输出分页能力。
它主要解决以下问题:
- 在 Windows 上稳定执行多行 PowerShell、CMD 或 Bash 脚本,减少转义和编码问题。
- 通过系统 OpenSSH 执行远端脚本,并统一处理工作目录、超时和进程终止。
- 用持久 PTY 会话完成需要提示符、持续输出或多轮输入的任务。
- 直接读写本地和远端文件,避免为简单文件操作反复拼接 Shell 命令。
- 限制返回给模型的输出大小,并保留游标供后续分页读取或搜索。
- 对常见高危命令进行二次确认,并记录经过基础脱敏的本地审计日志。
[!WARNING] 本项目可以执行任意本地命令和 SSH 远程命令,也可以读写文件。只应在你信任的 MCP 客户端和主机上使用。高危确认是防误操作机制,不是权限隔离或安全沙箱。
功能概览
| 能力 | 说明 |
| --- | --- |
| 本地执行 | sbash、python_exec |
| 远端执行 | remote_exec,支持 profile、远端环境变量、超时和进程组清理 |
| 交互终端 | 本地或远端 PTY 会话,支持读取、写入、等待、停止和关闭 |
| 本地文件 | 文本、Hex、Base64 读取,以及文本或二进制写入 |
| 远端文件 | 读取、写入、上传、下载、精确替换和 unified diff |
| 远端搜索 | 自动使用 rg、git grep 或受限 Python fallback |
| 大输出处理 | 头尾预览、游标分页、按 literal 或安全正则搜索 |
| 操作保护 | 高危命令二次确认、参数绑定验证码、脱敏审计日志 |
环境要求
- Node.js 20 或更高版本。
- npm。
- Windows 推荐 PowerShell 7。
- 使用远端功能时,需要可用的系统
ssh和scp;Windows 上通常来自 OpenSSH Client。 - 远端主机需要 POSIX
sh或bash。 python_exec默认通过uv run python执行;未安装 uv 时可传useUv: false。remote_search推荐远端安装 ripgrep;缺少时会尝试git grep或受限的 Python literal 搜索。
本项目以 Windows 本地环境加 Linux SSH 远端为主要使用场景,同时保留本地 bash 和远端 sh 支持。
一键接入
发布到 npm 后,Codex 用户可以直接注册并启动 MCP Server:
codex mcp add remotessh -- npx -y remotessh-mcp@latest查看是否注册成功:
codex mcp list其他使用 JSON 配置的 MCP 客户端可直接通过 npx 启动:
{
"mcpServers": {
"remotessh": {
"command": "npx",
"args": ["-y", "remotessh-mcp@latest"]
}
}
}如需固定行为并避免自动升级,将 latest 替换为具体版本,例如 [email protected]。
第一次启动后,需要在 ~/.remotessh-mcp/config.json 中配置自己的 SSH profile。Windows 对应路径为 %USERPROFILE%\.remotessh-mcp\config.json。
从源码运行
克隆仓库后,在项目根目录执行:
npm ci
npm run build构建入口位于 dist/index.js。启动 MCP Server:
npm startstdio MCP Server 正常运行时不会显示交互界面,而是等待 MCP 客户端通过标准输入输出通信。
手动接入 MCP 客户端
路径必须指向本机实际生成的 dist/index.js,并建议使用绝对路径。
Codex 配置示例:
[mcp_servers.remotessh]
type = "stdio"
command = "node"
args = ["D:/path/to/remotessh-mcp/dist/index.js"]
enabled = true
startup_timeout_sec = 30使用 JSON 配置的 MCP 客户端可参考:
{
"mcpServers": {
"remotessh": {
"command": "node",
"args": ["D:/path/to/remotessh-mcp/dist/index.js"]
}
}
}修改源码后需要重新执行 npm run build,并重启 MCP 客户端,使其加载新的 dist/index.js。
配置远端主机
首次启动时会自动创建运行目录和空配置:
Windows: %USERPROFILE%\.remotessh-mcp\config.json
Linux/macOS: ~/.remotessh-mcp/config.json配置示例:
{
"activeRemote": "dev-server",
"defaults": {
"maxBytes": 12000,
"maxLines": 200,
"timeoutMs": 30000,
"idleMs": 1000,
"maxCaptureBytes": 8388608,
"maxStoredBytes": 67108864,
"maxStoredOutputs": 128,
"maxTerminals": 12,
"terminalBufferBytes": 512000
},
"remotes": [
{
"name": "dev-server",
"host": "server.example.com",
"user": "developer",
"port": 22,
"identityFile": "C:\\Users\\YOUR_NAME\\.ssh\\id_ed25519",
"defaultCwd": "/home/developer",
"remoteShell": "bash",
"sourceProfile": true,
"extraSshArgs": [],
"uvPathHints": ["~/.local/bin/uv", "uv"],
"tags": ["linux", "development"]
}
]
}主要字段:
| 字段 | 说明 |
| --- | --- |
| activeRemote | 调用时省略 remote 后使用的默认 profile |
| name | profile 名称,在 MCP 工具参数中引用 |
| host | SSH 主机名、IP 或 ~/.ssh/config 中的 Host 别名 |
| user / port | 可选的 SSH 用户和端口 |
| identityFile | 可选的私钥文件路径,不要填写私钥内容 |
| defaultCwd | 远端命令和终端的默认工作目录 |
| remoteShell | bash 或 sh |
| sourceProfile | 执行远端命令前是否加载 shell profile |
| extraSshArgs | 传给系统 ssh 的额外参数 |
| uvPathHints | 远端查找 uv 时使用的候选路径 |
| tags | 自定义 profile 标签 |
SSH 认证由系统 OpenSSH 处理。推荐使用 ssh-agent、~/.ssh/config 或受操作系统权限保护的私钥文件,不要把密码、私钥内容或 token 写入项目目录。
可以通过 REMOTESSH_MCP_HOME 修改运行目录:
$env:REMOTESSH_MCP_HOME = "D:\mcp-data\remotessh"常用示例
本地脚本
sbash 默认使用无 profile 的 PowerShell 7 和 UTF-8 临时脚本:
{
"script": "rg -n \"TODO\" src",
"shell": "pwsh",
"cwd": "D:\\work\\project"
}多行 Python 或容易受 Shell 转义影响的代码使用 python_exec:
{
"code": "from pathlib import Path\nprint(len(list(Path('.').rglob('*.ts'))))",
"cwd": "D:\\work\\project",
"useUv": true
}远端一次性命令
{
"remote": "dev-server",
"cwd": "/home/developer/project",
"script": "git status --short && npm run build",
"timeoutSec": 120
}remote_exec 适合短时、非交互脚本。它会验证 cwd,并默认在超时后尝试终止远端脚本进程组。需要提示符、多轮输入或持续状态时,应改用 terminal 工具。
环境变量分为两类:
env:传给远端 shell。sshEnv:只传给本地ssh进程。
交互终端
先打开终端:
{
"remote": "dev-server",
"cwd": "/home/developer/project"
}然后使用返回的 terminalId 写入命令并等待:
{
"terminalId": "TERMINAL_ID",
"input": "npm run build",
"completion": "auto",
"timeoutSec": 60
}不再使用的终端应调用 terminal_close。对于持续运行的服务,可使用 terminal_write 后分次调用 terminal_read。
本地文件
{
"path": "D:\\work\\project\\README.md",
"offset": 0,
"maxBytes": 12000,
"format": "text"
}file_read 支持 text、hex 和 base64。offset 与 nextOffset 始终表示原文件的字节位置;文本分页会保持完整 UTF-8 字符边界。
远端文件
读取文件:
{
"remote": "dev-server",
"remotePath": "/home/developer/project/README.md",
"format": "text",
"maxBytes": 12000
}精确替换:
{
"remote": "dev-server",
"cwd": "/home/developer/project",
"replacements": [
{
"path": "src/config.ts",
"oldText": "const enabled = false;",
"newText": "const enabled = true;",
"expectedCount": 1
}
],
"checkOnly": true
}精确替换只接受 cwd 内的相对路径,会在写入前统一验证匹配次数,并通过同目录临时文件进行原子替换。先使用 checkOnly: true 预检,确认无误后再去掉该参数。已有可靠 unified diff 时,也可以向同一工具传入 patch。
远端源码搜索
{
"remote": "dev-server",
"cwd": "/home/developer/project",
"pattern": "createServer",
"paths": ["src"],
"globs": ["*.ts"],
"mode": "literal",
"caseSensitive": true,
"contextBefore": 2,
"contextAfter": 4,
"maxMatches": 20
}搜索路径必须位于 cwd 内。默认执行大小写不敏感的 literal 搜索;需要正则时显式使用 mode: "regex"。Python fallback 仅支持 literal,并受扫描文件数和字节数限制。
大输出分页与搜索
命令输出被截断时会返回 outputId 和 nextCursor。继续读取:
{
"cursor": "NEXT_CURSOR",
"maxBytes": 12000,
"maxLines": 200
}在保留的输出中搜索:
{
"outputId": "OUTPUT_ID",
"pattern": "failed",
"mode": "literal",
"maxMatches": 20,
"maxMatchBytes": 500,
"maxTotalBytes": 4000
}outputMode: "smart" 在截断时返回头尾预览,outputMode: "head" 只返回开头。正则搜索会拒绝已知不安全的回溯表达式,并在独立 worker 中设置硬超时。
工具列表
| 分类 | 工具 |
| --- | --- |
| 本地执行 | sbash、python_exec |
| 远端执行 | remote_exec、remote_search |
| Remote profile | remote_list、remote_get_active、remote_set_active |
| 输出处理 | output_read、output_search |
| 本地文件 | file_read、file_write、file_write_hex |
| 远端文件 | remote_file_read、remote_file_write、remote_file_write_hex、remote_file_apply_patch、remote_upload、remote_download |
| 交互终端 | terminal_open_local、terminal_open_remote、terminal_list、terminal_read、terminal_write、terminal_write_wait、terminal_stop、terminal_close |
具体参数、默认值和返回结构以 MCP 客户端读取到的实时 tool schema 为准。
默认值
| 参数 | 默认值 |
| --- | ---: |
| Shell | pwsh |
| 首屏最大字节数 | 12000 |
| 首屏最大行数 | 200 |
| 命令超时 | 30s |
| 终端空闲判定 | 1s |
| 单个 stdout/stderr 最大捕获 | 8 MiB |
| 已保存输出总量 | 64 MiB |
| 已保存输出数量 | 128 |
| 输出保留时间 | 1h |
| 最大终端数量 | 12 |
| 单终端缓冲区 | 512000 bytes |
这些限制用于避免大段日志占满模型上下文或 MCP Server 内存。完整成功且未截断的命令默认不会创建 outputId;需要保留时可显式传 includeOutputId: true。
安全与审计
审计日志默认位于:
Windows: %USERPROFILE%\.remotessh-mcp\audit.jsonl
Linux/macOS: ~/.remotessh-mcp/audit.jsonl日志包含工具名、本地或远端类型、profile、工作目录、有限长度的命令摘要、退出码、耗时和风险等级。常见的 token、password、secret、API key、Authorization header 和 URL 凭据会做基础脱敏,但不能保证识别所有自定义敏感格式。
常见高危操作会在第一次调用时停止执行,并返回一个 8 位 sure 验证码。获得用户明确授权后,使用完全相同的工具和关键参数重试,并添加验证码:
{
"script": "HIGH_RISK_COMMAND",
"sure": "12345678"
}验证码具备以下约束:
- 仅可使用一次,有效期 10 分钟。
- 与工具名和完整关键参数的 SHA-256 指纹绑定。
- 修改命令、路径、目标远端、环境变量或写入内容后失效。
- challenge 中不保存敏感参数原文。
内置规则主要覆盖递归强制删除、格式化文件系统、向块设备写入、关机或重启、停止系统服务、清空防火墙规则、强制删除容器等常见高危命令。规则无法识别所有危险写法,因此在运行 MCP 客户端时仍应遵循最小权限原则:
- 使用权限受限的本地账号和远端 SSH 账号。
- 不要用 root 作为日常 profile。
- 不要关闭 SSH 主机密钥校验。
- 将配置目录和私钥限制为当前用户可读。
- 定期检查
audit.jsonl,并按需要缩短保留周期或清理日志。 - 不要把 MCP stdio 转发到不可信网络或多用户服务。
项目结构
src/index.ts MCP 入口与工具注册
src/tools/ Tool schema 和 handler
src/tool-runtime.ts 异常处理、安全确认和结果整形
src/process.ts 子进程、超时和输出捕获
src/exec.ts 本地与远端脚本执行
src/local-files.ts 本地文件读写
src/remote/ 远端文件、搜索、传输和超时逻辑
src/terminal.ts PTY 生命周期管理
src/output.ts 大输出存储、分页和搜索
src/config.ts 配置读取、校验和保存
src/audit.ts 审计日志构建检查
公开源码包含的基础检查命令:
npm run typecheck
npm run build
npm pack --dry-run许可证
本项目使用 Apache License 2.0。
