跳到主要内容

可扩展性:技能、MCP、插件与内建扩展

30 秒导读: OpenWork 是一个跑在你自己文件上的 AI agent 桌面应用。裸模型只会说话——它不知道你的公司规范、连不上你的 Notion、也没有画图的手。本章讲 OpenWork 最核心的产品价值:用四条互补的路给 agent 装能力(技能 / MCP / 插件 / 内建扩展),以及它们如何全部落到 opencode.json.opencode/ 目录、和服务端 runtime 配置这三处载体上。

本章聚焦「能力从哪来、装到哪去、agent 运行时怎么看见」。想先了解 OpenWork 的整体三 sidecar 架构,看 02-orchestrator;想了解承载这些读写 API 的服务端本身,看 03-openwork-server


1. 这是什么(零基础也能懂)

一句话定义: OpenWork 底层跑的是 OpenCode 引擎,它天生支持技能、MCP、插件三种扩展点;OpenWork 在其上再加一层「内建扩展」和「一键安装」的 UI,把「给 agent 装能力」变成点几下按钮的事。

为什么需要它。 一个只有基础工具(读文件、跑命令、搜网页)的 agent,遇到下面这些请求会卡住:

  • "按我们团队的 PR 规范来改" —— 它不知道你的规范。
  • "查一下我 Google 日历上周五有没有空" —— 它连不上 Google。
  • "把这个功能画成一张架构图" —— 它没有生成图片的能力。

四条路,各补一块。 OpenWork 把「装能力」这件事拆成四种手段,每种补的东西不一样:

扩展路径白话:它给 agent 补什么典型例子
技能 Skills一段领域知识 / 操作手册,按需注入"我们的发布流程"、"如何写符合规范的 commit"
MCP一条通往外部系统的连线(带工具)连 GitHub、Linear、Notion、自建服务
插件 Plugins一段改造引擎本身的代码拦截请求、加自定义工具、改 prompt
内建扩展 ExtensionsOpenWork 随包带的托管能力Google Workspace、OpenAI 生图

一句话直觉: 把 agent 想成一个新来的实习生。技能是给他的《员工手册》;MCP 是给他公司各系统的门禁卡;插件是直接改造他的工位设备;内建扩展是公司已经配好、开箱即用的那几台机器。

用起来什么样。 用户在 OpenWork 的「Extensions」设置面板里操作,底层每一步都归结为对三处载体的读写:添加一个技能 = 往 .opencode/skills/<name>/SKILL.md 写一个文件;连一个 MCP = 往 runtime 配置里加一条 mcp 记录;装一个插件 = 往 opencode.jsonplugin 数组里加一项。UI 分区见 apps/app/src/react-app/domains/settings/pages/extensions-view.tsx:10ExtensionsSection = "all" | "mcp" | "skills" | "plugins"


2. 顶层全景(它大概怎么转)

2.1 三处载体

理解本章的关键,是先记住能力最终落到哪三处——所有扩展路径都在往这三处之一写:

载体位置谁在读承载什么
.opencode/ 目录文件工作区内(受版本控制)OpenCode 引擎按目录约定加载技能、命令、agent、目录级插件文件
opencode.json工作区 / 全局引擎启动时读plugin 数组、mcp 映射(用户手写的)
服务端 runtime 配置服务端专属 SQLite(runtime DB)服务端构建后注入给引擎OpenWork 通过 UI 添加的 MCP / 插件

前两处是 OpenCode 原生的、用户可手写、可提交进 git;第三处是 OpenWork 私有的——UI 加的 MCP 不直接写用户的 opencode.json,而是存进 runtime DB,再在构建引擎配置时合并注入(见 openwork-runtime-config.ts:94mcp: runtimeMcpMap(runtimeConfig))。这样「用户手写的配置」和「OpenWork 帮你加的」互不污染。

2.2 一张图:四条路如何汇入引擎

怎么读这张图:左边是四条扩展路径(用户视角),中间是它们各自落地的载体,右边是最终消费者——OpenCode 引擎。从左到右是「安装 → 落地 → 生效」。

