Anybox 当前插件系统设计结构说明

本文档根据当前仓库代码整理,说明插件包的文件结构、插件清单格式、agent 侧插件管理逻辑、desktop 侧 IPC/UI 连接方式,以及插件在安装后如何进入 MCP、技能和项目会话运行链路。

代码范围:packages/anyboxagent 与 packages/desktop 核心实现:packages/anyboxagent/src/plugin/plugin.ts 生成日期:2026-05-18

1. 总体定位

当前插件系统的核心并不在 Electron renderer 内,而是在 packages/anyboxagent 中实现。插件被设计成一类“能力包”,一个插件包可以声明三类能力:

  • MCP server:插件安装后会生成一个或多个全局 MCP server 配置,供项目会话按选择加载。
  • Skill:插件可以携带 SKILL.md 工作流说明,安装并在项目中选中插件后,这些技能会进入技能发现范围。
  • App connector:插件可以声明需要 API key 的远程 MCP 连接器,密钥由认证存储管理,运行时再解析到远程请求头或授权字段。
关键结论: 插件包提供能力定义,安装记录保存启用状态和配置,项目配置保存“当前项目选中了哪些插件”。会话运行时最终通过项目 MCP 解析与技能发现,把被选中的插件能力纳入当前会话。

2. 插件包文件结构

插件包的约定入口是 .anybox-plugin/plugin.json。运行时只扫描已下载安装到本机数据目录的插件包:

<agent-data>/plugins/installed/<plugin-id>/<version>/.anybox-plugin/plugin.json

系统也支持非版本化目录:

<agent-data>/plugins/installed/<plugin-id>/.anybox-plugin/plugin.json

版本化目录和非版本化目录都会被扫描。同一个搜索根内如果出现多个同名插件,系统会按 manifest 的 version 选择较新的版本。

推荐目录形态

<plugin-id>/
  <version>/
    .anybox-plugin/
      plugin.json
    skills/
      <skill-directory>/
        SKILL.md
        references/
        scripts/
        assets/
    assets/
      app-icon.png
      composer-icon.svg
    server.js
    package.json
路径 作用
.anybox-plugin/plugin.json 插件清单。声明插件元信息、MCP server、技能目录、App connector、权限说明和运行时模板。
skills/<skill>/SKILL.md 插件内置技能。系统会读取 frontmatter 中的 namedescription,生成 plugin:<plugin-id>:<skill-directory> 形式的技能 ID。
skills/<skill>/references 技能附加资料。不会被自动全量加载,只有技能说明要求读取时才通过技能资源工具访问。
assets 界面图标、截图或技能资源。manifest 的 interface.logocomposerIcon 可引用这里的资源。
server.js 或其他运行文件 stdio MCP 插件可把命令、参数、环境变量写在 manifest 的 runtime 中,由安装逻辑生成 MCP 配置。

内置插件策略

当前项目不再保留内置插件包。所有插件都必须先通过 catalog 下载/安装,落到 plugins/installed 数据目录后,agent 才会扫描和启用。

3. plugin.json 设计结构

manifest 由 Zod schema 校验,文件必须是严格 JSON。核心字段如下:

字段 类型 用途
name string 插件 ID 的来源。系统会 trim 并转小写作为 pluginID
version string 版本选择和安装记录使用。版本化包中同名插件按此字段比较。
description string 默认描述。若 interface.shortDescription 存在,目录展示优先使用后者。
author string 或 object 发布者信息。object 支持 nameemailurl
homepagerepositorylicensekeywords 可选 用于目录展示、文档链接和元信息。
interface object 桌面插件页展示信息,包括名称、短描述、长描述、分类、图标、品牌色、默认提示等。
mcpServers array 声明一个或多个 MCP server 模板。安装后转换为全局 MCP server 配置。
skills string 或 string[] 技能根目录声明。不写时默认扫描 skills
apps array 声明 App connector。安装后生成远程 MCP server 绑定,API key 单独保存。
commandsagents string 或 string[] 已纳入 schema,但当前核心安装链路主要消费 MCP、skills、apps。

