Feishu MCP Gateway
README.md
# Feishu MCP Gateway
一个部署在 **Cloudflare Workers** 上的飞书远程 MCP 网关,用于把飞书官方 MCP 安全地接入 ChatGPT 等支持 Streamable HTTP MCP 的客户端。
本项目使用 **飞书 User Access Token(UAT)**,而不是 Tenant Access Token(TAT)。首次部署后通过浏览器完成一次飞书 OAuth 授权,Worker 会保存并自动刷新 UAT,后续所有 MCP 请求都以被授权用户本人的身份访问飞书资源。
> 适合:希望让 AI 搜索、读取、创建、更新自己的飞书云文档,并且不想把飞书 Token 直接暴露给 MCP 客户端的场景。
## 工作方式
```mermaid
flowchart LR
A[ChatGPT / MCP Client] -->|/mcp/随机密钥| B[Cloudflare Worker]
B -->|X-Lark-MCP-UAT| C[飞书官方 MCP]
B --> D[Durable Object]
D -->|保存 / 刷新 UAT| E[飞书 OAuth]
```
核心设计:
- 使用飞书官方远程 MCP:`https://mcp.feishu.cn/mcp`
- 通过 OAuth 获取代表当前用户的 `user_access_token`
- 使用 Durable Object 保存 token,并串行刷新一次性 `refresh_token`
- MCP 地址使用高强度随机路径密钥保护
- `FEISHU_APP_SECRET`、`MCP_GATEWAY_KEY` 仅作为 Cloudflare Secret 保存
- ChatGPT 永远拿不到飞书 UAT、refresh token 或 App Secret
## 默认开放的飞书能力
默认 `wrangler.toml` 中允许:
| Tool | 作用 |
|---|---|
| `search-user` | 搜索企业内用户 |
| `get-user` | 获取用户信息 |
| `fetch-file` | 获取云文档中的文件/图片 |
| `search-doc` | 搜索云文档 |
| `create-doc` | 创建云文档 |
| `fetch-doc` | 读取云文档 |
| `update-doc` | 更新云文档 |
| `list-docs` | 获取知识空间节点下文档列表 |
| `get-comments` | 查看文档评论 |
| `add-comments` | 添加文档评论 |
可以通过 `wrangler.toml` 的 `LARK_ALLOWED_TOOLS` 缩小工具范围。若只需要读取,建议移除创建、更新和评论写入工具,同时在飞书后台关闭对应写权限。
## 前置条件
你需要:
- 一个飞书企业自建应用
- Cloudflare 账号
- Node.js 20+
- 一个支持远程 MCP / Streamable HTTP 的客户端,例如 ChatGPT Developer Mode
## 操作流程
### 1. 配置飞书自建应用
在飞书开放平台创建或进入一个自建应用,并确保你本人位于应用的可用范围内。
在 **权限管理** 中开通 `wrangler.toml` 的 `LARK_OAUTH_SCOPES` 所列用户身份权限。默认包含云文档、知识库、评论、通讯录查询等权限。
其中必须包含:
```text
offline_access
```
它用于获取 `refresh_token`,让 Worker 可以长期自动刷新 UAT。
如果应用安全设置中存在“刷新 user_access_token”相关开关,也需要开启并重新发布应用版本。
### 2. 克隆并安装
```powershell
git clone https://github.com/wangling-miao/feishu-mcp.git
cd feishu-mcp
npm install
npm run typecheck
```
### 3. 生成随机 MCP 密钥
```powershell
python -c "import secrets; print(secrets.token_urlsafe(32))"
```
保存输出结果,后面会作为 `MCP_GATEWAY_KEY`。
### 4. 配置 Cloudflare Secrets
复制示例文件:
```powershell
Copy-Item .env.production.example .env.production
```
编辑 `.env.production`:
```dotenv
FEISHU_APP_ID=cli_xxxxxxxxxxxxxxxx
FEISHU_APP_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
MCP_GATEWAY_KEY=你的高强度随机密钥
```
> `.env.production` 已被 `.gitignore` 排除。不要把真实 App Secret 或随机密钥提交到 Git。
### 5. 部署到 Cloudflare Workers
```powershell
npx wrangler@latest login
npx wrangler@latest deploy --secrets-file .env.production
```
部署完成后会得到类似:
```text
https://feishu-mcp-gateway.<account>.workers.dev
```
### 6. 配置飞书 OAuth 回调地址
回到飞书开放平台,在应用的 **安全设置 / 重定向 URL** 中添加:
```text
https://feishu-mcp-gateway.<account>.workers.dev/oauth/callback
```
保存配置,并按飞书要求重新发布应用版本。
### 7. 首次绑定你的飞书账号
浏览器访问:
```text
https://feishu-mcp-gateway.<account>.workers.dev/auth/<MCP_GATEWAY_KEY>
```
完成飞书登录和授权后,Worker 会:
1. 获取 authorization code
2. 换取 `user_access_token` 与 `refresh_token`
3. 调用飞书用户信息接口验证 UAT
4. 将 token 安全保存到 Durable Object
5. 后续自动刷新过期 token
检查绑定状态:
```text
https://feishu-mcp-gateway.<account>.workers.dev/auth/status/<MCP_GATEWAY_KEY>
```
正常结果应包含:
```json
{
"authorized": true,
"user_name": "...",
"open_id": "ou_...",
"has_refresh_token": true
}
```
### 8. 接入 ChatGPT
MCP Endpoint:
```text
https://feishu-mcp-gateway.<account>.workers.dev/mcp/<MCP_GATEWAY_KEY>
```
在 ChatGPT 中:
1. 打开 Developer Mode / 自定义 MCP 配置
2. 添加远程 MCP
3. Transport 选择 Streamable HTTP / Streaming HTTP
4. Authentication 选择 `No Authentication`
5. 填入上面的 MCP Endpoint
6. Scan / Refresh Tools
这里的 `No Authentication` 只表示 ChatGPT 不再额外发送 OAuth Header;真正的网关认证由随机 URL 密钥完成,飞书侧则由 Worker 注入 UAT。
### 9. 测试
项目提供 PowerShell 测试脚本:
```powershell
.\scripts\test.ps1 `
-BaseUrl "https://feishu-mcp-gateway.<account>.workers.dev" `
-GatewayKey "你的MCP_GATEWAY_KEY"
```
脚本会检查授权状态、MCP `initialize` 与 `tools/list`。
## 常用维护
### 重新绑定飞书账号
```powershell
Invoke-RestMethod -Method Post `
"https://feishu-mcp-gateway.<account>.workers.dev/auth/logout/<MCP_GATEWAY_KEY>"
```
然后重新访问:
```text
/auth/<MCP_GATEWAY_KEY>
```
### 修改允许的 MCP 工具
编辑 `wrangler.toml`:
```toml
LARK_ALLOWED_TOOLS = "search-doc,fetch-doc,list-docs"
```
重新部署:
```powershell
npx wrangler@latest deploy --secrets-file .env.production
```
### 修改 OAuth 权限
同步修改:
1. 飞书开放平台中的用户身份权限
2. `wrangler.toml` 中 `LARK_OAUTH_SCOPES`
3. 必要时重新 OAuth 授权
## 常见问题
### `code=20005 msg=invalid access token`
通常表示 UAT 无效或已过期。本项目会自动刷新 UAT;若持续出现,请检查:
- 是否已经通过 `/auth/<KEY>` 完成 OAuth
- `offline_access` 是否已经开通
- refresh token 权限/开关是否生效
- 应用是否重新发布
- 当前用户是否仍在应用可用范围内
### 为什么不用 TAT?
TAT 代表“应用”,不是创建应用的个人。应用不会因为是你创建的,就自动继承你的个人云文档权限。UAT 才代表完成 OAuth 的飞书用户,因此更适合“让 AI 操作我自己的飞书文档”这一场景。
### 能访问哪些文档?
最终权限取决于三层:
1. OAuth 用户本人拥有的资源权限
2. 自建应用申请并获批的用户身份 scope
3. `LARK_ALLOWED_TOOLS` 允许暴露给 MCP 客户端的工具
## 安全建议
- 使用至少 32 字节随机 `MCP_GATEWAY_KEY`
- 不要把真实 `.env.production` 提交 Git
- 不需要写操作时,移除写工具与写权限
- 泄露随机密钥后立即更换并重新部署
- 不要在日志中打印 UAT、refresh token 或 App Secret
## 项目结构
```text
.
├── src/
│ └── index.ts # Worker、OAuth、MCP 代理和 Durable Object
├── scripts/
│ └── test.ps1 # 部署后测试
├── wrangler.toml # Cloudflare Worker 配置
├── .env.production.example # Secret 示例
├── package.json
└── tsconfig.json
```
## License
当前仓库未附加开源许可证;如需二次分发,请先确认授权方式。
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues