Skip to main content
Glama
README.md
# wsl-bridge-mcp

一个 MCP 服务器,让 Windows 侧的 AI 编程代理(**Claude Code、Codex、OpenCode**)可以像操作本地环境一样操作 WSL 发行版:读写/编辑文件、执行命令、管理长驻进程、流式查看日志、搜索文件内容——全部由运行在 Windows 上的代理完成。

**WSL 内部零安装。** 只依赖系统自带的 `wsl.exe` 和 Windows 对 WSL 文件系统的 UNC 访问视图。

## 工作原理

双通道设计兼顾低延迟,同时绕开常见的 WSL 桥接坑:

```
Agent(Windows,MCP 客户端)──stdio──▶ wsl-bridge-mcp(Windows,TS/Node)
                                           │
                           ┌───────────────┴────────────────┐
                           ▼                                 ▼
                 文件通道(UNC)                    执行通道(常驻 shell)
                 \\wsl.localhost\<distro>\…       wsl.exe -d <distro> -- stdbuf -o0 bash
                 Node fs,二进制安全               每个发行版一个,哨兵帧协议
                           │                                 │
                           └───────── 路径转换 ──────────────┘
                                        + 护栏 + 审计日志
```

- **文件操作** 走 `\\wsl.localhost\<distro>\…`(9P 协议),通过 Node `fs` 完成——不派生 `wsl.exe`,二进制安全,速度快。
- **命令执行 / 搜索 / 进程管理** 走每个发行版一个的长驻 `wsl.exe … bash` 进程,使用哨兵标记帧协议——摊薄了约 50–150ms 的派生开销,并提供真正的管道用于流式输出。
- **路径转换** 集中处理并带缓存;代理侧统一使用 POSIX 路径。
- **护栏** 拦截灾难性命令(`rm -rf /`、`dd of=/dev/sd*`、fork 炸弹等),支持可选确认;另提供可选的路径沙箱和完整审计日志。

## 安装

```bash
npm install -g wsl-bridge-mcp
# 或者不安装直接使用:
npx wsl-bridge-mcp
```

要求 Node ≥ 20 和一个 WSL2 发行版(`\\wsl.localhost` 推荐在 Windows 11 上使用)。

## 配置

配置是可选的。只要设置了默认发行版,默认值即可开箱即用。
优先级:环境变量(`WSL_BRIDGE_*`)> `.wsl-bridge.json`(从当前工作目录向上查找)> 默认值。

将 `.wsl-bridge.example.json` 复制为 `.wsl-bridge.json`(或设置环境变量):

| 配置项 | 环境变量 | 默认值 | 说明 |
|-----|---------|---------|---------|
| `defaultDistro` | `WSL_BRIDGE_DISTRO` | — | 工具未指定 `distro` 时使用的发行版 |
| `commandTimeoutMs` | `WSL_BRIDGE_COMMAND_TIMEOUT_MS` | 30000 | `run_command` 超时 |
| `scriptTimeoutMs` | `WSL_BRIDGE_SCRIPT_TIMEOUT_MS` | 120000 | 长耗时操作(搜索、系统信息)超时 |
| `maxOutputBytes` | `WSL_BRIDGE_MAX_OUTPUT_BYTES` | 1048576 | 输出截断上限 |
| `guardrailMode` | `WSL_BRIDGE_GUARDRAIL_MODE` | `block-and-confirm` | `block-and-confirm` / `block` / `off` |
| `sandboxDirs` | `WSL_BRIDGE_SANDBOX_DIRS` | `[]` | POSIX 路径;为空 = 整个发行版 |
| `logDir` | `WSL_BRIDGE_LOG_DIR` | `%APPDATA%\wsl-bridge-mcp` | 审计日志目录(Windows 侧) |
| `prewarmShells` | `WSL_BRIDGE_PREWARM_SHELLS` | `true` | 启动时预派生默认发行版的 shell(消除首条命令的延迟) |

`sandboxDirs` 在环境变量中使用 `;` 分隔。

## 连接你的代理

### Claude Code