interface 字段

interface 用于桌面端目录展示,不直接决定运行时行为。常用字段包括:

  • displayName:插件页展示名称。
  • shortDescriptionlongDescription:列表和详情描述。
  • developerName:发布者展示名称。
  • category:目录分类,系统归一化到 CodeBrowserGitDatabaseDocsAutomationDesign
  • capabilitieswebsiteURLprivacyPolicyURLtermsOfServiceURL:供界面展示或后续扩展使用。
  • composerIconlogoscreenshotsbrandColor:视觉素材字段。

mcpServers 字段

每个 MCP server 声明会被归一化为 PluginMcpServerCatalogEntry

{
  "id": "notes",
  "name": "Manifest Notes",
  "description": "Optional detail",
  "risk": "low",
  "permissions": ["Starts a stdio MCP server"],
  "tools": [
    {
      "name": "list_notes",
      "title": "List Notes",
      "description": "List notes.",
      "readOnly": true
    }
  ],
  "configFields": [
    {
      "key": "ROOT_PATH",
      "label": "Root path",
      "type": "path",
      "required": true,
      "defaultValue": "~"
    }
  ],
  "runtime": {
    "transport": "stdio",
    "command": "node",
    "args": ["server.js"],
    "timeoutMs": 30000
  },
  "installReview": ["Review text shown before install."]
}

id 可省略。省略时系统使用 default,生成的 MCP server ID 为 plugin.<plugin-id>;如果有显式 ID,例如 notes,则生成 plugin.<plugin-id>.notes

runtime 字段

stdio runtime

  • transport: "stdio"
  • command:启动命令。
  • args:命令参数,可使用 ${CONFIG_KEY} 占位符。
  • env:进程环境变量,也可使用占位符。
  • cwdtimeoutMstoolPolicies:可选运行配置。

remote runtime

  • transport: "remote"
  • serverUrlconnectorId 至少一个可解析。
  • authorizationheaders:远程请求认证信息。
  • allowedToolsrequireApproval:控制工具暴露和审批策略。
  • provider 当前 schema 支持 openai

apps 字段

App connector 用于“需要用户保存 API key 才能连接”的远程 MCP。它声明 credential 字段,安装插件时生成一个远程 MCP server,但不会把 API key 写入 MCP 配置。

{
  "appID": "docs",
  "name": "Docs API",
  "credential": {
    "key": "DOCS_API_KEY",
    "label": "Docs API key",
    "type": "password",
    "required": true,
    "secret": true
  },
  "runtime": {
    "transport": "remote",
    "serverUrl": "https://docs.example.test/mcp",
    "headers": {
      "x-api-key": "${DOCS_API_KEY}"
    },
    "allowedTools": {
      "readOnly": true
    },
    "requireApproval": "always"
  }
}

对应生成的 connector ID 为 plugin-app:<plugin-id>:<appID>,MCP server ID 为 plugin.<plugin-id>.app.<appID>

4. 插件系统在项目中的实现

4.1 agent 侧是插件系统的主体

packages/anyboxagent/src/plugin/plugin.ts 是插件系统的主体文件,承担以下职责:

  • 定义 manifest、catalog、installed record、connector status 等 Zod schema。
  • 扫描插件包目录,读取并校验 .anybox-plugin/plugin.json
  • 把原始 manifest 归一化成 UI 和 API 可消费的 PluginCatalogItem
  • 安装、更新、删除插件,并同步生成或删除 MCP server 配置。
  • 保存和删除 App connector API key,并在远程 MCP 连接时解析真实认证信息。
  • 列出已安装插件技能根目录,供技能系统发现插件技能。

4.2 插件目录发现

插件扫描入口只使用下载安装到本机数据目录的插件包搜索根:

  • ANYBOX_PLUGIN_INSTALL_DIR:测试或显式配置时使用的插件安装目录。
  • <agent-data>/plugins/installed:默认插件安装目录。

