mcpField
F
feishu-inout

feishu-inout

github.com/joe960913生产力353 次安装31 周前更新
代码仓库

关于 feishu-inout

feishu-inout 用于操作 Feishu/Lark 文档、消息、日历、会议、多维表格和群组。它结合官方远程 MCP 服务与 Open API,并提供凭据配置指引。

主要功能

  1. 01读取和编辑文档
  2. 02搜索文档和消息
  3. 03管理日历与会议
  4. 04操作多维表格
  5. 05管理群聊
  6. 06引导配置凭据与 OAuth

适用场景

  1. 01查找或更新 Feishu/Lark 文档
  2. 02发送消息并查看聊天记录
  3. 03管理日程与会议安排
  4. 04读取或更新多维表格记录

MCP 相关

通过 `https://mcp.feishu.cn/mcp` 上的官方远程 MCP 服务处理消息等操作;日历、多维表格和群组管理使用 Open API。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/joe960913/feishu-inout --skill feishu-inout

安装后在 Claude Code 中输入/feishu-inout确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

LICENSE
.gitignore
README.md
README_CN.md
scripts/
feishu_mcp.py

详细介绍

飞书 InOut - 飞书/Lark 文档、消息、日历、多维表格与群组操作

通过官方飞书/Lark Remote MCP 服务(https://mcp.feishu.cn/mcp)和开放 API,操作云文档、发送/搜索消息、管理日历事件和会议、使用多维表格,以及管理群聊。零依赖,纯 Python。

安全:凭据处理规则

重要——请始终遵守以下规则:

  • 绝不在任何 shell 命令中直接填入 FEISHU_APP_ID 或 FEISHU_APP_SECRET 的值
  • 绝不回显、打印或输出 App Secret 的值
  • 运行任何脚本命令前,确保已加载环境变量:如果 echo $FEISHU_APP_ID 返回空值,先运行 source ~/.zshrc(或 source ~/.bashrc)
  • 脚本会自动从环境变量读取凭据——无需将其作为参数传入

快速检查:用户是否已完成配置?

检查以下两项:

  1. 是否已设置环境变量 FEISHU_APP_ID 和 FEISHU_APP_SECRET?(运行 echo $FEISHU_APP_ID——如果为空,先运行 source ~/.zshrc)
  2. 是否存在有效的 UAT 令牌?(运行脚本的 whoami 命令)

如果两项都已就绪 → 跳转到使用方法。 如果任一项缺失 → 引导用户完成首次设置。


首次设置

告诉用户:“设置大约需要 5 分钟。我会一步步引导你操作——按步骤进行,并在每一步完成后告诉我。”

开始前,询问用户:

你需要哪些功能?

  1. 只读(搜索、阅读、浏览)——权限最少,设置最快
  2. 读写(+ 创建、编辑、评论)——推荐,可满足大多数场景
  3. 全部功能(+ 发送/搜索消息、日历/会议、多维表格、群组管理)——消息功能通过 MCP 使用用户身份(UAT),日历/多维表格/群组使用开放 API

根据用户的选择,在步骤 2 中显示对应的权限字符串。请注意,步骤 6(机器人能力)对于所有选项都是可选的。

必须显示与用户选择相对应的权限字符串:

选项 1(只读):

docx:document:readonly,search:docs:read,wiki:wiki:readonly,im:chat:read,task:task:read

选项 2(读写,推荐):

docx:document:readonly,search:docs:read,wiki:wiki:readonly,im:chat:read,task:task:read,docx:document,docx:document:create,docx:document:write_only,docs:document.media:upload,docs:document.media:download,wiki:node:read,wiki:node:create,docs:document.comment:read,docs:document.comment:create,contact:user:search,contact:contact.base:readonly,contact:user.base:readonly,board:whiteboard:node:read,drive:drive

选项 3(全部功能):

docx:document:readonly,search:docs:read,wiki:wiki:readonly,im:chat:read,task:task:read,docx:document,docx:document:create,docx:document:write_only,docs:document.media:upload,docs:document.media:download,wiki:node:read,wiki:node:create,docs:document.comment:read,docs:document.comment:create,contact:user:search,contact:contact.base:readonly,contact:user.base:readonly,board:whiteboard:node:read,drive:drive,im:message,im:message:send_as_bot,im:chat,search:message,im:message.send_as_user,im:message.p2p_msg:get_as_user,im:message.group_msg:get_as_user,calendar:calendar:readonly,calendar:calendar,bitable:app:readonly,bitable:app,im:chat:create

建议用户一次性启用所有权限(选项 3),以免日后需要更多功能时重新授权。如果用户倾向于最小权限,则显示对应的选项。

引导用户将字符串粘贴到开放平台 → 权限管理 → 批量导入/导出。

重要:批量导入后,提醒用户,部分权限(在下表中标记为“需要审批”),例如 im:message.send_as_user、search:message、im:message.p2p_msg:get_as_user、im:message.group_msg:get_as_user,需要管理员审批。等待审批期间,其他功能均可正常使用——用户可以立即开始使用文档、评论、日历和多维表格。

总共 6 个步骤。每完成一步后,都要确认用户已完成,再进入下一步。

步骤 1:创建飞书/Lark 应用
  1. 前往 Lark 开放平台(中国大陆:open.feishu.cn)并登录
  2. 点击右上角的创建企业自建应用
  3. 输入应用名称(任意名称,例如“My Doc Assistant”)和描述
  4. 创建完成后,前往应用详情页
  5. 在凭证与基础信息页面,记下:
    • App ID(格式:cli_xxxxxxxxxxxxxxxx)
    • App Secret(字母数字字符串)

提醒用户将这些信息设为环境变量(见步骤 4)。不要让用户将 App Secret 发给你或粘贴到对话中。

步骤 2:启用 API 权限

进入应用 → 权限管理 → 批量导入/导出,粘贴与上方用户选择相对应的权限字符串。

或者逐项启用:

核心(必需):

权限范围描述授权类型
docx:document:readonly查看文档应用
search:docs:read搜索文档用户
wiki:wiki:readonly查看知识库用户 + 应用
im:chat:read查看聊天信息应用
task:task:read查看任务应用

写入/编辑(追加、替换、插入、覆盖、删除、创建文档):

权限范围描述授权类型
docx:document查看和编辑文档应用
docx:document:create创建文档应用
docx:document:write_only写入文档应用
docs:document.media:upload上传图片应用
wiki:node:read查看知识库节点应用
wiki:node:create创建知识库节点应用

评论(get-comments、add-comments):

权限范围描述授权类型
docs:document.comment:read读取评论应用
docs:document.comment:create创建评论应用

用户(search-user、get-user):

权限范围描述授权类型
contact:user:search搜索用户用户
contact:contact.base:readonly联系人信息应用
contact:user.base:readonly用户信息应用

文件(fetch-file):

权限范围描述授权类型
docs:document.media:download下载图片/附件应用
board:whiteboard:node:read查看白板应用
drive:drive管理云盘文件应用

消息(send-msg、reply、get-msgs、search-msgs 等):

权限范围描述授权类型
im:message管理消息应用
im:message:send_as_bot以机器人身份发送应用
im:chat管理聊天应用
search:message搜索消息用户(需审批)
im:message.send_as_user以用户身份发送用户(需审批)
im:message.p2p_msg:get_as_user读取私聊历史记录用户(需审批)
im:message.group_msg:get_as_user以用户身份读取群聊消息用户(需审批)

日历/会议(create-event、list-events):

权限范围描述授权类型
calendar:calendar:readonly查看日历用户
calendar:calendar管理日历和活动用户

多维表格(list-tables、list-records、create-record、update-record):

权限范围描述授权类型
bitable:app:readonly查看多维表格数据用户
bitable:app管理多维表格数据用户

群组管理(create-group、add-members、list-groups):

权限范围描述授权类型
im:chat:create创建群组应用

注意:仅当用户选择“所有功能”时,才需要启用消息、日历、多维表格和群组管理权限。消息功能通过使用 UAT(用户身份)的官方 MCP 实现——机器人能力为可选项,并非必需。日历、多维表格和群组管理使用 Open API。

启用后,“用户”类型权限显示“与用户权限范围一致”属于正常情况。“应用”类型显示“-”也属于正常情况。

确认所有权限均显示 ✅ 已启用。

步骤 3:添加重定向 URL(用于 OAuth)

进入应用 → 安全设置 → 重定向 URL → 添加:

http://localhost:9876/callback

这是用于获取 User Access Token(UAT)的 OAuth 回调 URL。

第 4 步:设置环境变量

引导用户自行设置凭据。不要让用户向你发送 App Secret,也不要在对话中输出或复述凭据值。

根据用户的操作系统:

macOS / Linux:

echo 'export FEISHU_APP_ID="your_app_id"' >> ~/.zshrc
echo 'export FEISHU_APP_SECRET="your_app_secret"' >> ~/.zshrc
source ~/.zshrc

Windows(PowerShell):

[System.Environment]::SetEnvironmentVariable('FEISHU_APP_ID', 'your_app_id', 'User')
[System.Environment]::SetEnvironmentVariable('FEISHU_APP_SECRET', 'your_app_secret', 'User')

设置后重启终端或 IDE。

验证(仅验证 App ID,绝不输出 Secret):

  • macOS/Linux:echo $FEISHU_APP_ID
  • Windows:echo $env:FEISHU_APP_ID
第 5 步:通过 OAuth 登录以获取 UAT

运行登录命令:

python3 ~/.claude/skills/feishu-inout/scripts/feishu_mcp.py login

流程:

  1. 脚本会在浏览器中打开飞书/Lark 授权页面
  2. 如果显示“权限不足”,浏览器会列出确切缺少的权限——在开放平台启用这些权限,然后点击“重试”,无需一次性启用所有权限
  3. 用户在浏览器中点击授权
  4. 浏览器显示“授权成功!你可以关闭此页面。”
  5. 终端显示 UAT saved!——完成

令牌将在 2 小时后过期;脚本会通过 refresh_token 自动刷新。如果令牌过期太久,请重新运行 login。

验证所有内容均已就绪:

python3 ~/.claude/skills/feishu-inout/scripts/feishu_mcp.py whoami
python3 ~/.claude/skills/feishu-inout/scripts/feishu_mcp.py search-doc "test"
第 6 步:机器人能力(可选)

通过 MCP 收发消息使用 UAT(用户身份),因此发送或读取消息不需要机器人能力。send-message MCP 工具会以已认证用户的身份发送消息,而不是以机器人的身份发送。

不过,如果用户需要机器人身份(例如,以机器人身份发送自动通知),可以选择启用:

  1. 前往应用 → 添加能力 → 启用 机器人
  2. 前往版本管理与发布 → 创建版本 → 提交审核
  3. 审核通过后,将机器人添加到目标群组

此步骤完全可选。如果用户只需要以自己的身份发送消息,请跳过。

设置完成!

完成所有步骤后,祝贺用户,并建议尝试以下操作来验证一切正常:

一切就绪!试试以下任一操作,开始使用:

  • “显示我的飞书/Lark 文档”
  • “搜索关于[主题]的文档”
  • “创建一个名为[标题]的新文档”
  • “我今天有哪些会议?”
  • “给[姓名]发条消息:你好!”

只需自然地交流——其余的交给我来处理。


身份验证

脚本会自动选择最合适的令牌:

  • UAT(用户访问令牌)——首选。支持搜索文档、访问个人文档及其他用户级操作
  • TAT(租户访问令牌)——UAT 不可用时的后备选项。功能有限:无法搜索,只能访问已授权给应用的文档

这两种令牌使用不同的 MCP 请求头:

  • UAT → X-Lark-MCP-UAT
  • TAT → X-Lark-MCP-TAT

检查当前状态:

python3 ~/.claude/skills/feishu-inout/scripts/feishu_mcp.py whoami

重新登录(令牌过期时):

python3 ~/.claude/skills/feishu-inout/scripts/feishu_mcp.py login

提取文档 ID

从飞书/Lark URL 中提取 docID:

https://xxx.feishu.cn/docx/ABC123def      → docID = ABC123def
https://xxx.larksuite.com/docx/ABC123def   → docID = ABC123def
https://xxx.feishu.cn/wiki/XYZ789abc       → docID = XYZ789abc
https://xxx.feishu.cn/docs/doccn123c       → docID = doccn123c

规则:docID 是 /docx/、/wiki/ 或 /docs/ 后面的最后一个路径段。


用法

所有操作均使用 scripts/feishu_mcp.py 脚本($S = 下方的完整路径):

S=~/.claude/skills/feishu-inout/scripts/feishu_mcp.py

# Auth
python3 $S login                                   # OAuth login to get UAT
python3 $S whoami                                  # Show current token status

# Read documents
python3 $S fetch-doc <docID>                       # Read full document
python3 $S fetch-doc <docID> 0 5000                # Paginated read (offset, limit)

# Search
python3 $S search-doc <keyword>                    # Search documents (needs UAT)
python3 $S search-user <keyword>                   # Search users

# Browse
python3 $S list-docs                               # List "My Library"
python3 $S list-docs <docID>                       # List child docs
python3 $S get-user                                # Get current user info
python3 $S get-user <open_id>                      # Get specific user info

# Create document (one step, with markdown content)
python3 $S create-doc <title> '<markdown>'
python3 $S create-doc <title> '<markdown>' '{"wiki_space":"my_library"}'
python3 $S create-doc <title> '<markdown>' '{"folder_token":"fldcnXXX"}'

# Update document (7 modes)
python3 $S append <docID> '<markdown>'             # Append to end
python3 $S overwrite <docID> '<markdown>'          # Overwrite entire doc (use with caution)
python3 $S replace <docID> '<selection>' '<md>'    # Replace matched range
python3 $S insert-after <docID> '<sel>' '<md>'     # Insert after match
python3 $S insert-before <docID> '<sel>' '<md>'    # Insert before match
python3 $S delete-range <docID> '<selection>'      # Delete matched content

# Comments
python3 $S get-comments <docID>                    # Get all comments
python3 $S get-comments <docID> whole              # Whole-doc comments only
python3 $S get-comments <docID> segment            # Inline comments only
python3 $S add-comments <docID> <text>             # Add a text comment

# Files
python3 $S fetch-file <token>                      # Get file/image content
python3 $S fetch-file <token> whiteboard           # Get whiteboard content

# Messaging (via MCP)
python3 $S send-msg <chat_id|open_id> <text> [--user]  # Send markdown message
python3 $S send-card <chat_id|open_id> '<json>' [--user] # Send interactive card
python3 $S reply <message_id> <text> [--thread]    # Reply to a message
python3 $S get-msgs <chat_id> [time] [count]       # Get group chat history
python3 $S get-msgs-user <open_id> [time] [count]  # Get DM history
python3 $S search-msgs <keyword> [time]            # Search messages across chats
python3 $S get-thread <thread_id>                  # Get thread replies

# Calendar / Meeting (via Open API)
python3 $S create-event <title> <start> <end> [attendees_json]  # Create event with video meeting
python3 $S list-events [date]                                    # List events (default: today)

# Bitable / Multi-dimensional Table (via Open API)
python3 $S list-tables <app_token>                               # List tables in a bitable
python3 $S list-records <app_token> <table_id> [page_size]       # List records
python3 $S create-record <app_token> <table_id> '<fields_json>'  # Create a record
python3 $S update-record <app_token> <table_id> <record_id> '<fields_json>'  # Update a record

# Group Management (via Open API, uses TAT/bot identity)
python3 $S create-group <name> [members_json]                    # Create a group chat
python3 $S add-members <chat_id> '<members_json>'                # Add members to group
python3 $S list-groups                                           # List groups bot is in

# Advanced (raw JSON call to any tool)
python3 $S call <toolName> '<jsonArgs>'
python3 $S update-doc '{"doc_id":"xxx","mode":"replace_range","selection_by_title":"## Section","markdown":"New content"}'
选择语法(用于替换 / 插入 / 删除)
  • 范围匹配:起始文本...结束文本——匹配两个文本片段之间的所有内容
  • 精确匹配:精确文本——不含 ...,进行精确匹配
  • 按标题选择:在 update-doc 的 JSON 模式中使用 selection_by_title: "## 标题",以定位整个章节

工作流

读取文档
  1. 从用户的 URL 中提取 docID
  2. 运行 fetch-doc <docID>
  3. 解析返回的 JSON——result.content[0].text 中包含 Markdown 内容
  4. 对于大型文档,使用分页:fetch-doc <docID> <offset> <limit>
搜索并读取
  1. 运行 search-doc <keyword> 查找文档
  2. 从结果的 items 数组中提取 id(docID)和 title
  3. 如果有多个结果,列出这些结果并让用户选择
  4. 运行 fetch-doc <docID> 读取选定的文档
创建文档(一步完成)
  1. 运行 create-doc <title> '<markdown>',创建并填入内容
  2. 可选指定位置:知识库节点 wiki_node、知识库空间 wiki_space(my_library = 个人知识库)或文件夹 folder_token
  3. 返回 doc_id 和 doc_url
  4. 注意:未指定位置时,文档会创建在个人空间根目录中,不会出现在“最近”列表里。建议使用 wiki_space: "my_library",方便用户查找
编辑文档

优先使用局部更新,而不是覆盖:

  1. append — 在末尾添加内容
  2. replace — 查找并替换指定内容(使用 start...end 范围匹配或精确文本)
  3. insert-after / insert-before — 在指定位置后/前插入
  4. delete-range — 删除匹配的内容
  5. overwrite — 最后手段,会清空整个文档(图片、评论等也会丢失)

按标题定位整个章节(适合替换/删除整个章节):

python3 $S call update-doc '{"doc_id":"xxx","mode":"replace_range","selection_by_title":"### Section Title","markdown":"### Section Title\n\nReplaced content"}'

selection_by_title 会从标题匹配到下一个同级标题。

浏览知识库
  1. 运行 list-docs 查看“我的知识库”
  2. 或运行 list-docs <docID> 查看子文档(响应中包含 has_child 字段)
  3. 递归浏览更深层级
@提及工作流
  1. 运行 search-user <name> 获取用户的 open_id
  2. 在 add-comments 中使用高级模式:call add-comments '{"doc_id":"xxx","elements":[{"type":"mention","open_id":"ou_xxx"}]}'
创建文档并发送到群聊
  1. 运行 create-doc <title> '<markdown>' 创建文档
  2. 运行 send-msg <chat_id> <text>,将文档链接分享给群组(在文本中包含文档 URL)
  3. 要 @提及用户:在消息文本中使用 <mention-user id="openId"/> 语法(先运行 search-user 获取 open_id)
发送消息

消息通过官方 Feishu/Lark MCP 使用 UAT(用户身份)发送,无需机器人能力。

  • 群消息:send-msg <chat_id> <text> — 以已认证用户的身份发送
  • 私聊:send-msg <open_id> <text> --user — 通过 open_id 向用户发送
  • 交互式卡片:send-card <chat_id|open_id> '<json>' [--user] — 发送卡片消息
  • 回复:reply <message_id> <text> — 回复指定消息
  • 在话题中回复:reply <message_id> <text> --thread — 在话题中回复
  • 群聊历史记录:get-msgs <chat_id> [time] [count] — 按时间筛选获取聊天记录
  • 私聊历史记录:get-msgs-user <open_id> [time] [count] — 读取私聊记录
  • 搜索:search-msgs <keyword> [time] — 搜索所有聊天中的消息
  • 话题回复:get-thread <thread_id> — 获取话题中的所有回复

Markdown 格式:send-msg 支持在消息文本中使用 Markdown 语法。

@提及语法:

  • 提及特定用户:<mention-user id="openId"/>
  • 提及所有人:<mention-user id="all"/>
  • 支持 Emoji:[SMILE]、[THUMBSUP] 等

get-msgs、get-msgs-user、search-msgs 的时间筛选条件:today、yesterday、this_week、last_week、this_month、last_month、last_30_minutes、last_3_days 等。

创建会议
  1. 运行 create-event <title> <start> <end> — 自动创建 Feishu/Lark 视频会议
  2. 邀请参会者:create-event "Sprint Review" "2026-03-28T14:00+08:00" "2026-03-28T15:00+08:00" '["ou_xxx","ou_yyy"]'
  3. 先使用 search-user 获取参会者的 open_id
使用 Bitable
  1. 从 Bitable URL 中提取 app_token:https://xxx.feishu.cn/base/XXX — app_token = XXX
  2. 运行 list-tables <app_token> 查看可用的数据表
  3. 运行 list-records <app_token> <table_id> 读取数据
  4. 运行 create-record 或 update-record 写入数据
创建群组并添加成员
  1. 运行 create-group "Project Alpha" '["ou_xxx","ou_yyy"]',创建群组并添加初始成员
  2. 或运行 create-group "Project Alpha",然后运行 add-members <chat_id> '["ou_xxx"]'
  3. 群组管理使用机器人身份(TAT),需要启用机器人能力

错误处理

代码含义解决方案
-32011缺少身份验证凭据检查是否已设置 FEISHU_APP_ID 和 FEISHU_APP_SECRET 环境变量
-32003凭据无效或已过期TAT:检查 App Secret;UAT:运行 login 重新授权
-32601未找到工具或方法运行 tools 查看可用工具
-32602参数无效检查参数名称和格式
-32700JSON 解析错误检查 JSON 参数格式
429请求频率受限等待几秒后重试
99991679用户尚未授权此权限范围重新运行 login,或在应用的权限管理中启用该权限
常见问题

search-doc 返回 "required ... search:docs:read" → 此权限需要用户身份(UAT)。运行 login 获取 UAT。

fetch-doc 返回 "permission denied" → 在 TAT 模式下,必须将应用添加为文档协作者。使用 UAT(运行 login 后)即可访问用户有权限访问的所有文档。

登录后浏览器没有响应 → 检查是否已在应用的安全设置中添加重定向 URL http://localhost:9876/callback。

UAT 已过期 → 脚本会自动尝试通过 refresh_token 刷新。如果 refresh_token 也已过期(30 天),请重新运行 login。

评论

支持 Markdown