用户操作(UI/手写) 落地载体 消费者
┌─────────────┐
│ ① 技能 │──写文件──▶ .opencode/skills/<n>/SKILL.md ─┐
└─────────────┘ │
┌─────────────┐ │
│ ② MCP │──写 DB──▶ runtime 配置(mcp 映射) ────────┤
└─────────────┘ │ ▼
┌─────────────┐ │(构建时合并) ┌──────────────────┐
│ ③ 插件 │──写 DB/json─┴──▶ plugin 数组─▶│ OpenCode 引擎 │
└─────────────┘ │ (buildOpenwork- │
┌─────────────┐ │ RuntimeConfig) │
│ ④ 内建扩展 │──随包内建──▶ openwork_extension_* 工具 ──────┘
└─────────────┘ (服务端 action 注册表)

MCP 那条线还有一个「热同步」旁路:UI 加 MCP 后,除了写 runtime DB,服务端还会立刻 POST /mcp 把这一条推给正在运行的引擎(server.ts:2166),不必等引擎重启就能连接。见 §3.2。

2.3 部件一句话职责

部件干什么文件
skills.ts扫描/读写工作区与全局技能apps/server/src/skills.ts
skill-hub.ts从远程 Hub 仓库拉取并安装技能apps/server/src/skill-hub.ts
mcp.ts列出/增删/开关 MCP(写 runtime DB)apps/server/src/mcp.ts
plugins.ts列出/增删 OpenCode 插件apps/server/src/plugins.ts
cloud-plugins.ts安装 marketplace 云插件包apps/server/src/cloud-plugins.ts
claude-plugin-bundle.ts把 Claude Code 插件仓库转成云插件包apps/server/src/claude-plugin-bundle.ts
extensions/index.ts内建扩展 action 的注册表与派发apps/server/src/extensions/index.ts
openwork-runtime-config.ts构建引擎可见的最终配置(注入插件+MCP)apps/server/src/openwork-runtime-config.ts

3. 核心机制(逐个机制,由浅入深)

3.0 基线:扩展之前 agent 免费拿到什么

在讲四条扩展路之前,先明确基线:agent 不装任何扩展时,已经有一整套内建工具。前端在 apps/app/src/lib/build-in-tools.ts 里为这些工具逐个定义了类型和识别函数,用来渲染每种工具调用的 UI。

这份清单就是「裸 agent 的能力边界」:bashreadwriteeditgrepglobwebfetchwebsearchtask(子 agent)、lspapply_patchtodowrite,以及一个特殊的 skill(见 build-in-tools.ts:351SkillToolPart)。

注意 skill 也在这份内建清单里——这说明「调用技能」本身是引擎的一等工具,而技能内容才是可扩展的部分。四条扩展路做的,都是在这条基线之上追加能力。

3.1 技能 Skills —— 给 agent 的操作手册

要解决的小问题: 怎么把「一段领域知识/操作步骤」按需喂给 agent,而不是塞满上下文。

思路: 一个技能就是一个文件夹,里面有一个 SKILL.md,frontmatter 写 namedescription,正文写操作手册。引擎按 description 判断相关性,需要时才用 skill 工具把正文读进来。

技能长什么样(示意,非源码):

---
name: release-checklist
description: Use when cutting a new release — bumps version, updates changelog.
---
# 发布流程
1.`pnpm test`
2. 更新 CHANGELOG
3. 打 tag …

发现:多来源、多约定的扫描。 OpenWork 不只认自己的目录,还要兼容 Claude Code、通用 agent 等约定。listSkills 会沿工作区向上直到 .git 边界逐层找项目技能,再可选地找全局技能(skills.ts:119listSkills):

作用域扫描的目录
项目<root>/.opencode/skills<root>/.claude/skills
全局~/.config/opencode/skills~/.claude/skills~/.agents/skills~/.agent/skills