```bash
claude mcp add wsl-bridge -- node /path/to/wsl-bridge-mcp/dist/server.js
# 或已全局安装 / 通过 npx:
claude mcp add wsl-bridge -- npx wsl-bridge-mcp
```

在服务器配置中通过环境变量设置默认发行版,或在每次调用时传入 `distro`。

### Codex

添加到 Codex 的 MCP 配置(`~/.codex/config.toml` 或等效位置):

```toml
[mcp_servers.wsl-bridge]
command = "npx"
args = ["wsl-bridge-mcp"]
env = { WSL_BRIDGE_DISTRO = "Ubuntu-24.04" }
```

### OpenCode

添加到 OpenCode 的 MCP 配置(例如 `opencode.json`):

```json
{
  "mcp": {
    "wsl-bridge": {
      "type": "local",
      "command": ["npx", "wsl-bridge-mcp"],
      "environment": { "WSL_BRIDGE_DISTRO": "Ubuntu-24.04" }
    }
  }
}
```

## 工具(28 个)

**发现类:** `list_distros`、`get_system_info`、`check_wsl_status`
**路径类:** `translate_path`、`resolve_path`
**文件类(UNC):** `read_file`、`read_multiple_files`、`write_file`、`edit_file`、`list_directory`、`get_file_info`、`create_directory`、`move_file`、`delete_path`
**执行类:** `run_command`、`set_cwd`
**进程与日志:** `start_process`、`get_process_status`、`read_process_output`、`list_processes`、`stop_process`
**搜索类:** `search_files`、`search_content`
**辅助类:** `list_ports`、`get_env`、`set_env`、`diagnose`、`query_audit_log`

## 性能、流式输出与保真度

部分工具参数可解锁更低延迟、真正的流式输出和可校验的二进制传输:

**延迟**
- **`/mnt/<盘符>` 直连访问** —— 对 `/mnt/c/...` 等 drvfs 路径的文件操作会通过 Node `fs` 直接解析到 Windows 盘符(`C:\...`),完全跳过 WSL/9P。其他路径(`/home`、`/tmp`、`/mnt/wsl` 等)仍走 UNC。适用时 `translate_path` 会报告直连的 `windowsPath`。盘符只探测一次并缓存。
- **`list_directory` 分页** —— 传入 `offset`/`limit` 可对大目录分页遍历,只对返回的当前页做 `stat`。响应中包含 `total`、`offset`、`limit`、`hasMore`。
- **Shell 预热** —— `prewarmShells: true`(默认)会在启动时派生默认发行版的 shell,让第一条命令不必承担 `wsl.exe` 的派生开销。

**流式输出与 stderr**
- **`run_command` / `start_process` 的 `separateStderr: true`** —— 单独捕获 stderr,而不是合并进 stdout。此时 `run_command` 返回独立的 `stdout` 和 `stderr`;`start_process` 会写入一个 `.err` 文件,可通过 `read_process_output` 加 `which: "stderr"` 读取。
- **`read_process_output` 的 `stream: true`** —— 在 follow 期间,将每个新数据块以 `notifications/message` 推送(客户端传了 `progressToken` 时还会推送 `notifications/progress`),然后返回最终偏移量。无需轮询即可实时收到日志;无论客户端是否忽略通知,最终负载都会完整返回,不会丢数据。
- **内存安全读取** —— `read_file` 通过文件描述符只读取所需字节(利用 `offset`/`limit`/`maxBytes`),超大文件不会整体加载进内存。

**二进制保真**
- **`read_file` / `write_file` 的 `sha256: true`** —— 返回(读/写的)字节的 `sha256`。写入后读取并比对哈希,即可验证字节级精确往返。`write_file` 还会回显 `mimeType`。

## 安全性

