Files
oc_session/README.md
T
ypshidifu 35513f1cdf wsl-round-mcp:修复代理劫持导致的 502 + 输入嗅探增强
- 两个脚本的 HTTP 请求改为 ProxyHandler({}) 强制绕过系统代理:
  环境有 HTTP_PROXY/HTTPS_PROXY 时,urllib 会把 localhost 请求也丢给代理,
  结果代理回 502,看起来像 OC 挂了其实是被劫走(本轮实测复现)
  需要走代理时用 MCPCTL_USE_PROXY=1 / OCSKILL_USE_PROXY=1 显式开启
- ocskill 输入嗅探增强:未知后缀按魔数/内容识别 .b64、zip、markdown
- frontmatter 支持 YAML 块标量(description: > |),中文折行不补空格
- 新增子仓库自身 .gitignore(父仓库的 ignore 对子仓库无效,__pycache__ 曾被误提交)
- README 补充代理 502 与 401 随机密码的排查说明
2026-09-23 12:24:31 +08:00

149 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# wsl-round-mcp — 本机 ⇄ WSL OpenCode 互通工具
打通**本机 OpenCode** 与 **WSL 里的 OpenCode**:skill 列表互查、skill 一键推送、MCP 配置对调开关。
全部零第三方依赖,只要装了 Python 3 就能跑。
---
## 一、双击就能用(小白版)
把整个 `wsl-round-mcp` 文件夹拷到任意位置,双击对应的 bat:
| 文件 | 作用 |
| --- | --- |
| `skill-list.bat` | 连接 WSL 的 OC,列出它当前有哪些 skill |
| `skill-push.bat` | 会让你粘贴一个 skill 路径(zip / 目录 / SKILL.md / base64),校验格式后写进 WSL 的 skill 目录 |
| `skill-pull.bat` | 会让你输入 skill 名,把它从 WSL 拷回本机 `skills-backup\` |
| `mcp-status.bat` | 查看 MCP 当前是开是关、第1行是什么模式 |
| `mcp-on.bat` | 把配置对调为「含 MCP」并热重载 |
| `mcp-off.bat` | 把配置对调为「安静版(无 MCP)」并热重载 |
> bat 内部会自动 `chcp 65001`,中文输出不会乱码。
> 没装 Python 或没加进 PATH,会提示 `Python not found in PATH`。
---
## 二、命令行用法
### 1. `ocskill.py` — skill 互通
```bash
# 列出 WSL OC 的 skill(API 连不上会自动退回目录扫描)
python ocskill.py list
# 推送:压缩包(自动解压)
python ocskill.py push .\my-skill.zip
# 推送:整个 skill 目录
python ocskill.py push .\my-skill
# 推送:单个 SKILL.md(会自动包成以 name 命名的目录)
python ocskill.py push .\SKILL.md
# 推送:base64 内容
python ocskill.py push <一长串base64> --base64
# 只校验格式、不写入
python ocskill.py push .\my-skill --dry-run
# 覆盖同名 skill(先自动备份成 .bak-时间戳)
python ocskill.py push .\my-skill --force
# 反向:把 WSL 里的 skill 拷回本机
python ocskill.py pull java-expert --out .\skills-backup
# 看两端目录与 API 连接状态
python ocskill.py dirs
```
**push 的完整流程**(对应「先解码 → 确认标准 skill 格式 → 传入 skill 目录」):
1. **解码归一**:zip 就解压(带 zip-slip 目录穿越防护),目录原样用,
单个 `.md` 会包成目录,base64 字符串先解成文件再判断是 zip 还是 md。
2. **定位 `SKILL.md`**:允许压缩包里多套一层父目录(最深 3 层)。
3. **校验标准 skill 格式**,四项全过才算通过:
- 找得到 `SKILL.md`
- 文件以 `---` 开头,有 YAML frontmatter
- frontmatter 里有 `name`,且只含 `字母/数字/._-`
- frontmatter 里有 `description`(大模型靠它决定何时调用)
4. **写入** `\\wsl.localhost\<发行版>\root\.config\opencode\skills\<name>\`,
OC 会 watch 这个目录(约 100ms 去抖后自动 rescan 并推 `skill.reload`),**不用重启**。
常用参数:
| 参数 | 默认 | 说明 |
| --- | --- | --- |
| `--distro` | `Ubuntu-24.04` | WSL 发行版名 |
| `--url` | 自动探测 | 显式指定 OC 地址,如 `http://localhost:4096` |
| `--port` | `4096` | OC 端口(等价于环境变量 `OC_PORT`) |
| `--password` | 自动读 | OC 的 `server.password`,先试 Bearer、401 再试 Basic |
### 2. `mcpctl.py` — MCP 配置对调开关
```bash
python mcpctl.py status # 看状态(只读)
python mcpctl.py on # 对调成含 MCP + 热重载
python mcpctl.py off # 对调成安静版 + 热重载
python mcpctl.py mode # 看第1行
python mcpctl.py mode 手动 # 改第1行(自动/手动/关闭,或 auto/manual/off)
python mcpctl.py status --target wsl # 操作 WSL 那一份配置
python mcpctl.py off --no-reload # 只对调文件,不调用重载
```
它读的正是 `mcpcfg.txt` 那三行:
```
自动 ← 第1行:模式
C:\...\opencode.json.1 ← 第2行:含 MCP 的原始配置
C:\...\opencode.json ← 第3行:删了 MCP 的安静配置
```
**状态判定只看活文件**(文件名为 `opencode.json` 的那份)里 `mcp.servers` 是否非空,
所以对调之后第2/3行的身份怎么漂移都不影响判断——这与 TUI 插件、server 插件完全一致。
模式语义(三个入口共用同一套规则):
| 模式 | `/mcpon` `/mcpoff` | 大模型(server 插件) | 本工具 `mcpctl.py` |
| --- | --- | --- | --- |
| 自动 | 可用(视为手动切换一次) | 可用 | 可用 |
| 手动 | **仅此可用** | 拒绝 | 可用(等价于用户输入命令) |
| 关闭 | 不注册 | 拒绝 | 拒绝(可用 `--ignore-mode` 强行) |
热重载打的是 `POST /api/location/reload`,会重建 location 并重读磁盘配置,MCP 立即生效;
失败时配置文件已经对调完成,重启 OC 一样生效。
---
## 三、连不上 OC 怎么办
**先看这一条(最常见):有 HTTP 代理时会假报 502。**
两个脚本已默认**绕过系统代理**直连(`ProxyHandler({})`)。
如果环境里有 `HTTP_PROXY` / `HTTPS_PROXY`,`urllib` 默认会把 `localhost` 请求也丢给代理,
结果是**代理回 502**,看起来像 OC 挂了、其实是被劫走了。
确实需要走代理时,设环境变量再运行:`MCPCTL_USE_PROXY=1` / `OCSKILL_USE_PROXY=1`。
其余排查:
1. 确认 WSL 里的 OC 起了:`opencode serve --port 4096`
2. 端口不对就加 `--port`,或设环境变量 `OC_PORT`
3. 提示 `401 WWW-Authenticate: Basic realm="Secure Area"` → OC 启用了服务密码。
用 `--password` 传值(默认自动从 `opencode.json` 的 `server.password` 读;
若该字段为空但 OC 仍要 401,说明它用了随机密码,需启动时设 `OPENCODE_SERVER_PASSWORD`)
4. `localhost` 不通 → 工具会自动 `wsl hostname -I` 取 WSL 真实 IP 再试
5. 全都失败 → `list` 会自动降级为**直接扫目录**,照样能看到 skill 列表
---
## 四、和另外两个仓库的关系
本目录是独立 git 仓库,**分支名 = 文件夹名** `wsl-round-mcp`,远程与主仓库共用同一个根:
| 文件夹 | 分支 | 内容 |
| --- | --- | --- |
| `oc_session/`(主仓库) | `main` | TUI 插件 `oc-session-all`(`/sessions-all`、`/mcpon`、`/mcpoff`) |
| `oc_session/ai-mcp/` | `ai-mcp` | server 插件 `ai-mcp.ts`,给大模型用的 `mcp_switch` 工具 |
| `oc_session/wsl-round-mcp/` | `wsl-round-mcp` | 本目录:skill 互通 CLI + MCP 命令行开关 |
远程:`https://git.ypshidifu.cn/youpaishidifu/oc_session.git`