内容
# WizNote MCP Server
为知笔记 (WizNote) 的 MCP (Model Context Protocol) 服务,为 AI 提供语义搜索和知识整理、管理笔记、「剪藏」网页的能力。
## 24 个 MCP 工具
| # | 工具 | 用途 |
|---|------|------|
| 1 | `wiznote_kb_list` | 列出知识库 |
| 2 | `wiznote_kb_overview` | 知识库概览(笔记数+目录结构+标签数) |
| 3 | `wiznote_category_list` | 列出文件夹 |
| 4 | `wiznote_category_create` | 创建文件夹 |
| 5 | `wiznote_note_list` | 列出笔记(分页、排序) |
| 6 | `wiznote_note_get` | 获取笔记完整内容 |
| 7 | `wiznote_note_create` | 创建笔记 |
| 8 | `wiznote_note_update` | 更新笔记/移动目录/设置标签 |
| 9 | `wiznote_note_delete` | 删除笔记 |
| 10 | `wiznote_note_search` | BM25 全文搜索(模糊/短语/布尔/Chunk) |
| 11 | `wiznote_tag_list` | 列出所有标签 |
| 12 | `wiznote_tag_create` | 创建标签(支持层级) |
| 13 | `wiznote_tag_rename` | 重命名标签 |
| 14 | `wiznote_tag_delete` | 删除标签 |
| 15 | `wiznote_note_list_by_tag` | 按标签列出笔记 |
| 16 | `wiznote_clip` | 剪藏 — 原始网页保存 |
| 17 | `wiznote_save_content` | 剪藏 — AI 处理后保存 |
| 18 | `wiznote_batch_read` | 剪藏 — 读取网页供 AI 处理 |
| 19 | `wiznote_organize` | 整理笔记 — 列出目录笔记供分类 |
| 20 | `wiznote_note_batch_get` | 批量并发获取笔记内容 |
| 21 | `wiznote_export_category` | 导出目录为 Markdown 合集 |
| 22 | `wiznote_recent_changes` | 最近变更追踪(N 天内) |
| 23 | `wiznote_category_rename` | 重命名文件夹 |
| 24 | `wiznote_normalize` | 笔记规范化的数据准备 |
---
### 操作类型说明
各工具按操作类型分为三类,可在 MCPHub 等客户端中按需启用/禁用:
| 类型 | 说明 | 工具列表 |
|------|------|---------|
| 🔍 **只读** | 查询/检索,不对笔记做任何修改 | `kb_list`, `category_list`, `note_list`, `note_get`, `note_search`, `tag_list`, `note_list_by_tag`, `batch_read`, `organize`, `note_batch_get`, `export_category`, `recent_changes`, `normalize` |
| ✏️ **写入** | 创建或修改笔记/文件夹/标签 | `category_create`, `note_create`, `note_update`, `tag_create`, `tag_rename`, `clip`, `save_content`, `category_rename` |
| 🗑️ **删除** | 永久删除笔记或标签 | `note_delete`, `tag_delete` |
各工具的工具描述中会显示 `[只读]` / `[写入]` / `[删除]` 前缀,MCPHub 等客户端可据此过滤。
### 场景推荐:AI 外挂知识库
若你仅将此 MCP 服务作为 AI 外挂知识库使用(**不对笔记做任何修改**),只启用以下 **13 个只读工具**即可:
```
启用: wiznote_kb_list, wiznote_category_list, wiznote_note_list,
wiznote_note_get, wiznote_note_search, wiznote_tag_list,
wiznote_note_list_by_tag, wiznote_batch_read, wiznote_organize,
wiznote_note_batch_get, wiznote_export_category,
wiznote_recent_changes, wiznote_normalize
禁用: wiznote_category_create, wiznote_note_create, wiznote_note_update,
wiznote_tag_create, wiznote_tag_rename, wiznote_tag_delete,
wiznote_clip, wiznote_save_content, wiznote_category_rename,
wiznote_note_delete (共 10 个写入/删除工具)
```
这样即使连接的是只读账号,AI 也能正常查询和检索笔记内容,不会触发任何写入操作。
---
## 项目特色
### 🔍 BM25 全文搜索 + Chunk 级 RAG
`wiznote_note_search` 内建嵌入式 **Bleve BM25 全文检索引擎**(纯 Go,零外部依赖),让 AI 能通过关键词快速定位笔记,而不再依赖 WizNote 服务端有限的搜索能力。
- **中文分词**:支持 CJK 分词,对中文内容搜索友好
- **模糊匹配**:容忍拼写错误(`emb~2` 可匹配到 `embedding`)
- **短语与布尔查询**:支持 `"exact phrase"` 精确匹配、`+rust -c++` 布尔组合、`title:rust` 字段限定
- **Chunk 级搜索**:新增 `mode="chunk"` 返回匹配段落片段+标题面包屑,AI 无需拉全文直接阅读片段回答
- **增量索引**:首次启动全量建索引,后续智能同步;创建/更新/删除笔记时实时更新 chunk
- **离线可用**:索引在服务本地,不依赖 WizNote 服务端搜索接口
- **非 24/7 友好**:服务重启时毫秒级恢复
- **三层同步引擎**:T1 层次化探针(默认24h)检测外部新增/修改,T2 定向增量精准更新,T3 统计采样检测删除
- **搜索时自动清理已删除笔记**:返回搜索结果后异步验证 TOP 3 笔记的存在性,已删除笔记从索引中移除
### 🏷️ 标签体系
WizNote API 原生支持标签管理。现提供完整的标签 CRUD:
- 列出、创建、重命名、删除标签
- 标签支持树形层级结构(通过父标签 GUID 关联)
- 按标签列出笔记
AI 在整理笔记时,先扫描现有标签池,优先复用已有标签,无匹配时再创建新标签。标签支持多标签。
### 📦 批量操作
WizNote API 本身不提供批量端点,以下工具通过客户端并发实现:
- **批量获取**:输入多个 docGuid,并发下载完整内容,返回纯文本正文
- **目录导出**:遍历目录下笔记,并发获取正文,组装为 Markdown 合集
- **最近变更**:按修改时间倒序列出指定天数内的笔记
- **文件夹重命名**:补齐 WizNote API 已有的 `PUT /ks/category/rename` 端点
### 📝 笔记规范化
`wiznote_normalize` 为 AI 提供笔记规范化的数据准备工作:
- 并发获取目录下全部笔记的完整正文(HTML→Text 净化)
- 检测标题首字符是否为英文标点(`,` `.` `!` `?` `#` `:` `;` `~`),标记出自动命名与手动命名的笔记
- AI 据此工作:以标点开头的笔记只打标签不改标题;其余则根据正文生成新标题并分配标签
这个工具遵循**数据准备模式** —— 只做数据获取和特征标记,智能决策完全由 AI 完成。
---
## 「剪藏」两种工作模式
### 模式一:原始网页保存
```
用户说:"保存这个网页到wiznote"
→ wiznote_clip(urls=[url1, url2])
→ 每个URL独立保存为一条笔记
→ 图片/CSS/JS 全部下载到本地
```
**工具:`wiznote_clip`**
| 参数 | 说明 |
|------|------|
| `urls` | 一个或多个 URL,每个独立保存 |
| `timeout` | 每 URL 超时(默认 60s,最大 600s) |
| `use_browser` | 浏览器渲染(默认 true) |
| `category` | 保存目录,默认 `/网页收藏/原始网页/` |
### 模式二:AI 处理保存
```
用户说:"把这个网页AI处理保存到wiznote"
→ wiznote_batch_read(urls=[url1, url2]) ← 读取原始内容
→ AI 分析内容、去噪、重新组织
→ wiznote_save_content(title, content) ← 保存结构化笔记
→ 多URL合并为一条笔记
```
**步骤 1:`wiznote_batch_read`**
| 参数 | 说明 |
|------|------|
| `urls` | 一个或多个 URL 读取纯文本 |
| `timeout` | 每 URL 超时(默认 60s) |
返回:纯文本正文(无 HTML 标签)+ 图片 URL 列表
**步骤 2:`wiznote_save_content`**
| 参数 | 说明 |
|------|------|
| `title` | 笔记标题 |
| `content` | Markdown 格式正文(AI 整理后) |
| `category` | 保存目录,默认 `/网页收藏/AI处理/` |
| `source_url` | 原文链接 |
| `image_urls` | 图片 URL 列表(自动下载) |
---
## 目录规则
AI 根据用户意图自动决策目录存放位置:
| 用户说 | AI 行为 |
|--------|---------|
| "保存到/Linux/目录" | 调用 `wiznote_category_create` 创建(若不存在)→ 存入 |
| "存放到合适的目录" | 调用 `wiznote_category_list` 查看现有目录 → 按内容匹配最深子目录 |
| "保存到wiznote"(未提及目录)| 原始网页 → `/网页收藏/原始网页/`;AI 处理 → `/网页收藏/AI处理/` |
AI 优先选择最具体的子目录(如 `/编程/JAVA/` 而非 `/编程/`)。
---
## 整理笔记
### 工具:`wiznote_organize`
当用户说"帮我整理一下wiznote的某某目录"时,AI 通过此工具获取目录下的笔记列表,分析后分类归入合适的文件夹。
| 参数 | 说明 |
|------|------|
| `source` | 源目录路径(**必须是没有子目录的叶子目录**) |
| `target` | 目标根目录(可选,默认全目录树) |
| `count` | 最大返回笔记数(默认 50,最大 200) |
### 前置检查(AI 强制执行)
```
用户说:"帮我整理一下wiznote的/网页收藏/原始网页/目录"
↓
AI 调用 wiznote_category_list() 检查 /网页收藏/原始网页/ 是否有子目录
├── 有子目录 → 取消任务,告知用户
└── 无子目录 → 继续
↓
AI 调用 wiznote_organize(source="/网页收藏/原始网页/")
→ 获取笔记列表(标题+docGuid)
↓
AI 分析每个标题,判断应放入哪个目录
↓
AI 调用 wiznote_note_update(docGuid="xxx", category="/目标目录/")
→ 逐篇移动笔记
```
### 两种整理模式
| 用户说 | AI 行为 |
|--------|---------|
| "帮我整理一下wiznote的/网页收藏/原始网页/目录" | 在整个目录树中找最佳匹配目录 |
| "帮我整理一下wiznote的/网页收藏/原始网页/目录,整理到/Linux/目录下" | 在 `/Linux/` 的子目录中找最佳匹配 |
### 笔记移动
通过 `wiznote_note_update` 的 `category` 参数实现笔记移动。只需传入新目录路径,无需修改笔记的 HTML 内容。
---
## 笔记规范化
### 工具:`wiznote_normalize`
当用户说"将wiznote中某某目录下的笔记规范化"时,AI 通过此工作流执行:
**工作流:**
```
用户说:"将 /网页收藏/原始网页/ 目录下的笔记规范化"
↓
Step 1: AI 调用 wiznote_category_list 检查目录是否有子目录
├── 有子目录 → 取消
└── 无子目录 → 继续
↓
Step 2: AI 调用 wiznote_tag_list 获取现有标签池
↓
Step 3: AI 调用 wiznote_normalize(source="/网页收藏/原始网页/")
→ 返回每条笔记的 docGuid, title, body, startsWithPunctuation
↓
Step 4: AI 遍历每条笔记:
├── startsWithPunctuation == true (标题以英文标点开头如 , . ! ? # : ; ~)
│ └── 该笔记是人为命名 → 只加标签,不改标题
│
└── startsWithPunctuation == false
└── 根据 body 生成新标题 → 调用 wiznote_note_update(title=新标题)
↓
Step 5: AI 分析正文内容主题,匹配标签
├── 有相似现有标签 → 复用 tagGuid
└── 无匹配 → 调用 wiznote_tag_create 创建新标签
↓
Step 6: AI 调用 wiznote_note_update(docGuid, tagGuids="guid1*guid2")
→ 设置标签(pipe 分隔,支持多标签)
```
**工具参数:**
| 参数 | 必填 | 说明 |
|------|------|------|
| `source` | ✅ | 源目录路径(**必须是叶子目录**)|
| `count` | — | 最大返回笔记数(默认 50,最大 200)|
| `kbGuid` | — | Knowledge base GUID |
---
> 开发者请参阅 [ARCHITECTURE.md](./ARCHITECTURE.md) 了解设计原理、方案选型和实现细节。
## 快速开始
### 方法一:Docker Compose(推荐)
```bash
# 1. 复制环境变量配置
cp .env.example .env
# 编辑 .env,填写 WIZNOTE_USERNAME 和 WIZNOTE_PASSWORD
# 2. 启动
docker compose up --build
# 3. AI 客户端连接
http://localhost:8080/mcp
# 4. CloakBrowser-Manager Web GUI
http://localhost:8081
```
### 方法二:直接运行
```bash
# 需要 CloakBrowser-Manager 环境
export WIZNOTE_USERNAME=your@email.com
export WIZNOTE_PASSWORD=your_password
export WIZNOTE_INDEX_DIR=./data # BM25 索引持久化目录
go build -o wiznote-mcp ./cmd/wiznote-mcp/
./wiznote-mcp
```
### 环境变量
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `WIZNOTE_USERNAME` | — | **必填** 为知笔记账号 |
| `WIZNOTE_PASSWORD` | — | **必填** 为知笔记密码 |
| `WIZNOTE_AS_URL` | `https://as.wiz.cn` | 账号服务器 URL(私有部署时改)|
| `WIZNOTE_PORT` | `8080` | MCP 服务端口 |
| `WIZNOTE_INDEX_DIR` | `./data` | BM25 索引持久化目录 |
| `WIZNOTE_SYNC_CRUD_HOOK` | `true` | T0 CRUD 钩子开关 |
| `WIZNOTE_SYNC_PROBE_INTERVAL_HOURS` | `24` | T1 探针周期(检测外部新增/修改)|
| `WIZNOTE_SYNC_PROBE_SAMPLE_RATE` | `1.0` | T1 探针采样率 |
| `WIZNOTE_SYNC_DELETION_INTERVAL_HOURS` | `168` | T3 删除检测周期 |
| `WIZNOTE_SYNC_DELETION_SAMPLE_COUNT` | `100` | T3 采样数 |
| `WIZNOTE_READ_ONLY` | `false` | 只读模式(禁用所有写入/删除工具)|
| `WIZNOTE_READ_CATEGORIES` | `["/"]` | 读权限目录范围(JSON 数组,前缀匹配)|
| `WIZNOTE_WRITE_CATEGORIES` | `["/网页收藏/"]` | 写权限目录范围(JSON 数组,前缀匹配)|
| `HTTPS_PROXY` | — | 代理(下载 CloakBrowser)|
| `CLOAKBROWSER_DATA_DIR` | `/data` | Manager profile 数据目录 |
---
## 其他说明
**本项目仅为个人研究学习使用**
**GitHub**:https://github.com/jiadxin/wiznote-mcp