一个面向团队协作场景的 Codex marketplace 仓库,当前提供 codex-lark-plugin,用于把飞书文档同步到本地索引,再通过 MCP tools 在 Codex 中完成知识检索、摘要、最近更新和文档差异比较。
如果你是第一次接入,建议先看本文;如果你要看插件目录级说明和脚本细节,再看 plugins/codex-lark-plugin/README.md。
真实飞书模式支持两种鉴权方式:
tenant:应用身份。适合团队共享目录、共享 folder、wiki 根节点这类“应用本身就应该能读”的资源。user:用户身份。适合“我的文件夹”、个人私有文档、或者只有当前登录用户能访问的资源。
可以用这条经验快速判断:
- 如果你要接企业共享知识库,先试
tenant - 如果你要接个人文档或遇到权限不够,再切
user
把下面地址替换成你实际发布的仓库地址:
codex marketplace add https://github.com/cKnight107/codex-lark-plugin安装后通常会出现两类目录:
- 插件缓存目录:
~/.codex/plugins/cache/codex-lark-marketplace/codex-lark-plugin/<version>/ - 插件运行时目录:
~/.codex/codex-lark-plugin/
建议提前创建运行时目录,用来存放索引和用户 token:
mkdir -p ~/.codex/codex-lark-plugin第一次接入时,先在飞书开放平台创建一个自建应用,并拿到:
App IDApp Secret
后面 README 中的这些配置都依赖这两个值:
LARK_FEISHU_APP_IDLARK_FEISHU_APP_SECRET
不管你最终用 tenant 还是 user,都建议先在飞书开放平台里为应用申请最小必需权限。
首次接入至少建议准备这些 scope:
drive:drive:readonly:读取云空间/文件夹元数据space:document:retrieve:读取文档基础信息docx:document:readonly:读取文档正文offline_access:仅user模式需要,用于刷新用户 token
最小建议:
- 如果只想先验证目录能不能列出来,至少先有
drive:drive:readonly - 如果要真正同步正文并做摘要/检索,补上
docx:document:readonly - 如果要用
user授权,补上offline_access
在飞书开放平台里,给应用新增权限后,不要只停留在“已勾选”状态,还要完成应用发布或让当前租户可用;否则本地 OAuth 成功了,token 里也可能拿不到新 scope。
实操上要记住两点:
- 权限变更后,先在飞书后台完成发布
- 如果你之前已经拿过
user_access_token,新增权限后必须重新授权一次
旧 token 不会自动带上新权限。
如果你要使用 user 模式,需要在飞书开放平台里为应用配置 OAuth 回调地址。
本项目默认使用:
http://127.0.0.1:3333/callback
建议在飞书后台的应用安全设置里至少加入这个地址;如果你本机更习惯用 localhost,可以额外加入:
http://localhost:3333/callback
填写规则只有一条最重要:
- 飞书后台登记的回调地址,必须与本地发起 OAuth 时使用的
redirect_uri完全一致,包括协议、域名、端口和路径
例如你本地如果填的是:
http://127.0.0.1:3333/callback
那飞书后台也必须填这一条,不能只填 localhost,也不能少 /callback。
通常在这里:
~/.codex/plugins/cache/codex-lark-marketplace/codex-lark-plugin/<version>/.mcp.json
仓库里的 .mcp.json 只是模板,真正给自己机器配置时,建议把运行时数据写到:
~/.codex/codex-lark-plugin/index.json~/.codex/codex-lark-plugin/feishu-user-token.json
{
"LARK_DOCS_SOURCE": "feishu",
"LARK_INDEX_PATH": "~/.codex/codex-lark-plugin/index.json",
"LARK_FEISHU_APP_ID": "cli_xxx",
"LARK_FEISHU_APP_SECRET": "secret_xxx",
"LARK_FEISHU_SYNC_ROOTS": "[{\"type\":\"folder\",\"token\":\"fldcn_xxxxx\"}]",
"LARK_FEISHU_TOKEN_MODE": "tenant"
}LARK_FEISHU_SYNC_ROOTS 是一个 JSON 数组,可以配置多个入口,例如:
[
{ "type": "folder", "token": "fldcn_xxxxx" },
{ "type": "wiki", "token": "wikcn_xxxxx" }
]{
"LARK_DOCS_SOURCE": "feishu",
"LARK_INDEX_PATH": "~/.codex/codex-lark-plugin/index.json",
"LARK_FEISHU_APP_ID": "cli_xxx",
"LARK_FEISHU_APP_SECRET": "secret_xxx",
"LARK_FEISHU_SYNC_ROOTS": "[{\"type\":\"folder\",\"token\":\"fldcn_xxxxx\"}]",
"LARK_FEISHU_TOKEN_MODE": "user",
"LARK_FEISHU_USER_TOKEN_PATH": "~/.codex/codex-lark-plugin/feishu-user-token.json",
"LARK_FEISHU_OAUTH_REDIRECT_URI": "http://127.0.0.1:3333/callback",
"LARK_FEISHU_OAUTH_SCOPE": "offline_access drive:drive:readonly space:document:retrieve docx:document:readonly"
}本项目已经内置用户授权脚本:
LARK_FEISHU_APP_ID=cli_xxx \
LARK_FEISHU_APP_SECRET=secret_xxx \
LARK_FEISHU_OAUTH_REDIRECT_URI=http://127.0.0.1:3333/callback \
LARK_FEISHU_OAUTH_SCOPE="offline_access drive:drive:readonly space:document:retrieve docx:document:readonly" \
LARK_FEISHU_USER_TOKEN_PATH=~/.codex/codex-lark-plugin/feishu-user-token.json \
npm run login:feishu-oauth运行后脚本会:
- 在本地启动一个 HTTP 回调服务
- 在终端打印飞书授权链接
- 你在浏览器里登录并授权
- 飞书回调到本地地址
- 脚本把
user_access_token和refresh_token写入LARK_FEISHU_USER_TOKEN_PATH
默认推荐的 token 文件位置是:
~/.codex/codex-lark-plugin/feishu-user-token.json
当前插件对 user_access_token 的处理方式不是后台定时刷新,而是在真正发起飞书 API 请求前做一次检查。
工作流程如下:
- 先从环境变量和
LARK_FEISHU_USER_TOKEN_PATH指向的本地文件读取user_access_token、refresh_token以及它们各自的过期时间 - 每次请求飞书前,如果
LARK_FEISHU_TOKEN_MODE=user,插件会先判断user_access_token是否仍然有效 - 如果
user_access_token还没过期,就直接使用当前 token 发请求 - 如果已经过期,但本地仍然有
refresh_token,插件会先获取app_access_token,再调用飞书的authen/v1/refresh_access_token换取新的user_access_token - 刷新成功后,新的
user_access_token、refresh_token和过期时间会回写到LARK_FEISHU_USER_TOKEN_PATH对应的本地文件,供后续请求继续复用
可以把它理解成“请求时懒刷新”:
- 没有独立的后台定时任务
- 只有真正要访问飞书时才会检查是否过期
- 过期后优先自动刷新,刷新不了才需要重新授权
要让这套机制正常工作,需要同时满足:
LARK_FEISHU_TOKEN_MODE=user- 已经通过
npm run login:feishu-oauth拿到并保存过用户 token - OAuth scope 里包含
offline_access - 仍然保留
LARK_FEISHU_APP_ID和LARK_FEISHU_APP_SECRET因为刷新user_access_token时需要先获取应用级 token
如果缺少 refresh_token,或者授权时没有拿到 offline_access,那用户 token
过期后就无法自动续期,只能重新执行一次 OAuth 登录。
用户授权完成后,确保 .mcp.json 里的关键字段至少是这几个:
{
"LARK_DOCS_SOURCE": "feishu",
"LARK_INDEX_PATH": "~/.codex/codex-lark-plugin/index.json",
"LARK_FEISHU_TOKEN_MODE": "user",
"LARK_FEISHU_USER_TOKEN_PATH": "~/.codex/codex-lark-plugin/feishu-user-token.json"
}如果还要同步真实飞书,别忘了同时保留:
LARK_FEISHU_APP_IDLARK_FEISHU_APP_SECRETLARK_FEISHU_SYNC_ROOTS
当你发现“能列目录但读不了正文”或“新增文档类型后还是报权限不足”时,通常不是代码问题,而是权限还没补全。
建议按这个顺序处理:
- 去飞书开放平台给应用新增所需权限
- 完成应用发布,让权限变更生效
- 更新本地
LARK_FEISHU_OAUTH_SCOPE - 重新执行一次
npm run login:feishu-oauth
最常见的场景:
- 能看到 folder,但读取正文失败:补
docx:document:readonly user模式下 token 过期后不能续期:确认包含offline_access- 新增了权限但依然报错:通常是没有重新授权,旧 token 还在用旧 scope
如果你已经填好 .mcp.json 对应的配置,也可以直接用命令做最小验证:
LARK_DOCS_SOURCE=feishu \
LARK_INDEX_PATH=~/.codex/codex-lark-plugin/index.json \
LARK_FEISHU_APP_ID=cli_xxx \
LARK_FEISHU_APP_SECRET=secret_xxx \
LARK_FEISHU_SYNC_ROOTS='[{"type":"folder","token":"fldcn_xxxxx"}]' \
LARK_FEISHU_TOKEN_MODE=user \
LARK_FEISHU_USER_TOKEN_PATH=~/.codex/codex-lark-plugin/feishu-user-token.json \
npm run test:feishu-smoke如果你接的是共享知识库,也可以先把 LARK_FEISHU_TOKEN_MODE 改成 tenant 试通。
常用命令:
# 用真实飞书配置强制同步到本地索引
npm run sync:feishu
# 拉起用户 OAuth 授权
npm run login:feishu-oauth
# 做一次最小联通检查
npm run test:feishu-smoke优先检查飞书开放平台里登记的回调地址是否与本地使用的 LARK_FEISHU_OAUTH_REDIRECT_URI 完全一致。
如果资源在某个用户的“我的空间”里,通常更适合 user 模式;如果是团队共享 folder / wiki,先用 tenant 更省事。
最常见原因只有两个:
- 飞书后台已经勾选权限,但还没发布
- 旧的
user_access_token没有重新授权
.
├── .agents/plugins/marketplace.json
├── plugins/
│ └── codex-lark-plugin/
│ ├── .codex-plugin/plugin.json
│ ├── .mcp.json
│ ├── assets/
│ ├── scripts/
│ └── skills/
└── docs/
Sample 模式:
npm run build
npm run sync:sample
npm test真实飞书模式:
npm run sync:feishu
npm run test:feishu-smoke