教程

Agent Plugins 如何让 AI Coding Agent 自动获得新能力?Plugin Manifest、Skills、MCP 与 JSON 数据结构详解

装上插件,Coding Agent 不会突然变聪明。它只是按固定位置多读了几份 JSON。

前两篇分别讲了 箱子长什么样,以及 何时不该装箱。今天假设你已经决定发 Plugin。读者真正想知道的是:Cursor、Claude Code、Antigravity 装完这个目录之后,模型怎么「突然会」查发票、写周报?答案不是权重更新,也不是系统提示被改写。规范见 Agent Plugins 1.0.0:客户端先读根上的 plugin.json,再按固定位置发现 skills/ 和 mcp.json。Google Cloud Developer Plugin 走的也是这条路。本文把安装后的 JSON hop 走完,接到 MCP 与 JSON Schema 的校验链。

五跳流水线,不是「自动学会」

「自动获得新能力」听起来像模型学会了新技能。工程上它是五跳,一跳都省不了。第一跳:客户端把目录落到插件根,解析后的路径不得逃出根——符号链接指向根外,整条路径拒掉。第二跳:读 plugin.json,过闭集 Schema,拿到 name 和规范版本。这一跳失败,整包不加载,后面三跳不会发生。第三跳:若存在 skills/,只看直接子目录里恰好叫 SKILL.md 的普通文件,抽出 name 与 description 放进上下文。第四跳:若存在 mcp.json,按每条 type 去连,握手后再 tools/list。第五跳:模型对上描述或工具名,才读 Skill 正文,或发起 tools/call。

规范故意不管安装按钮长什么样。Google Developers Blog 写得很清楚:安装、权限、沙箱、确认 UX 是各客户端的义务。Agents CLI、Cursor、Claude Code 的对话框可以完全不同。可移植的是目录和两份闭集 JSON。所以评审不要问「用户点哪里」,要问「装完之后内存里多了哪几份对象」。缺 Manifest,后面四跳不会发生。Manifest 过了但 mcp.json 的 $schema 和 plugin.json 对不上,只停 MCP,技能继续。某一份 SKILL.md 不合 Agent Skills,只跳过那一项。

横向委托仍不在这条流水线里。另一个团队的发票 Agent 怎么被发现,是 Agent Card 的事,见站内 A2A 文。今天只谈:这个 Coding Agent 如何长出一组技能和工具。先承认「新能力」是发现结果,再谈每一跳的 JSON。

这一跳 客户端此刻持有的 JSON 模型此刻能做什么
读 plugin.json身份对象:name / version / $schema还不能做事,只知道箱子合法
走 skills/技能元数据数组(尚无正文)能选中说明书,正文按需再读
连 MCP 再 tools/list工具名加 inputSchema能按 Schema 填参,尚未执行

先过 Manifest:plugin.json 是身份合同

客户端必须先读根上的 plugin.json,再发现组件。不能换文件名,也不能把技能或 MCP 内联进 Manifest。Schema 是闭集:只允许 $schema、name、version、description、author、homepage、repository、license、keywords、extensions。多出来的顶层键,客户端必须报告并忽略,但不能因此拒载。真正致命的是缺必填、类型错、或 name 违规——那种情况整包拒绝,不得发现任何组件。1.0.0 的 $schema 必须是 https://agent-plugins.org/schemas/1.0.0/plugin.schema.json。客户端用它选本地规则,加载时不得去网上拉 Schema。

name 是标识符,不是商店展示名。长度 1–64,只能小写字母、数字、连字符和点,首尾必须是字母或数字,禁止 -- 和 ..。My-Plugin、-start 会让整包拒载。版本推荐 SemVer,但「看起来不像 SemVer」不能当拒载理由。作者对象只允许 name / email / url。客户端私货放 extensions.com.example.client,或根上的反向域名目录;不要发明第五个顶层键去塞 hooks。把 hooks 写进 plugin.json 的顶层,规范要求忽略它——你的 IDE 若「刚好能读」,换一家就丢。

下面是一份可进仓库的完整 Manifest,比最小两字段本多了给人看的元数据。先让它能 parse,且过官方 Schema,再谈安装按钮。keywords 帮目录检索;description 帮人决定要不要装,不帮模型选工具。模型选技能看的是 SKILL.md 的 description,选工具看的是 tools/list。把 Manifest 描述写成工具说明书,发现面仍然是空的。