搜索根下会扫描一级插件目录,并同时检查非版本化 manifest 与子目录版本化 manifest。同名插件按 manifest 的 version 选择最新版本。

4.3 目录归一化

normalizeCatalogItem 会把 manifest 转换成统一的目录项:

  • id:由 manifest.name 归一化而来。
  • name:优先使用 interface.displayName
  • publisher:优先使用 interface.developerName,否则使用 author。
  • category:把 CodingEngineering 映射为 Code,把 DocumentationProductivity 映射为 Docs
  • risk:从 MCP server、App connector、skills 推导最高风险,skills-only 插件按 low 参与计算。
  • permissionstoolsconfigFields:从所有 MCP server 和 App connector 汇总。
  • skills:扫描技能目录并生成技能预览。

4.4 安装记录

已安装插件存储在 SQLite 表 installed_plugins 中,主键是 pluginID。记录结构包括:

字段 含义
pluginIDversion 安装的插件 ID 与当前 catalog 版本。
enabled 插件整体启用状态。同步到所有由插件生成的 MCP server。
mcpServerIDmcpServerIDs 兼容旧字段和当前多 server 列表。由 manifest 的 MCP server 与 App connector 生成。
skillIDs 安装时快照出的插件技能 ID,例如 plugin:my-plugin:review
connectorIDs App connector 的认证存储 ID,例如 plugin-app:manifest-lab:docs
config 插件配置值。用于替换 runtime 中的 ${CONFIG_KEY} 占位符。
installedAtupdatedAt 安装与更新时间戳。
lastDiagnosticlastConnectorDiagnostics 最近一次 MCP 诊断结果。

4.5 安装流程

  1. 前端调用 desktop IPC desktop:install-plugin
  2. 主进程转发到 agent API:PUT /api/plugins/installed/:pluginID
  3. agent 调用 Plugin.install(pluginID, input)
  4. 系统查找 catalog 插件;如果插件不存在返回 PLUGIN_NOT_FOUND,如果风险为 critical 则拒绝安装。
  5. 系统校验和归一化配置:必填字段必须有值;没有显式值时使用 defaultValue;其他额外配置会保留。
  6. 生成 mcpServerIDsskillIDsconnectorIDs
  7. 写入 installed_plugins 表。
  8. 调用 Config.setMcpServer(GLOBAL_CONFIG_ID, serverID, runtimeBinding),把插件能力写成全局 MCP server 配置。

4.6 MCP runtime 绑定

插件安装后不会直接运行 MCP server,而是生成全局 MCP 配置。会话真正需要工具时,MCP manager 通过 Config.resolveProjectMcpServers(projectID) 找到当前项目可用 server,并按 server 配置创建 transport。

stdio runtime 会生成 commandargsenvcwd 等字段。生成时会使用安装记录中的 config 替换 ${CONFIG_KEY} 占位符。

remote runtime 会生成 serverUrlauthorizationheadersallowedToolsrequireApproval 等字段。普通 remote MCP 可以直接写 serverUrl;App connector remote MCP 则先写入 connectorId,实际认证信息运行时再解析。

4.7 App connector 密钥处理

App connector 的 API key 不写入全局 MCP 配置。保存 API key 时,agent 调用认证模块写入 provider credential,connector ID 形如 plugin-app:<plugin-id>:<appID>

MCP client 创建 remote transport 时,如果发现 server 配置里有 connectorId,会动态导入插件模块并调用 resolveConnectorRemoteServer(connectorId)。该函数会:

  1. 解析 connector ID,找到插件和 app 声明。
  2. 确认插件已安装且启用。
  3. 从认证存储读取激活的 API key。
  4. 把 API key 合并到临时配置对象中。
  5. 替换 app runtime 的 serverUrlauthorizationheaders 占位符。

这样全局 MCP 配置只包含 connectorId,不会持久化真实密钥;真实密钥只在建立远程 MCP transport 时进入请求配置。

