真实案例带你理解mcp skill command- claude_0x03

在现代软件开发流程中,自动化文档生成是提升工程效率的关键环节。Release Notes(发布说明) 的编写往往是一项重复性高但容错率低的工作,传统的手动整理方式不仅耗时,还容易遗漏关键变更。本文将以一个真实的 Release Notes 生成器 为例,深入剖析如何利用 Model Context Protocol (MCP) 的核心组件——CommandAgentSkill,构建一个高效、分层且成本优化的自动化系统。

通过本案例,读者将直观理解 MCP 架构中的三层编排逻辑:Command 作为用户交互入口负责参数收集与流程协调;Agent 在独立上下文中执行复杂的 Git 日志分析与分类任务;Skill 则提供领域特定的知识预加载或标准化输出能力。这种架构不仅实现了业务逻辑与底层知识的解耦,还通过模型分层策略(如入口使用轻量级模型,核心分析使用高性能模型)显著降低了 Token 消耗。文章将详细拆解四个关键配置文件的源码,阐述 AskUserQuestion、allowedTools、memory 等高级特性的最佳实践,帮助开发者掌握构建复杂 AI 工作流的核心技巧。

为什么选择 Release Notes 生成器作为典型案例

在探讨抽象的架构决策树之前,通过具体的代码实例来理解概念往往更为高效。Release Notes 生成器 是一个极具代表性的工程场景:它输入起始 Git Tag 和目标版本号,输出一份按照 feat(新功能)、fix(修复)、chore(杂项)和 breaking(破坏性变更)分类整理的 Markdown 文档。几乎每个技术团队都经历过手动维护发布说明的痛苦,当版本迭代频繁时,自动化这一过程成为刚需。

选择该案例并非因为它业务逻辑极其复杂,而是因为它完美覆盖了 MCP 架构中的所有关键要素。首先,它展示了 Command 如何作为协调入口处理用户交互;其次,Agent 需要在独立的上下文中扫描 Commit 记录并进行语义分类,体现了隔离执行的优势;再者,它演示了两种 Skill 模式的分工协作——一种是用于预加载 Git 日志解析知识的只读 Skill,另一种是直接调用以生成格式化文件的写入 Skill。

此外,该案例还涉及了 模型分层优化跨会话记忆(Memory) 的应用。通过在入口处使用低成本模型,在核心分析层使用高智力模型,可以在保证质量的同时大幅降低成本。同时,利用 Memory 机制记录上次处理的 SHA 值,避免了重复分析历史提交。这种“麻雀虽小,五脏俱全”的设计,使其成为学习 MCP 三层编排架构的理想范本。

> 注意:本文提供的源码旨在展示教学清晰度的最小闭环。若需亲手构建,请参照下方的 Frontmatter 配置与正文逻辑创建四个核心文件;若仅关注架构抽象,跟随后续的拆解分析即可理解核心原理。

系统全景:四层组件与三层架构解析

整个 Release Notes 生成系统由四个核心文件构成,它们分别对应 MCP 架构中的不同角色。为了便于理解,首先通过下表明确各组件的类型、文件位置及其具体职责:

组件名称类型文件位置核心职责
release-notes-crafterCommand.claude/commands/release-notes-crafter.md系统入口,负责通过结构化菜单询问用户起始 Tag、目标版本号及风格偏好。
release-notes-agentSubagent.claude/agents/release-notes-agent.md执行核心,在独立上下文中扫描 Git Commit,依据规则进行分类并返回结构化数据。
git-log-readerSkill (Preload).claude/skills/git-log-reader/SKILL.md知识库,预加载至 Agent,指导其如何读取 Git Log 及识别 Conventional Commits 规范。
release-notes-formatterSkill (Direct).claude/skills/release-notes-formatter/SKILL.md输出层,接收分类后的数据,按照既定模板生成最终的 RELEASENOTES<version>.md 文件。

架构数据流向总览

