Claude Code 中 Skill 与 MCP 的协同工作机制
以
obsidian-plugin-devSkill 与obsidian-apiMCP 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.json 的 mcpServers 字段中声明:
{
"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 本质上是编写时固化的文档,存在三个结构性缺陷:
- 静态快照问题:Skill 中的 API 参考是编写时的快照。当 Obsidian 发布新版本(如新增 API 或修改签名)时,Skill 内容不会自动更新。
- 知识遗忘风险:AI 模型可能在长上下文中逐渐偏离 Skill 注入的规范,回退到预训练知识中的过时或错误信息。
- 精度上限:速查表为了控制篇幅必须压缩信息。例如
Vault类有数十个方法,速查表仅列出核心方法的简要签名,参数类型、返回值、重载等细节可能被省略。
3.2 MCP Server 的局限性
MCP Server 能提供实时精确的 API 定义,但也有不足:
- 无架构指导:MCP 只返回原始类型定义,不提供"何时使用哪个 API"的设计建议。
- 无代码模板:MCP 不包含项目脚手架、构建配置、最佳实践等工程知识。
- 依赖项目环境:需要目标项目已执行
npm install obsidian,否则无法读取.d.ts文件。 - 查询需要先验知识: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 当前方案的已知局限
- MCP 的 d.ts 解析器基于正则和大括号计数,对于嵌套泛型、条件类型等复杂 TypeScript 语法可能解析不完整。更健壮的方案应使用 TypeScript Compiler API(
ts.createSourceFile)进行 AST 级解析。 - Skill 与 MCP 之间无显式协议。AI 是否在生成代码前调用 MCP 验证,取决于模型的自主判断,而非强制约束。
- 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"
}
}
}