{
  "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
  "name": "invoice-ops",
  "version": "1.2.0",
  "description": "Invoice query MCP plus the weekly-summary skill, shipped as one directory",
  "author": {
    "name": "Finance Platform",
    "url": "https://docs.example.com/invoice-ops"
  },
  "homepage": "https://docs.example.com/invoice-ops",
  "repository": "https://github.com/example/invoice-ops",
  "license": "MIT",
  "keywords": ["invoices", "weekly-summary", "mcp"]
}

安装之后:客户端手里的能力快照

规范不要求客户端导出一份「已安装能力」文件。但评审需要看见装完之后内存里是什么。把五跳的结果收成一份快照 JSON:plugin 身份、已发现技能(只含元数据)、MCP 连接状态、tools/list 回来的工具合同。这份快照不是 plugin.schema.json 的实例,不要拿包装 Schema 去校验它。它是你们 CI 的夹具:断言技能数、工具名、inputSchema 的必填项。装完却对不上,说明发现或握手出了问题,而不是「模型还没学会」。

「自动获得」在这份对象里看得很清楚。skills[].loaded 是 metadata,不是 body——启动时大约一百个 token,正文按需再读。tools[] 来自握手后的 tools/list,不是手写进 plugin.json。mcpServers[].status 是运行时,不是包装合同。如果快照里 tools 为空,但 MCP 显示 connected,说明握手过了、Server 没暴露工具——去查 Server,不要改 Manifest。反过来,Manifest 合法、快照里技能为零,去查 skills/ 是不是把 SKILL.md 藏深了一层。

Google Cloud Developer Plugin 装完之后,客户端侧同样是:箱子身份 + gcloud 护栏技能的元数据 + Developer Knowledge MCP 的工具清单。用户感觉「Agent 会查 Cloud 文档了」,数据上只是 tools 数组多了几项。把快照和仓库里的 plugin.json / mcp.json 并排 diff,能立刻发现有人把运行时状态写回了包装文件——那是 drift,不是规范字段。

{
  "plugin": {
    "name": "invoice-ops",
    "version": "1.2.0",
    "spec": "1.0.0"
  },
  "skills": [
    {
      "name": "write-weekly-summary",
      "description": "Turn invoice query results into the weekly summary finance reads. Use when the user asks for a week-end report.",
      "path": "skills/write-weekly-summary/SKILL.md",
      "loaded": "metadata"
    }
  ],
  "mcpServers": [
    {
      "id": "invoice-tools",
      "type": "streamable-http",
      "status": "connected"
    }
  ],
  "tools": [
    {
      "name": "query_invoices",
      "server": "invoice-tools",
      "inputSchema": {
        "type": "object",
        "required": ["week"],
        "properties": {
          "week": { "type": "string", "pattern": "^[0-9]{4}-W[0-9]{2}$" },
          "status": { "type": "string", "enum": ["open", "paid", "overdue"] }
        }
      }
    }
  ]
}

技能跳:frontmatter 变成发现面

Agent Plugins 不重写 SKILL.md。发现规则只有一条:skills/ 的直接子目录里,有一份名为恰好 SKILL.md 的普通文件。藏在 skills/deploy/extra/SKILL.md 不会被看见。不合 Agent Skills 的那一项必须跳过,其他技能和 MCP 继续加载。客户端抽进上下文的,是 frontmatter 里的 name 与 description,外加路径以便按需再读正文、scripts/、references/。

description 必须同时写「做什么」和「何时用」。写成 invoice-ops-skill-v2 或第一人称口号,发现面等于零——箱子装上了,模型选不中,用户会以为插件坏了。其实坏的是说明书。scripts/ 仍是「请用已有 shell 跑这个脚本」,参数走 argv,不是 tools/list 里的一等工具。快照的 tools[] 里不要出现脚本名;出现了,说明有人把 Skill 附件误记成 MCP。

技能正文按需加载,是为了省窗口。快照保持 loaded: metadata,是为了抓住「把整本 runbook 注入系统提示」的回归。窗口被说明书撑爆,不是 Plugin 格式的锅,是客户端加载策略的锅。规范只保证技能能被发现;怎么暴露给模型和用户,仍由客户端决定。

MCP 跳:连上再 tools/list