系统的执行流程遵循严格的分层逻辑,数据流向如下:

  1. 入口层(Command):用户触发 /release-notes-crafter,Command 使用 haiku 模型进行轻量级交互,收集必要参数。
  2. 执行层(Agent):Command 调用 release-notes-agent。Agent 加载 git-log-reader Skill 的知识,在独立上下文中执行 git log 命令,解析并提交分类结果。此过程对主对话透明,避免刷屏。
  3. 输出层(Skill):Command 获取 Agent 返回的结构化 JSON 数据后,调用 release-notes-formatter Skill,将数据渲染为 Markdown 文件并保存至本地。
graph TD
    User[用户] -->|触发命令| Command[release-notes-crafter<br/>Model: Haiku]
    Command -->|Step 1: AskUserQuestion| User
    Command -->|Step 2: Invoke Agent| Agent[release-notes-agent<br/>Model: Sonnet]
    Agent -->|Preload Skill| GitSkill[git-log-reader Skill<br/>Commit解析知识]
    Agent -->|Execute Bash| LocalGit[本地 Git 仓库]
    LocalGit -->|Commit List| Agent
    Agent -->|Return Structured JSON| Command
    Command -->|Step 3: Invoke Skill| Formatter[release-notes-formatter Skill<br/>Markdown排版]
    Formatter -->|Write File| Output[RELEASE_NOTES_v1.2.md]

    style Command fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px
    style Agent fill:#ffebee,stroke:#c62828,stroke-width:2px
    style Formatter fill:#e3f2fd,stroke:#1565c0,stroke-width:2px

注:颜色编码说明——绿色代表 Command 层,负责编排;红色代表 Agent 链,负责核心计算;蓝色代表输出 Skill,负责最终呈现。

实战演示:系统运行流程与交互体验

假设上述四个配置文件已正确部署在项目目录中,用户可以通过以下命令在 Claude Code 环境中触发该工作流:

cd /your-project-root
/release-notes-crafter

执行后,系统将按以下步骤自动运行,整个过程大约持续一分钟,且主对话界面保持整洁:

  1. 参数确认阶段:Claude 会弹出一个结构化的单选菜单,分三步确认关键信息:
    • 起始 Tag:默认为上一个发布的 Tag,用户可修改。
    • 目标版本号:例如输入 v1.2.0。
    • 文档风格:选择 terse(简洁)或 detailed(详细)。
  2. 后台分析阶段:Command 派遣 release-notes-agent 进入独立上下文。Agent 执行 git log <since>..HEAD,依据 Conventional Commits 规范对提交记录进行分类。
  3. 数据返回阶段:Agent 完成分析后,返回结构化数据,例如:“feat × 7, fix × 4, breaking × 1, chore × 12”。值得注意的是,这部分的详细日志不会污染主对话窗口。
  4. 文件生成阶段:Command 接收数据后,调用 release-notes-formatter Skill。Skill 根据模板生成格式精美的 Markdown 文件。
  5. 结果输出:在项目的 release-notes/ 目录下,用户可以看到生成的 RELEASE_NOTES_v1.2.0.md 以及一份简要的 output.md 摘要。

这种设计的最大优势在于上下文隔离。用户不会在主窗口中看到数十条 git log 的输出刷屏,所有的中间处理细节都被封装在 Agent 的独立会话中,极大地提升了用户体验和对话的可读性。

核心组件深度拆解:Command 层设计哲学

Command 源码分析

release-notes-crafter 作为系统的入口,其核心代码如下:

---
description: Craft release notes for a given version — fetches commits between tags, categorizes them, writes a polished RELEASE_NOTES.md
argument-hint: [since-tag] [target-version]
model: haiku
---

## Workflow

### Step 1: Collect Parameters
Use the AskUserQuestion tool to confirm:
- Starting tag (defaults to most recent tag if not given)
- Target version (e.g., v1.2.0)
- Tone: terse / detailed

