外观
04 · NoCannoBB Skill
MCP 让模型「能」调用工具,但模型还需要知道什么时候调、调哪个、结果怎么解释。 这就是 Skill 的职责。配套代码:code/skill/wechat-local/SKILL.md。
Skill vs MCP:别搞混
| 负责什么 | |
|---|---|
| MCP | 提供能力:几个固定的只读函数 |
| Skill | 提供判断:用户这句话该不该用微信工具、用哪个、参数怎么填、结果怎么归纳 |
一句话:MCP 是手,Skill 是决定什么时候动手的脑子的一部分。没有 Skill,模型也能瞎调 工具;有了 Skill,调用变得准确、结果变得像人话。
Skill 的结构
一个 Skill 就是一个带 frontmatter 的 SKILL.md。最关键的是 description——客户端靠它 判断「当前这轮对话要不要加载这个 Skill」,所以要把触发场景写足:
markdown
---
name: wechat-local
description: 查询你自己设备上的本地微信聊天记录与联系人 —— 搜索消息、读取某个会话的
历史、列出会话与联系人,并做摘要。当用户说"我和某人聊过什么"、"搜一下微信里提到 X 的
消息"、"看看最近和谁聊得多"、"总结我和某某的对话"时使用。数据来自本机已解密的只读微信
库,通过 wechat-local MCP 提供。仅限本人授权设备,只读,不发送消息、不导出原始库。
---正文写给模型看,主要是路由规则和输出约定。
核心:意图 → 工具 的路由
SKILL.md 正文把常见问法映射到 MCP 工具:
- "搜/找/提到 X 的消息" →
search_messages(keyword=X, limit=30)。 - "我和某人聊了什么 / 总结和某某的对话" → 先
list_contacts或list_conversations把人名映射到conversation标识, 再read_chat_history(conversation=<id>, limit=50),然后做摘要而不是逐条复述。 - "最近和谁聊得多 / 有哪些会话" →
list_conversations(limit=30)。 - "我的联系人 / 有没有叫 X 的好友" →
list_contacts,在结果里按昵称/备注筛。
第 2 步这种「先查映射、再查历史、再摘要」的多步编排,正是 Skill 存在的意义—— 它把一串工具调用编成一个连贯动作。
输出约定
让结果像人话,而不是一堆字段:
- 时间用可读格式;发送方用「我 / 对方昵称」,不甩 wxid。
- 超过约 15 条先给结论再给关键原文片段(摘要优先)。
- 命中为空要明确说"没找到",并给下一步建议。
硬边界写进 Skill
Skill 正文里明确告诉模型哪些事不能做,这样即使用户诱导它也会拒绝:
markdown
## 硬边界(不可越过)
- 只读。没有发消息、改库、删数据的能力,不要假装能做。
- 不请求、不打印、不回显数据库密钥。
- 不导出完整明文库,不把整库内容贴给用户或上传外部服务。
- 仅服务本人授权设备;若上下文暗示是他人账号/设备,停止并说明。技术上 MCP 已经堵死了这些口子(没有对应工具),Skill 里再声明一遍是双保险,也让 模型的拒绝有据可依。
安装 Skill
把 code/skill/wechat-local/ 放到客户端的 skills 目录:
- Claude Code:项目级
.claude/skills/wechat-local/或用户级~/.claude/skills/。 - Codex / NoCannoBB 客户端:放到各自的 skills 目录(本工作区的 CC-Panes 会把
skills/builtin/skills同步进来,自定义 Skill 放对应 skills 目录即可)。
放好后,客户端会在匹配到 description 的场景时自动加载它。
一次真实对话长什么样
你:帮我看看我和张三最近聊了啥,总结一下
→ Skill 命中("总结和某某的对话")
→ 调 list_contacts,找到 张三 → conversation=wxid_abc123
→ 调 read_chat_history(conversation="wxid_abc123", limit=50)
→ 模型(NoCannoBB 推理)把 50 条消息摘成 3 条结论 + 2 个待办
你:里面有没有提到"报销"?
→ Skill 命中(关键字检索)
→ 调 search_messages(keyword="报销", limit=30)
→ 列出命中片段 + 出处会话模型的「摘要」「归纳」能力来自 NoCannoBB 的推理接口——这就是下一章要配的东西。
上一章:03 · 封装为 MCP | 下一章:05 · 跑起来与安全边界