5. Desktop 侧连接方式

5.1 主进程 IPC

Electron 主进程在 packages/desktop/src/main/ipc.ts 注册插件相关 IPC。它们本质上是 agent API 的薄封装:

Desktop IPC Agent API 作用
desktop:get-plugin-catalog GET /api/plugins/catalog 读取插件目录。
desktop:get-installed-plugins GET /api/plugins/installed 读取已安装插件。
desktop:install-plugin PUT /api/plugins/installed/:pluginID 安装插件并写入 MCP 绑定。
desktop:update-installed-plugin PATCH /api/plugins/installed/:pluginID 保存配置或启停插件。
desktop:delete-installed-plugin DELETE /api/plugins/installed/:pluginID 删除安装记录、MCP 绑定和 connector credential。
desktop:get-installed-plugin-diagnostic GET /api/plugins/installed/:pluginID/diagnostic 诊断插件主 MCP server。
desktop:get-installed-plugin-connectors GET /api/plugins/installed/:pluginID/connectors 读取 App connector 连接状态。
desktop:save-installed-plugin-connector-api-key PUT /api/plugins/installed/:pluginID/connectors/:appID/api-key 保存 App connector API key。

5.2 Renderer 插件管理页

Renderer 的状态管理主要在 packages/desktop/src/renderer/src/app/use-settings-page.ts,展示组件在 packages/desktop/src/renderer/src/app/plugins/PluginsPage.tsx

  • loadPlugins 同时读取 catalog 和 installed 列表,并为已安装插件加载 connector 状态。
  • installPlugin 使用当前 draft config 安装插件,然后刷新插件列表和 MCP 能力。
  • updateInstalledPlugin 保存配置或启停插件。
  • deleteInstalledPlugin 删除插件并刷新相关诊断与 connector 状态。
  • saveInstalledPluginConnectorApiKey 保存或清空 app connector API key。

PluginsPage 负责目录过滤、详情展示、风险标签、工具预览、MCP bindings、安装审查、配置表单和 connector 表单。界面层不会自己解释 manifest,而是消费 agent 返回的 PluginCatalogItemInstalledPlugin

6. 项目级启用与会话运行

插件安装是全局行为,项目级选择决定某个项目会话中哪些插件 MCP server 和插件技能可用。

6.1 项目插件选择

agent 项目 API 提供:

  • GET /api/projects/:id/plugins:返回所有已启用的已安装插件。
  • GET /api/projects/:id/plugins/selection:返回当前项目选中的插件 ID,且会过滤掉未安装或未启用的插件。
  • PUT /api/projects/:id/plugins/selection:保存项目选中的插件 ID。

desktop renderer 中的 use-project-composer.ts 会读取这些接口,把插件显示为 composer 顶部菜单里的可选项,并在用户切换时调用 updateProjectPluginSelection

6.2 MCP server 解析

项目 MCP server 解析由 Config.resolveProjectMcpServers(projectID) 完成。它会读取项目配置中的 selected_plugins,把每个插件 ID 映射为 plugin.<pluginID> 前缀,然后从全局 MCP server 列表中挑出匹配的 server。

如果项目显式设置了 selected_mcp_servers,返回结果会包含显式选择的 MCP server 加上选中插件生成的 MCP server;如果没有显式 MCP 选择,则返回项目级 MCP server,并补充选中插件生成的全局 MCP server。

6.3 技能发现

技能系统默认扫描项目技能 .anybox/skills 和用户技能 ~/.anybox/skills。插件技能由 Plugin.listInstalledPluginSkillRoots(pluginIDs) 提供根目录,只有已安装、已启用,并且在当前项目选中的插件会进入技能扫描范围。

会话构建 prompt 时,会通过 Skill.resolveTurnSkillIDs 结合项目选中的插件 ID 过滤可用技能,再由 SystemPrompt.skills 生成技能目录提示。技能内容本身仍然遵守渐进加载:只有模型明确调用 load-skill 时才读取完整 SKILL.md