### Step 2: Analyze Commits
Use the Agent tool to invoke the release-notes-agent:
- subagent_type: release-notes-agent
- prompt: Analyze commits from 
<since>..HEAD, return structured JSON

### Step 3: Write Release Notes
Use the Skill tool to invoke the release-notes-formatter skill with the categorized data.

关键设计决策解析

在该 Command 的配置中,有三个值得深入探讨的设计决策,它们体现了 MCP 架构的最佳实践。

决策一:为何选择 model: haiku?

Command 的核心职责是“协调”而非“计算”。它主要负责与用户交互、分发任务给 Agent 和 Skill。因此,使用成本低廉且响应速度快的 Haiku 模型处理入口交互具有极高的性价比。真正的重型分析任务(如语义分类、Breaking Change 识别)被委托给了使用 Sonnet 模型的 Agent。

> 深度思考:既然 Haiku 足够便宜,为何不全程使用?测试发现,Haiku 在处理复杂的 Conventional Commits 分类时准确率较低,特别是面对如 refactor(api)!: 这样包含 Scope 和 Breaking Marker 的组合时,容易出错。一旦分类错误,后续的人工修正成本将远超节省的 Token 费用。因此,“入口用便宜模型,核心干活用贵模型”是经过权衡后的最优配比。

决策二:为何使用 AskUserQuestion 工具?

传统的自然语言提问(如“请问用户要从哪个 tag 开始”)存在不确定性:用户可能回答模糊(如“呃,上一个”),导致模型需要二次推断。使用 AskUserQuestion 工具可以弹出结构化的单选菜单或预填默认值的输入框。这不仅规范了返回值格式,还能一次性有序地收集多个参数,避免了多轮对话中的信息丢失或乱序问题。

决策三:严格区分 Agent 工具与 Skill 工具

在调用子任务时,必须使用专用的 Agent ToolSkill Tool。尽管早期版本中曾将 Task 重命名为 Agent,但在当前架构下,两者等价。关键在于,绝对不要尝试通过 Bash 命令去间接调用 Agent 或 Skill。Bash 仅用于执行系统级命令(如 git),而 Agent 和 Skill 的调度必须由框架层面的工具完成,以确保上下文隔离和状态管理的正确性。

核心组件深度拆解:Agent 层与职责分离

Agent 源码分析

release-notes-agent 是整个系统中信息密度最高的部分,它充分利用了 Agent Frontmatter 的高级特性:

---
name: release-notes-agent
description: Use this agent PROACTIVELY when you need to draft release notes
  from a git commit range. This agent reads git log, categorizes commits using
  its preloaded git-log-reader skill, and returns structured data for a
  formatter skill to consume.
allowedTools:
  - "Bash(git log*)"
  - "Bash(git tag*)"
  - "Bash(git show*)"
  - "Read"
model: sonnet
color: blue
maxTurns: 8
permissionMode: acceptEdits
memory: project
skills:
  - git-log-reader
hooks:
  PreToolUse:
    - matcher: "Bash(git *)"
      hooks:
        - type: command
          command: python3 ${CLAUDE_PROJECT_DIR}/.claude/hooks/scripts/hooks.py --agent=voice-hook-agent
          timeout: 5000
          async: true
---

## Workflow

1. Run `git log <since-ref>..HEAD` per the preloaded git-log-reader skill instructions
2. Classify each commit (feat / fix / chore / refactor / docs / breaking)
3. For breaking changes, read commit body via `git show 
<sha>`
4. Memory: Update your agent memory with the commit range processed for historical tracking
5. Return structured JSON: { feat: [...], fix: [...], chore: [...], breaking: [...] }

字段详解与最佳实践