每个目录还支持两种布局:扁平的 skills/<name>/SKILL.md,以及领域分组skills/<domain>/<name>/SKILL.md——listSkillsInDir 找不到直接的 SKILL.md 时会再往下钻一层(skills.ts:95-113)。同名技能按扫描顺序去重取先见者(skills.ts:140-145)。

写入。 用户导入/新建技能时,upsertSkill 一律写到项目的 projectSkillsDir,即 .opencode/skills/<name>/SKILL.md(skills.ts:189;路径定义见 workspace-files.ts:20)。写入前 buildSkillContent 会校验名字、补齐 frontmatter,并强制 frontmatter 的 name 与 payload 一致(skills.ts:154)。

从 Hub 远程安装。 skill-hub.ts 让用户从一个 GitHub 仓库(默认 different-ai/openwork-hub,见 skill-hub.ts:13DEFAULT_HUB_REPO)浏览并一键安装技能。installHubSkill(skill-hub.ts:182)的关键细节:

  • 用 GitHub trees API 递归列出 skills/<name>/所有文件(不止 SKILL.md),逐个下载写入——所以带辅助脚本/资源的技能也能装全。
  • 路径穿越防护:每个目标路径都过 resolveSafeChild(skill-hub.ts:172),确保解析后仍在技能目录内,拒绝 ..
  • 目录列表带 5 分钟内存缓存(CATALOG_TTL_MS),避免频繁打 GitHub API。

3.2 MCP —— 通往外部系统的连线

要解决的小问题: 怎么让 agent 用上 GitHub、Notion、或你自建服务的工具,而这些系统各有各的鉴权。

思路: MCP(Model Context Protocol,模型上下文协议)是一套标准,一个 MCP server 对外暴露一组工具;引擎作为 client 连上去就能用这些工具。OpenWork 负责「配置这条连线 + 走完鉴权」。

三层来源、就近覆盖。 listMcp(mcp.ts:41)把 MCP 分三个来源合并,优先级从低到高:

来源(source)来自哪谁写的
config.global~/.config/opencode/opencode.jsonmcp用户手写
config.project工作区 opencode.jsonmcp用户手写
config.remote服务端 runtime DB 的 mcp 映射OpenWork UI 加的

同名时项目覆盖全局、runtime 覆盖项目(mcp.ts:53-83)。还有一个巧妙细节:isMcpDisabledByTools(mcp.ts:34)会检查 tools.deny 里有没有 mcp.<name>mcp.* 等 glob——用户可以不删 MCP、只在 deny 列表里把它「静音」,UI 会把这类标成 disabledByTools

