Claude Code 学习笔记(二)自定义Skill 与 MCP 的协同工作

Claude Code 中 Skill 与 MCP 的协同工作机制

obsidian-plugin-dev Skill 与 obsidian-api MCP Server 为实例

1. 引言

Claude Code 提供了两种扩展 AI 能力的机制:Skill(技能包)和 MCP Server(Model Context Protocol 服务器)。二者在设计哲学上分属不同范式——前者是静态知识注入,后者是动态工具调用——但在实际工程中可以构成互补的协同关系。

本文以 Obsidian 插件开发场景为例,分析二者的技术特征、局限性,以及联合部署后的协同效果。

2. 机制概述

2.1 Skill:静态知识注入

Skill 是 Claude Code 的按需加载知识包,存储于 ~/.claude/skills/<skill-name>/ 目录下。其核心结构如下:

~/.claude/skills/obsidian-plugin-dev/
├── SKILL.md                    # 入口文档(YAML frontmatter + 主体内容)
├── references/                 # 参考文档(按需加载)
│   ├── api-quick-reference.md
│   ├── ui-patterns.md
│   ├── editor-extensions.md
│   ├── framework-integration.md
│   ├── publishing-checklist.md
│   └── troubleshooting.md
├── assets/                     # 项目模板
│   ├── template-simple/
│   ├── template-view/
│   └── template-editor-extension/
└── scripts/
    └── init-obsidian-plugin.ps1

触发机制:当用户的请求与 SKILL.md 中 description 字段的语义匹配时,Claude Code 自动将 SKILL.md 注入到上下文中。references 子文档可由 AI 在需要时主动读取。

本实例中 Skill 提供的知识

知识域 内容 来源
需求分类 3 级决策树(简单/视图/编辑器扩展) 经验总结
项目脚手架 3 套完整可编译模板 官方示例提炼
API 速查 66 类 + 92 接口 + 56 函数的方法表 obsidian.d.ts 提炼
UI 模式 9 种组件的完整代码模板 官方文档
编辑器扩展 CodeMirror 6 扩展开发指南 官方文档
质量规则 9 条强制性代码规范 社区审核标准

2.2 MCP Server:动态工具调用

MCP(Model Context Protocol)是一种标准化的工具服务协议。MCP Server 作为独立进程运行,通过 stdio 与 Claude Code 通信,向 AI 暴露可调用的工具函数。

~/.claude/mcp-servers/obsidian-api/
├── package.json
└── index.mjs         # MCP Server 实现

注册方式:在 ~/.claude.jsonmcpServers 字段中声明:

{
  "mcpServers": {
    "obsidian-api": {
      "command": "cmd",
      "args": ["/c", "node", "C:\\Users\\123\\.claude\\mcp-servers\\obsidian-api\\index.mjs"],
      "type": "stdio"
    }
  }
}

本实例中 MCP 提供的工具

工具名 功能 输入 输出
lookup_api 查询 API 类型定义 query(如 "Vault.read"), project_path obsidian.d.ts 提取的真实签名 + JSDoc
list_api 列出所有导出声明 project_path, filter(可选) 按类型分组的声明列表

工作原理index.mjs 在运行时读取项目目录下 node_modules/obsidian/obsidian.d.ts 文件,通过大括号深度追踪算法解析顶级声明块,支持精确匹配、Class.method 成员查询、模糊搜索和全文检索四级回退策略。

3. 单独工作时的能力边界

3.1 Skill 的局限性

Skill 本质上是编写时固化的文档,存在三个结构性缺陷:

  1. 静态快照问题:Skill 中的 API 参考是编写时的快照。当 Obsidian 发布新版本(如新增 API 或修改签名)时,Skill 内容不会自动更新。
  2. 知识遗忘风险:AI 模型可能在长上下文中逐渐偏离 Skill 注入的规范,回退到预训练知识中的过时或错误信息。
  3. 精度上限:速查表为了控制篇幅必须压缩信息。例如 Vault 类有数十个方法,速查表仅列出核心方法的简要签名,参数类型、返回值、重载等细节可能被省略。

3.2 MCP Server 的局限性

MCP Server 能提供实时精确的 API 定义,但也有不足:

  1. 无架构指导:MCP 只返回原始类型定义,不提供"何时使用哪个 API"的设计建议。
  2. 无代码模板:MCP 不包含项目脚手架、构建配置、最佳实践等工程知识。
  3. 依赖项目环境:需要目标项目已执行 npm install obsidian,否则无法读取 .d.ts 文件。
  4. 查询需要先验知识:AI 需要先知道"应该查询什么"才能调用 MCP。如果 AI 不知道某个类的存在,就不会主动去查询它。

4. 协同工作模型

当 Skill 与 MCP 同时部署时,二者在 AI 的推理流程中形成知识层 + 验证层的分工:

用户请求: "创建一个插件,读取所有 Markdown 文件并统计字数"
         │
         ▼
   ┌─────────────┐
   │  Skill 层    │  决策树判断 → 选择 template-simple
   │ (知识注入)   │  加载 API 速查 → 初步确定使用 Vault.getMarkdownFiles() + Vault.read()
   │              │  加载质量规则 → 确定 normalizePath、onunload 等约束
   └──────┬───────┘
          │
          ▼
   ┌─────────────┐
   │  MCP 层     │  lookup_api("Vault.getMarkdownFiles") → 确认返回 TFile[]
   │ (实时验证)  │  lookup_api("Vault.read") → 确认参数为 TFile, 返回 Promise<string>
   │             │  lookup_api("TFile") → 确认 TFile 的属性(path, basename, extension 等)
   └──────┬──────┘
          │
          ▼
   ┌─────────────┐
   │  代码生成    │  基于模板 + 经过验证的 API 签名 → 生成类型安全的代码
   └─────────────┘