逐字段分析该配置,可以揭示 Agent 设计的精髓:

  • description:这是 Claude 自动匹配 Agent 的依据。务必包含 PROACTIVELY 关键词,明确触发条件为“需要从 Git 范围起草发布说明时”。
  • allowedTools:实施最小权限原则。仅授予 Bash(git *) 的子集和 Read 权限,明确禁止 Write 权限。输出文件的操作交由 Skill 完成,确保 Agent 专注于数据分析。
  • model: sonnet:相比入口层的 Haiku,这里使用更强大的 Sonnet 模型,以应对 Conventional Commits 的分类和 Breaking Change 的判断,这些任务需要较强的上下文理解能力。
  • maxTurns: 8:设置最大执行轮数。通常处理 50 条 Commit 只需 3-5 轮,设置 8 轮既提供了足够的余量,又防止了因逻辑错误导致的死循环。
  • memory: project:启用项目级记忆。Agent 可以将上次处理的 SHA 值存入记忆文件,下次运行时可直接跳过已处理的提交,实现增量更新。
  • skills: [git-log-reader]预加载 Skill。这是实现职责分离的关键,详见下文。
  • hooks.PreToolUse:在每次调用 Git 命令前触发钩子(如播放音效),提供后台运行的反馈,防止用户误以为程序卡死。

职责分离:Agent 骨架与 Skill 知识

新手常犯的错误是将所有逻辑(Git 命令、正则表达式、错误处理)全部写入 Agent 的 Markdown 正文中,导致文件臃肿且难以维护。正确的做法是遵循 职责分离 原则:

  • Agent 管“做什么”:仅保留工作流的骨架(如“运行 git log”、“分类”、“返回 JSON”)。
  • Skill 管“怎么做”:将具体的领域知识(如“Git Log 解析格式”、“Conventional Commits 前缀表”、“Breaking Change 识别规则”)封装在 Skill 中。

这种设计使得 Agent 文件保持简洁,而复杂的业务知识则被模块化地存储在 Skill 中,便于复用和维护。

核心组件深度拆解:Skill 层的预加载机制

Skill 源码分析

git-log-reader 是一个典型的 预加载 Skill,其配置如下:

---
name: git-log-reader
description: Instructions for reading git commits between two refs and
  classifying them as conventional commits (feat/fix/chore/refactor/docs/breaking).
user-invocable: false
---

## Instructions

1. Fetch commits:

git log --pretty=format:"%H|%s|%an|%ad" --date=short ..HEAD

Parse each line into `{ sha, subject, author, date }`.

2. Classify by conventional commit prefix:
- `feat:` / `feat(scope):` → **feat**
- `fix:`  / `fix(scope):`  → **fix**
- `chore:` / `refactor:` / `docs:` / `test:` / `style:` → accordingly
- No recognized prefix → **uncategorized**(flag for human review)

3. Detect breaking changes:
- Subject contains `!:` (e.g., `feat!: drop Node 14`)
- OR commit body contains `BREAKING CHANGE:` (fetch via `git show 
<sha>`)

4. Return per-category lists, preserving commit sha so the formatter can link back.

user-invocable: false 的意义

配置项 user-invocable: false 是该 Skill 的关键属性。它表示该 Skill 不会出现在用户的 / 命令菜单中,用户无法直接通过 /git-log-reader 触发它。

这种设计适用于那些“不自洽的半成品指令”。git-log-reader 单独运行毫无意义,它必须依附于 Agent 的上下文,作为 Agent 的“私人手册”或“知识库”存在。隐藏此类 Skill 可以避免用户困惑,保持命令界面的整洁,同时确保领域知识仅在需要的场景下被加载和使用。

通过将解析规则、分类逻辑和 Breaking Change 的检测标准封装在此 Skill 中,Agent 只需简单地引用该 Skill,即可具备专业的 Git 日志处理能力,无需在自身提示词中重复这些细节。这种模块化的知识管理方式是构建大型 AI 应用系统的基石。

4.4 Skill(直接调用):release-notes-formatter