UI 加的 MCP 写哪。 addMcp / removeMcp / setMcpEnabled 全部只动 runtime DB(mcp.ts:88/104/120,底层是 writeRuntimeOpencodeConfig),不碰用户的 opencode.jsonsetMcpEnabled 特意用「按路径更新」而非整块覆盖,以保留条目内的行内注释(mcp.ts:118-120 的注释,提到 #1444 回归)。

OAuth 流程(最有工程含量的一支)。 远程 MCP 常需要 OAuth。这条流程由引擎驱动,OpenWork 桌面端弹一个模态框(apps/app/.../connections/mcp-auth-modal.tsx)扮演「浏览器」。以 mcp.oauth-flow.e2e.test.ts 佐证的完整链路:

怎么读:每一步命中即进入下一步;虚线是「远程工作区 loopback 打不通」时的手动兜底。

引擎 OAuth 提供方(MCP server)
│ POST /mcp/<name>/auth
├───── 发现 + 动态客户端注册(DCR)──────▶ POST /register
│◀──── 返回 authorizationUrl(带 PKCE S256 challenge)

用户打开 authorizationUrl ─────────────────▶ GET /authorize
│◀──── 302 重定向到引擎 loopback callback(带 code)

├───── 用 code 换 token(PKCE 验证)───────▶ POST /token
│◀──── access token(持久化到 mcp-auth.json,跨重启复用)

└───── 已鉴权的 MCP 握手 ──────────────────▶ POST /mcp ✔ connected

┆ (loopback 不可达时) POST /mcp/<name>/auth/callback ← 手动兜底

测试断言了几处关键行为:授权 URL 必带 code_challenge_method=S256(PKCE 防截获,mcp.oauth-flow.e2e.test.ts:163);token 落盘到 mcp-auth.json 供跨重启复用(:210);登出 DELETE /mcp/<name>/auth 会删除存储的 token 并断连(:228)。无 OAuth 的普通远程 MCP 则简单得多,mcp.remote-connect.e2e.test.ts 佐证:addMcplistMcpremoveMcp 一条龙,只动 runtime 配置。

引擎热同步(engine sync)。 runtime DB 是「真相源」,但正在跑的引擎实例未必立刻知道。syncRuntimeMcpToOpencodeEngine(server.ts:2828)负责把 runtime MCP 进引擎:

  • 逐条 POST /mcp,单条失败不阻断后续——一个坏 MCP 不能拖垮其余条目的注册(server.ts:2851-2858)。
  • 对 5xx/网络错误重试一次(引擎常在 dispose 后短暂重建中),4xx 不重试(postMcpEntryWithRetry,server.ts:2883)。
  • 把最后一次同步结果按工作区记下来(recordEngineMcpSyncResult),GET /workspace/:id/mcp 会带上 engineSync 字段(server.ts:2144),让 UI 能解释「为什么这个明明启用的 MCP 却显示未连接」。
  • 启动时 syncAllWorkspacesRuntimeMcpToEngine(server.ts:2949)补推所有工作区——因为注入的 runtime 配置文件只覆盖 workspaces[0],其余工作区的 MCP 靠它才对引擎可见。

mcp.engine-sync.e2e.test.ts 用一个 mock opencode server 佐证了这些重试/失败上报路径。

3.3 插件 Plugins —— 改造引擎本身

要解决的小问题: 技能只是知识、MCP 只是外连,想改引擎行为(拦请求、加工具、改 prompt)怎么办?

思路: 插件是 OpenCode 原生的扩展方式(README 原话:插件是扩展 OpenCode 的 native 方式)。在 opencode.jsonplugin 数组里列一个 npm 包名或文件路径,引擎加载它,插件导出的钩子就生效了。

最小配置(README opencode.json 示例):

{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-wakatime"]
}

四种来源、有加载序。 listPlugins(plugins.ts:53)聚合插件并给出 loadOrder:

来源(source/scope)来自哪
config / project工作区 opencode.jsonplugin 数组 + runtime DB 的插件列表
dir.project<root>/.opencode/plugins/*.js|.ts
dir.global~/.config/opencode/plugins/*.js|.ts

加载序固定为 ["config.global", "config.project", "dir.global", "dir.project"](plugins.ts:85)。

规格归一化去重。 插件规格五花八门(@scope/pkg@1.2file:.../abs/path、裸包名),normalizePluginSpec(plugins.ts:11)把版本号/协议前缀剥掉再比,避免同一插件写两遍。addPlugin 也用它判重后才追加进 runtime 插件列表(plugins.ts:89)。

OpenWork 自己注入的内建插件。 构建引擎配置时,plugin 数组头部会硬塞几个 OpenWork 私有插件,再接上用户的 runtime 插件(openwork-runtime-config.ts:85-92):

plugin: [
"opencode-chrome-devtools", // 浏览器自动化
openworkExtensionsPreviewPluginPath(), // 暴露 openwork_extension_* / openwork_ui_* 工具
openworkCapabilitiesKnowledgePluginPath(),
openworkAnthropicAdaptiveThinkingPluginPath(),
openworkAnthropicToolSchemaPluginPath(),
...runtimePluginList(runtimeConfig), // 用户装的
]

其中 openworkExtensionsPreviewPluginPath() 指向的那个插件,正是把「内建扩展」接进 agent 的桥梁——见 §3.5。这几个内建插件的解析路径要兼顾开发态(.ts)和 Electron 打包态(app.asar 外的 opencode-plugins/*.js),逻辑在 openwork-extensions-plugin-path.ts:17openworkPluginPath

3.4 云插件包与 Claude 插件兼容 —— 一键装一整包

要解决的小问题: 技能、MCP、命令、agent 往往成套出现(一个团队的整套配置)。逐个装太累,能不能一个链接装一整包?

思路: 云插件(marketplace package)把「若干配置对象」打成一个 CloudPluginResolved,installCloudPlugin(cloud-plugins.ts:596)遍历其成员,按类型分别落地。

命名空间隔离。 一整包的东西全部装到 <plugin-namespace>/ 子目录下,避免和你已有的技能/命令撞名。落地路径由 getPluginObjectInstallPath(cloud-plugins.ts:239)按对象类型决定:

对象类型落地路径
skill.opencode/skills/<ns>/<name>/SKILL.md
agent.opencode/agents/<ns>/<name>.md
command.opencode/commands/<ns>/<name>.md
mcpaddMcp 写 runtime 配置(不落文件)

注意 MCP 成员不写文件,而是复用 §3.2 的 addMcp(cloud-plugins.ts:614-627)——所以云插件里的 MCP 也自动走 runtime DB + 引擎热同步那套。卸载 removeCloudPlugin(cloud-plugins.ts:703)按安装时记下的文件清单精确回滚:文件删文件,MCP 调 removeMcp

兼容 Claude Code 插件仓库。 很多现成插件是 Claude Code 格式(.claude-plugin/plugin.json + .mcp.json + skills//commands//agents/)。claude-plugin-bundle.ts 的巧思是:不新写一套安装逻辑,而是把 GitHub 仓库解析成同样的 CloudPluginResolved 形状,从而白嫖 installCloudPlugin 的命名空间、frontmatter 翻译、MCP 注册、卸载全套(见文件顶部注释,claude-plugin-bundle.ts:1-12)。

resolveClaudePluginBundle(claude-plugin-bundle.ts:267)处理了不少现实脏活:

  • URL 解析容忍 github.com/owner/repoowner/repo.git 后缀、/tree/<ref>/<subdir>,并只允许 github.com(parseClaudePluginSource:71)。
  • 分支名可含斜杠(release/v1),/tree/<...> 里 ref 和子目录的边界因此有歧义——resolveRefAndTree 逐个候选去撞 trees API,取第一个能解析的(:159)。
  • 定位插件根:给定子目录、仓库根、或最浅的含 plugin.json 的目录;同深度出现多个则报「歧义,请在 URL 里指定目录」(locatePluginRoot:201)。
  • 不支持的部分明确降级并告警而非静默:声明了 hooks、用了 ${CLAUDE_PLUGIN_ROOT} 的 MCP、技能带 SKILL.md 以外的额外文件——都推进 warnings 让用户知情(:291、:344、:331)。

UI 侧对应 apps/app/.../connections/modals/claude-plugin-import-modal.tsxadd-mcp-modal.tsx

3.5 内建扩展 Extensions —— 随包带的托管能力

要解决的小问题: Google Workspace、生图这类能力,鉴权和 API 调用都复杂,不该让每个用户自己配 MCP。OpenWork 想开箱即用

思路(两段桥): 内建扩展的能力不作为普通工具直接给 agent,而是通过一个「元工具」桥接。这样 agent 的工具列表保持精简,需要时再按需发现:

agent 想干活 → openwork_extension_list_actions(发现有哪些扩展 action)
→ openwork_extension_call(extensionId, action, args)
│ (OpenCode 插件, 在引擎内)
▼ HTTP POST /experimental/extensions/call
openwork-server 的扩展注册表
│ 按 extensionId 派发
┌─────────┴──────────┐
▼ ▼
google-workspace openai-image-generation
(日历/Gmail/Drive/Chat) (gpt-image-2 生 PNG)

第一段桥:引擎内的元工具。 openwork-extensions-preview.ts 是一个 OpenCode 插件(就是 §3.3 里被硬注入的那个),它:

  • 通过 experimental.chat.system.transform 往系统提示里塞一句「不确定能不能做时,先查 OpenWork 扩展」(openwork-extensions-preview.ts:204)。
  • 暴露 openwork_extension_list_actions / openwork_extension_call 两个工具,底层打服务端的 /experimental/extensions/*(:209、:224)。
  • 顺带暴露 openwork_ui_* 一组工具,让 agent 能反向控制 OpenWork 桌面 UI(开设置、加 provider、读跨会话历史),经一个带 token 的本地 UI bridge(discoverUiBridge:91)。

第二段桥:服务端的 action 注册表。 extensions/index.ts 是派发中枢:OPENWORK_EXPERIMENTAL_EXTENSION_ACTIONS 汇总所有内建扩展的 action;callExperimentalExtensionAction(extensions/index.ts:37)按 extensionId 找到对应模块调用;找不到实现则回 501「已注册但未实现」。HTTP 入口在 routes/core.ts:266(list)与 :275(call)。

两个现成扩展:

扩展(extensionId)提供的 action(节选)鉴权
google-workspacecalendar_list_eventsgmail_create_draftdrive_search_fileschat_send_messageGoogle OAuth
openai-image-generationstatusimage_generate(gpt-image-2 出 PNG)OpenAI API key

生图扩展的落地细节值得一看(openai-image-generation.ts:154generateOpenAiImageArtifact):key 依次从环境变量服务和进程环境找(OPENWORK_OPENAI_IMAGE_API_KEYOPENAI_API_KEY,:55);生成的 PNG 只写到工作区的 artifacts/ 下,且过 resolveSafeChildPath 防路径穿越(:101);把 base64 解码落盘后回一个相对路径(:164-178)。


4. 巧妙之处(可借鉴的技术)

  • 一份安装逻辑,喂三种来源。 云插件、Claude 插件仓库最终都被规整成 CloudPluginResolved,复用同一个 installCloudPlugin(cloud-plugins.ts:596)。新增一种「插件源」= 写一个解析器,而非再抄一套安装/卸载/命名空间/回滚。这是「归一化到一个内部表示」的典范。

  • 用户配置与工具配置分家。 UI 加的 MCP/插件进 runtime DB,不污染用户手写的 opencode.json;构建时才合并注入(openwork-runtime-config.ts:94)。用户随时能把自己的配置提交进 git,而不会混入 OpenWork 的私货。

  • 单条失败不连坐 + 有限重试。 引擎 MCP 热同步逐条推、坏条目跳过、5xx 才重试一次(server.ts:2851postMcpEntryWithRetry:2883)。一个失效的第三方 MCP 不会让整批注册瘫痪。

  • 降级要吵、要留痕。 Claude 插件遇到不支持的 hooks/${CLAUDE_PLUGIN_ROOT}/多余文件,一律进 warnings 而非静默丢弃(claude-plugin-bundle.ts:291);MCP 同步失败也记录并经 engineSync 字段回给 UI(server.ts:2144)。宁可让用户看见「装了但有东西没生效」。

  • 元工具做能力发现。 内建扩展不塞满工具列表,而是 list_actions + call 两个元工具按需发现(openwork-extensions-preview.ts:209),配一句系统提示引导。加新扩展不用改 agent 的工具 schema。


5. 边界与局限(诚实)

  • Claude 插件的 hooks 不支持。 声明了 hooks 会被跳过并告警(claude-plugin-bundle.ts:291)。
  • 插件本地 MCP 命令不支持。${CLAUDE_PLUGIN_ROOT} 指向插件内命令的 MCP 会被跳过(claude-plugin-bundle.ts:344)——OpenWork 只接远程/独立 MCP。
  • 技能只装 SKILL.md(部分路径)。 Claude 插件里带额外文件的技能,通过 bundle 路径导入时只装 SKILL.md(claude-plugin-bundle.ts:331);但 §3.1 的 Hub 安装路径会装全整个技能目录——两条路径行为不同,注意区分。
  • 内建扩展是实验性的。 走的是 /experimental/extensions/*,注册了但没实现的 action 会明确回 501(extensions/index.ts:63)。目前只有 Google Workspace 和 OpenAI 生图两个。
  • 只接受 github.com 的插件源。 非 github.com 的 URL 直接拒(claude-plugin-bundle.ts:77)。

6. 横向对比

本章讲的是 OpenWork「装能力」这一面;它和同组其它章共同拼出完整系统:

  • 承载这些读写 API、鉴权、审计的服务端本身 → 03-openwork-server
  • 引擎、服务端、路由三个 sidecar 由谁监管、如何启停 → 02-orchestrator
  • 这些扩展在 UI 里长什么样、会话如何实时渲染工具调用 → 05-frontend
  • 远程/云工作区下 MCP 的 loopback 兜底与托管 worker → 06-remote-cloud

与 shelf 内其它 coding agent 的取舍:OpenWork 不自造扩展协议,而是站在 OpenCode 的原生扩展点上(技能/插件/MCP 都是 OpenCode 的概念),只在其上加「一键安装 + 托管扩展 + UI」。它的差异化不在「发明新扩展模型」,而在「把已有扩展模型的安装体验做到点几下」。


7. 代码地图(导航索引)

主题文件关键符号
技能扫描(多来源/多布局)apps/server/src/skills.tslistSkillslistSkillsInDirparseSkillEntry
技能写入apps/server/src/skills.tsupsertSkillbuildSkillContentdeleteSkill
技能远程安装apps/server/src/skill-hub.tslistHubSkillsinstallHubSkillDEFAULT_HUB_REPOresolveSafeChild
MCP 列举/增删/开关apps/server/src/mcp.tslistMcpaddMcpremoveMcpsetMcpEnabledisMcpDisabledByTools
MCP 引擎热同步apps/server/src/server.tssyncRuntimeMcpToOpencodeEnginepostMcpEntryWithRetrysyncAllWorkspacesRuntimeMcpToEngine
插件列举/增删/归一化apps/server/src/plugins.tslistPluginsaddPluginnormalizePluginSpec
云插件安装/卸载apps/server/src/cloud-plugins.tsinstallCloudPluginremoveCloudPlugingetPluginObjectInstallPath
Claude 插件包解析apps/server/src/claude-plugin-bundle.tsresolveClaudePluginBundleparseClaudePluginSourcelocatePluginRoot
内建扩展派发apps/server/src/extensions/index.tscallExperimentalExtensionActionlistExperimentalExtensionActions
Google Workspace 扩展apps/server/src/extensions/google-workspace.tsGOOGLE_WORKSPACE_EXTENSION_ACTIONScallGoogleWorkspaceExtensionAction
OpenAI 生图扩展apps/server/src/extensions/openai-image-generation.tsOPENAI_IMAGE_GENERATION_EXTENSION_ACTIONSgenerateOpenAiImageArtifact
引擎内元工具桥apps/server/src/opencode-plugins/openwork-extensions-preview.tsOpenWorkExtensionsPreviewopenwork_extension_call
内建插件路径解析apps/server/src/openwork-extensions-plugin-path.tsopenworkPluginPathopenworkExtensionsPreviewPluginPath
最终引擎配置构建apps/server/src/openwork-runtime-config.tsbuildOpenworkRuntimeConfigObject、注入 plugin 数组 + runtimeMcpMap
runtime 配置存取apps/server/src/runtime-opencode-config-store.tsruntimeMcpMapruntimePluginListwriteRuntimeOpencodeConfig
路径约定apps/server/src/workspace-files.tsprojectSkillsDirprojectPluginsDiropencodeConfigPath
前端内建工具类型apps/app/src/lib/build-in-tools.tsSkillToolPartisSkillToolPart 等识别函数
扩展设置面板apps/app/src/react-app/domains/settings/pages/extensions-view.tsxExtensionsViewExtensionsSection
MCP OAuth 模态apps/app/src/react-app/domains/connections/mcp-auth-modal.tsxOAuth 授权 URL / callback 处理