1. 从手动搬运到一键直达:这套方案到底解决了什么问题
每次写完一篇长文,最烦的从来不是写本身,而是写完之后的搬运工作。本地 Markdown 文件躺在编辑器里,要发到飞书文档上给团队看,得先打开飞书、新建文档、复制粘贴、重新调格式、图片还得一张张传。一篇三千字的稿子,光搬运就能耗掉十几分钟,格式还经常乱掉——标题层级没了、表格变成一堆竖线、代码块全糊在一起。
我前前后后试过不少办法。手动复制是最笨的,但也是最多人还在用的。后来用飞书自带的导入功能,支持 Markdown 文件上传,但每次都要手动点好几步,而且图片路径处理经常出问题。再后来想用 API 自动化,结果卡在权限配置上,飞书的企业自建应用权限申请流程对个人开发者不算友好,折腾半天没跑通。
直到我把 AI Agent 和 MCP 协议这套组合拳打顺了,才真正实现了“写完即上传”的体验。现在我的工作流是这样的:在本地用 Markdown 写完稿子,跟 AI 助手说一句“帮我把这篇传到飞书”,几十秒后飞书文档链接就回来了,格式完整、图片正常、表格清晰。整个过程不需要我打开飞书客户端,不需要手动操作任何界面。
这套方案的核心价值在于三点。第一是省时间,把重复性的搬运工作完全交给 AI 和自动化流程,一篇文档从写完到上线飞书,从十几分钟压缩到不到一分钟。第二是保格式,Markdown 的标题、列表、表格、代码块、图片在转换过程中能最大程度保留原始结构,不会出现手动复制那种格式崩坏的情况。第三是可复用,一旦流程跑通,以后每篇文档都可以走同样的管道,形成稳定的内容发布流水线。
适合谁来参考这套方案?如果你经常需要把本地 Markdown 文档同步到飞书,不管是技术文档、项目周报、会议纪要还是知识库条目,这套流程都能帮你省下大量机械操作的时间。如果你对 AI Agent 和 MCP 协议感兴趣,想找一个实际可落地的场景来练手,这个项目也是很好的切入点——它涉及 API 调用、协议理解、文件处理和错误排查,麻雀虽小五脏俱全。
接下来我会把这套方案的完整实现过程拆开讲清楚,包括整体设计思路、MCP 协议的核心机制、飞书 API 的对接细节、实操步骤、参数配置,以及我踩过的那些坑。
2. 整体方案设计与技术选型拆解
2.1 为什么选 MCP + Agent 这套组合
先说清楚 MCP 是什么。MCP 全称 Model Context Protocol,翻译过来叫“模型上下文协议”,本质上是一套让 AI 模型和外部工具、数据源之间标准化通信的协议。你可以把它理解成 AI 世界的 USB 接口——以前每个 AI 工具要对接外部服务,都得自己写一套适配代码,有了 MCP 之后,只要外部服务实现了 MCP Server,任何支持 MCP 的 AI 客户端都能直接调用。
我选这套方案而不是直接写脚本调飞书 API,核心理由有三个。
第一个理由是交互自然。写个 Python 脚本调 API 当然也能实现上传,但每次都要打开终端、敲命令、传参数。用 MCP + Agent 的方式,我只需要用自然语言跟 AI 说“把这篇文档传到飞书”,Agent 会自动理解意图、调用对应的 MCP 工具、处理返回结果。这种交互方式对非技术用户友好得多,也更符合“AI 替我干活”的直觉。
第二个理由是扩展性强。MCP 协议是标准化的,今天我用它对接飞书,明天想对接其他文档平台,只要那个平台有 MCP Server,Agent 端几乎不用改代码。这种可插拔的架构比写死一个脚本要灵活得多。
第三个理由是错误处理更智能。直接调 API 的话,遇到 token 过期、权限不足、网络超时这些问题,脚本往往直接报错退出。而 Agent 可以在 MCP 工具返回错误后,根据错误信息自动尝试修复——比如重新获取 token、换一种上传方式、或者提示我手动处理。这种“智能重试”的能力在实际使用中非常省心。
2.2 飞书文档 API 的能力边界
飞书开放平台提供了丰富的文档相关 API,我实际用到的主要是这几个。
创建文档接口用于在指定文件夹下新建一个飞书文档,返回文档的 token 和 URL。导入文件接口支持把 Markdown、Word、Excel 等格式的文件导入为飞书云文档,这个接口对 Markdown 的支持相当不错,标题、列表、表格、代码块都能正确转换。上传素材接口用于上传图片等媒体文件,返回一个 file_token,可以在文档中引用。获取文件夹列表接口用来找到目标文件夹的 token,方便把文档创建在正确的位置。
这里有个关键点需要说明:飞书 API 的权限模型是基于应用(App)的。你需要先在飞书开放平台创建一个企业自建应用,申请对应的文档权限(如docx:document、drive:drive等),然后获取 App ID 和 App Secret,用它们换取 tenant_access_token 或 user_access_token。tenant_access_token 是以应用身份操作,user_access_token 是以用户身份操作。对于个人使用场景,我建议用 user_access_token,因为这样创建的文档归属你自己,权限管理也更简单。
2.3 整体架构长什么样
整个方案的架构可以分成四层。
最上层是用户交互层,也就是你跟 AI 助手对话的界面。可以是支持 MCP 的桌面客户端,也可以是命令行工具,甚至可以是聊天窗口。你在这里用自然语言发出指令。
第二层是Agent 调度层,AI 模型在这里理解你的意图,决定调用哪个 MCP 工具,传入什么参数,以及如何处理返回结果。这一层是“大脑”。
第三层是MCP Server 层,这是实际执行操作的模块。它封装了飞书 API 的调用逻辑,对外暴露标准化的 MCP 工具接口,比如upload_markdown_to_feishu、create_feishu_doc等。Agent 通过 MCP 协议跟它通信。
最底层是飞书开放平台,提供实际的文档创建、文件导入、素材上传等 API 能力。
数据流向是这样的:你在交互层说“把这篇文档传到飞书”,Agent 解析出意图和文件路径,通过 MCP 协议调用 MCP Server 的upload_markdown_to_feishu工具,MCP Server 读取本地 Markdown 文件、处理图片、调用飞书 API 完成上传,然后把飞书文档链接返回给 Agent,Agent 再展示给你。
2.4 关键选型对比:几种上传方式的优劣
在确定最终方案之前,我对比了几种常见的 Markdown 转飞书文档的方式,列个表方便你参考。
| 方案 | 实现难度 | 格式保留 | 自动化程度 | 适用场景 |
|---|---|---|---|---|
| 手动复制粘贴 | 极低 | 差 | 无 | 偶尔发一两篇 |
| 飞书客户端导入 | 低 | 较好 | 半自动 | 不频繁的文档同步 |
| Python 脚本调 API | 中 | 好 | 全自动 | 有编程基础、固定流程 |
| MCP + Agent | 中高 | 好 | 全自动+智能 | 追求自然交互、多平台扩展 |
手动复制粘贴的问题很明显,格式丢失严重,尤其是表格和代码块,粘过去基本要重新排版。飞书客户端导入比手动好一些,但每次都要打开客户端、找到导入入口、选择文件,步骤还是太多。Python 脚本能实现全自动,但交互方式不自然,每次都要敲命令。MCP + Agent 的方案在自动化程度和交互体验上都是最优的,代价是前期配置稍微复杂一点,但一次配置长期受益。
我最终选 MCP + Agent,还有一个很实际的原因:我日常已经在用 AI 助手处理各种任务,把上传飞书这个能力集成进去之后,不需要切换工具,在一个对话窗口里就能完成“写稿-改稿-上传”的全流程。这种工作流的连贯性,比省下的那几分钟操作时间更有价值。
3. 核心细节解析与实操要点
3.1 MCP Server 的工具设计
MCP Server 是整个方案的核心执行单元,它的工具设计直接决定了 Agent 能做什么、怎么做。我设计了三个核心工具,覆盖从创建文档到上传内容的完整流程。
工具一:create_feishu_doc。这个工具负责在飞书指定文件夹下创建一个空文档,返回文档的 document_id 和 URL。参数包括title(文档标题)和folder_token(目标文件夹的 token,可选,不传则创建在根目录)。这个工具看起来简单,但它是后续所有操作的基础——你得先有个文档,才能往里写内容。
工具二:upload_markdown_to_feishu。这是最核心的工具,负责把本地 Markdown 文件的内容写入飞书文档。参数包括document_id(目标文档 ID)、markdown_content(Markdown 文本内容)、image_base_path(图片基础路径,用于解析相对路径的图片)。这个工具内部会做几件事:解析 Markdown 中的图片引用、上传图片到飞书素材库、把图片链接替换为飞书可识别的格式、调用飞书文档 API 写入内容。
工具三:import_markdown_file。这个工具走的是飞书“导入文件”接口,直接把整个 Markdown 文件导入为飞书文档。参数包括file_path(本地文件路径)和folder_token(目标文件夹)。这个工具的好处是格式转换由飞书官方处理,兼容性最好;缺点是导入后的文档结构可能跟预期有细微差异,比如某些嵌套列表的层级可能变化。
提示:三个工具可以组合使用。最简单的流程是直接用
import_markdown_file一步到位;如果需要更精细的控制(比如先创建文档再分段写入),就用create_feishu_doc+upload_markdown_to_feishu的组合。
3.2 飞书 API 鉴权:token 获取与刷新
飞书 API 的鉴权是整个流程中最容易出问题的环节。我详细说一下。
首先你需要在飞书开放平台创建企业自建应用,拿到 App ID 和 App Secret。然后调用鉴权接口获取 token。飞书支持两种 token:tenant_access_token和user_access_token。前者以应用身份操作,有效期 2 小时;后者以用户身份操作,有效期也是 2 小时,但需要额外的 OAuth 流程。
对于个人使用场景,我推荐用tenant_access_token,因为获取方式简单,不需要跳转授权页面。获取方式如下:
curl -X POST "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal" \ -H "Content-Type: application/json" \ -d '{ "app_id": "your_app_id", "app_secret": "your_app_secret" }'返回结果里会有tenant_access_token和expire(过期时间,秒)。你需要在每次调用 API 前检查 token 是否过期,过期了就重新获取。我的做法是在 MCP Server 里维护一个 token 缓存,记录获取时间和过期时间,每次调用前判断是否需要刷新。
这里有个坑要注意:飞书的 token 有效期是 2 小时,但如果你在 token 即将过期时发起请求,可能会遇到“token 已过期”的错误。我的经验是提前 5 分钟刷新,也就是缓存有效期设为 1 小时 55 分钟,避免边界情况。
3.3 Markdown 解析与图片处理
Markdown 里的图片处理是另一个容易翻车的点。本地 Markdown 文件里的图片通常是相对路径,比如,但飞书文档需要的是可访问的 URL 或者上传后的 file_token。
我的处理流程是这样的:先用正则表达式扫描 Markdown 内容,找出所有图片引用,提取出图片路径。然后判断路径类型——如果是网络 URL(以 http/https 开头),直接保留;如果是本地相对路径,就拼接基础路径得到绝对路径,读取文件内容,调用飞书素材上传接口上传,拿到 file_token,再把 Markdown 里的图片引用替换成飞书可识别的格式。
飞书文档 API 写入图片的方式比较特殊,需要在内容块中使用image类型的 block,并传入 file_token。具体格式如下:
{ "block_type": 27, "image": { "token": "上传后获得的file_token" } }这里有个细节:飞书素材上传接口需要指定父节点类型和 token。对于文档图片,父节点类型是docx_image,父节点 token 是文档的 document_id。上传成功后会返回 file_token,这个 token 在文档内可以直接使用。
注意:飞书素材上传有大小限制,单张图片不能超过 20MB。如果你有大量高清图片,建议先压缩再上传,否则会报错。
3.4 Markdown 语法到飞书文档块的映射
飞书文档 API 使用的是“块”(Block)的概念,每个段落、标题、列表、表格都是一个独立的块。Markdown 语法需要转换成对应的块类型。我整理了一个映射表:
| Markdown 语法 | 飞书块类型 | block_type 值 |
|---|---|---|
# 标题 | 一级标题 | 3 |
## 标题 | 二级标题 | 4 |
### 标题 | 三级标题 | 5 |
| 普通段落 | 文本 | 2 |
- 列表项 | 无序列表 | 12 |
1. 列表项 | 有序列表 | 13 |
> 引用 | 引用 | 15 |
| 代码块 | 代码 | 14 |
| 表格 | 表格 | 31 |
| 图片 | 图片 | 27 |
转换过程中有几个容易出问题的地方。第一是嵌套列表,飞书的列表块支持嵌套,但需要通过children字段来组织层级关系,处理起来比较绕。第二是表格,飞书表格块的结构比较复杂,需要先创建表格块,再填充单元格内容,而且表格的行列数在创建时就确定了,不能动态增减。第三是代码块,需要指定语言类型,飞书支持的语言列表跟 Markdown 的常见语言标识不完全一致,需要做映射。
我的建议是:如果文档结构比较简单(标题+段落+少量列表),用upload_markdown_to_feishu逐块写入完全没问题。如果文档里有大量复杂表格和嵌套列表,直接用import_markdown_file走飞书官方导入接口更省心,格式兼容性更好。
4. 完整实操流程:从零跑通一键上传
4.1 环境准备与依赖安装
先把基础环境搭好。你需要准备的东西包括:一个飞书账号(企业版或个人版都行)、一台能跑 Python 的电脑、一个支持 MCP 的 AI 客户端。
飞书这边,先去开放平台创建企业自建应用。进入开发者后台,点击“创建应用”,选择“企业自建应用”,填个名字和描述。创建完成后,在“凭证与基础信息”页面拿到 App ID 和 App Secret。然后在“权限管理”页面申请以下权限:docx:document(文档读写)、drive:drive(云空间读写)、drive:file(文件上传)。申请后需要管理员审批,个人版账号一般秒过。
Python 环境这边,我用的 Python 3.10,需要安装几个依赖库:
pip install requests markdown-it-py mcprequests用于调飞书 API,markdown-it-py用于解析 Markdown 语法,mcp是 MCP 协议的 Python SDK。如果你打算用 Node.js 写 MCP Server,对应的包是@modelcontextprotocol/sdk,安装方式类似。
AI 客户端这边,我用的是支持 MCP 的桌面客户端。配置方式是在客户端的配置文件里添加 MCP Server 的启动命令。以 JSON 配置为例:
{ "mcpServers": { "feishu-uploader": { "command": "python", "args": ["/path/to/feishu_mcp_server.py"], "env": { "FEISHU_APP_ID": "your_app_id", "FEISHU_APP_SECRET": "your_app_secret" } } } }配置完成后重启客户端,Agent 就能识别到飞书上传工具了。
4.2 MCP Server 核心代码实现
下面是我写的 MCP Server 核心代码,用 Python 实现。代码分三个部分:鉴权模块、Markdown 处理模块、MCP 工具定义。
鉴权模块负责获取和缓存 token:
import time import requests class FeishuAuth: def __init__(self, app_id, app_secret): self.app_id = app_id self.app_secret = app_secret self._token = None self._expire_at = 0 def get_token(self): if self._token and time.time() < self._expire_at: return self._token resp = requests.post( "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal", json={"app_id": self.app_id, "app_secret": self.app_secret} ) data = resp.json() if data.get("code") != 0: raise Exception(f"获取token失败: {data}") self._token = data["tenant_access_token"] # 提前5分钟刷新 self._expire_at = time.time() + data["expire"] - 300 return self._tokenMarkdown 处理模块负责解析图片和转换格式:
import re import os def extract_images(markdown_text, base_path): """提取Markdown中的图片引用,返回图片列表和替换后的文本""" pattern = r'!\[([^\]]*)\]\(([^)]+)\)' images = [] def replace(match): alt, src = match.group(1), match.group(2) if src.startswith(('http://', 'https://')): return match.group(0) # 网络图片保留原样 abs_path = os.path.join(base_path, src) images.append({"alt": alt, "path": abs_path, "original": match.group(0)}) return f'-1}}}}})' new_text = re.sub(pattern, replace, markdown_text) return new_text, imagesMCP 工具定义部分,用mcpSDK 注册工具:
from mcp.server import Server from mcp.types import Tool, TextContent server = Server("feishu-uploader") auth = FeishuAuth(os.environ["FEISHU_APP_ID"], os.environ["FEISHU_APP_SECRET"]) @server.tool() async def import_markdown_file(file_path: str, folder_token: str = "") -> str: """将本地Markdown文件导入为飞书文档""" token = auth.get_token() # 读取文件 with open(file_path, "r", encoding="utf-8") as f: content = f.read() # 调用飞书导入接口 # ... 具体实现见下文 return f"文档已创建: {doc_url}"4.3 飞书文档导入接口的调用细节
飞书的“导入文件”接口是异步的,调用后会返回一个 ticket,你需要轮询查询导入结果。完整流程分三步。
第一步,上传文件到飞书云空间。调用POST /open-apis/drive/v1/files/upload_all,传入文件名、父文件夹 token、文件内容。返回 file_token。
第二步,创建导入任务。调用POST /open-apis/drive/v1/import_tasks,传入 file_token、文件类型(md表示 Markdown)、目标文件夹 token、目标文件名。返回 ticket。
第三步,轮询查询任务结果。调用GET /open-apis/drive/v1/import_tasks/{ticket},直到返回job_status为success,此时会返回导入后的文档 token 和 URL。
轮询间隔我设的是 1 秒,最多轮询 30 次。实测下来,一篇三千字的 Markdown 文档导入通常 3-5 秒完成。如果超过 30 秒还没成功,大概率是文件有问题或者权限不足,需要检查。
注意:导入接口对 Markdown 文件的大小有限制,不能超过 20MB。另外,导入后的文档格式跟原始 Markdown 可能有细微差异,比如某些特殊符号的转义、表格对齐方式等,这是正常现象。
4.4 图片上传与替换的完整流程
如果走upload_markdown_to_feishu这条路(逐块写入),图片处理流程如下。
先扫描 Markdown 内容,提取所有本地图片路径。然后逐个上传到飞书素材库:
def upload_image(auth, doc_id, image_path): token = auth.get_token() with open(image_path, "rb") as f: files = {"file": (os.path.basename(image_path), f, "image/png")} data = { "parent_type": "docx_image", "parent_node": doc_id, "size": os.path.getsize(image_path) } resp = requests.post( "https://open.feishu.cn/open-apis/drive/v1/medias/upload_all", headers={"Authorization": f"Bearer {token}"}, files=files, data=data ) result = resp.json() if result.get("code") != 0: raise Exception(f"图片上传失败: {result}") return result["data"]["file_token"]拿到 file_token 后,在构建文档块时使用image类型块,传入 token。飞书文档 API 会自动把图片渲染到文档中。
这里有个实操心得:图片上传是串行的,一张一张传。如果文档里有十几张图,整个上传过程可能要十几秒。我试过改成并发上传,但飞书接口对并发有限制,容易触发限流。所以还是老老实实串行,稳一点。
4.5 在 Agent 端配置与调用
MCP Server 跑起来之后,Agent 端需要做两件事:一是配置 MCP Server 的连接信息,二是确保 Agent 能正确识别和调用工具。
配置方式前面已经说了,在客户端的 MCP 配置里加上 Server 的启动命令和环境变量。配置完成后,你可以在对话里问 Agent“你有哪些飞书相关的工具”,如果配置正确,Agent 会列出import_markdown_file、create_feishu_doc、upload_markdown_to_feishu这三个工具。
调用的时候,直接用自然语言描述需求就行。比如:
- “把
/Users/me/docs/report.md这个文件传到飞书” - “帮我在飞书创建一个叫‘项目周报’的文档,内容用我本地这个 Markdown 文件”
- “把这篇 Markdown 上传到飞书,放到‘技术文档’文件夹里”
Agent 会自动解析出文件路径、目标文件夹等信息,调用对应的 MCP 工具。如果信息不全,比如你没说文件夹,Agent 会追问或者使用默认值。
我实测下来,从发出指令到拿到飞书文档链接,一篇普通长度的文档大概 20-40 秒。其中大部分时间花在图片上传和飞书服务端处理上,Agent 本身的调度几乎不耗时。
5. 常见问题与排查技巧实录
5.1 权限报错:从 99991672 到 99991663
飞书 API 的权限报错是最常见的。我遇到过的主要有这几个错误码。
99991672:通常是应用没有申请对应的权限。解决方法是去开放平台权限管理页面,检查是否申请了docx:document、drive:drive、drive:file这三个权限,申请后需要重新发布应用版本,等审批通过后生效。
99991663:token 无效或已过期。检查 token 是否正确获取、是否在有效期内。如果用的是tenant_access_token,确认应用是否已发布且审批通过。未发布的应用获取的 token 权限受限。
99991661:请求参数错误。常见原因是 folder_token 传错了,或者文件类型不支持。检查文件夹 token 是否正确,文件扩展名是否为.md。
实操心得:飞书的错误信息有时候比较模糊,光看错误码很难定位问题。我的做法是在 MCP Server 里把完整的请求参数和响应内容都打日志,出问题的时候看日志比看错误码快得多。
5.2 图片上传失败:路径、格式与大小
图片上传失败的原因主要有三类。
第一类是路径问题。Markdown 里的图片路径是相对路径,但 MCP Server 的工作目录可能跟 Markdown 文件不在同一个目录。我的处理方式是在调用工具时显式传入image_base_path参数,指定图片的基础路径。如果不传,默认用 Markdown 文件所在目录。
第二类是格式问题。飞书素材上传接口支持 PNG、JPG、JPEG、GIF、BMP、WEBP 等常见格式。如果你有 SVG 图片,需要先转成 PNG 再上传。我遇到过 SVG 上传后无法显示的问题,后来统一转成 PNG 解决了。
第三类是大小问题。单张图片不能超过 20MB。超过的话需要先压缩。我用 Pillow 库写了个简单的压缩函数,把图片质量降到 85%,尺寸限制在 2000px 以内,基本能压到 5MB 以下,画质损失肉眼几乎看不出来。
5.3 格式错乱:表格、代码块与嵌套列表
格式错乱是 Markdown 转飞书文档时最让人头疼的问题。我踩过的坑包括:表格变成纯文本、代码块丢失语言标识、嵌套列表层级混乱。
表格问题的根源在于飞书表格块的结构比较复杂。如果用逐块写入的方式,需要先创建表格块,再逐行逐列填充单元格。我的建议是:如果文档里有表格,优先用import_markdown_file走官方导入接口,格式兼容性最好。如果必须逐块写入,那就把表格转成飞书支持的格式,或者干脆用图片代替表格。
代码块问题主要是语言标识的映射。Markdown 里写```python,飞书代码块需要的是python这个语言标识,大部分情况下是一致的,但有些语言标识飞书不支持,比如text、plain,需要映射成plain_text。
嵌套列表的问题在于飞书的列表块需要通过children字段组织层级。我的处理方式是递归解析 Markdown 的列表结构,构建对应的块树。这部分代码稍微复杂一点,但逻辑是清晰的:遇到缩进就增加层级,遇到同级就平铺。
5.4 常见问题速查表
| 问题现象 | 可能原因 | 排查方法 | 解决方案 |
|---|---|---|---|
| 报错 99991672 | 权限未申请 | 检查开放平台权限列表 | 申请权限并重新发布 |
| 报错 99991663 | token 过期 | 检查 token 获取时间 | 重新获取 token |
| 图片不显示 | 路径错误 | 检查 image_base_path | 传入正确的图片基础路径 |
| 图片上传失败 | 格式不支持 | 检查图片扩展名 | 转成 PNG/JPG |
| 表格格式乱 | 块类型不匹配 | 检查表格块结构 | 改用 import 接口 |
| 代码块无高亮 | 语言标识错误 | 检查语言映射 | 映射为飞书支持的语言 |
| 导入超时 | 文件过大 | 检查文件大小 | 压缩文件或拆分上传 |
| 文档创建在根目录 | folder_token 未传 | 检查参数 | 传入正确的文件夹 token |
5.5 几个让我少走弯路的实操技巧
第一个技巧:先用小文件测试。不要一上来就拿几千字带几十张图的文档测试,先用一个简单的 Markdown 文件跑通流程,确认鉴权、上传、格式转换都没问题,再逐步增加复杂度。
第二个技巧:日志要打全。MCP Server 里每个 API 调用的请求参数和响应内容都打日志,出问题的时候直接看日志定位,比猜快得多。我用的是 Python 的logging模块,日志级别设成 DEBUG,输出到文件。
第三个技巧:token 缓存要持久化。如果你的 MCP Server 是每次调用都重启的(有些客户端是这样的),token 缓存放在内存里就没意义了。可以把 token 和过期时间写到本地文件,下次启动时先读文件,没过期就直接用。
第四个技巧:图片先压缩再上传。尤其是截图,原始尺寸往往很大,压缩到 2000px 宽、质量 85%,肉眼几乎看不出差别,但上传速度快很多,也不容易触发大小限制。
第五个技巧:文件夹 token 提前准备好。飞书的文件夹 token 不是一眼能看到的,需要调 API 获取。我的做法是提前调一次GET /open-apis/drive/v1/files列出根目录下的文件夹,找到目标文件夹的 token 记下来,配置到 MCP Server 的环境变量里,省得每次都要查。
6. 进阶玩法:让这套流程更顺手
6.1 批量上传与目录同步
单篇上传跑通之后,很自然会想到批量处理。我现在的做法是:把要上传的 Markdown 文件放在一个目录里,跟 Agent 说“把这个目录下所有 Markdown 文件都传到飞书”,Agent 会遍历目录、逐个上传,最后返回一个文档链接列表。
批量上传有几个要注意的点。第一是限流,飞书 API 对调用频率有限制,批量上传时要在每次请求之间加个短延迟,我设的是 500ms,实测下来不会触发限流。第二是错误隔离,某个文件上传失败不应该影响其他文件,每个文件独立处理,失败的记录下来最后统一报告。第三是目录结构映射,如果本地目录有子文件夹,可以考虑在飞书里创建对应的文件夹结构,保持组织方式一致。
6.2 与写作流程的深度集成
我现在的工作流已经跟这套上传方案深度绑定了。写稿的时候在本地用 Markdown 编辑器写,写完之后直接跟 AI 助手说“传到飞书”,几十秒后链接就回来了。整个过程不需要打开飞书客户端,不需要手动操作任何界面。
更进一步,我还在 Agent 端配置了一些快捷指令。比如“发周报”会自动找到本周的周报文件并上传到指定的飞书文件夹,“发技术文档”会把docs/目录下的最新文档同步到飞书知识库。这些快捷指令本质上就是预设了文件路径和目标文件夹的模板,用起来非常顺手。
6.3 扩展到其他文档平台
MCP 协议的好处在于标准化。今天我用它对接飞书,明天如果想对接其他文档平台,只要那个平台有 MCP Server,Agent 端几乎不用改代码。我目前正在尝试把同样的流程扩展到其他支持 MCP 的文档平台,思路是一样的:写一个 MCP Server 封装平台的 API,Agent 端配置一下就能用。
这种可插拔的架构意味着,你在这套方案上投入的学习成本是可以复用的。理解了 MCP 协议的工作原理、掌握了 Agent 调用工具的方式、踩过了 API 鉴权和格式转换的坑,换一个平台无非是换一套 API 调用逻辑,整体框架不用动。
6.4 安全与权限的边界控制
最后说一下安全方面的考虑。飞书应用的 App Secret 是敏感信息,不要硬编码在代码里,也不要在对话里明文传输。我的做法是放在环境变量里,MCP Server 启动时从环境变量读取。另外,申请权限时遵循最小必要原则,只申请真正需要的权限,不要图省事申请一堆用不到的权限。
对于团队使用场景,建议用tenant_access_token而不是user_access_token,这样文档归属应用而不是个人,人员变动时不会影响文档的归属和权限。个人使用场景用哪种都行,看个人偏好。
我在实际使用中还有一个体会:这套方案最大的价值不在于省了多少操作时间,而在于它把“上传文档”这个动作从我的注意力里彻底移除了。以前每次写完稿子,脑子里还要惦记着“待会儿要传到飞书”,现在完全不用想,一句话的事。这种认知负担的释放,比省下的几分钟操作时间重要得多。