在完成了数据的提取与分类后,我们需要一个专门的组件来处理最终的文档生成。这就是 release-notes-formatter Skill 的职责所在。它不关心数据从何而来,只关注如何将结构化的 JSON 数据转化为符合团队规范的 Markdown 文档。这种职责分离的设计使得该 Skill 具有极高的通用性,既可以被 Agent 自动调用,也可以由用户手动触发。

---
name: release-notes-formatter
description: Formats categorized commit data into a polished
  RELEASE_NOTES_
<version>.md following the project's house style. Writes
  to release-notes/RELEASE_NOTES_
<version>.md and release-notes/output.md.
---

## Instructions

1. Read the Markdown template from [reference.md](reference.md)
2. Render each category section (skip empty categories so空分桶不留空 heading)
3. Prepend breaking changes at the top with ⚠ marker — breaking 最显眼
4. Append compare link: `https://github.com/
<repo>/compare/<since-tag>...<target-version>`
5. Write to `release-notes/RELEASE_NOTES_<target-version>.md`
6. Write a one-paragraph summary to `release-notes/output.md`

## Additional resources

- For template, category headers, tone examples, see [reference.md]
- For 10 real release notes across OSS projects as style reference, see [examples.md]

上述代码块定义了一个标准的 Skill 配置文件。其中,Instructions 部分清晰地列出了执行步骤:首先读取模板,然后渲染各个分类章节,特别强调了跳过空分类以保持文档整洁,并将破坏性变更置顶以引起注意。最后,它会生成两个文件:完整的发布说明和一份简短的摘要。这种明确的指令集确保了输出结果的一致性,无论输入数据如何变化,最终生成的文档格式始终符合项目规范。

这里有两个关键的设计细节值得深入探讨。首先,该 Skill 没有设置 user-invocable: false。这意味着它不仅可以在 Agent 内部被静默调用,还可以作为独立命令通过 /release-notes-formatter 直接触发。只要当前上下文中存在已分类的 Commit 数据(例如用户手动粘贴的 JSON),该 Skill 就能立即工作。这种设计打破了 Skill 必须依附于特定 Agent 的限制,使其成为一个独立可复用的操作单元,极大地提升了灵活性。

其次,该 Skill 采用了渐进式揭露(Progressive Disclosure)的设计模式。仔细观察 SKILL.md 的内容,你会发现核心指令非常精简,而具体的 Markdown 模板和风格示例则被外部引用到了 reference.md 和 examples.md 中。这种设计的核心理由是节省 Token。如果将数百行的模板和示例直接嵌入 SKILL.md,每次 Skill 被加载到上下文时都会消耗大量 Token。通过外部引用,LLM 仅在真正需要生成文档时才去读取这些大文件,从而显著降低了日常交互的成本。

这种“简述 + 引用”的模式是构建高效 Skill 生态的基本原则。在大型项目中,随着业务逻辑的复杂化,知识库文件往往会变得非常庞大。如果将所有知识都堆砌在主配置文件中,不仅会导致上下文窗口迅速耗尽,还会增加 LLM 理解核心指令的难度。通过将静态知识(如模板、规范)与动态指令(如处理逻辑)分离,我们既保持了主配置的轻量级,又确保了在需要时能够获取详尽的背景信息。

5. 完整执行流程时序图

为了更直观地理解 Command、Agent 和 Skill 之间的协作关系,我们可以梳理整个 Release Notes 生成器的执行时序。这个过程涉及多个组件的切换和数据流转,清晰地展示了 MCP 架构如何处理复杂任务。从用户发起请求开始,系统会经历参数收集、子 Agent 启动、数据处理以及最终文档生成的完整闭环。

