mcp思源
mcp-siyuan 以a的形式运行 边车 并将其HTTP API公开为MCP工具。它讲两种运输方式-- 可流式传输HTTP 用于远程客户端(Claude Desktop、Claude.ai连接器、n8n)和 标准 对于本地Claude Code,因此相同的映像和代码路径适用于这两个用例。
flowchart LR
Client["Claude Desktop / Claude.ai / n8n / Claude Code"]
CFA["Cloudflare Access
(JWT auth)"]
Portal["MCP Portal
(aggregator)"]
Server["mcp-siyuan
(this repo)"]
Kernel["SiYuan kernel
(internal HTTP endpoint)"]
Client -->|streamable HTTP| CFA
CFA --> Portal
Portal -->|JSON-RPC over HTTP| Server
Server -->|/api/* POST| Kernel
Client -. stdio .-> Serverstdio路径由本地Claude代码直接使用;HTTP路径穿过经过身份验证的边缘(例如Cloudflare Access)和MCP门户聚合器。
______________________________________________________________________
工具目录
所有工具均暴露在 siyuan_ 在入口处添加前缀(例如。, siyuan_list_notebooks).在内部,它们被注册为裸名。每个写入工具都接受一个可选 idempotency_key --看 操作员操作手册.
第1层——读取/查询
| 工具 | 说明 |
|---|---|
siyuan_list_notebooks | 列出思源工作区中的所有笔记本。 |
siyuan_sql_query | 对思源的内部数据库执行只读SQL SELECT。 |
siyuan_get_document | 通过块ID获取文档的markdown内容 |
siyuan_search | 快速全文搜索所有思源内容(无周围上下文)。 |
siyuan_get_block | 按ID获取单个块的内容和元数据 |
siyuan_get_block_attrs | 获取块的所有属性(系统和自定义)。 |
第二层——写作
| 工具 | 说明 |
|---|---|
siyuan_create_notebook | 在思源中创建一个新笔记本。 |
siyuan_rename_notebook | 重命名现有笔记本。 |
siyuan_remove_notebook | 删除笔记本及其所有文档。 |
siyuan_create_document | 在思源笔记本中创建新文档。接受 idempotency_key. |
siyuan_update_block | 更新现有块的内容。接受 idempotency_key. |
siyuan_insert_block | 相对于锚块插入新块。接受 idempotency_key. |
siyuan_append_block | 将内容附加到文档或容器块的末尾。接受 idempotency_key. |
siyuan_delete_block | 按ID删除块 |
siyuan_set_block_attrs | 在块上设置属性。接受 idempotency_key. |
siyuan_move_doc | 将一个或多个文档移动到新的父文档或笔记本。 |
siyuan_rename_doc | 重命名文档而不移动它 |
siyuan_move_block | 将块移动到新位置。 |
siyuan_daily_note | 在笔记本中创建或打开今天的每日笔记。 |
Smart——LLM人体工程学高级工具
| 工具 | 说明 |
|---|---|
siyuan_get_recent_docs | 获取最近修改的文档,最新的优先。 |
siyuan_find_tasks | 在思源笔记中查找任务/待办事项。 |
siyuan_get_backlinks | 获取引用(链接到)给定块或文档的所有块。 |
siyuan_get_tags | 列出整个工作区中使用的所有标签及其使用计数。 |
siyuan_search_by_tag | 查找具有特定标记的所有块。 |
siyuan_get_block_children | 获取一个块及其子块作为树结构。 |
siyuan_search_with_context | 搜索思源,返回带有周围上下文块的结果。 |
siyuan_capture_task | 在今天的每日笔记中添加一个新任务复选框。 |
siyuan_get_document_outline | 获取文档的标题大纲。 |
出口
| 工具 | 说明 |
|---|---|
siyuan_export_pdf | 将思源文档导出为PDF(WeasyPrint;A3/A4/A5/信纸/法律/小报,肖像/风景,图像质量1-100)。由于WeasyPrint不执行JavaScript,因此数学块呈现为原始LaTeX。 |
调用示例 (第ai条或任何MCP客户):
{
"tool": "siyuan_create_document",
"args": {
"notebook": "20210817205410-2kvfpfn",
"path": "/Inbox/2026-04-30 Quick note",
"markdown": "# Hello\n\nFrom the API.",
"idempotency_key": "inbox-2026-04-30-quick-note"
}
}手写的目录是诚实的 tests/test_readme_tool_catalog.py,如果此处没有记录注册的工具,则CI将失败。
______________________________________________________________________
交通建筑
MCP规范通过多种导线格式演变而来;我们在生产中运行的是 可流式传输HTTP (又名“流式HTTP传输”) 无状态 会议,加 标准 对于本地子流程客户端。我们故意不使用旧的HTTP+SSE拆分:
- 标准 --Claude Code启动时使用
python -m mcp_siyuan作为一个子流程。没有身份验证,没有网络——IPC通过管道。集TRANSPORT=stdio(默认设置)。 - 可流式传输HTTP --Claude Desktop、Claude.ai连接器和n8n使用。JSON-RPC
POST /mcp可选的服务器流式响应。集TRANSPORT=http。需要MCP_API_KEY(如果没有服务器,启动时会很快失败)。 - HTTP+SSE(传统) --原件
/sse+/messages分裂。我们不运行它。当前的MCP规范整合在可流式HTTP上,每个请求协商分块或SSE风格的响应。
stateless_http=True 在可流式传输的HTTP服务器上设置,因此Cloudflare终止的空闲连接不会使孤立的MCP会话留在内存中;每个请求都是独立授权和分派的。看 mcp_siyuan/server.py 对于跑步者来说。
有关更深入的FastMCP协议详细信息,请参阅 FastMCP文档.
______________________________________________________________________
FastMCP使用说明
如果您正在做出贡献,此回购遵循一组值得了解的小约定:
- 工具注册明确 在
mcp_siyuan/server.py:每个工具函数都由traced_tool(...)然后交给mcp.tool(...)包装纸可以保存__name__和__doc__因此FastMCP可以对模式进行反思。 - Auth使用
TokenVerifier子类(mcp_siyuan/auth.py).HMAC比较了静态承载(MCP_API_KEY).HTTP模式下需要;服务器拒绝在没有它的情况下启动。 - 这
/health端点 已注册@mcp.custom_route("/health", methods=["GET"])它使用30秒的缓存(可通过以下方式配置)探测上游思源内核UPSTREAM_PROBE_INTERVAL).通过?diag=1还可以转储最近的工具调用振铃缓冲区(请参阅操作员Runbook)。 - 误差传播:工具会引发正常异常(
SiYuanError,ValueError等等)。FastMCP捕获并将其转换为MCP错误有效载荷。这traced_tool包装附加[request_id=...]以便客户端可以关联错误消息。 - 异步优先:每个工具功能都是
async def.内核客户端(mcp_siyuan/client.py)包裹httpx.AsyncClient单个模块级别sy = SiYuanClient()singleton在调用之间重用。
对于底层框架的工具定义、传输和中间件机制,请参考FastMCP文档,而不是在此处重新记录它们。
______________________________________________________________________
配置
所有配置都是通过环境变量进行的。 mcp_siyuan/config.py 解析它们 pydantic-settings.
与思源的联系
| 变量 | 默认值 | 注释 |
|---|---|---|
SIYUAN_URL | http://siyuan:6806 | 内核终结点。必须 http:// 或 https://默认情况下,假设sidecar模式,且SiYuan容器可在同一Docker网络上访问 |
SIYUAN_TOKEN | *(空)* | 来自思源设置的API令牌。如果未设置,服务器将在启动时发出警告;呼叫将未经身份验证。 |
UPSTREAM_PROBE_INTERVAL | 30 | 秒 /health 探测结果被缓存。 |
服务器传输
| 变量 | 默认值 | 注释 |
|---|---|---|
TRANSPORT | stdio | 其中之一 stdio, http. |
HOST | 127.0.0.1 | 绑定主机(HTTP模式)。容器部署通常绑定 0.0.0.0. |
PORT | 8000 | 绑定端口(HTTP模式)。 |
MCP_API_KEY | *(空)* | 持票人代币。 必需 在HTTP模式下;服务器拒绝在没有它的情况下启动。在生产环境中通过您的秘密存储/编排器变量注入。 |
可观察性和可靠性
| 变量 | 默认值 | 注释 |
|---|---|---|
SIYUAN_LOG_LEVEL | INFO | 设置根日志级别。JSON格式化程序发出 ts, level, request_id, tool_name, caller, args_size_bytes, kernel_status, latency_ms, outcome, message. |
SIYUAN_DIAG_BUFFER_SIZE | 50 | 内存中最近保存的工具调用记录数 /health?diag=1. |
SIYUAN_IDEMPOTENCY_TTL_SECONDS | 300 | 进程内写入工具重放缓存的TTL。 |
每个都设置在哪里
- 生产(HTTP) 套
TRANSPORT=http,HOST=0.0.0.0,PORT=8000,加MCP_API_KEY,SIYUAN_URL,以及SIYUAN_TOKEN从你的秘密商店。看compose.yaml对于容器形状。 - 当地克劳德代码(stdio) 从您的shell环境中读取或
.env默认值在一般情况下是正确的;你通常只需要SIYUAN_TOKEN. - CI/测试 忽略其中大部分——测试模拟内核客户端。
______________________________________________________________________
部署
图像建立在每次推送的基础上 main容器编排器拾取新图像并将其滚动到中定义的堆栈中 compose.yaml。在我们的设置中:
- 推送到
main. - git推送webhook触发
Dockerfile建造。 - 新映像将替换正在运行的容器。
- Cloudflare Tunnel+Access边缘提供服务;MCP门户聚合器路由
/siyuan/*命名空间到此服务器。
要查看状态,请点击 /health 端点位于经过身份验证的边缘后面。
Dockerfile为WeasyPrint安装Pango、Cairo和Noto字体。生产容器在严格的内存限制下运行(请参阅 compose.yaml).
单副本约束:服务器在进程内存中保存幂等缓存和诊断缓冲区。运行多个副本会将这些缓存拆分为每个pod,并破坏调用者所依赖的重播语义。在没有将缓存迁移到Redis(或类似的共享存储)的情况下,不要水平扩展此服务。
______________________________________________________________________
操作员操作手册
症状: No approval received.
我们在车队中的多台MCP服务器上看到了一种可重复的故障模式:
- 连续几个相同的MCP工具调用返回文字错误
No approval received. - 字节相同的重试——相同的参数、相同的对话、相同的MCP会话——最终成功。
- 相同的字符串出现在无关的上游服务器上,强烈表明故障起源于共享层(MCP门户聚合器、FastMCP框架或Claude客户端)中的上游服务器之上。它是 不 由该服务器的代码生成。
现在为任何操作员/代理提供手动解决方法:
- 使用相同的参数重试一次调用。
- 如果重试成功, 从不 提交破坏性的下游操作(取消任务、删除笔记、发送消息),直到收到真正的成功返回值。
- 如果重试也失败了,请向用户说明——不要盲目循环。
对于写入工具,请通过 idempotency_key 以便意外的客户端重试不会创建重复的文档/块。缓存正在处理中,默认为5分钟TTL(SIYUAN_IDEMPOTENCY_TTL_SECONDS);失败是明确的 不 缓存,因此真正的重试仍然可以产生新的内核调用。
诊断表面: /health?diag=1
每次工具调用都分配一个UUID v4 request_id 并附加到内存中的环形缓冲区(大小 SIYUAN_DIAG_BUFFER_SIZE,默认值为50)。要提取最近的活动,请执行以下操作:
curl -H "Authorization: Bearer $MCP_API_KEY" \
"https:///health?diag=1" | jq '.diag[-10:]'每个条目包含 ts, request_id, caller, tool_name, args_size_bytes, kernel_status, latency_ms, outcome,以及 error.一样 request_id 显示为 [request_id=…] 在返回给MCP客户端的任何错误消息上,以及 request_id 中每个JSON日志行上的字段 docker logs.
要按请求筛选容器日志,请执行以下操作:
docker logs 2>&1 | jq -c 'select(.request_id == "abc-123-...")'跨系统相关性
一旦你有一个 request_id 从失败开始,接下来的调查步骤就在这个回购之外:
- 恢复门户/FastMCP源
"No approval received"--可能的候选者:门户聚合器、FastMCP框架或Claude客户端连接器代码。 - 拉取边缘身份验证日志 (例如Cloudflare Access)在故障时间戳处获取公共主机名。查找JWT的拒绝/刷新或来源的5xx回复。
- 复制
curl直接使用与Claude使用的承载令牌相同的公共主机名。如果故障模式在克劳德之外再现→ 服务器/门户端。如果不→ 克劳德客户参与。 - 每次通话审核批准门控 在门户配置和任何可能以调用站点不期望的方式触发批准提示的Claude连接器设置中。
FastMCP版本引脚
fastmcp 被固定在 ==3.2.4 在 pyproject.toml。这是有意的,而未获得批准的根本原因调查是开放的——已知的固定框架版本使上游调查易于处理。启动横幅日志 fastmcp_version;如果它从引脚漂移,服务器会发出 ERROR 日志行,但不会崩溃。在没有与团队协调的情况下,不要放松。
______________________________________________________________________
本地开发
设置venv并运行测试套件:
uv sync
uv run pytest通过stdio与当地思源赛跑
export SIYUAN_URL=http://localhost:6806
export SIYUAN_TOKEN=your-siyuan-token
uv run python -m mcp_siyuan在另一个终端中,配置Claude Code以作为MCP服务器启动此命令。
在隧道后运行可流式传输的HTTP
export TRANSPORT=http
export HOST=127.0.0.1
export PORT=8000
export MCP_API_KEY=$(openssl rand -hex 32)
export SIYUAN_TOKEN=your-siyuan-token
uv run python -m mcp_siyuan然后曝光 cloudflared tunnel --url http://127.0.0.1:8000 或 tailscale serve 用于测试。
冒烟测试
# Unit + integration tests (mocks SiYuan)
uv run pytest
# Single test module
uv run pytest tests/test_idempotency.py -v
# Verify README catalog stays in sync with registered tools
uv run pytest tests/test_readme_tool_catalog.py______________________________________________________________________
版本控制和发布
两个地方需要就版本达成一致:
pyproject.tomls[project] versionmcp_siyuan/__init__.pys__version__
发布-提交模式(参见提交 8f82d78):将两者合并为一个 chore: sync __init__.__version__ with pyproject (X.Y.Z) commit,后面跟着a chore(release): vX.Y.Z [skip ci] 承诺。这种漂移是由人类造成的,而不是CI。
CHANGELOG.md 与发布提交一起更新。
______________________________________________________________________
相关工作
对上游调查的交叉引用(未收到RCA批准、门户缓存、服务器整合、门户认证)存在于团队的内部跟踪器中,而不是在此公共README中。