4.1 各阶段的职责划分

阶段 Skill 的贡献 MCP 的贡献
需求分析 决策树分类,选择模板
架构设计 插件骨架结构,文件组织
API 选择 速查表提供候选 API
API 验证 从 d.ts 返回精确签名
代码生成 质量规则约束 确保类型正确
构建配置 esbuild/tsconfig 模板
发布流程 审核清单 + CI 模板

4.2 实测对比

Vault.read() 方法为例:

仅 Skill(来自 api-quick-reference.md):

read(file: TFile): Promise<string>    // 读取文件内容

Skill + MCP(MCP 返回的真实定义):

/**
 * Read the content of a cached vault file.
 * @param file - The file to read
 */
read(file: TFile): Promise<string>;

差异分析:本例中方法签名一致,但 MCP 额外提供了 JSDoc 注释(“cached vault file” 这一语义信息对正确使用至关重要——它意味着该方法读取的是缓存内容,而非直接磁盘 I/O)。对于更复杂的 API(如 Editor 类的多重载方法),MCP 的精确签名可以避免参数顺序或类型错误。

5. 协同效果的量化评估

评估维度 仅 Skill 仅 MCP Skill + MCP
模板选择准确性 无此能力
API 方法名正确率 中高(依赖速查表覆盖度) 高(可枚举所有声明)
API 签名精确度 中(压缩信息可能丢失细节) 高(原始 d.ts)
设计模式合理性 高(9 种 UI 模式) 无此能力
代码规范合规性 高(9 条质量规则) 无此能力
API 版本同步性 低(静态快照) 高(跟随 npm 版本)
幻觉风险 低(有 d.ts 兜底)
冷启动能力 高(无需项目环境) 低(依赖 node_modules) 高(Skill 兜底)

6. 局限性与改进方向

6.1 当前方案的已知局限

  1. MCP 的 d.ts 解析器基于正则和大括号计数,对于嵌套泛型、条件类型等复杂 TypeScript 语法可能解析不完整。更健壮的方案应使用 TypeScript Compiler API(ts.createSourceFile)进行 AST 级解析。
  2. Skill 与 MCP 之间无显式协议。AI 是否在生成代码前调用 MCP 验证,取决于模型的自主判断,而非强制约束。
  3. references 文档的按需加载依赖 AI 的主动读取。如果 AI 未读取相关 reference 文件,其中的知识不会生效。

6.2 可能的改进方向

方向 具体措施
解析精度 将 MCP 的正则解析替换为 TypeScript Compiler API
强制验证 在 SKILL.md 中加入明确指令:“生成 Obsidian API 调用前必须先调用 lookup_api 验证”
自动补全 MCP 增加 suggest_api 工具,根据功能描述推荐合适的 API
版本对齐 MCP 返回结果中附带 Obsidian 版本号,与 manifest.json 的 minAppVersion 联动

7. 结论

Skill 与 MCP 在 Claude Code 中分别承担知识供给事实验证的角色。Skill 提供体系化的工程知识(架构决策、代码模板、质量规范),解决的是"如何做"的问题;MCP 提供实时的类型系统访问,解决的是"做得对不对"的问题。

二者的协同并非简单叠加,而是形成了一条从设计验证的完整链路:Skill 缩小了搜索空间(从无限可能收敛到合理方案),MCP 在最终输出前提供了事实校验(从合理方案收敛到正确实现)。这种分层架构在其他领域同样适用——任何需要"领域知识 + 精确规范"的 AI 辅助开发场景,都可以参考此模式。

附录 A:文件清单

# Skill(知识层)
~/.claude/skills/obsidian-plugin-dev/
├── SKILL.md                              462 行, 入口文档
├── references/
│   ├── api-quick-reference.md            497 行, API 速查表
│   ├── ui-patterns.md                    593 行, UI 组件模式
│   ├── editor-extensions.md              491 行, CM6 扩展指南
│   ├── framework-integration.md          362 行, 框架集成
│   ├── publishing-checklist.md           239 行, 发布清单
│   └── troubleshooting.md               256 行, 问题排查
├── assets/
│   ├── template-simple/                  6 文件, 简单插件模板
│   ├── template-view/                    8 文件, 视图插件模板
│   ├── template-editor-extension/        8 文件, 编辑器扩展模板
│   └── github-release.yml               CI 发布模板
└── scripts/
    └── init-obsidian-plugin.ps1          项目初始化脚本

# MCP Server(验证层)
~/.claude/mcp-servers/obsidian-api/
├── package.json
└── index.mjs                             348 行, lookup_api + list_api

附录 B:MCP 注册配置

// ~/.claude.json (摘录)
{
  "mcpServers": {
    "obsidian-api": {
      "command": "cmd",
      "args": ["/c", "node", "<path-to>/mcp-servers/obsidian-api/index.mjs"],
      "type": "stdio"
    }
  }
}
1 个赞