sequenceDiagram
    participant User as 用户
    participant Claude as Claude (主对话)
    participant Cmd as Command: release-notes-crafter
    participant Agent as Agent: release-notes-agent
    participant Skill1 as Skill: git-log-reader (预加载)
    participant Git as 本地 Git 仓库
    participant Skill2 as Skill: release-notes-formatter
    participant FS as 文件系统

    User->>Claude: /release-notes-crafter
    Claude->>Cmd: 加载 Command 内容为提示词
    Cmd->>Claude: 调用 AskUserQuestion
    Claude->>User: 弹出三步单选菜单 (since, target, tone)
    User->>Claude: 返回参数 (v1.1.0, v1.2.0, terse)
    Claude->>Agent: 工具调用: subagent_type=release-notes-agent
    Note over Agent: 启动独立上下文, 注入 skills: [git-log-reader]
    Agent->>Skill1: 执行预加载的解析规则
    Skill1->>Git: git log v1.1.0..HEAD
    Git-->>Skill1: 返回 48 条 commit
    Skill1->>Git: git show 
<sha> (检查 breaking)
    Git-->>Skill1: 返回 commit body
    Skill1-->>Agent: 结构化数据 {feat:[], fix:[], breaking:[]}
    Agent->>Skill2: 工具调用: release-notes-formatter
    Note over Skill2: 运行时调用, 读取 reference.md
    Skill2->>FS: Write RELEASE_NOTES_v1.2.0.md
    Skill2->>FS: Write release-notes/output.md
    Skill2-->>Agent: 完成信号
    Agent-->>Claude: 返回执行结果 (摘要 + 文件路径)
    Claude-->>User: 展示最终结果

这张时序图揭示了两个至关重要的架构特性。首先是 Agent 上下文的真正隔离。release-notes-agent 在一个独立的沙箱环境中运行,它无法访问主对话的历史记录,也不受主上下文提示词的干扰。它仅依赖于自身的 Frontmatter、预加载的 git-log-reader Skill 以及 Command 传递的参数。这种隔离机制确保了主对话不会被大量的中间数据(如 48 条 Commit 日志或 Breaking Change 的详细分析)所污染,从而保持了主会话的清洁和高效。

其次是 两种 Skill 调用模式的并存与互补。在这个流程中,git-log-reader 是通过 Agent 启动时的 skills: 字段进行预加载的,它成为了 Agent 能力的一部分,用于处理特定的领域知识。而 release-notes-formatter 则是在运行时通过 Skill 工具显式调用的,它作为一个独立的操作单元,接收结构化数据并执行格式化任务。这种混合使用模式展示了 MCP 架构的灵活性:既可以通过预加载增强 Agent 的专业能力,又可以通过运行时调用实现模块化的功能复用。

6. 两种 Skill 模式对比

在实际开发中,开发者常常困惑于何时使用预加载 Skill,何时使用直接调用 Skill。为了澄清这一概念,我们可以通过对比 git-log-reader 和 release-notes-formatter 这两个典型案例来总结规律。这两种模式并非互斥,而是针对不同场景的最佳实践选择。理解它们的差异有助于设计出更加高效且易于维护的 Agent 系统。

特性Agent Skill(预加载)Skill(直接调用)
典型例子git-log-readerrelease-notes-formatter
加载时机Agent 启动时注入 System Prompt被显式调用时执行
触发方式通过 Agent Frontmatter 的 skills: 字段通过 Skill 工具或 /skill-name 命令
核心作用为 Agent 注入领域知识与解析规则在当前上下文执行一个独立的操作流程
用户可见性通常设置为 user-invocable: false可以出现在 / 菜单中供用户直接选择
Token 成本Agent 每轮对话都携带 Skill 内容仅在调用时消耗 Token 读取相关文件

基于上述对比,我们可以提炼出一条经验法则:如果 Skill 提供的是 Agent 完成任务所必需的背景知识或解析逻辑,应选择预加载;如果 Skill 代表的是一个独立、可复用的操作步骤,应选择直接调用。 git-log-reader 属于前者,因为如果没有它,Agent 就无法理解如何解析 Git 日志,它是 Agent 能力的基石。而 release-notes-formatter 属于后者,因为它是一个通用的格式化引擎,只要有符合规范的数据输入,它就可以在任何上下文中工作,不依赖于特定的 Agent 状态。