7. 构建与打包

Desktop 构建脚本 packages/desktop/scripts/prepare-agent-runtime.mjs 只打包 agent server、Bun、node-pty 和 workspace dependencies,不复制任何插件包。

校验脚本 packages/desktop/scripts/verify-agent-runtime.mjs 会拒绝包含 plugins/builtinplugins/registry/plugin-registry.json 的 runtime。

8. 安全与约束

  • 风险等级:插件和 server 支持 lowmediumhighcritical。安装逻辑拒绝 critical 风险插件,UI 也禁止安装。
  • 路径越界防护:插件技能目录解析使用 package root 相对路径校验,阻止 manifest 把技能目录指向包外路径。
  • 配置校验:安装和更新时会校验必填配置字段,并用默认值补齐。
  • 密钥处理:普通 MCP config field 仍会存在安装记录中;App connector 的 API key 则通过认证存储保存,不写入全局 MCP server 配置。
  • 权限说明:manifest 中的 permissionsinstallReview 会展示在插件详情页,帮助安装前审查。
  • 运行时审批:MCP 工具仍受 MCP server 配置中的 toolPoliciesallowedToolsrequireApproval 约束。

9. 从插件到会话可用能力的完整链路

  1. 插件作者在 .anybox-plugin/plugin.json 声明元信息、MCP server、skills 或 apps。
  2. agent catalog API 拉取远程插件元数据,用户安装时下载插件包到本机 plugins/installed 目录。
  3. agent 扫描已下载插件 manifest,归一化为 PluginCatalogItem
  4. desktop 插件页展示 catalog,用户选择安装。
  5. agent 安装插件,写入 installed_plugins,并生成全局 MCP server 配置。
  6. 用户在某个项目的 composer 菜单里选择插件,项目配置写入 selected_plugins
  7. MCP manager 解析项目 MCP server 时,把选中插件生成的全局 MCP server 注入当前项目可用 server 列表。
  8. 技能系统根据项目选中的插件 ID 扫描插件技能根目录,把插件技能放入当前会话可发现技能列表。
  9. 会话运行时按 MCP transport 启动 stdio server 或连接 remote server;App connector 在连接时动态解析 API key。

10. 主要源码位置索引

文件 职责
packages/anyboxagent/src/plugin/plugin.ts 插件 schema、manifest 扫描、catalog 归一化、安装/更新/删除、MCP 绑定、connector 密钥解析、插件技能根目录。
packages/anyboxagent/src/server/routes/settings.ts 插件设置 API 路由:catalog、installed、diagnostic、connectors。
packages/anyboxagent/src/server/usecases/settings.ts 设置 API use case,负责把 PluginError 转成 API error。
packages/anyboxagent/src/server/routes/projects.ts 项目插件选择 API 路由。
packages/anyboxagent/src/server/usecases/projects.ts 项目插件列表、选择、技能和 MCP selection 关联逻辑。
packages/anyboxagent/src/config/config.ts 全局/项目配置,保存 selected_plugins,解析项目 MCP server。
packages/anyboxagent/src/skill/skill.ts 插件技能发现、项目技能过滤、prompt 技能目录生成。
packages/anyboxagent/src/mcp/client.ts 创建 stdio 或 remote MCP transport,remote connector 运行时解析。
packages/anyboxagent/src/mcp/manager.ts 按项目解析 active MCP servers,发现工具并管理 MCP client 生命周期。
packages/desktop/src/main/ipc.ts desktop IPC 到 agent plugin/project API 的转发层。
packages/desktop/src/renderer/src/app/use-settings-page.ts 插件设置页状态管理和操作函数。
packages/desktop/src/renderer/src/app/plugins/PluginsPage.tsx 插件目录和详情 UI。
packages/desktop/src/renderer/src/app/use-project-composer.ts 项目 composer 中插件选项加载和切换。
packages/desktop/scripts/prepare-agent-runtime.mjs desktop 构建 managed agent runtime,不复制插件包。