Skip to main content
Glama
README.md
# ChatGPT Feishu MCP

一个面向云端 ChatGPT 的轻量远程 MCP。常驻服务只有一个 Node.js 进程;飞书请求按需交给飞书官方 `lark-cli`,无需数据库、Redis 或常驻浏览器。

## 能力边界

仅暴露 8 个工具:

- `feishu_auth_status`:检查并验证当前飞书用户授权
- `feishu_auth_start` / `feishu_auth_complete`:设备码授权两步流程
- `feishu_document_read`:读取飞书 Docx 或 Wiki 页面,返回 Markdown
- `feishu_document_create`:在云空间或 Wiki 创建 Docx,可同时写入正文
- `feishu_document_edit`:追加、精确替换文字、在块后插入、替换单个块
- `feishu_wiki_browse`:列知识空间、列节点、解析节点
- `feishu_message_send_to_me`:由应用机器人向当前已授权用户本人发送文本或 Markdown 消息

服务故意不提供删除、移动、权限修改、整篇覆盖、任意收件人、群发、聊天记录和通讯录能力。文档与知识库操作固定使用 `user` 身份;消息工具固定使用 `bot` 身份,且收件人只能是当前授权用户本人。

## 本机运行

要求 Node.js 22+ 和飞书官方 `lark-cli`:

```bash
npx @larksuite/cli@1.0.93 install
cd /root/chatgpt-feishu-mcp
npm install
npm test
npm start
```

默认监听 `127.0.0.1:8787`:

```bash
curl http://127.0.0.1:8787/healthz
```

## 飞书用户授权

在 ChatGPT 中依次调用:

1. `feishu_auth_status`
2. 未就绪时调用 `feishu_auth_start`
3. 用户打开返回的 `verification_uri_complete`(或 verification URL)并批准
4. 调用 `feishu_auth_complete`,传入 `flow_id`

`device_code` 只保存在 MCP 进程内存,不返回 ChatGPT,也不写日志。服务重启后未完成的授权流程会失效,重新开始即可。授权只申请文档内容读、Docx 创建/读/写、Wiki 空间/节点读与节点创建以及离线续期所需 scope。token 由 `lark-cli` 保存在 `~/.lark-cli`;Docker 部署已持久化该目录。

## 发送飞书消息

`feishu_message_send_to_me` 的收件人固定为当前通过 `feishu_auth_*` 授权的飞书用户,消息以配置应用的机器人身份发送。工具调用前,用户必须明确确认收件人、完整消息内容和 bot 发送身份。支持:

- `format="text"`:按原文发送
- `format="markdown"`:转换成飞书富文本消息
- `idempotency_key`:一小时内重试同一消息时复用,避免重复发送

飞书应用需要开通 `im:message:send_as_bot`,并确保应用机器人对目标用户可用。该工具不允许传入其他用户 ID 或群聊 ID。

## 接入云端 ChatGPT

### 推荐:Secure MCP Tunnel

开发和个人使用建议让服务只监听回环地址,再用 ChatGPT 的 Secure MCP Tunnel 暴露 `/mcp`。这样无需在本服务里再维护一套面向 ChatGPT 的 OAuth 服务,也不会把无认证端点直接暴露到公网。

在 ChatGPT 开发者模式中新建 MCP app,填入 Tunnel 给出的 HTTPS MCP URL。连接后先让 ChatGPT 调用 `feishu_auth_status`。

### 公网部署

若直接部署公网,必须在反向代理或本服务前增加符合 ChatGPT 要求的 OAuth 2.1 Authorization Code + PKCE,并使用稳定 HTTPS 域名。不要用静态 API key 代替;ChatGPT 自定义 MCP 连接不能可靠地为每个用户附加自定义密钥头。

容器启动:

```bash
docker compose up -d --build
```

反向代理只需转发 `/mcp` 和可选的 `/healthz`。生产环境不要把 compose 中的 `127.0.0.1` 端口绑定改成公网地址,除非前面已有 OAuth 网关。

## Markdown 注意事项

写入内容按飞书官方 Markdown 规则解析。需要显示为字面量的 `\\`、反引号、`*`、`_`、`[`、`]`、`$`、`~`、`<` 应加反斜杠;读取后得到的转义不要删除。多行正文通过 stdin 传给 CLI,不经过 shell,因此不会发生命令注入或 shell 展开。

块编辑前,请先用 `feishu_document_read(detail="with-ids")` 获取最新 block ID;结构改变后不要复用旧 ID。

## 环境变量

见 `.env.example`。建议保持:

- `MAX_CONCURRENT_COMMANDS=2`:避免突发并发占满小机器
- `MAX_CONTENT_CHARS=200000`:限制单次写入大小
- `MAX_MESSAGE_CHARS=20000`:限制单条飞书消息长度
- `HOST=127.0.0.1`:仅 Tunnel / 本机代理可访问

本服务不记录工具参数或文档正文。

## 本机当前运行配置

MCP 已注册为 systemd 用户服务:

```bash
systemctl --user status chatgpt-feishu-mcp.service
systemctl --user restart chatgpt-feishu-mcp.service
curl http://127.0.0.1:8787/healthz
```

OpenAI Secure MCP Tunnel 使用 `feishu-local` Profile,由 `tunnel-client` 的本地 runtime 管理:

```bash
tunnel-client runtimes status feishu-local --json
tunnel-client doctor --profile feishu-local --explain
tunnel-client runtimes stop feishu-local
tunnel-client runtimes connect --alias feishu-local \
  --profile feishu-local \
  --tunnel-id <TUNNEL_ID> \
  --mcp-server-url http://127.0.0.1:8787/mcp \
  --runtime-api-key file:/root/.config/openai-tunnel/runtime.key
```

本机同时启用了 `openai-feishu-tunnel.service`,登录或重启后会恢复 Tunnel:

```bash
systemctl --user status openai-feishu-tunnel.service
systemctl --user restart openai-feishu-tunnel.service
```

Profile 位于 `/root/.config/tunnel-client/feishu-local.yaml`,Runtime API Key 位于 `/root/.config/openai-tunnel/runtime.key`,文件权限必须保持 `0600`。本地 Tunnel 管理界面的实际地址可从以下命令读取:

```bash
base_url=$(cat /root/.local/state/tunnel-client/health/feishu-local.url)
printf '%s/ui\n' "$base_url"
```