这种区分不仅关乎技术实现,更关乎系统设计的清晰度。预加载 Skill 使得 Agent 更加“专业”,适合处理垂直领域的复杂任务;而直接调用 Skill 使得功能更加“模块化”,适合构建可组合的工作流。在实际项目中,往往需要结合使用这两种模式,以发挥 MCP 架构的最大潜力。例如,一个复杂的代码审查 Agent 可能预加载了多种语言的分析 Skill,但在生成最终报告时,则会调用一个通用的报告格式化 Skill。

7. 实验:拆掉重来看看

理论讲解之后,最好的学习方式莫过于动手实验。通过尝试不同的触发方式,我们可以更深入地理解 Command、Agent 和 Skill 之间的边界与协作机制。以下三个实验分别展示了从全自动到半自动,再到完全手动的不同交互模式,帮助开发者掌握每种组件的适用场景。

实验 1:不用 Command,直接对话

> 帮我根据 v1.1.0..HEAD 起一份 release notes 草稿

在这个实验中,我们没有使用 /release-notes-crafter 命令,而是直接使用自然语言发起请求。观察发现,Claude 能够自动识别并派遣 release-notes-agent,这是因为在 Agent 的 Description 中包含了 PROACTIVELY 关键字或相关的语义描述。这种方式省去了参数选择的步骤,体验更加流畅。然而,代价是用户需要在自然语言中清晰地表达所有必要参数(如版本号范围、语气风格等),否则 Agent 可能需要多次反问确认,增加了交互轮次。

实验 2:直接调用 Skill

> /release-notes-formatter

在这个实验中,我们直接触发了格式化 Skill。观察发现,Skill 会立即提示缺少必要的输入数据——即分桶好的 Commit 信息。它不会尝试自己去运行 git log,也不会去分析代码库。这清晰地展示了职责分离的原则:release-notes-formatter 只负责排版,不负责数据分析。这个实验验证了 Skill 的独立性,同时也提醒开发者,直接调用 Skill 的前提是上下文中必须已经存在其所需的数据结构。

实验 3:对话式触发排版

> 已知 feat 有 X/Y/Z、fix 有 P/Q、breaking 有 W,给我排一份 v1.2.0 release notes

在这个实验中,用户在对话中直接提供了结构化数据,并请求生成 Release Notes。观察发现,Claude 能够自动匹配 release-notes-formatter,因为其 Description 与用户意图高度吻合。系统将上下文中的分桶数据作为输入传递给 Skill,并成功生成了文档。这种用法非常适合那些已经手工整理好数据、仅需借助模板进行格式化的场景。它展示了 LLM 在意图识别和工具匹配方面的强大能力,使得非技术人员也能轻松利用复杂的 Skill。

触发方式路径覆盖机制
/release-notes-crafterCommand 主动触发Command 优先
"帮我起份 release notes"Claude 匹配 Agent DescriptionAgent 自动匹配
/release-notes-formatterSkill 主动触发Skill 主动调用
"给我排一份 release notes"Claude 匹配 Skill DescriptionSkill 自动匹配

通过这四个维度的对比,我们可以清楚地看到三种扩展机制的“触发面”。Command 提供了结构化的入口,Agent 提供了智能化的代理,而 Skill 提供了原子化的能力。在实际应用中,开发者可以根据任务的复杂度和用户的交互习惯,灵活选择最合适的触发方式,或者将它们组合起来,构建出既强大又易用的 AI 辅助工具。

8. 踩过的坑

在真实项目的落地过程中,我们积累了一些宝贵的经验教训。以下是一些常见的陷阱及其解决方案,希望能帮助开发者避开这些弯路,提高开发效率。

坑 1:Task 还是 Agent?

在早期的文档或代码中,你可能会看到 Task tool 的写法。从 v2.1.63 版本开始,官方正式将其重命名为 Agent tool,但旧名称 Task 仍作为别名保留。这导致新老文档混用,容易引发困惑。建议在新项目中统一使用 Agent 术语,以保持代码的一致性和可读性。如果遇到旧代码,无需紧急修改,两者在功能上是完全等效的。

