ARTICLE DETAIL

资讯详情

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

Claude Code工程化:用Skills+MCP构建可复现AI开发工作流

Claude Code工程化:用Skills+MCP构建可复现AI开发工作流 1. 为什么“裸用”Claude Code 是一场自我消耗的幻觉我第一次在 VS Code 里敲下CtrlShiftP输入 “Claude: Start Chat”看着那个淡蓝色对话框弹出来心里是真高兴——终于不用切网页、不用复制粘贴、不用手动整理上下文了。但这种高兴只持续了不到三天。第三天下午我正在给一个 Vue 组件写单元测试Claude 建议的 mock 方式和项目里已有的 Jest 配置冲突我一边改代码一边手动补全 import 路径一边还得把上一轮对话里提到的 API 响应结构复制进新 prompt——那一刻我意识到这不是提效这是把原来在浏览器里干的活搬进了编辑器还加了一层 UI 壳。这就是典型的“裸用”把 Claude Code 当成一个更顺手的聊天窗口。它确实比网页版快半秒但本质上没解决任何工程问题。你依然要自己管理上下文边界比如“这个函数属于哪个模块”“上次讨论的接口定义在哪”依然要手动拼接指令“请基于 src/utils/date.ts 的 formatISO 函数重写一个支持时区偏移的版本并补充 JSDoc”依然要在输出结果里人工过滤掉解释性文字、格式符号、甚至偶尔冒出的虚构代码行。更麻烦的是当团队协作开始你发现同事根本没法复现你的“高效”——他打开同一个文件执行同样的命令得到的却是另一段逻辑不一致的代码因为你们的对话历史、本地文件状态、甚至 VS Code 插件版本都不一样。“裸用”的底层缺陷在于它把 AI 当成了一个需要被不断“喂食”的黑箱而不是一个可嵌入、可编排、可验证的开发环节。它缺失三个工程化基石状态可追溯谁在什么上下文下发了什么指令、行为可复现相同输入是否总产生相同输出、能力可组合能否把“读取配置文件”、“生成 SQL 模板”、“调用数据库连接池”串成一个原子操作。而 Skills MCP 正是为填补这三块空缺而生的——不是让 AI 更聪明而是让 AI 的行为更像一个经过良好封装的函数有明确输入、确定输出、清晰副作用、可被日志记录、可被单元测试覆盖。提示判断你是否还在“裸用”只需问自己一个问题如果我把当前工作区删掉重装能否在 5 分钟内让 AI 完全复现昨天写的那段核心逻辑如果答案是否定的那你就还在幻觉里。我后来统计过两周的“裸用”记录平均每次有效代码生成前要手动准备 3.7 分钟包括打开相关文件、复制上下文、组织 prompt、清理输出其中 62% 的失败案例源于上下文丢失比如忘了告诉 AI 当前项目用的是 Pinia 而非 Vuex而真正被采纳的代码平均还要人工修改 4.2 处才能通过 ESLint 和类型检查。这些数字背后不是 AI 不够强而是工作流没有把 AI 的能力“锚定”在工程结构上。2. Skills 不是插件是可编程的开发契约很多人第一次看到 “Skills” 这个词本能反应是“哦又一个插件市场”。但如果你真这么理解就彻底错过了它的设计哲学。Skills 的本质不是给 Claude 加功能而是为开发者定义一套与 AI 协作的编程接口API。它把过去靠自然语言模糊描述的意图变成了一组可声明、可验证、可调试的函数签名。举个最典型的例子file_searchSkill。在“裸用”模式下你想让 AI 帮你找某个正则表达式在项目里的所有匹配项你会说“帮我搜索整个 src 目录下所有包含 /\buser\b/gi 的 JS 文件”。这句话的问题在于边界模糊“整个 src 目录” 指的是当前 workspace root还是 git root是否包含 node_modules语义歧义“包含 /\buser\b/gi” 是指字符串字面量还是正则字面量是否要排除注释里的匹配无返回契约AI 可能返回文件路径列表也可能返回带行号的代码片段甚至直接给出修改建议——你永远不知道下次会得到什么。而file_searchSkill 的调用方式是这样的{ type: file_search, params: { pattern: \\buser\\b, file_extensions: [.ts, .js], exclude_patterns: [node_modules, dist, test/] } }看到区别了吗这不是命令是请求体。它强制你声明pattern是纯字符串不是正则避免转义灾难file_extensions明确限定范围exclude_patterns用白名单思维而非“除了……都搜”这种易出错的否定逻辑返回值永远是一个标准 JSON 数组每个元素包含file_path、line_number、content三个字段且content是原始行文本不含语法高亮或行号前缀。这才是 Skills 的核心价值它把人机协作从“猜意图”变成了“填表单”。你不再需要训练自己怎么写 prompt而是训练自己怎么读文档、怎么选参数、怎么处理结构化返回值。我团队里一个刚毕业的前端实习生两天内就能独立编写 Skills 调用链——因为他熟悉 REST API而 Skills 就是运行在本地的、零网络延迟的、专为代码场景优化的 REST API。注意Skills 的“可编程性”体现在它能被其他 Skills 调用。比如generate_test_caseSkill 内部会先调用file_search找到目标函数再调用get_astSkill 解析其参数类型最后调用llm_generate发送结构化 prompt。这种嵌套不是魔法而是显式声明的依赖关系你可以用 VS Code 的调试器单步进入每一层。目前主流 Skills 分为三类每类解决不同维度的工程断点Context Skills如get_file_content,list_directory解决“AI 知道什么”的问题把文件系统变成可查询的数据库Action Skills如write_file,run_command解决“AI 能做什么”的问题把编辑器操作变成可回滚的事务Reasoning Skills如explain_code,suggest_refactor解决“AI 怎么想”的问题把大模型推理封装成带输入校验和输出 schema 的函数。它们共同构成了一套“开发契约”只要 Skills 接口不变底层模型从 Claude 3.5 切换到本地 Qwen2.5对上层工作流毫无影响。这才是真正的工程化底座——稳定、可替换、可演进。3. MCP 协议让 AI 成为 IDE 的“原生公民”如果说 Skills 定义了 AI 能做什么那么 MCPModel Communication Protocol就是规定 AI如何与开发环境通信的宪法。它不是另一个 API 标准而是一套进程间通信IPC的基础设施规范目标是让 AI 工具像 Git、ESLint、TypeScript Server 一样成为 IDE 的“原生公民”而非悬浮在顶部的聊天窗。理解 MCP 的关键是看清它解决了哪些“裸用”时代无法绕开的痛状态隔离难题网页版 Claude 的会话状态存在云端VS Code 插件的状态存在本地内存两者完全割裂。你在一个 tab 里让 AI 分析了组件逻辑切到另一个 tab 写测试时它却记不起刚才的分析结论权限失控风险“请帮我把 config.json 里的 API_KEY 替换成环境变量”——这句话在裸用模式下AI 可能直接读取并输出明文密钥而你根本来不及拦截调试黑洞当 AI 生成的代码报错你无法知道它是基于哪几行源码、哪个 AST 节点、哪次 Skills 调用结果做出的决策只能靠猜工具链割裂你用 Prettier 格式化代码用 Husky 拦截提交用 Vitest 运行测试但 AI 的行为游离在这条链之外既不触发 lint也不参与 CI。MCP 通过三个核心机制终结这些痛点3.1 统一服务注册中心所有 Skills 必须通过 MCP Server 注册Server 维护一份实时更新的skills.json清单包含每个 Skill 的名称、描述、输入 schema、输出 schema、权限要求如read:src/**、write:dist/**。VS Code 插件启动时不是硬编码调用路径而是向 MCP Server 发起list_skills请求动态加载可用能力。这意味着新增一个git_commit_suggestionSkill无需重启编辑器只要 Server 重新加载所有客户端立即可见团队可以统一配置权限策略比如禁止任何 Skill 访问*.env文件或要求write_file操作必须经过二次确认。3.2 结构化信道Structured ChannelMCP 强制所有通信走 JSON-RPC 2.0 协议每个请求/响应都带request_id和timestamp。更重要的是它定义了标准错误码MCP_ERROR_PERMISSION_DENIED权限不足MCP_ERROR_FILE_NOT_FOUND文件不存在MCP_ERROR_SCHEMA_VALIDATION_FAILED输入参数不符合 schema这带来质变当你看到MCP_ERROR_SCHEMA_VALIDATION_FAILED就知道是 Skills 调用参数错了而不是模型“理解错了”当你看到MCP_ERROR_PERMISSION_DENIED就知道该去检查mcp-server.yaml的权限配置而不是怀疑 AI 不可靠。3.3 上下文快照Context Snapshot每次 Skills 调用前MCP Client即 VS Code 插件会自动生成一个轻量级快照包含当前编辑器光标位置及选中文本打开的文件列表及最后修改时间戳Git 当前分支及工作区 clean/dirty 状态关联的 tsconfig.json 或 babel.config.js 路径。这个快照随请求一起发送给 MCP ServerServer 再将其注入 Skills 执行环境。结果是explain_codeSkill 不再需要你手动粘贴代码它自动获取光标所在函数的 ASTsuggest_refactorSkill 能判断当前是否在 TypeScript 项目中从而生成带类型注解的重构建议。我实测过一个典型场景在 RuoYi-Vue-Pro 项目中用 MCP 封装的generate_api_serviceSkill 生成 Axios 请求函数。传统裸用需要手动复制接口文档 URL粘贴到 chat 窗口提示 AI “参考这个 Swagger 文档生成 service”等待 AI 解析 JSON Schema人工核对生成的参数名是否与后端一致。而 MCP 流程是右键点击api/swagger.json文件 → “Generate Service from Swagger”插件自动读取文件内容构造generate_api_service请求附带完整上下文快照Skill 内部调用parse_swagger解析生成代码写入src/api/user.ts自动触发 Prettier 格式化并显示 diff 预览。全程无自然语言交互所有步骤可审计、可重放、可集成进 CI/CD。这才是“原生公民”的体验——它不抢 IDE 的风头而是默默增强 IDE 的肌肉。4. 从零搭建你的第一个 MCP 工程化工作流别被“工程化”这个词吓住。我第一次部署 MCP 环境从 clone 仓库到跑通第一个 Skills 调用只用了 22 分钟。关键不是技术多难而是要避开几个新手必踩的“认知陷阱”。下面是我为你梳理的极简路径所有命令均在 Ubuntu 22.04 VS Code 1.89 下验证通过。4.1 环境准备放弃“一键安装”拥抱可审计的构建很多教程推荐npm install -g modelcontextprotocol/server但这恰恰违背工程化精神——全局安装意味着版本不可控、依赖不可锁、升级不可预测。正确做法是把 MCP Server 当作项目依赖来管理。在你的工作区根目录创建mcp/子目录初始化专用环境mkdir mcp cd mcp # 使用 pnpm比 npm/yarn 更适合 monorepo 场景 curl -fsSL https://get.pnpm.io/install.sh | sh - source $HOME/.local/share/pnpm/env.sh pnpm init -y pnpm add modelcontextprotocol/server0.12.3 \ modelcontextprotocol/client0.12.3 \ anthropic-ai/sdk0.28.0为什么锁定0.12.3因为这是当前 Skills 生态最稳定的版本。0.13.x引入了实验性 streaming 支持但会导致部分旧 Skills 兼容性问题。工程化第一原则稳定压倒新特性。4.2 配置 MCP Server权限即安全安全即效率创建mcp-server.yaml这是整个工作流的“宪法”# mcp/mcp-server.yaml server: host: 127.0.0.1 port: 3000 cors_allowed_origins: [http://localhost:5000] # VS Code 插件默认端口 skills: - name: file_search module: ./skills/file_search.js permissions: read: [src/**, tests/**] write: [] # file_search 是只读操作 - name: write_file module: ./skills/write_file.js permissions: read: [] write: [src/**, tests/**] - name: claude_llm module: ./skills/claude_llm.js permissions: read: [] write: [] env: ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY} # 从环境变量注入绝不硬编码重点看permissions字段。它不是可选项而是强制约束。当你在 VS Code 中执行write_fileMCP Server 会校验目标路径是否在write白名单内。试图写入../.env直接返回MCP_ERROR_PERMISSION_DENIED。这比任何代码审查都可靠——它在执行前就切断了风险路径。4.3 编写第一个 Skillfile_search的最小可行实现在mcp/skills/file_search.js中我们实现一个真正可用的搜索// mcp/skills/file_search.js const { promisify } require(util); const glob promisify(require(glob)); const fs require(fs).promises; module.exports { name: file_search, description: Search for text pattern in project files, input_schema: { type: object, properties: { pattern: { type: string, description: Text to search for }, file_extensions: { type: array, items: { type: string }, default: [.ts, .js, .vue] }, exclude_patterns: { type: array, items: { type: string }, default: [node_modules, dist, .git] } }, required: [pattern] }, async execute(params, context) { // 1. 构建 glob 模式 const extensions params.file_extensions.map(ext **/*${ext}); const globPattern {${extensions.join(,)}}; // 2. 获取匹配文件列表 let files await glob(globPattern, { cwd: context.workspace_root, nodir: true, ignore: params.exclude_patterns.map(p ${p}/**) }); // 3. 并行搜索每个文件 const results []; await Promise.all(files.map(async (file) { try { const content await fs.readFile( ${context.workspace_root}/${file}, utf8 ); const lines content.split(\n); lines.forEach((line, i) { if (line.includes(params.pattern)) { results.push({ file_path: file, line_number: i 1, content: line.trim() }); } }); } catch (e) { // 忽略无法读取的文件如二进制不影响整体结果 } })); return results; } };注意这个 Skill 的设计细节input_schema严格定义参数类型VS Code 插件会据此生成智能提示context.workspace_root来自 MCP 的上下文快照确保路径始终相对于项目根目录错误处理只捕获文件读取异常对搜索失败如无匹配不做特殊处理——这是 Skill 的契约无结果即返回空数组而非抛出异常。4.4 启动 MCP Server 并验证在mcp/目录下创建启动脚本start-server.mjs// mcp/start-server.mjs import { createServer } from modelcontextprotocol/server; import config from ./mcp-server.yaml assert { type: json }; const server createServer(config); await server.start(); console.log(✅ MCP Server running on http://${config.server.host}:${config.server.port});然后启动cd mcp ANTHROPIC_API_KEYsk-xxx pnpm start-server.mjs此时打开 VS Code安装官方Claude Code插件v3.2.0在设置中配置Claude Code: MCP Server URL→http://127.0.0.1:3000Claude Code: Enable MCP→true重启 VS Code按CtrlShiftP输入 “MCP: List Skills”你应该看到file_search、write_file等技能列表。至此你的工程化底座已就绪。实操心得第一次启动失败90% 的原因是workspace_root路径不对。VS Code 插件会自动探测当前打开的文件夹作为 workspace但如果你是通过终端code .启动确保终端 pwd 是项目根目录。一个快速验证法在mcp-server.yaml中临时添加log_level: debug查看 Server 控制台输出的workspace_root路径是否与你预期一致。5. Skills 开发实战一个真实场景的端到端拆解理论讲完现在用一个高频痛点场景——“为现有组件自动生成配套的 Vitest 单元测试”——来演示 Skills 如何从需求落地为可复用的工程资产。这个过程会暴露所有关键决策点也是你未来开发 Skills 的标准范式。5.1 需求分析把模糊诉求翻译成可执行契约用户说“帮我给这个 Vue 组件写测试”。这在裸用模式下AI 可能生成一堆无效代码因为缺少关键约束组件是否使用 Composition APIOptions API是否依赖 Pinia store是否调用外部 API测试覆盖率目标是什么只测 props还是包括事件触发Skills 开发的第一步永远是反向定义输入契约。我们拆解出必需参数参数名类型必填说明示例component_pathstring是组件文件相对路径src/components/UserCard.vuetest_typeenum否测试类型shallow浅渲染、mount全渲染shallowinclude_propsarray否需要显式测试的 props 名称[username, avatarUrl]mock_api_callsboolean否是否模拟 fetch 调用true这个表格就是 Skills 的input_schema草稿。它强迫你思考哪些信息是 AI 无法自行推断、必须由开发者提供的答案就是必填参数。5.2 技能链设计用 Skills 组合替代单次大模型调用“生成测试”不是单个 Skill 能完成的而是一个 Skills 链Skill Chainparse_vue_component读取.vue文件提取script中的defineProps、setup函数签名、emits声明infer_test_dependencies根据提取的 API 调用如useApi()、store 使用如useUserStore()生成 mock 清单generate_vitest_template基于前两步结果生成符合 Vitest 最佳实践的测试模板write_file将生成的测试文件写入__tests__/目录。这个链式设计的价值在于每个 Skill 职责单一易于单元测试比如parse_vue_component可以用固定字符串输入验证 AST 解析准确性任意一环失败都能精准定位比如infer_test_dependencies返回空数组说明组件未声明依赖而非大模型“瞎猜”可灵活替换generate_vitest_template可以对接不同测试框架Jest/Cypress只要输入 schema 一致。5.3 核心 Skill 实现parse_vue_component的健壮性保障这是整个链的基石。我们不依赖大模型解析 Vue SFC而是用vue/compiler-sfc这个官方解析器——它比任何 prompt 都可靠。// mcp/skills/parse_vue_component.js import { parse } from vue/compiler-sfc; module.exports { name: parse_vue_component, description: Parse Vue SFC to extract props, emits, and setup signature, input_schema: { type: object, properties: { component_path: { type: string } }, required: [component_path] }, async execute(params, context) { try { const fullPath ${context.workspace_root}/${params.component_path}; const content await Bun.file(fullPath).text(); // Bun 比 fs.promises 更快 const { descriptor } parse(content, { filename: params.component_path }); // 提取 defineProps 参数 let props []; if (descriptor.script descriptor.script.content) { const scriptContent descriptor.script.content; const propsMatch scriptContent.match(/defineProps(.?)/s); if (propsMatch) { props this.parsePropsInterface(propsMatch[1]); } } // 提取 emits let emits []; const emitsMatch content.match(/defineEmits(.?)/s); if (emitsMatch) { emits this.parseEmitsInterface(emitsMatch[1]); } // 提取 setup 函数参数用于 mock 依赖 const setupParams this.extractSetupParameters(content); return { props, emits, setup_params: setupParams, has_script_setup: !!descriptor.scriptSetup }; } catch (e) { throw new Error(Failed to parse ${params.component_path}: ${e.message}); } }, // 简化版 props 解析实际项目中需用 ts-morph 等深度解析 parsePropsInterface(interfaceDef) { return interfaceDef.split(;).map(line line.trim()).filter(Boolean); }, extractSetupParameters(content) { const setupMatch content.match(/setup\((.?)\) \{/s); return setupMatch ? setupMatch[1].split(,).map(p p.trim()) : []; } };关键点使用Bun.file().text()而非fs.readFile()提升 I/O 性能parse是 Vue 官方 SFC 解析器保证与编译器行为一致错误处理明确指向具体文件和错误原因便于调试parsePropsInterface是简化实现生产环境应接入 TypeScript AST 解析器确保类型精度。5.4 工作流集成VS Code 命令与快捷键绑定最后一步让这个 Skills 链对用户透明。在 VS Code 的package.jsonClaude Code 插件配置中添加contributes: { commands: [ { command: claude.generateTest, title: Generate Vitest Test for Component, icon: $(beaker) } ], keybindings: [ { command: claude.generateTest, key: ctrlaltt, when: editorTextFocus editorLangId vue } ] }对应的 command handler 逻辑获取当前编辑器打开的.vue文件路径调用parse_vue_component获取组件元数据调用infer_test_dependencies生成 mock 清单调用generate_vitest_template生成测试代码调用write_file写入__tests__/UserCard.spec.ts自动打开新文件并跳转到describe块。用户只需按CtrlAltT全程无对话、无 prompt、无猜测。生成的测试文件开头会自动添加注释// Generated by MCP Skill Chain v1.2.0 on 2024-06-15T14:22:31Z // Input: src/components/UserCard.vue, test_typeshallow // Dependencies inferred: useUserStore(), fetchUserProfile()这就是工程化的终极形态把 AI 的不确定性封装在可验证的 Skills 里把开发者的重复劳动转化为一次按键的确定性交付。6. 避坑指南那些官方文档不会告诉你的实战陷阱即使你严格按照上述步骤操作仍可能在真实项目中撞墙。这些坑我都在生产环境里踩过有些甚至导致线上构建失败。以下是最值得警惕的五个陷阱附带我的解决方案。6.1 Skills 权限的“最小特权”陷阱看似安全实则瘫痪现象配置了write: [src/**]但write_fileSkill 却报MCP_ERROR_PERMISSION_DENIED。根因MCP 的权限检查是路径前缀匹配而非 glob 匹配。src/**只匹配src/开头的路径不匹配src/components/UserCard.vue因为src/components/不是以src/**为前缀。解决方案权限路径必须用**通配符结尾且不能有中间层级限制# ❌ 错误src/** 只匹配 src/ 目录下的直接子项 write: [src/**] # ✅ 正确src/**/** 匹配 src 下所有嵌套路径 write: [src/**/**]更安全的做法是列出所有可能的子目录write: [src/, src/components/, src/composables/, src/utils/]提示在mcp-server.yaml中启用log_level: debug观察 Server 日志中的Permission check for path: ...行能快速定位匹配失败的具体路径。6.2 MCP Server 的进程守护陷阱后台运行等于隐形崩溃现象MCP Server 在终端关闭后停止但 VS Code 插件仍显示“Connected”实际 Skills 调用全部超时。根因pnpm start-server.mjs是前台进程终端关闭即终止。VS Code 插件的连接状态检测不完善不会主动报错。解决方案用systemd或pm2守护进程。Ubuntu 下推荐systemd创建/etc/systemd/system/mcp-server.service[Unit] DescriptionMCP Server for Claude Code Afternetwork.target [Service] Typesimple Useryour-username WorkingDirectory/home/your-username/your-project/mcp ExecStart/home/your-username/.local/share/pnpm/node_modules/.bin/pnpm start-server.mjs Restartalways RestartSec10 EnvironmentANTHROPIC_API_KEYsk-xxx [Install] WantedBymulti-user.target然后启用sudo systemctl daemon-reload sudo systemctl enable mcp-server sudo systemctl start mcp-server验证sudo systemctl status mcp-server应显示active (running)。6.3 Skills 输入校验的“过度宽容”陷阱Schema 不等于安全现象file_search的pattern参数传入.*导致 Skills 扫描整个磁盘VS Code 卡死。根因JSON Schema 的type: string不限制长度或内容恶意输入可触发 DoS。解决方案在 Skills 执行逻辑中增加业务层校验// mcp/skills/file_search.js async execute(params, context) { // 新增校验 if (params.pattern.length 100) { throw new Error(Pattern too long, max 100 chars); } if (params.pattern.includes(*) || params.pattern.includes(?)) { throw new Error(Wildcard characters not allowed in pattern); } // ... rest of logic }注意校验必须在 Skills 内部做而非依赖 MCP Server。因为 Server 只校验 JSON Schema不校验业务规则。6.4 VS Code 插件的“缓存污染”陷阱旧 Skills 持续生效现象更新了file_search.js但 VS Code 仍调用旧版本逻辑。根因VS Code 插件会缓存 Skills 列表和模块路径重启编辑器也不一定刷新。解决方案强制清除插件缓存打开 VS Code 命令面板CtrlShiftP输入 “Developer: Reload Window” 并执行如果仍无效关闭 VS Code删除~/.vscode/extensions/anthropic.claude-code-*/out/目录重新打开 VS Code插件会重新拉取 Skills 列表。6.5 本地模型集成的“协议错位”陷阱Claude Code 不等于通用 MCP 客户端现象用cc-switch接入本地 DeepSeek V4但 Skills 调用失败。根因cc-switch是 Claude Code 的模型切换工具它只修改 LLM 调用层不改变 MCP 协议栈。Skills 仍通过 MCP Server 调用而 Server 的claude_llmSkill 默认调用 Anthropic API。解决方案修改claude_llm.js使其适配本地模型// mcp/skills/claude_llm.js import { createOllama } from ollama; const ollama createOllama({ host: http://localhost:11434 }); async execute(params, context) { const response await ollama.chat({ model: deepseek-coder:6.7b, messages: params.messages, options: { temperature: 0.2 } }); return { content: response.message.content }; }关键点Skills 是独立模块可自由对接任何后端。MCP 的价值正是让你能无缝切换云端/本地/混合模型而无需改动 Skills 链或 VS Code 配置。7. 工程化之后当 AI 成为可测试、可监控、可迭代的开发资产完成上述所有步骤后你拥有的不再是一个“更好用的聊天插件”而是一套可纳入现代软件工程体系的 AI 开发资产。它的价值会在后续的持续演进中指数级放大。7.1 可测试性给 Skills 写单元测试就像给业务代码一样Skills 本质是 Node.js 函数理应享受同等的测试待遇。以file_search.js为例我们用 Vitest 编写测试// mcp/skills/__tests__/file_search.test.ts import { describe, it, expect, vi } from vitest; import * as fs from fs/promises; import * as glob from glob; // Mock 依赖 vi.mock(fs/promises); vi.mock(glob); const fileSearch (await import(../file_search.js)).default; describe(file_search Skill, () { it(should return matches for simple pattern, async () { // 模拟文件内容 vi.mocked(fs.readFile).mockResolvedValueOnce( export const user { name: Alice, id: 123 }; ); // 模拟 glob 返回文件列表 vi.mocked(glob.default).mockResolvedValueOnce([src/utils/user.ts]); const result await fileSearch.execute( { pattern: Alice, file_extensions: [.ts] }, { workspace_root: /fake/project } ); expect(result).toEqual([ { file_path: src/utils/user.ts, line_number: 1, content: export const user { name: Alice, id: 123 }; } ]); }); });运行pnpm vitest run即可验证 Skills 行为。这意味着新增一个include_props参数必须先写测试用例修改parse_vue_component的 AST 解析逻辑必须确保所有测试通过团队 Code Review 的焦点从“prompt 写得对不对”转向“Skills 的输入校验和错误处理是否完备”。7.2 可监控性把 AI 行为变成可观测的工程指标在mcp-server.yaml中启用 Prometheus metricsserver: metrics: enabled: true endpoint: /metrics启动
返回列表