Claude Skills 与 MCP 协作机制解析:从原理到工程实践 1. 从零认识 Claude Skills它到底解决了什么问题第一次听到 Claude Skills 这个词很多人会下意识地把它和 MCP 混为一谈。我刚开始接触的时候也是这个反应毕竟那段时间 MCP 协议的热度实在太高几乎所有的讨论都围绕着“怎么把外部工具接进模型”展开。但真正上手用了一段时间之后才发现Skills 和 MCP 解决的是两个完全不同层面的问题理解这一点是决定你要不要投入时间折腾它的关键。先说结论MCP 解决的是“模型能碰到什么”的问题Skills 解决的是“模型知道怎么做”的问题。打个比方MCP 像是给你的助手配了一把万能钥匙让它能打开各种房间的门而 Skills 更像是一本操作手册告诉它进了房间之后该按什么顺序、用什么手法去完成具体任务。两者不是替代关系而是互补关系。你可以只用 MCP 不用 Skills也可以只用 Skills 不接 MCP但如果两个都用上整个工作流的顺畅程度会有明显提升。那 Claude Skills 具体是什么形态的东西说白了它就是一个结构化的文件夹里面包含一个SKILL.md文件作为入口再加上若干辅助脚本、参考资料、模板文件。模型在需要的时候会读取这个文件按照里面定义的流程去执行任务。它不依赖任何特殊的运行时环境不需要编译不需要部署服务本质上就是“把一套做事的方法写成模型能看懂的文档”。这个设计思路其实非常朴素但威力在于它把“领域知识”和“模型能力”解耦了。以前你想让模型按照公司内部的代码规范写代码得在每次对话里把规范贴一遍或者写一个很长的系统提示词。现在你只需要把规范整理成一个 Skill模型在合适的时机自动加载既省 token 又不容易遗漏。对于经常重复同类任务的人来说这个效率提升是实打实的。适合读这篇内容的人大概分三类一是已经在用 Claude Code 做日常开发想进一步提升自动化程度的二是团队里需要统一工作流程、降低协作摩擦的技术负责人三是对 Agent 架构感兴趣想通过一个具体案例理解“技能系统”设计思路的开发者。不管你是哪一类接下来的内容都会从实际操作的层面展开尽量把每个环节讲透。2. Skills 的核心机制与设计逻辑拆解2.1 为什么是“文件夹 Markdown”而不是插件系统很多人第一次看到 Skills 的目录结构时会觉得过于简单甚至有点“不正式”。一个文件夹一个 Markdown 文件几个可选的脚本这就完了没有注册机制没有依赖声明没有版本管理看起来像是临时拼凑的方案。但恰恰是这种极简设计让它的上手门槛降到了几乎为零。我试过对比几种不同的扩展方案。传统的插件系统通常需要你遵循特定的接口规范写一堆样板代码还要处理生命周期钩子、依赖注入这些概念。对于专业开发者来说不算什么但对于只想“让模型按我的方式做事”的人来说这些额外负担完全是浪费精力。Skills 的做法是把复杂度转移到模型侧——模型本身足够聪明能读懂自然语言描述的流程那就不需要你用代码去定义每一步。另一个关键考量是可移植性。一个 Skill 文件夹可以放在项目仓库里跟着代码走也可以放在用户目录下作为个人工具箱还可以打包分享给同事。它不绑定任何特定的 IDE 或平台只要运行环境支持读取文件系统就能用。这种“文件即配置”的思路和当年 Docker 用 Dockerfile 定义环境、GitHub Actions 用 YAML 定义流水线是一个道理降低认知负担的同时提高了传播效率。当然简单也有简单的代价。没有强制的 schema 校验意味着 Skill 的质量完全取决于写作者的水平一个逻辑混乱的SKILL.md会让模型执行得一塌糊涂。没有版本管理意味着多人协作时容易出现覆盖冲突。这些问题在实际使用中确实会遇到后面我会专门讲怎么规避。2.2 SKILL.md 的加载时机与触发逻辑理解 Skills 最关键的一点是搞清楚模型什么时候会去读这个文件。它不是每次对话都加载也不是永远不加载而是根据当前任务和 Skill 的描述信息做匹配。具体来说模型首先看到的是所有可用 Skill 的名称和简短描述当它判断当前任务和某个 Skill 相关时才会去读取完整的SKILL.md内容。这个机制带来的直接好处是上下文窗口的节省。假设你有二十个 Skill每个完整内容平均两千字如果全部加载就是四万字直接吃掉一大块上下文。但实际运行时模型可能只需要其中一两个其余的只占用一行描述的空间。这种“按需加载”的设计让 Skill 数量可以持续增长而不会导致性能线性下降。那描述信息怎么写才能让模型准确匹配我的经验是用任务导向的语言而不是功能导向的语言。比如“当用户需要生成符合团队规范的 React 组件时使用”就比“React 组件生成器”要好因为前者描述了触发场景后者只是标签。模型在判断相关性时更擅长匹配场景描述而不是抽象名词。还有一个容易被忽略的细节Skill 的优先级和冲突处理。如果你同时装了两个功能重叠的 Skill模型可能会随机选一个也可能两个都读然后混淆。目前没有官方的优先级机制所以实际使用中要尽量避免功能重叠。如果确实需要多个相似 Skill建议在描述里明确区分适用场景比如一个用于“新项目初始化”另一个用于“存量项目重构”。2.3 与 MCP 协议的协作边界在哪里MCP 和 Skills 经常被放在一起讨论但它们的职责边界其实很清晰。MCP 负责连接外部资源——数据库、API、文件系统、第三方服务它定义的是“模型能调用哪些工具”。Skills 负责编排工作流程——先做什么、后做什么、遇到分支怎么处理它定义的是“模型该怎么组合这些工具”。举个具体的例子。假设你要做一个“自动生成周报”的功能。MCP 层面你需要接入日历服务获取本周会议记录接入项目管理工具获取任务完成情况接入文档系统用于写入结果。这些是 MCP 的活儿。而 Skills 层面你需要定义先拉取哪些数据怎么过滤无关信息按什么结构组织内容遇到数据缺失时怎么处理最终输出成什么格式。这些是 Skills 的活儿。实际使用中两者配合的方式通常是Skill 的SKILL.md里写明“第一步调用 XX 工具获取数据第二步调用 YY 工具处理”模型读到这个流程后通过 MCP 去实际执行工具调用。所以 Skill 更像是导演MCP 像是演员和道具。没有导演演员不知道该演什么没有演员导演的想法落不了地。注意不要试图用 Skill 去实现 MCP 该做的事。我见过有人在SKILL.md里写一堆 HTTP 请求的细节试图绕过 MCP 直接调 API。这样做短期能跑通但长期维护成本极高而且失去了 MCP 带来的统一鉴权、错误处理、重试机制等好处。3. 手把手搭建你的第一个 Skill3.1 目录结构规划与文件组织动手写之前先把目录结构想清楚。一个标准的 Skill 文件夹大概长这样my-skill/ ├── SKILL.md # 入口文件必须存在 ├── scripts/ # 可执行脚本可选 │ ├── process.py │ └── validate.sh ├── references/ # 参考资料可选 │ ├── style-guide.md │ └── api-schema.json └── assets/ # 模板、静态资源可选 └── template.docxSKILL.md是唯一必须存在的文件其他都是按需添加。我建议一开始只建SKILL.md等确实需要脚本或参考资料时再逐步补充。过早拆分目录会让结构复杂化反而不利于维护。关于存放位置通常有两个选择项目级和用户级。项目级放在项目根目录的.claude/skills/下跟着代码仓库走适合团队共享的规范类 Skill。用户级放在用户主目录的.claude/skills/下只对当前用户生效适合个人习惯类 Skill。如果同名 Skill 同时存在于两个位置项目级通常优先但具体行为建议实际测试确认。3.2 SKILL.md 的编写模板与要点SKILL.md的写法没有强制格式但根据我的实践以下结构效果最好--- name: react-component-generator description: 当需要创建符合团队规范的 React 函数组件时使用包括组件文件、样式文件和测试文件 --- # React 组件生成规范 ## 触发条件 当用户要求创建新的 React 组件或提到生成组件新建页面等关键词时使用本技能。 ## 执行步骤 1. 确认组件名称转换为 PascalCase 格式 2. 在 src/components/ 下创建组件目录 3. 生成 index.tsx使用函数式组件 TypeScript 4. 生成 styles.module.css使用 CSS Modules 5. 生成 index.test.tsx包含基础渲染测试 6. 更新 src/components/index.ts 导出新组件 ## 代码规范 - 组件必须使用 named export不用 default export - Props 接口命名格式为 XxxProps - 样式类名使用 camelCase - 测试文件覆盖率要求达到 80% 以上 ## 注意事项 - 如果组件目录已存在先询问用户是否覆盖 - 如果项目使用 JavaScript 而非 TypeScript跳过类型定义部分 - 生成后运行一次 lint 检查有错误则修复后再交付这个模板里有几个关键点值得展开说。frontmatter 里的 description 极其重要它是模型判断是否加载这个 Skill 的唯一依据必须写清楚“什么时候用”而不是“这是什么”。执行步骤要具体到可操作不要写“生成合适的代码”这种模糊表述要写清楚文件路径、命名规则、具体内容要求。注意事项要覆盖边界情况比如文件已存在怎么办、环境不匹配怎么办这些是实际运行中最容易出问题的地方。3.3 参数传递与动态内容处理Skill 执行过程中经常需要根据用户输入动态调整行为。比如用户说“创建一个叫 UserProfile 的组件”Skill 需要提取出UserProfile这个名称并应用到各个步骤中。这个提取过程不需要特殊语法模型会自然地从对话中理解并填充到流程里。但如果需要更精确的控制可以在SKILL.md里定义变量占位符## 输入参数 - componentName: 组件名称PascalCase 格式 - targetDir: 目标目录默认为 src/components/ - withTest: 是否生成测试文件默认为 true模型读到这些定义后会主动从用户输入中提取对应信息缺失的则使用默认值。这种方式比让模型自由发挥要稳定得多尤其是在团队协作场景下能保证不同人使用同一个 Skill 得到一致的结果。对于需要复杂计算的场景可以配合scripts/下的脚本。比如一个处理数据的 Skill可以在SKILL.md里写“运行python scripts/process.py --input {file}处理数据”模型会调用相应命令并读取输出。脚本的好处是逻辑确定性强不受模型理解偏差影响适合对准确性要求高的环节。4. 实战用 Skills 重构一个真实工作流4.1 场景选择与痛点分析拿一个我实际改造过的场景来说前端项目的新页面创建。在没上 Skills 之前每次新建一个页面我需要手动做这些事创建页面目录、写页面组件、写路由配置、写菜单项、写权限配置、写基础测试。步骤多且容易遗漏尤其是路由和权限这两块经常写完页面忘了注册调试半天才发现问题。这个场景适合用 Skill 来规范化的原因有三个步骤固定每次新建页面都是同样的流程容易出错人工操作总有遗漏频率高一个中型项目开发期可能每周要建十几个页面。三个条件都满足投入时间写 Skill 的回报就很明显。我统计过改造前后的数据改造前平均每个页面创建耗时约 8 分钟其中约 2 分钟花在排查遗漏上改造后平均耗时降到 2 分钟以内且基本不会出现遗漏。按每周创建 10 个页面算一周能省下一个多小时一个月就是四五个小时。这还没算上因为遗漏导致的调试时间。4.2 Skill 内容设计与步骤拆解这个 Skill 的SKILL.md核心部分大概是这样组织的--- name: create-page description: 当需要在前端项目中创建新页面时使用自动完成页面组件、路由、菜单、权限和测试文件的创建 --- # 前端页面创建流程 ## 前置检查 1. 确认当前目录是项目根目录存在 package.json 2. 读取 src/router/routes.ts 了解路由配置格式 3. 读取 src/config/menu.ts 了解菜单配置格式 4. 确认用户提供的页面名称和路径 ## 创建步骤 ### 第一步创建页面组件 - 路径src/pages/{PageName}/index.tsx - 使用函数式组件包含基础布局结构 - 导出方式named export ### 第二步注册路由 - 在 src/router/routes.ts 中添加路由项 - path 使用 kebab-case 格式 - 懒加载方式引入组件 ### 第三步添加菜单项 - 在 src/config/menu.ts 中添加对应菜单 - 菜单标题从页面名称转换而来 - 图标使用默认值后续手动调整 ### 第四步配置权限 - 在 src/config/permissions.ts 中注册页面权限码 - 权限码格式{module}:{page}:view ### 第五步生成测试文件 - 路径src/pages/{PageName}/index.test.tsx - 包含基础渲染测试和路由匹配测试 ## 验证步骤 1. 运行 npm run lint 检查代码规范 2. 运行 npm run test 确认测试通过 3. 运行 npm run build 确认无编译错误 4. 如有错误修复后重新验证 ## 注意事项 - 如果页面名称已存在终止流程并提示用户 - 如果路由文件格式与预期不符先询问用户再操作 - 所有文件创建完成后输出变更文件列表供用户确认这个设计里有几个我踩过坑之后总结的要点。前置检查不能省早期版本没有这一步结果在非项目目录下执行导致创建了一堆垃圾文件。验证步骤要写进流程让模型自己跑 lint 和 test有问题当场修复而不是等用户发现。注意事项要覆盖冲突场景同名页面、格式不匹配这些情况在实际使用中经常遇到提前定义好处理方式能避免很多混乱。4.3 效果验证与迭代优化第一版 Skill 上线后我用了两周时间收集问题。实际运行中暴露出来的问题主要有三类第一类是路径判断错误。有些项目页面放在src/pages/下有些放在src/views/下Skill 硬编码了路径导致后者失败。修复方式是在前置检查里增加路径探测逻辑读取项目配置文件判断实际使用的目录结构。第二类是格式假设过强。不同项目的路由配置格式差异很大有的用数组有的用对象有的用装饰器。Skill 最初假设了一种格式遇到其他格式就生成错误的代码。修复方式是把“读取现有配置并模仿其格式”作为明确步骤写进流程而不是预设格式。第三类是验证环节被跳过。模型有时候会“偷懒”觉得代码写完了就结束了不去跑验证命令。修复方式是在SKILL.md里把验证步骤标记为“必须执行”并说明“未经验证的输出视为未完成”。经过三轮迭代这个 Skill 的首次成功率从最初的六成左右提升到了九成以上。剩下的失败案例基本都是项目结构过于特殊导致的这种就属于正常范围手动处理即可。5. 常见问题排查与避坑指南5.1 Skill 不生效的排查思路Skill 写了但模型不加载这是最常见的问题。排查顺序建议如下排查项检查方法常见原因文件位置确认 SKILL.md 在正确的 skills 目录下放错目录如放到了项目根目录而非 .claude/skills/文件命名确认文件名严格为 SKILL.md大小写错误如 skill.md、Skill.mdfrontmatter 格式确认开头是 --- 包裹的 YAML缺少分隔符或格式错误导致解析失败description 质量检查是否描述了触发场景只写了功能名称模型无法判断何时使用权限问题确认运行环境有读取权限文件权限设置过严我遇到最多的情况是 description 写得太抽象。比如写“代码审查工具”模型不知道什么时候该用改成“当用户提交代码需要审查或提到代码检查时使用”命中率立刻上去了。这个细节看起来小但实际影响很大。5.2 执行结果不稳定的应对策略同一个 Skill 有时候执行得好有时候执行得差这种波动性主要来自三个源头。流程描述有歧义。比如写“生成合适的样式”什么叫合适模型每次理解可能不同。改成“生成 CSS Modules 文件类名使用 camelCase包含容器和内容两个基础类”确定性就强很多。步骤顺序不明确。如果步骤之间有依赖关系但没写清楚模型可能乱序执行。建议用有序列表并标注依赖比如“在完成第二步之后再执行第三步”。缺少异常处理。正常路径写得很清楚但遇到文件已存在、目录不存在这些情况没有定义行为模型就会自由发挥。把常见异常的处理方式写进注意事项能显著降低波动。5.3 多 Skill 协作时的冲突处理当项目里 Skill 数量增多冲突就不可避免。我遇到过两个 Skill 都试图修改同一个配置文件结果互相覆盖。也遇到过两个 Skill 的触发条件重叠模型随机选一个导致行为不一致。处理这类问题的原则是职责单一、边界清晰。每个 Skill 只负责一件事修改配置文件的 Skill 和生成代码的 Skill 分开。如果确实需要协作在SKILL.md里明确写出“本 Skill 完成后建议调用 XX Skill 进行后续处理”让模型知道衔接关系。对于触发条件重叠的情况可以在 description 里加入排除条件。比如“当需要创建新页面时使用不适用于修改现有页面”这样模型在修改场景下就不会误加载。提示定期审查项目里的 Skill 列表合并功能重叠的删除不再使用的。我一般每个月清理一次保持活跃 Skill 在十个以内太多会导致模型选择困难。5.4 团队共享时的版本管理Skill 跟着项目仓库走的时候版本管理就很重要。我的做法是在SKILL.md的 frontmatter 里加一个 version 字段每次修改都递增。同时在项目文档里维护一个变更记录说明每个版本改了什么、为什么改。多人同时修改同一个 Skill 时建议走代码审查流程和改代码一样对待。我见过因为两个人同时改SKILL.md导致流程逻辑冲突最后生成的文件一半新一半旧排查了半天才发现是合并问题。把 Skill 当代码管理能避免很多这类低级问题。6. 进阶玩法让 Skills 真正融入日常开发6.1 从个人工具到团队规范一个人用 Skill 和一群人用 Skill考虑的问题完全不同。个人用的时候怎么方便怎么来团队用的时候必须考虑一致性和可维护性。我推动团队使用 Skills 的过程中总结了几个关键动作。建立 Skill 评审机制。新 Skill 提交后由两到三个人实际跑一遍确认流程合理、边界清晰、结果稳定才能合并到主分支。统一命名规范。所有 Skill 名称使用 kebab-casedescription 统一以“当...时使用”开头方便模型匹配也方便人查找。定期同步会。每两周花半小时过一遍最近新增和修改的 Skill讨论遇到的问题和改进方向。这些机制看起来有点重但实际运行下来团队整体的开发效率提升明显。尤其是新人入职时以前需要口口相传的规范现在都固化在 Skill 里上手速度快了很多。6.2 结合 MCP 打造完整自动化链路单独用 Skills 已经能解决不少问题但结合 MCP 之后能做的事情更多。举个例子一个“代码审查”Skill 可以这样设计通过 MCP 接入代码仓库获取变更内容按照 Skill 里定义的审查规则逐项检查再通过 MCP 把审查结果写入 PR 评论。整个过程从拉取代码到输出结果全自动人只需要最后确认。这种组合的关键在于明确哪些环节用 MCP、哪些用 Skill。我的划分原则是需要和外部系统交互的用 MCP需要做判断和编排的用 Skill。比如“获取 PR 变更”是 MCP 的活儿“判断变更是否符合规范”是 Skill 的活儿“写入评论”又是 MCP 的活儿。按这个原则拆分两边各司其职维护起来也清晰。6.3 持续迭代从能用 to 好用Skill 写完只是开始真正让它变得好用需要持续迭代。我的习惯是每次使用后花一分钟记录这次哪里卡住了、哪里结果不对、哪里可以更快。攒够三五个问题就更新一版SKILL.md。迭代的方向通常有三个减少人工确认环节把更多判断逻辑写进流程让模型自己决策增加异常覆盖把实际遇到的新情况补充到注意事项里优化输出格式让结果更符合下游使用需求。经过几个月迭代一个 Skill 会越来越贴合实际工作最终变成离不开的工具。我个人的体会是Skills 的价值不在于技术有多复杂而在于它把“隐性知识显性化”这件事变得极其简单。以前那些只存在于老员工脑子里的操作流程现在花半小时就能整理成一个 Skill然后被所有人使用。这种知识沉淀的效率是它最吸引我的地方。