「v2 不再自动扫描全局 plugins/ 一级文件」这条没有实测支撑—— 注册与未注册两种情况都被 401 + 「session 才加载」挡住,从未触发 session, 无法区分。改为如实标注「已确认 / 待确认」: - 已确认:session 初始化才加载;v2 对 default 有 schema 校验 - 待确认:一级文件是否自动扫描(按 v2 文档显式注册,属官方支持路径) 另补:plugins 数组只放 server 插件,TUI 插件放 tui.json。
ai-mcp — 给大模型操作的 MCP 开关 server 插件
注册一个 mcp_switch 工具,让大模型自己切换 MCP 的开/关状态
(配置对调 + location.reload 热重载),配合 TUI 插件的 /mcpon /mcpoff 形成闭环。
分支名:ai-mcp | 文件:ai-mcp.ts
一、安装
加载机制(已确认 / 待确认)
- ✅ 已确认:插件在 session 初始化时才加载,不是进程启动时。 只启动
opencode serve而不建 session,看不到任何插件日志 (opencode-btw的报错都带http.span=即为证据)。- ✅ 已确认:OpenCode v2 对 default 导出有 schema 校验,缺则报
Plugin must export a default definition with an id and an effect or setup function., 所以 default 导出必须给。- ⚠️ 本轮未能验证:全局
~/.config/opencode/plugins/下的一级.ts文件 是否会被自动扫描。验证被 401(服务密码)+「session 才加载」双重挡住, 注册与未注册两种情况都没触发 session,无法区分。 v2 官方文档的说法是:只自动发现项目级.opencode/plugins/<name>/index.ts, 全局插件走opencode.json的plugins数组显式加载。 本仓库按文档显式注册(见下),这是官方支持的可靠路径。
把插件复制到全局插件目录:
~/.config/opencode/plugins/ai-mcp.ts # Linux / WSL
C:\Users\<你>\.config\opencode\plugins\ai-mcp.ts # Windows
然后在 opencode.json 里注册(两份配置都要加,否则 mcpoff 对调之后插件会消失):
{
"plugins": [
"opencode-btw",
"file:///root/.config/opencode/plugins/ai-mcp.ts" // WSL/Linux
// Windows 用: "file:///C:/Users/<你>/.config/opencode/plugins/ai-mcp.ts"
]
}
plugins数组只放 server 插件;TUI-only 插件({ id, tui })放进去会被 server loader 拒绝,它们的注册位置是tui.json的plugin数组。
依赖:插件目录下需有 package.json 声明 @opencode-ai/plugin 并装好
(OpenCode 启动时会跑 bun install;WSL 没有 bun 时手动 npm install --omit=dev)。
二、工具说明
| 字段 | 值 |
|---|---|
| 工具名 | mcp_switch |
| 参数 | action:on / off / status |
| 效果 | 对调两份配置 → 校验活文件 → location.reload 热重载 |
status 只读,任何时候都允许;on / off 按 mcpcfg.txt 第1行的模式门控:
| 模式 | 大模型调 mcp_switch |
用户 /mcpon /mcpoff |
|---|---|---|
| 自动 | ✅ 允许 | ✅(视为手动切换一次) |
| 手动 | ❌ 拒绝,提示用户用 /mcpon /mcpoff |
✅ 仅此可用 |
| 关闭 | ❌ 拒绝 | ❌ 不注册 |
reload 走三连尝试:client.location.reload({location}) → ({}) → 无参 →
兜底 POST /api/location/reload。全部失败时配置已经对调完成,重启 OpenCode 一样生效。
三、格式说明(双导出)
// 1) 命名导出 —— V1 legacy 形式(loader 直接调用拿 hooks)
export const AiMcp: Plugin = async (ctx) => ({ tool: { mcp_switch: tool({...}) } })
// 2) default 导出 —— V2 校验形式(OpenCode 2.0.x 的硬性要求)
export default { id: "ai-mcp", async setup(ctx) { ... } }
为什么两个都要:OpenCode v2 对 default 导出有 schema 校验,缺失会直接报
Plugin must export a default definition with an id and an effect or setup function.
(Missing key at ["default"])
(opencode-btw 就因为缺 default 在日志里反复报这条)。命名导出则是 legacy loader 的入口。
两者返回同一套 hooks,无论加载器认哪个,mcp_switch 都能注册成功。
tool helper 通过动态 import 装载:某端没装依赖时只写错误日志,
不会让整个插件文件加载失败。
四、排查
日志:~/.config/opencode/ai-mcp.log
| 日志内容 | 含义 |
|---|---|
module imported (pid=...) |
文件被 OpenCode import 了(模块级留痕,最先出现) |
ai-mcp server 插件已加载(命名导出/default/setup) |
插件函数被调用了(session 初始化时触发) |
| 什么都没有 | 没被加载 → 检查 plugins 数组是否注册、路径是否写对 |
无法加载 @opencode-ai/plugin |
依赖没装,去插件目录 npm install |
注意:插件在 session 初始化时才加载,不是进程启动时。 只启动
opencode serve不建 session,是看不到日志的。