外观
03 · 封装为 MCP
第 2 章的读库层已经是几个干净的 Python 函数。这一章把它们暴露成 MCP 工具, 让任意支持 MCP 的客户端(Claude Code、Codex、NoCannoBB 等)都能调用。配套代码: code/wechat_mcp/server.py。
什么是 MCP,为什么用它
MCP(Model Context Protocol)是一套「让 AI 客户端发现并调用外部工具」的标准协议。 你写一个 MCP Server,声明几个工具(名字、参数、返回),客户端启动它、把工具列表交给 模型,模型就能在对话中按需调用。
对我们来说,MCP 是那道闸门:模型只能看到我们声明的这几个只读工具,看不到密钥, 也发不出任意 SQL。
安装
powershell
cd course/wechat-ai-assistant/code
pip install -r wechat_mcp/requirements.txt # mcp[cli] + pycryptodome + zstandard用 FastMCP 声明工具
mcp 官方 SDK 提供 FastMCP,用装饰器就能把一个函数变成工具,docstring 会成为模型 看到的说明,类型注解会成为参数 schema:
python
from mcp.server.fastmcp import FastMCP
from wechat_win import db_reader_win as reader
mcp = FastMCP("wechat-local")
@mcp.tool()
def search_messages(keyword: str, limit: int = 30) -> list[dict]:
"""在所有会话里按关键字搜索消息(子串匹配,时间倒序)。"""
db = _require_msg()
...server.py 一共声明四个工具,和第 2 章的四个动作一一对应:
| 工具 | 说明 |
|---|---|
list_conversations(limit) | 列会话及其消息表 |
list_contacts(limit) | 列联系人 |
read_chat_history(conversation, limit) | 读某会话最近消息 |
search_messages(keyword, limit) | 全局关键字搜 |
刻意不声明的:execute_sql()、dump_key()、export_all_messages()。能力面越小越安全。
两种数据来源(密钥怎么处理)
server.py 启动时用 _resolve_plain_paths() 决定读哪个明文库,支持两种配置:
A. 指向已导出的明文库(推荐,MCP 层完全不碰密钥)
先用第 1 章的 CLI 导出一次明文库:
powershell
python -m wechat_win.main_win --out C:\temp\wx_plain再让 MCP 指向它:
WECHAT_PLAIN_DIR=C:\temp\wx_plainMCP 只读这个目录里的 message_0.db / contact.db,协议里、日志里、返回值里都不会出现 密钥。这是最干净的分层。
B. 指向加密库 + 显式密钥(MCP 启动时解密到临时文件)
WECHAT_ENC_MSG_DB=E:\xwechat_files\<wxid>\db_storage\message\message_0.db
WECHAT_ENC_CONTACT_DB=E:\xwechat_files\<wxid>\db_storage\contact\contact.db
WECHAT_MSG_KEY=<64位hex>密钥只通过环境变量传入,server.py 用它在启动阶段解密到临时明文文件,之后运行期 只读临时库。密钥永不打印、不写日志、不进返回值。进程退出时 atexit 自动删除临时库:
python
_TMP_FILES: list[str] = []
def _cleanup():
for f in _TMP_FILES:
try: os.remove(f)
except OSError: pass
atexit.register(_cleanup)默认脱敏
设 SANITIZE=1 时,返回结果里的 wxid / 群 id 会打码(_mask_wxid),昵称/备注保留可读。 适合把结果贴给别人看、或在录屏演示时用。
本地自测
不接客户端,直接用官方 inspector 手动点一遍工具:
powershell
# 以来源 A 为例
$env:WECHAT_PLAIN_DIR="C:\temp\wx_plain"
python -m mcp dev wechat_mcp/server.py # 打开 MCP Inspector,逐个工具试
# 或直接以 stdio 方式跑(供客户端拉起)
python -m wechat_mcp.server看到四个工具、list_contacts 能返回数据,就说明 MCP 层通了。
客户端注册(第 5 章还会细讲)
以 Claude Code / Codex 为例,在 MCP 配置里加一项,指向本 server(把 cwd 设为 code/ 目录以便 import wechat_win):
json
{
"mcpServers": {
"wechat-local": {
"command": "python",
"args": ["-m", "wechat_mcp.server"],
"cwd": "D:/SynologyDrive/workspace/sub2api-product/course/wechat-ai-assistant/code",
"env": { "WECHAT_PLAIN_DIR": "C:/temp/wx_plain", "SANITIZE": "0" }
}
}
}注册后,客户端里的模型就能看到 wechat-local 的四个工具了。下一章我们写一个 Skill, 让模型知道什么时候、怎么用它们。
上一章:02 · 只读读库层 | 下一章:04 · NoCannoBB Skill