mcp.json 必须在根上,不得写进 plugin.json,也不得换一个核心路径。顶层只能有 $schema 和 mcpServers。$schema 钉在 https://agent-plugins.org/schemas/1.0.0/mcp.schema.json,且必须和 Manifest 声明的规范版本一致。对不上,只停该插件的 MCP,技能继续。每条 server 必须显式 type:stdio、streamable-http,或可选的遗留 sse。客户端不得从对象形状去猜传输。streamable-http 的 url 必须是绝对 http/https,非回环必须 https。headers 是可见的包装数据,不是密钥槽。

连上之后的发现面才是 tools/list。包装文件回答「去哪连」;工具合同回答「这一跳 arguments 合不合法」。不要把 inputSchema 抄进 plugin.json,也不要把 name / version 抄进 inputSchema。鉴权失败是那一台 server 的连接失败,不是插件配置非法——规范不定义便携的 OAuth 字段,密钥仍走客户端运行时。线协议细节见站内 MCP 是什么。

下面是远程 MCP 的可移植片段。仓库夹具里不要写 API Key。连上后,把 tools/list 的结果填进快照的 tools[]。握手失败只跳过这一条 server,其他 server 和技能继续——这是规范的失败边界,不是产品口号。

{
  "$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json",
  "mcpServers": {
    "invoice-tools": {
      "type": "streamable-http",
      "url": "https://billing.example.com/mcp"
    }
  }
}
失败 死掉的 还活着的
plugin.json 的 name 含大写整包,不发现任何组件无
mcp.json 的 $schema 与 Manifest 不一致该插件全部 MCP技能继续加载
一份 SKILL.md frontmatter 坏了那一项技能其他技能 + MCP

独立失败,夹具留给 JSONVue

评审夹具至少四份:上面的合法 plugin.json、能力快照、可移植 mcp.json、一次 query_invoices 的 arguments。第一份必须过官方 plugin.schema.json。第二份用你们自己的快照 Schema,或只做结构断言——不要拿包装 Schema 去套。第三份过 mcp.schema.json。第四份过工具的 inputSchema。四份都叫 JSON,职责差一层:身份、库存、连接、调用。

再加两份负例:把 name 写成 Invoice-Ops;把 mcp.json 某条的 type 删掉。前者必须整包拒载。后者只跳过那条 server。如果你的 CI 把「多一个未知顶层字段」当成整包失败,你比客户端更严,要自己知道——规范要求报告并忽略多余字段,插件仍加载。密钥不要出现在任何一份进仓库的夹具里。

浏览器里即可完成:JSON 格式化看 Manifest、快照与 mcp.json 能否 parse;JSON Schema 校验核 $schema、name、mcpServers 与 inputSchema;JSON Diff对比快照和仓库里的包装文件,抓把运行时写回去的 drift;数据不离开本机。延伸阅读:MCP 与 JSON Schema、Plugins 总览、以及何时装箱。

相关文章:Google Agent Plugins 2026、Skills vs MCP vs Plugins、MCP 与 JSON Schema、MCP 是什么。

常见问题 FAQ

装上 Plugin,模型是被微调了吗?

没有。权重没变。客户端多了一份身份对象、一组技能元数据、以及 tools/list 回来的工具合同。用户感觉「会了」,是因为发现面变了,不是因为模型学会了发票业务。

能不能把工具清单写进 plugin.json,省掉 mcp.json?

不能。Manifest 不能内联组件,也不能改发现路径。工具清单来自握手后的 tools/list。写进 plugin.json 的顶层会被忽略;写进 extensions 只对那一家客户端有意义,换一家就丢。

能力快照能用官方 plugin.schema.json 校验吗?

不能。官方 Schema 只描述箱子身份。快照是客户端装配的库存,里面有运行时 status 和工具 inputSchema。给快照另写一份 Schema,或只在 CI 里断言关键字段。

各客户端安装 UX 不同,Plugin 还算可移植吗?

包装可移植,安装不必可移植。规范把安装、权限、沙箱明确排除。换客户端时,目录和两份闭集 JSON 不用分叉;确认对话框、企业策略可以完全不同。

总结与下一步

2026 年说「Plugin 让 Coding Agent 自动获得新能力」,可以收成一句:新能力是发现结果,不是权重。五跳走完,内存里多的是身份、技能元数据、工具合同。少一跳,用户看到的就是「装了但不会」。

落地顺序:先让 plugin.json 过官方 Schema;再走 skills/ 和 mcp.json;把结果收成快照夹具;第一次 tools/call 用 inputSchema 核 arguments。用 JSONVue 把四份合同留在本地。箱子总览读 Plugins 文;要不要装箱读决策文;线协议读 MCP 文。