ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

写一次 Skill,能否同时给 Codex、Cursor、Copilot 使用?Agent Plugins 1.0 来了

写一次 Skill,能否同时给 Codex、Cursor、Copilot 使用?Agent Plugins 1.0 来了 1. 为什么你的 Skill 在三个工具里要写三遍如果你同时用 Codex 写后端、用 Cursor 改前端、用 GitHub Copilot 补测试大概率遇到过这种糟心事同一个「SQL 变更审查」能力在 Codex 里是一份 SKILL.md在 Cursor 里要重写成.cursor/rules到了 Copilot 又得塞进.github/copilot-instructions.md。三份内容 90% 重复改一处规则另外两份就漂移最后没人知道哪份才是最新的。Agent Plugins 1.0 想解决的就是这个。它把「可复用的部分」收敛成一个厂商中立的目录格式根目录放plugin.json工作流放进skills/MCP Server 写进根目录mcp.json。兼容的客户端从同一份插件里发现并加载这些组件你不用再维护三套清单。但这里有个必须说清楚的边界Agent Plugins 1.0 目前只标准化了两样东西——Agent Skills 和 MCP Servers。Hooks、Rules、Commands、Custom Agents、安装入口、权限和认证仍然由各客户端自己决定。所以「写一次到处运行」的准确含义是工作流和工具只写一次客户端特有能力放进独立适配层。这篇不聊概念直接带你从零做一个能跑的portable-sql-review插件同一份 SQL 审查 Skill 配同一个本地 MCP Server在 Codex、Cursor、Copilot 里复用并给出安装、协议测试、功能验收和排错方法。适合谁适合已经在多个 AI 编码工具之间来回切换、被配置重复折磨过的开发者。先看一张对照表心里有个底能力CodexCursorCopilot是否属于 1.0 可移植核心skills/name/SKILL.md支持支持支持是Skill 的 scripts/references/assets支持支持支持是mcp.json中的 stdio MCP支持支持支持是Streamable HTTP MCP支持支持支持是Hooks各自实现各自实现各自实现否Rules / Instructions各自实现各自实现各自实现否Custom Agents / Commands各自实现各自实现各自实现否安装与 Marketplace各自实现各自实现各自实现否OAuth、密钥、权限各自实现各自实现各自实现否一句话概括可移植核心只放 Skill 和 MCP其余差异全部下沉到适配层。2. 前置准备TaoToken 接入与插件目录骨架在动手写插件之前先把模型调用这条链路打通。因为 Skill 本身只是提示词和流程真正干活的是背后的模型和 MCP 工具。我这边统一用 TaoToken 做模型接入它的好处是一个 Key 就能覆盖 Codex、Cursor、Copilot 这类客户端需要的 OpenAI 兼容接口省得每个工具配一套。你需要准备三样东西Base URL、API Key、Model ID。Base URL 用https://taotoken.net/apiKey 在控制台生成Model ID 按你实际要用的模型填。这三件套在后面的 Codex、Cursor、Copilot 配置里都会反复出现先记牢。去控制台拿 Key 的入口在这里https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite拿到 Key 之后先建插件目录骨架。最小插件只需要一个清单加一个 Skillportable-sql-review/ ├── plugin.json ├── skills/ │ └── sql-change-review/ │ ├── SKILL.md │ └── references/ │ └── review-rules.md ├── mcp.json ├── server/ │ └── server.mjs ├── tests/ │ └── test-server.mjs ├── samples/ │ └── risky.sql └── package.json这里三个文件千万别混淆根目录plugin.json声明 Agent Plugins 版本和插件身份可移植。skills/name/SKILL.md声明任务工作流可移植。根目录mcp.json声明 MCP Server 的启动方式可移植。注意plugin.json是闭合 Schema只允许$schema、name、version、description、author、homepage、repository、license、keywords、extensions这些顶层字段。你千万别自作聪明加skills、mcpServers、hooks字段客户端会直接报错并忽略。Skill 不需要声明路径客户端固定扫描skills/MCP 必须放在根目录mcp.json不能内联。另外提醒一句Agent Plugins 1.0 没有统一 OAuth 和凭据保存协议认证仍由客户端管理。所以插件清单里的env、headers都是可见配置不要把 API Key 写进去。模型侧的 Key 交给客户端自己的配置去存。3. 可复制配置plugin.json、mcp.json 与 SKILL.md这一节是全文的核心所有片段都能直接复制。先写根清单plugin.json{ $schema: https://agent-plugins.org/schemas/1.0.0/plugin.schema.json, name: portable-sql-review, version: 1.0.0, description: Review SQL changes with a portable workflow and a deterministic local MCP checker., author: { name: Example Author }, license: MIT, keywords: [sql, database, review, migration, safety] }再写mcp.json注意command必须是单个可执行文件名参数全部拆进args{ $schema: https://agent-plugins.org/schemas/1.0.0/mcp.schema.json, mcpServers: { portable-sql-review: { type: stdio, command: node, args: [${PLUGIN_ROOT}/server/server.mjs], cwd: ${PLUGIN_ROOT} } } }${PLUGIN_ROOT}指向插件安装目录${PLUGIN_DATA}指向客户端分配的持久化可写目录。两个 Schema 版本必须一致都写1.0.0。接着写 Skill 主文件skills/sql-change-review/SKILL.md--- name: sql-change-review description: Review SQL files, database migrations, DML, DDL, and stored-procedure changes for destructive operations, semantic drift, transaction risks, locking risks, and missing verification steps. Use when the user asks to review, migrate, execute, or troubleshoot SQL changes. --- # SQL Change Review Review the change as an engineering change, not as isolated SQL syntax. ## Workflow 1. Identify the target database, affected objects, execution environment, and intended business result. 2. Read the complete SQL change or diff. Do not infer omitted statements. 3. Call the review_sql tool from the portable-sql-review MCP server for every changed SQL script. 4. Treat tool findings as a deterministic first pass, not as proof that the SQL is safe. 5. Manually review row-selection semantics, transaction boundaries, lock duration, idempotency, and rollback plans. 6. Never execute destructive SQL merely because the static checker returned no finding. ## Required output 1. 60-second conclusion: safe, needs confirmation, or blocked. 2. Risk table: severity, location, evidence, impact, and fix. 3. Required changes before execution. 4. Verification SQL: pre-check, execution guard, and post-check. 5. Remaining uncertainty that must be confirmed by a human.这份 Skill 有四个关键点触发条件明确SQL、DML、DDL、迁移都能匹配、工具调用明确要求调用review_sql、工具边界明确静态扫描通过不等于可执行、输出结构明确三端最终都产出相似报告。领域规则单独放references/review-rules.md让主文件保持短小Agent 按需读取# SQL review rules ## Block by default - DELETE 或 UPDATE 缺少有效 WHERE 条件。 - TRUNCATE、DROP TABLE 没有恢复方案。 - 执行环境不明确时操作生产数据库。 - 使用不可信输入拼接动态 SQL。 ## Require evidence - 预计和实际影响行数。 - 大批量 DML 的索引支持。 - 长时间操作的锁等待检查。 - 不可逆修改的执行前快照。最后是 MCP Server 的核心扫描逻辑用 Node.js 原生实现不依赖第三方包function reviewSql(sql, dialect generic) { const normalized String(sql ?? ) .replace(/--.*$/gm, ) .replace(/\/\*[\s\S]*?\*\//g, ); const findings []; for (const match of normalized.matchAll(/\bDELETE\sFROM\s[\w.][\s\S]*?(?;|$)/gi)) { const statement match[0]; if (!/\bWHERE\b/i.test(statement) || /\bWHERE\s1\s*\s*1\b/i.test(statement)) { findings.push({ severity: critical, code: DELETE_WITHOUT_FILTER, message: DELETE 缺少有效 WHERE 条件可能删除整表数据。, evidence: statement.trim() }); } } for (const match of normalized.matchAll(/\bUPDATE\s[\w.][\s\S]*?(?;|$)/gi)) { const statement match[0]; if (!/\bWHERE\b/i.test(statement) || /\bWHERE\s1\s*\s*1\b/i.test(statement)) { findings.push({ severity: critical, code: UPDATE_WITHOUT_FILTER, message: UPDATE 缺少有效 WHERE 条件可能更新整表数据。, evidence: statement.trim() }); } } if (/\bTRUNCATE\b/i.test(normalized)) { findings.push({ severity: critical, code: TRUNCATE, message: 检测到 TRUNCATE必须确认环境和恢复方案。 }); } if (/\bDROP\sTABLE\b/i.test(normalized)) { findings.push({ severity: critical, code: DROP_TABLE, message: 检测到 DROP TABLE默认阻断。 }); } const blocked findings.some(item item.severity critical); return { dialect, decision: blocked ? blocked : findings.length ? review_required : no_static_finding, findings, disclaimer: 静态检查不替代执行计划、锁分析和业务语义核对。 }; }为什么不让 Skill 用自然语言判断全部风险因为正则扫描是确定性的同样的 SQL 每次得到相同结果MCP Tool 还能独立测试。Agent 把精力留给事务、锁、字段映射和业务语义这才是正确的分工。4. 验证请求协议测试与三端加载步骤写完别急着丢给 Agent先测 MCP 协议本身。测试脚本会做四件事initialize握手、tools/list发现review_sql、危险 SQL 返回blocked、带限定条件的 DELETE 不被误判。cd portable-sql-review node tests/test-server.mjs预期输出PASS: initialize, tools/list, risky SQL, scoped SQL这一步失败就别怀疑 Agent问题一定在插件、Node.js 或 MCP 协议层。顺手校验 JSON 语法python -m json.tool plugin.json /dev/null python -m json.tool mcp.json /dev/null准备测试用例samples/risky.sql-- 预期blocked DELETE FROM demo_orders; -- 预期blocked UPDATE demo_order_items SET quantity 0 WHERE 1 1;Cursor 加载把插件复制到本地插件目录然后重启或执行Developer: Reload Window。mkdir -p ~/.cursor/plugins/local cp -R ./portable-sql-review ~/.cursor/plugins/local/打开 Customize确认能看到sql-change-reviewSkill 和portable-sql-reviewMCP Server 已启用。GitHub Copilot 加载Copilot CLI 支持从本地目录安装。copilot plugin install ./portable-sql-review copilot plugin list进入交互会话后用/skills list检查 Skill 是否被发现。Codex 加载先建一个最小 Marketplace目录结构如下portable-demo-marketplace/ ├── .agents/plugins/marketplace.json └── plugins/portable-sql-review/marketplace.json内容{ name: portable-demo, interface: { displayName: Portable Demo }, plugins: [ { name: portable-sql-review, source: { source: local, path: ./plugins/portable-sql-review }, policy: { installation: AVAILABLE, authentication: ON_INSTALL }, category: Productivity } ] }然后添加并安装codex plugin marketplace add /absolute/path/to/portable-demo-marketplace codex plugin add portable-sql-reviewportable-demo codex plugin list --json三端装好后用同一条验收指令测试请使用 sql-change-review 检查 samples/risky.sql 给出 60 秒结论、风险表、修改建议和验证 SQL。验收时别只看 Agent 有没有说「危险」要逐项检查是否真的调用了 MCP Tool、是否识别两个危险语句、是否给出blocked、是否没有擅自执行 SQL、是否输出执行前后验证方案、是否说明静态扫描的能力边界。5. 常见报错排查401、local proxy failed 与 OAuth跨三端跑插件报错基本集中在几类。下面按真实错误对照排查。401 Unauthorized模型侧 Key 无效或没带上。检查客户端里配置的 Base URL 是否为https://taotoken.net/apiKey 是否复制完整前后别带空格Model ID 是否拼写正确。三件套缺一不可尤其 Codex 的auth.json里如果只填了 Key 没填 Base URL就会 401。local proxy failed / connection refusedMCP Server 没起来。先手动跑node server/server.mjs看有没有报错再确认mcp.json里command是node而不是一整段 Shell 命令args是数组。如果 Node.js 不在客户端进程可见的 PATH 里也会连不上用绝对路径或确保环境变量一致。reading choices / 返回结构解析失败多半是模型返回格式和客户端预期不符。检查 Model ID 是否选对了兼容模型有些客户端对choices字段结构敏感。换一个明确支持 OpenAI 兼容格式的模型通常能解决。OAuth / 认证弹窗反复出现Agent Plugins 1.0 没有统一认证协议认证由客户端管理。如果插件清单里写了env或headers存密钥删掉改由客户端自己的凭据机制保存。Codex 的auth.json、Cursor 的设置、Copilot 的登录态各自独立别指望一份配置通吃。Skill 出现但 MCP 没出现优先查mcp.json是否在插件根目录、文件名有没有误写成.mcp.json、企业管理员是否关闭了本地插件导入。Skill 藏太深没被发现规范只扫描skills/skill-name/SKILL.md这一层不会递归。skills/database/review/xxx/SKILL.md这种结构直接失效。插件依赖当前工作目录安装后路径会变。访问插件内文件一律用${PLUGIN_ROOT}写缓存用${PLUGIN_DATA}别用相对路径。一个客户端通过就以为三端都通过标准允许客户端逐步实现组件每个目标客户端都要跑相同验收用例并记录版本。排错时如果卡在接入层直接翻接入文档对照字段https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite6. 长期编码与 Agent 场景的落地建议如果你只是偶尔审查几条 SQL上面这套已经够用。但如果你要把这套插件长期挂在日常编码流程里甚至让 Agent 自动跑那模型调用的稳定性和额度就变成瓶颈。我自己的做法是把长期编码和 Agent 任务单独走 Coding Plan避免和临时对话抢额度。Coding Plan 入口https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite想先验证模型对话效果可以用模型对话页快速试https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite最后给一条仓库组织建议避免版本分叉agent-plugin-repo/ ├── plugins/portable-sql-review/ # 唯一业务能力来源 ├── .agents/plugins/marketplace.json ├── .github/plugin/marketplace.json └── adapters/ ├── codex/ ├── cursor/ └── copilot/plugins/是唯一核心两份 Marketplace 只是分发入口adapters/只放无法标准化的 Hooks、Rules、Commands。绝不允许在适配层复制 SKILL.mdCI 必须验证所有适配层仍指向同一个核心版本。还有一个容易踩的坑别为了「统一」把 Skill 写成空泛流程。跨端通用的 Skill 应该避免依赖某个客户端独有的工具名、专属 Slash Command、隐藏目录或未标准化的 Hook 返回格式。正确做法是在 Skill 里引用逻辑工具名和目标能力在 MCP 里提供确定性工具把厂商特有增强放进适配层再用同一套验收用例防止行为漂移。Hooks 为什么不能一起带走因为各客户端的生命周期事件、输入输出 JSON、阻断语义、权限模型、脚本环境都不同。如果 SQL 审查还想在命令执行前强制拦截正确姿势是公共 Skill 说明何时审查、公共 MCP 做确定性扫描、各端 Hook 按各自协议阻断、CI 作为最终门禁。Skill 负责指导MCP 负责能力Hook 负责节点控制CI 负责强制。真正能一次编写的是 Skill 工作流、引用的脚本规则资源、MCP Server 及其标准启动配置。仍然要分别处理的是 Marketplace 安装入口、Hooks/Rules/Commands、权限认证密钥、UI 与企业策略。用 Agent Plugins 1.0 保存唯一的可移植核心用很薄的适配层处理剩余差异再用一套相同验收用例守住行为一致性——这才是「写一次多端生效」的稳妥落地方式。
返回列表