关联主题::
同级:: 2026-02-09_星期一
下一级::
用 Claude Code 实现 Obsidian 文档秒级同步飞书
背景:一个真实的痛点
我日常用 Obsidian 写文章、做笔记,但团队协作和对外分享用的是飞书。每次要把 Obsidian 里写好的文档分享到飞书,就面临一个尴尬的问题:
手动复制粘贴——格式全乱,标题层级丢失,代码块变成纯文本,Mermaid 流程图直接消失。
导出再导入——步骤繁琐,每次都要导出 → 打开飞书 → 导入 → 手动调格式。
我想要的很简单:在终端里说一句”把这篇文档上传到飞书”,几秒钟后拿到飞书链接,格式完好,流程图也在。
这篇文章记录了我从调研、踩坑到最终实现的完整过程。
方案调研:三条路的取舍
方案一:Feishu-MCP 逐块写入
Feishu-MCP 是一个飞书的 MCP Server,能通过 Claude Code 直接操作飞书文档的每一个”块”——段落、标题、代码块、Mermaid 图表等。
优点很明显:精确控制每一个块的类型,Mermaid 代码可以直接创建为飞书原生图表块。
但实际测试下来,一篇 400 行的文档,逐块写入需要几十次 API 调用,整个过程需要好几分钟。对于一篇写好的文章来说,这个速度不可接受。
方案二:飞书 Import API 整篇导入
飞书提供了 Import API,可以直接把一个 Markdown 文件导入为飞书文档。整篇文档一次性导入,速度是秒级的。
但 Import API 有一个硬伤:不认识 Mermaid。它会把 ```mermaid 代码块当作普通代码块处理,在飞书文档里只是一段看不懂的代码文本。
方案三:ObShare 插件
ObShare 是一个 Obsidian 社区插件,也是用 Import API 上传,但它做了额外处理——把 Mermaid 代码块在本地渲染成 PNG 图片,再作为图片上传。
这解决了”Mermaid 在飞书里不显示”的问题,但图片毕竟不是原生图表,不能编辑、不能交互、在飞书里也不够美观。
最终方案:Import API + MCP 补刀
三条路各有长短,最终我取了个混合方案:
| 阶段 | 工具 | 作用 |
|---|---|---|
| 主力上传 | Python 脚本 (Import API) | 秒级导入整篇文档 |
| Mermaid 补刀 | Feishu-MCP | 将占位符替换为原生 Mermaid 块 |
思路是:
- 上传前,把 Mermaid 代码块提取出来,用占位符
[FEISHU_MERMAID_0]替换 - 用 Import API 秒级上传(占位符变成普通文本)
- 上传后,用 Feishu-MCP 找到占位符文本块,删除,在同位置插入原生 Mermaid 块
这样,无 Mermaid 的文档秒级完成,有 Mermaid 的文档也只多几秒钟。
实现过程
第一步:搞定飞书应用权限
在飞书开放平台创建一个企业自建应用,开通以下权限:
drive:drive— 云空间文件读写drive:drive:import— 文件导入docx:document— 文档读写drive:drive:permission:transfer— 权限转移wiki:wiki— 知识库读写(知识库模式需要)
记下 App ID、App Secret,配置到 .claude/feishu-config.env:
FEISHU_APP_ID = "cli_xxxxxxxx"
FEISHU_APP_SECRET = "xxxxxxxxxxxxxxxx"
FEISHU_API_DOMAIN = "https://open.feishu.cn"
FEISHU_WEB_DOMAIN = "https://my.feishu.cn"
FEISHU_DEFAULT_FOLDER = "xxxxxxxx" # 云空间上传目标文件夹
FEISHU_OPEN_ID = "ou_xxxxxxxx" # 你的 open_id(用于所有权转移)
# 知识库配置(可选,使用 --wiki 模式时需要)
FEISHU_WIKI_SPACE_ID = "xxxxxxxx" # 知识空间 ID
FEISHU_WIKI_PARENT_NODE = "xxxxxxxx" # 默认父节点 token第二步:Python 导入脚本
脚本的核心流程:
读取 MD → 剥离 frontmatter → 剥离 Obsidian 元数据 → 提取 Mermaid
→ 上传文件 → 创建导入任务 → 等待完成 → 清理 → 转移所有权
→ (知识库模式)移动到知识库 → 回写 feishu_url
几个关键的坑,都是对照 ObShare 源码才发现的:
坑 1:Import API 的 file_name 字段
飞书的 Import API 文档里没有强调这个字段,但它是必需的。缺少这个字段,简单文档能导入成功,复杂文档会直接报 job_status: 2(失败),没有任何错误信息。
# 错误写法(缺少 file_name)
payload = {
"file_extension": "md",
"file_token": file_token,
"type": "docx",
}
# 正确写法
payload = {
"file_extension": "md",
"file_name": "文档标题", # 不含扩展名!
"file_token": file_token,
"type": "docx",
}这个坑让我折腾了很久。一开始做二分法排查——把文档切成两半分别上传,两半都成功,合起来就失败。后来阅读 ObShare 的 feishu-api.ts 源码才发现这个差异。
坑 2:上传文件时 filename 不要带扩展名
在 upload_all 接口的 multipart 请求中,Content-Disposition 的 filename 字段不能带 .md 扩展名,否则导入可能出问题:
# file_name 字段 → 带 .md
'file_name': (None, '文档标题.md')
# file 部分的 filename → 不带 .md
'file': ('文档标题', md_bytes, 'application/octet-stream')坑 3:所有权转移的 member_type
飞书文档通过应用创建后,所有者是应用本身,需要转移给用户。ObShare 用的是 member_type: "userid",但我实测 userid 报错 Invalid parameter,换成 openid 才成功:
payload = {
"member_id": open_id,
"member_type": "openid" # 不是 userid
}这可能跟应用的权限范围有关,不同配置下行为可能不同。
坑 4:知识库 Wiki API 的异步/同步双模式
将云空间文档移动到知识库时,飞书的 move_docs_to_wiki API 有两种响应模式:
- 文档所有者是用户时(已完成所有权转移):同步返回
data.wiki_token - 文档所有者是应用时:异步返回
data.task_id,需要轮询/wiki/v2/tasks/{task_id}获取结果
这意味着所有权转移必须在移动到知识库之前执行,否则会走异步路径,还需要额外处理轮询逻辑。
# 情况1: 同步返回(推荐,先转移所有权再移动)
data = {"wiki_token": "Naa8wywOOiO0YvkaOZEcdWGNn3g"}
# 情况2: 异步返回(需要轮询)
data = {"task_id": "7471234567890123456"}
# 轮询时必须带 task_type 参数
GET /wiki/v2/tasks/{task_id}?task_type=move我的脚本同时处理了两种情况,并加了一个 _get_wiki_node_by_obj() 回退方案——如果轮询也失败,通过 obj_token 反查 node_token。
第三步:Mermaid 补刀(Feishu-MCP)
这一步交给 Claude Code + Feishu-MCP 自动完成。
上传脚本输出 JSON 结果,包含每个 Mermaid 代码块的原始代码。Claude Code 拿到结果后:
1. 获取飞书文档的块结构
mcp__feishu-mcp__get_feishu_document_blocks({
documentId: "D86Wd559ZogKXLxkEuicevW8nIf"
})
2. 找到占位符文本块
在返回的块列表中搜索文本内容为 [FEISHU_MERMAID_0]、[FEISHU_MERMAID_1] 的块,记录它们的 block_id 和在父块中的 index。
3. 从后往前替换
从后往前是为了避免删除前面的块后,后面块的 index 发生偏移:
# 先删除占位符块
delete_feishu_document_blocks(startIndex=65, endIndex=66)
# 在同位置插入原生 Mermaid
batch_create_feishu_blocks(index=65, blocks=[{
blockType: "mermaid",
options: { mermaid: { code: "flowchart TD\n A-->B" } }
}])
替换完成后,飞书文档里就是可交互的原生 Mermaid 图表了。
第四步:Obsidian 内容清理
上传前,脚本会自动处理两类 Obsidian 特有的内容:
YAML Frontmatter 剥离:Obsidian 的 frontmatter(--- 包裹的元数据)不需要出现在飞书文档中,但标题会从 title 字段提取。
Dataview 关联字段剥离:Obsidian 的 dataview 内联字段(如 关联主题::、同级::、下一级::)是本地知识管理用的元数据,上传飞书时自动去除,包括紧随其后的分隔线 ---。
# 这些内容会被自动剥离,不会出现在飞书文档中:
关联主题::
同级:: [[2026-02-08_星期六]]
下一级::
---
第五步:feishu_url 自动回写
上传成功后,脚本会自动把飞书文档的 URL 写回 Obsidian 文件的 frontmatter:
---
title: 人生行动力六要素模型
feishu_url: https://my.feishu.cn/wiki/Jb7ewxyRmitdWIkN5b8cgC57niA
---如果 frontmatter 中已有 feishu_url 字段,会更新为最新的 URL;如果没有,会新增。这样在 Obsidian 里就能直接看到对应的飞书链接,方便后续查阅和分享。
第六步:封装为 Claude Code Skill
把整个流程封装为一个 Skill,用自然语言触发:
.claude/skills/同步飞书/
├── skill.md ← SOP 定义
└── scripts/
└── feishu_import.py ← Import API 脚本
skill.md 定义了触发条件和执行步骤,Claude Code 读取后会严格按照 SOP 执行。
使用效果
在 Claude Code 里说一句话就行:
> 把"人生行动力六要素模型"这篇文章上传到飞书
Claude Code 自动执行:
[1/3] 执行导入脚本...
✓ 文件上传成功
✓ 导入完成: D86Wd559ZogKXLxkEuicevW8nIf
✓ 所有权已转移
✓ 已移动到知识库
✓ 已回写 feishu_url
[2/3] Mermaid 补刀(2 个图表)...
✓ [FEISHU_MERMAID_1] → 原生 Mermaid 块
✓ [FEISHU_MERMAID_0] → 原生 Mermaid 块
[3/3] 完成
文档 URL: https://my.feishu.cn/wiki/Jb7ewxyRmitdWIkN5b8cgC57niA
对比一下各方案的实际表现:
| 方案 | 400 行文档 | Mermaid 支持 | 知识库 | 操作方式 |
|---|---|---|---|---|
| Feishu-MCP 逐块 | 数分钟 | 原生图表 | 支持 | CLI |
| Import API 纯导入 | 3-4 秒 | 变成代码文本 | 不支持 | CLI |
| ObShare 插件 | 3-4 秒 | PNG 图片 | 不支持 | Obsidian GUI |
| 本方案(混合) | 5-8 秒 | 原生图表 | 支持 | CLI |
架构总结
┌─────────────────────────────────────────────────┐
│ 用户说"上传到飞书" │
└───────────────────────┬─────────────────────────┘
│
▼
┌─────────────────────────────────────────────────┐
│ Python 脚本 (feishu_import.py) │
│ │
│ 1. 剥离 YAML frontmatter │
│ 2. 剥离 Obsidian dataview 关联字段 │
│ 3. 提取 Mermaid → 替换为占位符 │
│ 4. Upload API → Import API → 轮询等待 │
│ 5. 清理临时文件 + 转移所有权 │
│ 6. (知识库模式)移动到知识库 │
│ 7. 回写 feishu_url 到 Obsidian 文件 │
│ 8. 输出 JSON(含 mermaid 代码列表) │
└───────────────────────┬─────────────────────────┘
│
有 Mermaid?
│ │
否 是
│ │
▼ ▼
返回 URL ┌────────────────────────┐
│ Feishu-MCP 补刀 │
│ │
│ 1. 获取文档块结构 │
│ 2. 定位占位符块 │
│ 3. 删除占位符 │
│ 4. 插入原生 Mermaid 块 │
└────────────┬────────────┘
│
▼
返回 URL
前置配置清单
如果你也想搭建这套方案,需要准备:
- 飞书开放平台应用 — 创建企业自建应用,开通文档、云空间和知识库权限
- Python 3 + requests 库 — 脚本运行环境
- Feishu-MCP — 安装到
.mcp.json,用于 Mermaid 补刀 - Claude Code — Anthropic 的 CLI 工具,用于编排整个流程
已知限制
- 图片不会上传:Import API 导入 Markdown 时,本地图片引用(
)不会自动上传。如果文档包含本地图片,需要先上传到图床替换为远程 URL。 - Callout 语法:Obsidian 的
> [!note]Callout 语法,Import API 会当作普通引用块处理。 - Wiki Links:
[[双链]]语法在飞书中没有对应概念,会变成纯文本。
这些限制在大部分分享场景下影响不大。如果需要完美还原,可以在 MCP 补刀阶段增加更多处理逻辑。
写在最后
这个项目最有意思的地方不是某个单一技术的使用,而是混合架构的思路:用最合适的工具做它最擅长的事。
Import API 擅长快速导入整篇文档,但处理不了 Mermaid;Feishu-MCP 能精确操作每个块,但逐块写入太慢。把两者组合起来,取长补短,就得到了一个既快又全的方案。
这种”主力 + 补刀”的模式,在很多自动化场景里都适用——先用粗粒度的方式完成 80% 的工作,再用细粒度的方式处理剩下的 20%。