内容
# 思源笔记MCP服务端
思源笔记的[模型上下文协议(MCP)](https://modelcontextprotocol.io)服务端,使用TypeScript编写。
## 功能
- **5工具网关** — 而不是约50个扁平工具,服务端只暴露`siyuan_discover` / `siyuan_describe` / `siyuan_execute_read` / `siyuan_execute_write` / `siyuan_execute_destructive`。能力按需发现,保持MCP客户端上下文小,破坏性操作在其自己的网关后隔离
- **统一全文搜索** — 一个关键词调用可以查找文档标题、块内容、**和数据库行**,并返回`avId`进行深入(普通SQL无法看到数据库行)
- **完整属性视图(数据库)支持** — 创建、读取、写入、更新、删除数据库和行;管理字段、视图、选择选项和文档支持的行
- **文档和块管理** — 创建、更新、删除、导出、折叠/展开、移动和批量编辑文档和块
- **完整笔记本生命周期** — 列出、创建、重命名、打开、关闭、删除、获取/设置配置
- **工作区文件访问** — 读取/写入/删除/重命名文件和列出工作区中的目录
- **SQL查询** — 通过`siyuan_sql`直接访问思源笔记的SQLite
- **实用工具** — 资产上传、Markdown导出、Sprig渲染、Pandoc转换、UI通知、服务端HTTP代理、工作区映射
- **纯HTTP** — 不需要本地工作区路径;与本地和远程思源笔记实例一起工作
---
## 安装
### 前提条件
- [思源笔记](https://b3log.org/siyuan/)正在运行(本地或远程)
- Node.js 18+
### 从npm
使用`npx`直接运行:
```bash
npx @yizixu/siyuan-mcp
```
或全局安装:
```bash
npm install -g @yizixu/siyuan-mcp
siyuan-mcp
```
### 从源码
```bash
git clone https://github.com/yizixu/siyuan-mcp.git
cd siyuan-mcp
npm install
npm run build
```
### 获取API令牌
在思源笔记中:**设置 → 关于 → API令牌** → 复制。
---
## 配置
| 环境变量 | 是否必填 | 描述 |
|---|---|---|
| `SIYUAN_API_TOKEN` | **是** | 思源笔记API令牌 |
| `SIYUAN_API_URL` | 否 | 基础URL(默认:`http://127.0.0.1:6806`) |
复制`.env.example`到`.env`并填写您的令牌,或直接设置环境变量。
---
## MCP客户端设置
### Claude Desktop / Cursor
使用npm:
```json
{
"mcpServers": {
"siyuan": {
"command": "npx",
"args": ["-y", "@yizixu/siyuan-mcp"],
"env": {
"SIYUAN_API_TOKEN": "您的令牌"
}
}
}
}
```
使用本地源码:
```json
{
"mcpServers": {
"siyuan": {
"command": "node",
"args": ["/绝对路径/到/siyuan-mcp/dist/index.js"],
"env": {
"SIYUAN_API_TOKEN": "您的令牌"
}
}
}
}
```
适用于远程思源笔记:
```json
{
"env": {
"SIYUAN_API_TOKEN": "您的令牌",
"SIYUAN_API_URL": "http://192.168.1.100:6806"
}
}
```
---
## 工具参考
服务端暴露**5个网关工具**。所有实际能力都是通过网关发现和执行的名为`domain.action`的操作:
| 工具 | 描述 |
|---|---|
| `siyuan_discover` | 按关键词、领域或风险级别查找操作。返回名称 + 一行摘要 + 风险 |
| `siyuan_describe` | 获取操作的完整输入JSON模式、示例调用及其建议的预检操作 |
| `siyuan_execute_read` | 执行只读操作(搜索、列出、获取、读取、导出) |
| `siyuan_execute_write` | 执行写操作(创建、插入、更新、重命名、移动、上传) |
| `siyuan_execute_destructive` | 执行破坏性操作(删除/移除)。隔离后MCP客户端可以单独控制 |
典型流程:
```
siyuan_discover(query: "数据库行")
→ [{ name: "db.add_rows", risk: "write", ... }]
siyuan_describe(operation: "db.add_rows")
→ { inputSchema, example, executeVia: "siyuan_execute_write", preflightOperation: "db.read" }
siyuan_execute_write(operation: "db.add_rows", args: { avId, rows: [...] })
```
### 操作目录(54个操作)
**搜索 / 系统**
| 操作 | 风险 | 描述 |
|---|---|---|
| `search.fulltext` | read | 跨标题、块**和数据库行**的全文关键词搜索;返回数据库命中的`avId` |
| `system.sql` | read | 思源笔记SQLite的只读SQL(无法看到数据库/AV行 — 使用`search.fulltext` / `db.read`) |
| `system.workspace_map` | read | 所有笔记本ID、文档树(2级)、数据库ID |
| `system.info` / `system.time` | read | 思源笔记版本 / 服务器时间 |
| `system.render_sprig` | read | 渲染Sprig模板字符串 |
| `system.upload_asset` | write | 将文件(base64)上传到资产文件夹 |
| `system.push_message` | write | 在思源笔记UI中显示toast通知 |
| `system.pandoc` | write | 运行Pandoc转换 |
| `system.forward_proxy` | write | 通过内核的服务端HTTP请求 |
**笔记本**
| 操作 | 风险 | 描述 |
|---|---|---|
| `notebook.list` | read | 列出所有笔记本 |
| `notebook.get_conf` | read | 获取笔记本的配置 |
| `notebook.create` / `notebook.rename` / `notebook.set_conf` | write | 创建 / 重命名 / 配置 |
| `notebook.open` / `notebook.close` | write | 挂载 / 卸载 |
| `notebook.remove` | destructive | 永久删除笔记本 |
**文档**
| 操作 | 风险 | 描述 |
|---|---|---|
| `doc.export_markdown` | read | 读取整个文档为干净的Markdown |
| `doc.resolve_path` | read | 转换文档ID ↔ 人类可读路径 |
| `doc.create` / `doc.update` | write | 创建 / 重命名 / 替换内容 / 移动 |
| `doc.delete` | destructive | 删除文档(支持dryRun) |
**块**
| 操作 | 风险 | 描述 |
|---|---|---|
| `block.get_content` / `block.get_attrs` / `block.list_children` | read | 读取Kramdown / 属性 / 子块 |
| `block.insert` / `block.update` / `block.move` / `block.fold` / `block.set_attrs` | write | 编辑块 |
| `block.batch` | write* | 单个调用中的多个操作;*如果任何操作是删除,则需要破坏性网关 |
| `block.delete` | destructive | 删除块 |
**数据库(属性视图)**
| 操作 | 风险 | 描述 |
|---|---|---|
| `db.read` | read | 字段定义 + 行,带过滤/分页 |
| `db.list_views` / `db.list_select_options` | read | 列出视图 / 选择选项 |
| `db.create` / `db.add_rows` / `db.update_cells` | write | 创建数据库 / 添加行 / 更新单元格 |
| `db.add_field` / `db.rename_field` | write | 管理列 |
| `db.add_view` / `db.update_view` | write | 管理视图 |
| `db.set_select_options` | write | 替换选择/多选选项 |
| `db.bind_row_to_doc` / `db.create_doc_backed_row` | write | 文档支持的行 |
| `db.delete_rows` / `db.delete_view` / `db.remove_field` | destructive | 删除行 / 视图 / 列 |
**文件(原始工作区访问)**
| 操作 | 风险 | 描述 |
|---|---|---|
| `file.read` / `file.list_dir` | read | 读取文件 / 列出目录 |
| `file.write` / `file.rename` | write | 写入 / 重命名-移动 |
| `file.remove` | destructive | 删除文件或文件夹 |
---
## 支持的AV字段类型
| 类型 | 描述 |
|---|---|
| `text` | 普通文本 |
| `number` | 数值 |
| `checkbox` | 布尔值 |
| `select` | 单选(一个选项) |
| `mSelect` | 多选(多个选项) |
| `date` | 日期/时间(Unix毫秒时间戳或ISO字符串) |
| `url` | URL |
| `email` | 电子邮件地址 |
| `phone` | 电话号码 |
| `mAsset` | 多资产(文件/图像) |
| `relation` | 另一个AV的关系 |
| `rollup` | 从关系中汇总/计算 |
只读/系统类型:`block`,`created`,`updated`,`lineNumber`,`template`
---
## 快速入门工作流程
### 查找任何内容(先搜索!)
```
siyuan_execute_read(operation: "search.fulltext", args: { query: "todo" })
→ 返回按文档分组的匹配块。
如果匹配在数据库中,则结果在其`databasesFound`中列出avId。
然后:
siyuan_execute_read(operation: "db.read", args: { avId: "<avId from search>" })
→ 该待办事项/任务/表格数据库的完整结构化行。
```
> **为什么不使用SQL?** `system.sql`只能看到`blocks`/`attributes`/`spans`/`assets`
> 表 — 它可以找到数据库*块*但**看不到其中的行**。始终
> 使用`search.fulltext`(或`db.read`)来定位待办事项、任务和表格条目。
### 创建具有字段的数据库
```
1. siyuan_execute_write(operation: "doc.create",
args: { notebookId, path: "/我的项目" })
→ 返回docId
2. siyuan_execute_write(operation: "db.create",
args: { name: "任务", parentDocId: docId,
fields: [
{ name: "状态", type: "select", options: ["待办", "进行中", "完成"] },
{ name: "截止日期", type: "date" },
{ name: "优先级", type: "select", options: ["低", "中", "高"] }
] })
→ 返回 { avID, viewId }
```
### 添加行/更新单元格
```
siyuan_execute_write(operation: "db.add_rows", args: { avId, rows: [
{ "状态": "待办", "截止日期": "2024-12-31", "优先级": "高" }
] })
siyuan_execute_write(operation: "db.update_cells", args: { avId, updates: [
{ rowId: "20240101120000-abc1234", fieldName: "状态", value: "完成" }
] })
```
### 查询SQL/工作区概述
```
siyuan_execute_read(operation: "system.sql",
args: { stmt: "SELECT id, content, hpath FROM blocks WHERE type='d' LIMIT 20" })
siyuan_execute_read(operation: "system.workspace_map", args: {})
→ 以Markdown返回所有笔记本ID、文档路径和数据库ID
```
---
## 默认视图约定
思源笔记的`renderAttributeView`通过视图镜头渲染数据 — 过滤视图可以隐藏行。该服务端在未指定`viewId`时自动优先选择名为**"默认"**(不区分大小写)的视图,确保无过滤访问。
**推荐**:在您通过编程方式访问的每个数据库中创建一个名为`Default`(无过滤器)的视图。
---
## 数据库工作原理
思源笔记属性视图存储为JSON文件,位于:
`{workspace}/data/storage/av/{avID}.json`
`create_database`工具通过思源笔记HTTP文件API(`/api/file/putFile`)写入此JSON文件 — 无需访问本地文件系统。所有其他AV操作都使用官方的`/api/av/`HTTP端点。
---
## 开发
```bash
npm run build # 编译TypeScript → dist/
npm start # 运行编译后的服务端
npm run dev # 监视模式(重新编译时更改)
```
### 发布
发布到npm通过`.github/workflows/publish.yml`自动化:
```bash
npm version patch # 或 minor / major — 更改package.json并创建git标签
git push && git push --tags
```
推送与`v*.*.*`匹配的标签会触发工作流程(检查 → 构建 → 带有出处证明的发布)。
身份验证使用[npm trusted publishing](https://docs.npmjs.com/trusted-publishers)(OIDC)— 无需令牌秘密;
GitHub Actions发布者已在npmjs.com上的包设置中注册。
---
## 许可证
MIT