Skip to main content
Glama
Dorimui
by Dorimui
README.md
# remotessh-mcp

[![npm version](https://img.shields.io/npm/v/remotessh-mcp.svg)](https://www.npmjs.com/package/remotessh-mcp)
[![license](https://img.shields.io/npm/l/remotessh-mcp.svg)](LICENSE)
[![node](https://img.shields.io/node/v/remotessh-mcp.svg)](package.json)

通过 stdio 为 AI CLI 提供本地命令、远程 SSH、交互终端、文件读写、源码搜索和大输出分页。

## npx 一键接入

要求 Node.js 20+。无需克隆仓库或全局安装,客户端通过 `npx -y remotessh-mcp@latest` 自动下载并启动 MCP Server。

### [Codex CLI](https://developers.openai.com/codex/mcp/)

```powershell
codex mcp add remotessh -- npx -y remotessh-mcp@latest
codex mcp list
```

Codex 默认只等待 MCP Server 启动 10 秒。首次冷安装或网络较慢时,在 `~/.codex/config.toml` 的对应配置中加入:

```toml
[mcp_servers.remotessh]
startup_timeout_sec = 180
```

### [Claude Code](https://code.claude.com/docs/en/mcp)

`--scope user` 使该 MCP 对当前用户的所有项目可用:

```powershell
claude mcp add --scope user --transport stdio remotessh -- npx -y remotessh-mcp@latest
claude mcp get remotessh
```

### [Gemini CLI](https://geminicli.com/docs/tools/mcp-server/)

Gemini CLI 的 timeout 单位是毫秒,这里为首次安装保留 180 秒:

```powershell
gemini mcp add --scope user --timeout 180000 remotessh npx -y remotessh-mcp@latest
gemini mcp list
```

### [OpenCode](https://opencode.ai/docs/mcp-servers/)

在全局或项目 `opencode.json` 中加入:

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "remotessh": {
      "type": "local",
      "command": ["npx", "-y", "remotessh-mcp@latest"],
      "enabled": true,
      "timeout": 180000
    }
  }
}
```

然后执行 `opencode mcp list` 检查连接状态。

### 通用 MCP 客户端

支持 stdio MCP 的客户端通常可以使用以下配置:

```json
{
  "mcpServers": {
    "remotessh": {
      "command": "npx",
      "args": ["-y", "remotessh-mcp@latest"]
    }
  }
}
```

如需可复现安装,将 `latest` 换成固定版本,例如 `remotessh-mcp@0.7.1`。

第一次启动会创建 `~/.remotessh-mcp/config.json`;Windows 对应 `%USERPROFILE%\.remotessh-mcp\config.json`。在其中添加自己的 SSH profile 后即可使用远端工具。

> [!WARNING]
> 本项目可以执行任意本地命令和 SSH 远程命令,也可以读写文件。只应在可信的 MCP 客户端和主机上使用。高危确认是防误操作机制,不是权限隔离或安全沙箱。

## 项目定位

它主要解决以下问题:

- 在 Windows 上稳定执行多行 PowerShell、CMD 或 Bash 脚本,减少转义和编码问题。
- 通过系统 OpenSSH 执行远端脚本,并统一处理工作目录、超时和进程终止。
- 用持久 PTY 会话完成需要提示符、持续输出或多轮输入的任务。
- 直接读写本地和远端文件,避免为简单文件操作反复拼接 Shell 命令。
- 限制返回给模型的输出大小,并保留游标供后续分页读取或搜索。
- 对常见高危命令进行二次确认,并记录经过基础脱敏的本地审计日志。

## 功能概览

| 能力 | 说明 |
| --- | --- |
| 本地执行 | `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` 支持。

## 从源码运行

克隆仓库后,在项目根目录执行:

```powershell
npm ci
npm run build
```

构建入口位于 `dist/index.js`。启动 MCP Server:

```powershell
npm start
```

stdio MCP Server 正常运行时不会显示交互界面,而是等待 MCP 客户端通过标准输入输出通信。

## 手动接入 MCP 客户端

路径必须指向本机实际生成的 `dist/index.js`,并建议使用绝对路径。

Codex 配置示例:

```toml
[mcp_servers.remotessh]
type = "stdio"
command = "node"
args = ["D:/path/to/remotessh-mcp/dist/index.js"]
enabled = true
startup_timeout_sec = 30
```

使用 JSON 配置的 MCP 客户端可参考:

```json
{
  "mcpServers": {
    "remotessh": {
      "command": "node",
      "args": ["D:/path/to/remotessh-mcp/dist/index.js"]
    }
  }
}
```

修改源码后需要重新执行 `npm run build`,并重启 MCP 客户端,使其加载新的 `dist/index.js`。

## 配置远端主机

首次启动时会自动创建运行目录和空配置:

```text
Windows: %USERPROFILE%\.remotessh-mcp\config.json
Linux/macOS: ~/.remotessh-mcp/config.json
```

配置示例:

```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` 修改运行目录:

```powershell
$env:REMOTESSH_MCP_HOME = "D:\mcp-data\remotessh"
```

## 常用示例

### 本地脚本

`sbash` 默认使用无 profile 的 PowerShell 7 和 UTF-8 临时脚本:

```json
{
  "script": "rg -n \"TODO\" src",
  "shell": "pwsh",
  "cwd": "D:\\work\\project"
}
```

多行 Python 或容易受 Shell 转义影响的代码使用 `python_exec`:

```json
{
  "code": "from pathlib import Path\nprint(len(list(Path('.').rglob('*.ts'))))",
  "cwd": "D:\\work\\project",
  "useUv": true
}
```

### 远端一次性命令

```json
{
  "remote": "dev-server",
  "cwd": "/home/developer/project",
  "script": "git status --short && npm run build",
  "timeoutSec": 120
}
```

`remote_exec` 适合短时、非交互脚本。它会验证 `cwd`,并默认在超时后尝试终止远端脚本进程组。需要提示符、多轮输入或持续状态时,应改用 terminal 工具。

环境变量分为两类:

- `env`:传给远端 shell。
- `sshEnv`:只传给本地 `ssh` 进程。

### 交互终端

先打开终端:

```json
{
  "remote": "dev-server",
  "cwd": "/home/developer/project"
}
```

然后使用返回的 `terminalId` 写入命令并等待:

```json
{
  "terminalId": "TERMINAL_ID",
  "input": "npm run build",
  "completion": "auto",
  "timeoutSec": 60
}
```

不再使用的终端应调用 `terminal_close`。对于持续运行的服务,可使用 `terminal_write` 后分次调用 `terminal_read`。

### 本地文件

```json
{
  "path": "D:\\work\\project\\README.md",
  "offset": 0,
  "maxBytes": 12000,
  "format": "text"
}
```

`file_read` 支持 `text`、`hex` 和 `base64`。`offset` 与 `nextOffset` 始终表示原文件的字节位置;文本分页会保持完整 UTF-8 字符边界。

### 远端文件

读取文件:

```json
{
  "remote": "dev-server",
  "remotePath": "/home/developer/project/README.md",
  "format": "text",
  "maxBytes": 12000
}
```

精确替换:

```json
{
  "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`。

### 远端源码搜索

```json
{
  "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`。继续读取:

```json
{
  "cursor": "NEXT_CURSOR",
  "maxBytes": 12000,
  "maxLines": 200
}
```

在保留的输出中搜索:

```json
{
  "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`。

## 安全与审计

审计日志默认位于:

```text
Windows: %USERPROFILE%\.remotessh-mcp\audit.jsonl
Linux/macOS: ~/.remotessh-mcp/audit.jsonl
```

日志包含工具名、本地或远端类型、profile、工作目录、有限长度的命令摘要、退出码、耗时和风险等级。常见的 token、password、secret、API key、Authorization header 和 URL 凭据会做基础脱敏,但不能保证识别所有自定义敏感格式。

常见高危操作会在第一次调用时停止执行,并返回一个 8 位 `sure` 验证码。获得用户明确授权后,使用完全相同的工具和关键参数重试,并添加验证码:

```json
{
  "script": "HIGH_RISK_COMMAND",
  "sure": "12345678"
}
```

验证码具备以下约束:

- 仅可使用一次,有效期 10 分钟。
- 与工具名和完整关键参数的 SHA-256 指纹绑定。
- 修改命令、路径、目标远端、环境变量或写入内容后失效。
- challenge 中不保存敏感参数原文。

内置规则主要覆盖递归强制删除、格式化文件系统、向块设备写入、关机或重启、停止系统服务、清空防火墙规则、强制删除容器等常见高危命令。规则无法识别所有危险写法,因此在运行 MCP 客户端时仍应遵循最小权限原则:

- 使用权限受限的本地账号和远端 SSH 账号。
- 不要用 root 作为日常 profile。
- 不要关闭 SSH 主机密钥校验。
- 将配置目录和私钥限制为当前用户可读。
- 定期检查 `audit.jsonl`,并按需要缩短保留周期或清理日志。
- 不要把 MCP stdio 转发到不可信网络或多用户服务。

## 项目结构

```text
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                   审计日志
```

## 构建检查

公开源码包含的基础检查命令:

```powershell
npm run typecheck
npm run build
npm pack --dry-run
```

## 许可证

本项目使用 [Apache License 2.0](LICENSE)。