- **护栏** 会扫描每个 `run_command` / `start_process` 命令中的危险模式。灾难性命令(`rm -rf /`、块设备写入、fork 炸弹、`mkfs`)被硬性拦截;有风险但可逆的命令(`shutdown`、`chmod -R /`)需要 `confirm=true`。可通过 `guardrailMode` 调整。`rm` 的目标会被规范化(去引号、去尾部斜杠),因此带引号的根目录 / `$HOME` / `~/` 写法也能被捕获。
- **路径沙箱**(`sandboxDirs`):设置后,修改类文件操作被限制在允许列表内,并会在 Linux 侧解析符号链接(`realpath -m`),因此沙箱内的符号链接无法逃逸。(符号链接解析刻意放在 Linux 侧:WSL 9P 会把符号链接呈现为 Windows 上的不透明 reparse 点,`fs.realpath` 无法穿透。)默认关闭。
- **Shell 安全输入**:环境变量名(`run_command`/`start_process` 的 env、`set_env`/`get_env` 的名称)必须是合法的 POSIX 标识符并被 shell 引用;`stop_process` 只接受大写信号枚举(`TERM`、`KILL`、`INT` 等),并如实报告 `sent`/`exitCode`。搜索模式使用单引号包裹,因此 `$`、反引号和引号会被字面匹配,绝不会被执行。
- **配置校验**:`.wsl-bridge.json` 的值按配置项逐项校验(zod);无效条目会向 stderr 告警并回退到默认值,而不是崩溃或静默异常。超时环境变量被限制为 `>= 0`——`0` 表示显式禁用超时。
- **审计日志**:每次工具调用(工具名、参数摘要、状态、耗时、发行版)都会追加到 `logDir` 下的 `audit.log`。可通过 `query_audit_log` 查询。
- **输出上限**:大输出会被截断到 `maxOutputBytes`,并附带提示。

## 故障排查

- **运行命令时出现 `Wsl/Service/E_UNEXPECTED`**:WSL 服务状态异常,尽管发行版显示为 *Running* 且 UNC 正常。用 `wsl --shutdown` 修复(会重启所有发行版——关闭 WSL 中正在运行的进程),然后重试。此状态下文件通道工具仍然可用。
- **`No distro specified`**:设置 `WSL_BRIDGE_DISTRO` 或 `defaultDistro`,或在每次调用时传 `distro`。运行 `list_distros` 查看发行版名称。
- **UNC 不可达**:确保发行版已启动(`wsl -d <distro> echo ok`)。优先使用 `\\wsl.localhost`(Win11+);`\\wsl$` 是备选方案。
- 运行 `diagnose` 工具对 UNC、shell 和权限做一次通过/失败的全项检查。

## 开发

```bash
npm install
npm run build        # tsc -> dist/
npm run typecheck    # 类型检查 src + tests
npm test             # 仅单元测试(无需 WSL)
npm run test:integration   # 针对真实 WSL 发行版的集成测试
npm run test:smoke   # 构建并在 stdio 上冒烟测试服务器
npm run test:e2e     # 构建并在 stdio 上跑完整 e2e 套件
npm run dev          # tsx watch
```

设置 `WSL_BRIDGE_DISTRO=<你的发行版>`,可让 e2e/smoke/integration 脚本针对非默认发行版运行。

TDQS

A3.6/5.0

Scored across 28 tools

Disambiguation5/5

Each tool targets a distinct resource and action: file operations, process management, environment variables, and system queries are cleanly separated. Even similar tools like run_command vs start_process or read_file vs read_multiple_files have clear behavioral differences. No two tools appear to do the same thing.

Naming Consistency5/5

Tool names consistently follow a verb_noun pattern in snake_case, such as write_file, list_directory, get_system_info, and stop_process. Minor exceptions like diagnose or check_wsl_status still fit the general style. The naming is predictable and makes it easy to infer what each tool does.

Tool Count2/5

With 28 tools, this exceeds the 25-tool threshold considered 'too many', though the broad scope of a WSL bridge justifies many of them. Still, consolidation is possible, e.g., merging get_file_info into list_directory or having diagnose call other tools. The set feels heavy even if each tool is individually useful.

Completeness4/5

The tool surface covers a comprehensive set of WSL operations: file CRUD and search, process execution and management, environment controls, system information, path translation, and an audit log. A minor gap is the lack of distro lifecycle management (start/stop/shutdown), but that is not essential for typical bridging tasks. Core workflows are fully covered with no dead ends.

Maintenance

ActivitySlowing
ResponsivenessNo issues