坑 2:Agent 里 allowedTools 忘声明 Git 命令族

Agent 的 allowedTools 字段是一个白名单机制,用于控制 Agent 可以执行哪些系统命令。如果只声明了 Bash(),虽然权限足够,但在安全审查中通常无法通过。如果声明得过于细致,例如只写了 Bash(git log),却遗漏了 git show*,那么当 Agent 尝试检查 Breaking Change 时,就会因为权限不足而报错。正确的做法是遵循最小权限原则,但务必覆盖完整的工作流,仔细列出所有需要的子命令,如 git log, git show, git diff 等。

坑 3:user-invocable: false 搞反

这是一个常见的配置错误。如果你希望某个 Skill 仅作为 Agent 的内部组件使用,而不希望用户在命令行中看到它,应该设置 user-invocable: false。然而,很多开发者误以为设为 true 才能让 Agent 使用,结果导致该 Skill 出现在用户的 / 菜单中。当用户点击时,由于缺乏必要的上下文数据,Skill 无法正常工作,导致用户体验糟糕。请记住:预加载给 Agent 用的 Skill,通常应隐藏于用户视野之外

坑 4:memory: project 不会自动总结

虽然 Agent 支持记忆功能,但它不会自动记录每一次执行的细节。如果你希望 Agent 记住上次处理到的 Commit SHA,以便下次增量更新,必须在 Agent 的指令中明确指示其更新 Memory。例如,在 release-notes-agent 的指令中加入:“4. Memory: Update your agent memory with the commit range processed for historical tracking”。如果不加这一句,Agent 每次都会从头开始处理,无法实现增量逻辑。这是一个容易被忽视但至关重要的细节。

坑 5:Skill 引用 reference.md 的路径

在 SKILL.md 中引用外部文件时,路径是相对于 Skill 目录本身 的,而不是项目的工作目录。例如,reference.md 意味着 reference.md 必须与 SKILL.md 位于同一目录下。很多开发者从其他示例中复制代码时,忽略了这一点,导致文件找不到错误。在构建复杂的 Skill 库时,建议保持目录结构的清晰,并严格检查相对路径的正确性,以避免此类低级错误。

拆完看全景

通过对 Release Notes 生成器的深入剖析,我们将前两篇文章中抽象的概念落实到了具体的代码和执行路径上。回顾整个架构,我们可以总结出以下几个核心设计原则:

  • 分层模型使用:Command 使用轻量级的 Haiku 模型进行协调和参数收集,Agent 使用能力更强的 Sonnet 模型进行复杂的逻辑处理和代码执行。这种分层策略既保证了响应速度,又控制了成本。
  • 职责分离与解耦:Agent 的正文保持简洁,专注于工作流编排;详细的领域知识和解析规则存储在 Skill 中。这种骨架与知识解耦的设计,使得系统更易于维护和演进。
  • 灵活的 Skill 模式:Skill 既可以通过预加载成为 Agent 的内在能力,也可以通过直接调用成为独立的操作单元。理解这两种模式的区别,是构建高效 MCP 应用的关键。
  • 渐进式揭露优化成本:通过在 SKILL.md 中仅保留核心指令,并将大量静态知识外置引用,我们有效地节省了 Token 消耗,提升了系统的经济性。
  • 上下文隔离保障清洁:Agent 的独立上下文机制,确保了主对话不会被海量的中间数据和推理过程所污染,为用户提供了清爽的交互体验。

下一篇系列文章将聚焦于 Commands,深入探讨官方内置命令有哪些、哪些值得开发者熟记,以及如何判断何时应该封装自定义 Command。这将进一步完善我们对 MCP 架构全貌的理解,帮助开发者构建出更加专业和高效的 AI 辅助工具。