feishu-user-plugin 1.3.10 → 1.3.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +2 -2
- package/.cursor-plugin/plugin.json +27 -0
- package/.mcpb/manifest.json +91 -0
- package/CHANGELOG.md +118 -0
- package/PRIVACY.md +105 -0
- package/README.en.md +130 -413
- package/README.md +88 -258
- package/package.json +5 -3
- package/scripts/build-mcpb.js +119 -0
- package/scripts/check-description-drift.js +73 -0
- package/scripts/check-docs-sync.js +7 -16
- package/scripts/check-mcp-registry-version.js +43 -0
- package/scripts/check-mcpb-version.js +33 -0
- package/scripts/check-scopes.js +99 -0
- package/scripts/check-tool-count.js +4 -3
- package/scripts/check-version.js +5 -0
- package/scripts/sync-claude-md.sh +3 -4
- package/scripts/sync-team-skills.sh +72 -57
- package/scripts/verify-app-name.js +64 -0
- package/skills/feishu-user-plugin/SKILL.md +3 -3
- package/skills/feishu-user-plugin/references/search.md +3 -3
- package/src/auth/credentials-monitor.js +185 -0
- package/src/auth/credentials.js +49 -0
- package/src/auth/identity-state.js +204 -0
- package/src/auth/lark-desktop.js +135 -0
- package/src/auth/uat.js +49 -35
- package/src/cli.js +87 -0
- package/src/clients/official/base.js +145 -14
- package/src/clients/official/calendar.js +3 -1
- package/src/clients/official/im.js +76 -2
- package/src/clients/official/okr.js +2 -1
- package/src/error-codes.js +40 -0
- package/src/events/lockfile.js +40 -4
- package/src/events/owner.js +11 -2
- package/src/index.js +1 -1
- package/src/logger.js +11 -5
- package/src/oauth.js +46 -10
- package/src/server.js +102 -37
- package/src/setup.js +44 -0
- package/src/test-all.js +40 -0
- package/src/test-cli-tool.js +87 -0
- package/src/test-credentials-monitor.js +124 -0
- package/src/test-display-label.js +88 -0
- package/src/test-error-codes.js +85 -0
- package/src/test-identity-state.js +172 -0
- package/src/test-lark-desktop.js +300 -0
- package/src/test-lockfile-pid.js +90 -0
- package/src/test-lru-cache.js +145 -0
- package/src/test-negative-cache.js +85 -0
- package/src/test-populate-sender-names.js +98 -0
- package/src/test-search-messages.js +101 -0
- package/src/test-send-shape.js +115 -0
- package/src/test-via-user.js +94 -0
- package/src/test-with-uat-retry.js +135 -0
- package/src/tools/_registry.js +24 -1
- package/src/tools/calendar.js +5 -5
- package/src/tools/im-read.js +52 -4
- package/src/tools/messaging-user.js +1 -1
- package/src/utils.js +83 -0
- package/scripts/generate-og-image.js +0 -39
- package/skills/feishu-user-plugin/references/CLAUDE.md +0 -523
package/README.en.md
CHANGED
|
@@ -1,189 +1,102 @@
|
|
|
1
|
-
# feishu-user-plugin
|
|
1
|
+
# feishu-user-plugin — Feishu MCP server + CLI tool
|
|
2
2
|
|
|
3
3
|
[](LICENSE)
|
|
4
4
|
[](https://nodejs.org)
|
|
5
5
|
[](https://modelcontextprotocol.io)
|
|
6
|
-
[](docs/TOOLS.md)
|
|
7
|
+
[](https://www.npmjs.com/package/feishu-user-plugin)
|
|
7
8
|
[](CONTRIBUTING.md)
|
|
8
9
|
|
|
9
|
-
**
|
|
10
|
+
[中文](README.md) · **English** · [Docs](https://ethanqc.github.io/feishu-user-plugin/en) · [CHANGELOG](CHANGELOG.md) · [npm](https://www.npmjs.com/package/feishu-user-plugin)
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
Feishu / Lark MCP server covering IM, docs, bitable, wiki, drive, calendar, tasks v2, OKR, and realtime events. **85 tools · 3 auth layers · 9 MCP prompts · MIT licensed · Node ≥18**.
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
Works with Claude Code, Codex, Cursor, Windsurf, VS Code, Claude Desktop, OpenClaw, and any MCP-compatible client.
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
There are two paths to user-identity messaging: **Feishu's official OAuth scope `im:message.send_as_user`** (requires creating a self-built app + admin approval), or this repo's **cookie + protobuf path** (zero app barrier — capture cookie and you're ready). This repo is no longer architecturally exclusive, but it remains the simpler option for "individual developers / no admin access / want to try quickly" scenarios.
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
- **Read everything** -- Group chats via bot API, P2P (direct messages) via OAuth UAT.
|
|
19
|
-
- **Full Feishu suite** -- Docs, Bitable, Wiki, Drive, Calendar, Tasks, Contacts -- all in one plugin.
|
|
20
|
-
- **3 auth layers** -- Cookie-based user identity, app credentials (Official API), and OAuth UAT (P2P reading).
|
|
21
|
-
- **Group management** -- Create groups, add/remove members, pin messages, emoji reactions.
|
|
22
|
-
- **Document editing** -- Not just read/create, but insert/update/delete content blocks.
|
|
23
|
-
- **Calendar & Tasks** -- Create events, check free/busy, manage tasks.
|
|
24
|
-
- **9 slash commands** for Claude Code -- `/send`, `/reply`, `/search`, `/digest`, `/doc`, `/table`, `/wiki`, `/drive`, `/status`
|
|
25
|
-
- **Auto session management** -- Cookie heartbeat every 4h, UAT auto-refresh with token rotation.
|
|
26
|
-
- **Real-time events** (v1.3.9) -- Machine-level WS: one owner process writes to `~/.feishu-user-plugin/events.jsonl`, all harnesses drain from a shared cursor — every event delivered exactly once across all MCP processes. `manage_ws_status` to diagnose/control. WS auto-starts on boot.
|
|
27
|
-
- **Multi-platform** -- Claude Code, Cursor, Windsurf, VS Code, OpenClaw.
|
|
18
|
+
## vs the official Feishu/Lark tools (released 2026)
|
|
28
19
|
|
|
29
|
-
|
|
20
|
+
- [`larksuite/lark-openapi-mcp`](https://github.com/larksuite/lark-openapi-mcp) — official OpenAPI MCP, **⚠ Beta**, last updated 2025-08 (9 months stale). Their README explicitly states "File upload/download not yet supported" and "Direct document editing not supported"; 1271 endpoint tools but preset.default only enables ~20, the rest "not undergone compatibility testing".
|
|
21
|
+
- [`larksuite/cli`](https://github.com/larksuite/cli) — official CLI (9.9k stars, actively maintained), 17 business domains, 200+ commands + 24 AI Agent Skills. **Now supports `+messages-send --as user`** via OAuth scope `im:message.send_as_user`. But it's a **CLI, not an MCP server**. Codex / Cursor / Windsurf etc would have to shell out to it.
|
|
30
22
|
|
|
31
|
-
|
|
23
|
+
**When to use this repo**:
|
|
32
24
|
|
|
33
|
-
|
|
25
|
+
- You want user-identity messaging / P2P chat reading but **can't / don't want to create a Feishu self-built app** (individual developer / no admin access) — the cookie path has zero barrier
|
|
26
|
+
- You use MCP protocol (Codex / Cursor / Windsurf / VS Code etc) and don't need mail / approval / HR / meeting-minutes domains that this repo doesn't cover
|
|
27
|
+
- You run multiple MCP clients simultaneously and need "every event delivered exactly once across the entire machine" (v1.3.9+ machine-level WS SSOT)
|
|
34
28
|
|
|
35
|
-
|
|
36
|
-
User Identity (cookie): You -> Protobuf -> Feishu (messages appear as YOU)
|
|
37
|
-
Official API (app token): You -> REST API -> Feishu (docs, tables, wiki, drive)
|
|
38
|
-
User OAuth (UAT): You -> REST API -> Feishu (read P2P chats, list all chats)
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
**One plugin. Everything Feishu. No other MCP needed.**
|
|
29
|
+
**When to use the official**: you need mail / approval / attendance / HR / hiring / meeting-minutes business-system domains; or you already have a Feishu app + admin-approved OAuth scopes and prefer the officially-maintained long-term path.
|
|
42
30
|
|
|
43
|
-
|
|
31
|
+
Full honest comparison: [docs/COMPARISON.md](docs/COMPARISON.md).
|
|
44
32
|
|
|
45
|
-
|
|
33
|
+
## Quick example
|
|
46
34
|
|
|
47
|
-
```bash
|
|
48
|
-
npx feishu-user-plugin
|
|
49
35
|
```
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
### Option 2: Clone and run locally
|
|
54
|
-
|
|
55
|
-
```bash
|
|
56
|
-
git clone https://github.com/EthanQC/feishu-user-plugin.git
|
|
57
|
-
cd feishu-user-plugin
|
|
58
|
-
npm install
|
|
59
|
-
npm start
|
|
36
|
+
You: send Wang Xiao Ming a message as me: "finished the code review, 3 nits"
|
|
37
|
+
Claude: [calls send_to_user] Sent
|
|
60
38
|
```
|
|
61
39
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
### Step 1: Create the App
|
|
67
|
-
|
|
68
|
-
1. Go to [Feishu Open Platform](https://open.feishu.cn/app) and log in
|
|
69
|
-
2. Click **Create Custom App** (创建自建应用) -- you must choose **Custom App** (自建应用), NOT marketplace/third-party types
|
|
70
|
-
3. Fill in the app name and description, then create it
|
|
71
|
-
|
|
72
|
-
### Step 2: Enable Bot Capability
|
|
73
|
-
|
|
74
|
-
1. In your app settings, go to **Add Capabilities** (添加应用能力)
|
|
75
|
-
2. Enable **Bot** (机器人)
|
|
76
|
-
|
|
77
|
-
### Step 3: Add Permissions (Scopes)
|
|
78
|
-
|
|
79
|
-
Go to **Permissions & Scopes** (权限管理) and add the following scopes:
|
|
80
|
-
|
|
81
|
-
| Scope | Purpose |
|
|
82
|
-
|-------|---------|
|
|
83
|
-
| `im:message` | Send messages as bot |
|
|
84
|
-
| `im:message:readonly` | Read message history |
|
|
85
|
-
| `im:chat:readonly` | List and read chats |
|
|
86
|
-
| `docx:document` | Read and create documents |
|
|
87
|
-
| `docx:document:readonly` | Read documents |
|
|
88
|
-
| `bitable:record` | Read and write Bitable records |
|
|
89
|
-
| `wiki:wiki:readonly` | Read wiki spaces and nodes |
|
|
90
|
-
| `drive:drive:readonly` | List Drive files and folders |
|
|
91
|
-
| `contact:user.base:readonly` | Look up users by email/mobile |
|
|
92
|
-
|
|
93
|
-
> Add more scopes as needed depending on which tools you use.
|
|
94
|
-
|
|
95
|
-
### Step 4: Get App Credentials
|
|
96
|
-
|
|
97
|
-
1. Go to **Credentials & Basic Info** (凭证与基础信息)
|
|
98
|
-
2. Copy the **App ID** (`cli_xxxxxxxxxxxx`) and **App Secret**
|
|
99
|
-
3. Set them as `LARK_APP_ID` and `LARK_APP_SECRET` in your environment
|
|
100
|
-
|
|
101
|
-
### Step 5: Publish and Approve
|
|
102
|
-
|
|
103
|
-
1. **Create a version** and submit it for review (创建版本)
|
|
104
|
-
2. Have your organization admin approve the app (管理员审核)
|
|
105
|
-
3. After approval, the app is live
|
|
106
|
-
|
|
107
|
-
### Step 6: Add Bot to Group Chats
|
|
108
|
-
|
|
109
|
-
Add your bot to the group chats where you want it to read messages. The bot can only access chats it has been added to.
|
|
110
|
-
|
|
111
|
-
## Environment Variables
|
|
112
|
-
|
|
113
|
-
| Variable | Required For | Description |
|
|
114
|
-
|----------|-------------|-------------|
|
|
115
|
-
| `LARK_COOKIE` | User identity tools | Feishu web session cookie string. Needed for `send_to_user`, `send_to_group`, `search_contacts`, etc. |
|
|
116
|
-
| `LARK_APP_ID` | Official API tools | App ID from Feishu Open Platform. Needed for `read_messages`, docs, tables, wiki, drive. |
|
|
117
|
-
| `LARK_APP_SECRET` | Official API tools | App Secret from Feishu Open Platform. Used together with `LARK_APP_ID`. |
|
|
118
|
-
| `LARK_USER_ACCESS_TOKEN` | P2P chat reading | OAuth user token. Needed for `read_p2p_messages` and `list_user_chats`. Obtained via `node src/oauth.js`. |
|
|
119
|
-
| `LARK_USER_REFRESH_TOKEN` | UAT auto-refresh | Refresh token for automatic UAT renewal. Obtained together with UAT via OAuth flow. |
|
|
120
|
-
|
|
121
|
-
All five variables are required for full functionality. Configure all of them during setup.
|
|
122
|
-
|
|
123
|
-
## How to Get Your Cookie
|
|
40
|
+
```
|
|
41
|
+
You: summarize today's discussion in the engineering group after 9am, post a daily digest to #daily
|
|
42
|
+
Claude: [read_messages → summarize → send_to_group] Sent
|
|
43
|
+
```
|
|
124
44
|
|
|
125
|
-
|
|
45
|
+
## Quick start
|
|
126
46
|
|
|
127
|
-
First, install Playwright MCP if you don't have it:
|
|
128
47
|
```bash
|
|
129
|
-
npx
|
|
48
|
+
npx feishu-user-plugin setup --app-id <APP_ID> --app-secret <APP_SECRET>
|
|
49
|
+
npx feishu-user-plugin oauth # OAuth UAT
|
|
50
|
+
# restart Claude Code / Codex
|
|
130
51
|
```
|
|
131
52
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
Claude Code will automatically:
|
|
135
|
-
1. Open feishu.cn in a browser via Playwright
|
|
136
|
-
2. Show you the QR code — scan it with Feishu mobile app
|
|
137
|
-
3. Extract the full cookie (including HttpOnly) via `context.cookies()`
|
|
138
|
-
4. Write it to your `.mcp.json` LARK_COOKIE field
|
|
139
|
-
5. Prompt you to restart Claude Code
|
|
53
|
+
Cookie capture (Playwright auto-QR / DevTools manual), Feishu app creation, per-client config — see [docs/AUTH-SETUP.md](docs/AUTH-SETUP.md).
|
|
140
54
|
|
|
141
|
-
|
|
55
|
+
## Three auth layers
|
|
142
56
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
6. Set it as `LARK_COOKIE` in your environment
|
|
57
|
+
| Layer | Credentials | Capabilities | Tools |
|
|
58
|
+
|---|---|---|---|
|
|
59
|
+
| User identity (cookie + protobuf) | `LARK_COOKIE` | Send text / image / file / post / @ / batch as the user | 8 |
|
|
60
|
+
| Official API (bot) | `LARK_APP_ID` + `LARK_APP_SECRET` | Group messages, docs, bitable, wiki, drive, calendar, tasks v2, OKR, contacts, realtime WS | 70+ |
|
|
61
|
+
| User OAuth UAT | `LARK_USER_ACCESS_TOKEN` + `LARK_USER_REFRESH_TOKEN` | P2P chat reading, user chat list; resources owned by the user when creating | 2 explicit + UAT-first across the suite |
|
|
149
62
|
|
|
150
|
-
|
|
63
|
+
Layers are independent — configure any subset.
|
|
151
64
|
|
|
152
|
-
|
|
65
|
+
## Capabilities
|
|
153
66
|
|
|
154
|
-
|
|
67
|
+
- **Send messages as you** (8): text / image / file / rich-text post / cards / batch; differentiator — Feishu's official API has no `send_as_user`
|
|
68
|
+
- **Read groups & P2P chats** (17): group messages / P2P / `merge_forward` auto-expanded / URL + Feishu doc links auto-extracted / external groups auto-fallback to UAT
|
|
69
|
+
- **Document suite** (27): Feishu docs (with `read_doc_markdown` saving ~60% tokens) / bitable (batch up to 500) / wiki (full write CRUD) / drive
|
|
70
|
+
- **Productivity** (21): calendar (read+write) / tasks v2 (with member management) / OKR (read + progress records) / contacts
|
|
71
|
+
- **Realtime events** (2): machine-level SSOT WS, every event delivered exactly once across the entire machine
|
|
72
|
+
- **Diagnostics & multi-account** (4): N profiles auto-switched per call, writes never auto-switch (avoids accidental cross-account creates)
|
|
155
73
|
|
|
156
|
-
|
|
74
|
+
Full tool list + cross-domain caveats + usage patterns: [docs/TOOLS.md](docs/TOOLS.md).
|
|
157
75
|
|
|
158
|
-
|
|
159
|
-
2. Add scopes: `im:message`, `im:message:readonly`, `im:chat:readonly`
|
|
160
|
-
3. In your app's **Security Settings** (安全设置), add the OAuth redirect URI: `http://127.0.0.1:9997/callback`
|
|
161
|
-
4. **Important**: Make sure "对外共享" (external sharing) is **disabled** in your app version settings — enabling it marks the app as b2c/b2b type, which blocks P2P chat access
|
|
162
|
-
5. Run the authorization flow:
|
|
76
|
+
## 9 MCP prompts (slash commands)
|
|
163
77
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
78
|
+
| Prompt | Purpose |
|
|
79
|
+
|---|---|
|
|
80
|
+
| `/send` | Send a message as yourself |
|
|
81
|
+
| `/reply` | Read recent messages then reply |
|
|
82
|
+
| `/digest` | Summarise recent group / P2P messages |
|
|
83
|
+
| `/search` | Search contacts / groups |
|
|
84
|
+
| `/doc` | Search / read / create a Feishu doc |
|
|
85
|
+
| `/table` | Operate on a bitable |
|
|
86
|
+
| `/wiki` | Search wiki space |
|
|
87
|
+
| `/drive` | List drive files / create folder |
|
|
88
|
+
| `/status` | Check all three auth layers |
|
|
174
89
|
|
|
175
90
|
## MCP Client Configuration
|
|
176
91
|
|
|
177
92
|
### Claude Code
|
|
178
93
|
|
|
179
|
-
Add to your project's `.mcp.json
|
|
180
|
-
|
|
181
|
-
**Using npx:**
|
|
94
|
+
Add to `~/.claude.json` `mcpServers` (recommended global) or your project's `.mcp.json`:
|
|
182
95
|
|
|
183
96
|
```json
|
|
184
97
|
{
|
|
185
98
|
"mcpServers": {
|
|
186
|
-
"feishu": {
|
|
99
|
+
"feishu-user-plugin": {
|
|
187
100
|
"command": "npx",
|
|
188
101
|
"args": ["-y", "feishu-user-plugin"],
|
|
189
102
|
"env": {
|
|
@@ -198,30 +111,7 @@ Add to your project's `.mcp.json` (or `~/.claude/.mcp.json` for global):
|
|
|
198
111
|
}
|
|
199
112
|
```
|
|
200
113
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
```json
|
|
204
|
-
{
|
|
205
|
-
"mcpServers": {
|
|
206
|
-
"feishu": {
|
|
207
|
-
"command": "node",
|
|
208
|
-
"args": ["/absolute/path/to/feishu-user-plugin/src/index.js"],
|
|
209
|
-
"env": {
|
|
210
|
-
"LARK_COOKIE": "your-cookie-string",
|
|
211
|
-
"LARK_APP_ID": "cli_xxxxxxxxxxxx",
|
|
212
|
-
"LARK_APP_SECRET": "your-app-secret",
|
|
213
|
-
"LARK_USER_ACCESS_TOKEN": "your-uat",
|
|
214
|
-
"LARK_USER_REFRESH_TOKEN": "your-refresh-token"
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
Then just say things like:
|
|
222
|
-
- "Send a message to Alice saying the meeting is at 3pm"
|
|
223
|
-
- "What did the engineering group chat about today?"
|
|
224
|
-
- "Search for docs about MCP"
|
|
114
|
+
Or via CLI: `npx feishu-user-plugin setup --app-id <APP_ID> --app-secret <APP_SECRET>`.
|
|
225
115
|
|
|
226
116
|
### Claude Desktop
|
|
227
117
|
|
|
@@ -245,6 +135,25 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
|
|
|
245
135
|
}
|
|
246
136
|
```
|
|
247
137
|
|
|
138
|
+
### Codex
|
|
139
|
+
|
|
140
|
+
Add to `~/.codex/config.toml`:
|
|
141
|
+
|
|
142
|
+
```toml
|
|
143
|
+
[mcp_servers.feishu-user-plugin]
|
|
144
|
+
command = "npx"
|
|
145
|
+
args = ["-y", "feishu-user-plugin"]
|
|
146
|
+
|
|
147
|
+
[mcp_servers.feishu-user-plugin.env]
|
|
148
|
+
LARK_COOKIE = "your-cookie-string"
|
|
149
|
+
LARK_APP_ID = "cli_xxxxxxxxxxxx"
|
|
150
|
+
LARK_APP_SECRET = "your-app-secret"
|
|
151
|
+
LARK_USER_ACCESS_TOKEN = "your-uat"
|
|
152
|
+
LARK_USER_REFRESH_TOKEN = "your-refresh-token"
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Or via CLI: `npx feishu-user-plugin setup --client codex --app-id <APP_ID> --app-secret <APP_SECRET>`.
|
|
156
|
+
|
|
248
157
|
### Cursor
|
|
249
158
|
|
|
250
159
|
Add to `.cursor/mcp.json` in your project:
|
|
@@ -269,7 +178,7 @@ Add to `.cursor/mcp.json` in your project:
|
|
|
269
178
|
|
|
270
179
|
### VS Code (Copilot)
|
|
271
180
|
|
|
272
|
-
Add to `.vscode/mcp.json` in your project:
|
|
181
|
+
Add to `.vscode/mcp.json` in your project (note: top-level key is `servers`, not `mcpServers`):
|
|
273
182
|
|
|
274
183
|
```json
|
|
275
184
|
{
|
|
@@ -314,9 +223,7 @@ Add to `~/.openclaw/openclaw.json` (note: key path is `mcp.servers`, not `mcpSer
|
|
|
314
223
|
}
|
|
315
224
|
```
|
|
316
225
|
|
|
317
|
-
Or via CLI: `openclaw mcp set feishu-user-plugin '{"command":"npx","args":["-y","feishu-user-plugin"],"env":{...}}'
|
|
318
|
-
|
|
319
|
-
> OpenClaw's built-in Feishu channel handles receiving messages (bot identity). This plugin adds user identity messaging + docs/bitable/calendar/tasks.
|
|
226
|
+
Or via CLI: `openclaw mcp set feishu-user-plugin '{"command":"npx","args":["-y","feishu-user-plugin"],"env":{...}}'`.
|
|
320
227
|
|
|
321
228
|
### Windsurf
|
|
322
229
|
|
|
@@ -340,264 +247,74 @@ Add to `~/.codeium/windsurf/mcp_config.json`:
|
|
|
340
247
|
}
|
|
341
248
|
```
|
|
342
249
|
|
|
343
|
-
##
|
|
344
|
-
|
|
345
|
-
### User Identity -- Messaging (10 tools, cookie auth)
|
|
346
|
-
|
|
347
|
-
| Tool | Description |
|
|
348
|
-
|------|-------------|
|
|
349
|
-
| `send_to_user` | Search user by name + send text -- one step |
|
|
350
|
-
| `send_to_group` | Search group by name + send text -- one step |
|
|
351
|
-
| `send_as_user` | Send text to any chat by ID, supports reply threading |
|
|
352
|
-
| `send_image_as_user` | Send image (requires `image_key` from `upload_image`) |
|
|
353
|
-
| `send_file_as_user` | Send file (requires `file_key` from `upload_file`) |
|
|
354
|
-
| `send_post_as_user` | Send rich text with title + formatted paragraphs |
|
|
355
|
-
| `batch_send` | Fan-out send to multiple targets in one call (text / image / file / post). v1.3.6 |
|
|
356
|
-
| `send_card_as_user` | Send a Feishu interactive card via bot identity (Official API). User-identity card sending is server-side disabled at the Feishu cookie auth tier — confirmed in v1.3.9. |
|
|
357
|
-
|
|
358
|
-
### User Identity -- Contacts & Info (5 tools, cookie auth)
|
|
359
|
-
|
|
360
|
-
| Tool | Description |
|
|
361
|
-
|------|-------------|
|
|
362
|
-
| `search_contacts` | Search users, bots, or group chats by name |
|
|
363
|
-
| `create_p2p_chat` | Create/get P2P (direct message) chat |
|
|
364
|
-
| `get_chat_info` | Group details (supports both oc_xxx and numeric ID) |
|
|
365
|
-
| `get_user_info` | User display name lookup by user ID |
|
|
366
|
-
| `get_login_status` | Check cookie, app credentials, and UAT status |
|
|
367
|
-
|
|
368
|
-
### User OAuth UAT -- P2P Chat Reading (2 tools)
|
|
369
|
-
|
|
370
|
-
| Tool | Description |
|
|
371
|
-
|------|-------------|
|
|
372
|
-
| `read_p2p_messages` | Read P2P (direct message) history |
|
|
373
|
-
| `list_user_chats` | List group chats the user is in |
|
|
374
|
-
|
|
375
|
-
### Official API -- IM (17 tools)
|
|
376
|
-
|
|
377
|
-
| Tool | Description |
|
|
378
|
-
|------|-------------|
|
|
379
|
-
| `list_chats` | List all chats the bot has joined |
|
|
380
|
-
| `read_messages` | Read message history (accepts chat name, oc_xxx, or numeric ID) |
|
|
381
|
-
| `send_message_as_bot` | Send message as bot to any chat |
|
|
382
|
-
| `reply_message` | Reply to a specific message (as bot) |
|
|
383
|
-
| `forward_message` | Forward a message to another chat |
|
|
384
|
-
| `delete_message` | Recall/delete a bot message |
|
|
385
|
-
| `update_message` | Edit a sent bot message |
|
|
386
|
-
| `add_reaction` | Add emoji reaction to a message |
|
|
387
|
-
| `delete_reaction` | Remove emoji reaction |
|
|
388
|
-
| `pin_message` | Pin a message in chat |
|
|
389
|
-
| `unpin_message` | Unpin a message |
|
|
390
|
-
| `create_group` | Create a new group chat |
|
|
391
|
-
| `update_group` | Update group name/description |
|
|
392
|
-
| `list_members` | List group members |
|
|
393
|
-
| `add_members` | Add users to a group |
|
|
394
|
-
| `remove_members` | Remove users from a group |
|
|
395
|
-
| `upload_image` / `upload_file` | Upload image/file, returns key for sending |
|
|
396
|
-
| `download_message_resource` | v1.3.7 (C2.4): download a message-attached image or file. Args: `message_id`, `key`, `kind=image|file`, `save_path?`. **Required save_path when bytes > 2 MiB** (Anthropic 5 MB inline cap). Replaces v1.3.6 download_image (message mode) + download_file. |
|
|
397
|
-
| `download_doc_image` | v1.3.7 (C2.4): download an image embedded in a docx (image_token + optional doc_token). Same 2 MiB cap. Replaces v1.3.6 download_image (docx mode). |
|
|
398
|
-
|
|
399
|
-
### Wiki, OKR, and Calendar (v1.3.4)
|
|
400
|
-
|
|
401
|
-
| Tool | Description |
|
|
402
|
-
|------|-------------|
|
|
403
|
-
| `get_wiki_node` | Resolve a Wiki node token to its underlying obj_type + obj_token + space_id |
|
|
404
|
-
| `list_user_okrs` | List a user's OKRs (requires open_id; filter by period_ids) |
|
|
405
|
-
| `get_okrs` | Batch-fetch full OKR details (objectives, key results, progress, alignments) |
|
|
406
|
-
| `list_okr_periods` | List OKR periods (quarters / years) |
|
|
407
|
-
| `list_calendars` | List the current user's calendars (primary + shared + subscribed) |
|
|
408
|
-
| `list_calendar_events` | List events in a calendar within a time range |
|
|
409
|
-
| `get_calendar_event` | Full event details (attendees, location, meeting link, attachments) |
|
|
410
|
-
|
|
411
|
-
All docx / bitable tools' `document_id` / `app_token` parameter also accepts a Wiki node token or a full Feishu URL — the plugin resolves it transparently.
|
|
412
|
-
|
|
413
|
-
### Official API -- Documents (5 tools)
|
|
414
|
-
|
|
415
|
-
| Tool | Description |
|
|
416
|
-
|------|-------------|
|
|
417
|
-
| `search_docs` | Search documents by keyword |
|
|
418
|
-
| `read_doc` | Read raw text content |
|
|
419
|
-
| `get_doc_blocks` | Get structured block tree |
|
|
420
|
-
| `create_doc` | Create a new document |
|
|
421
|
-
| `manage_doc_block` | Insert / update / delete blocks (`action=create|update|delete`). Supports generic `children`, image (`image_path`/`image_token`), and file (`file_path`/`file_token`) shortcuts. v1.3.7 consolidates the v1.3.6 trio create_doc_block / update_doc_block / delete_doc_blocks. |
|
|
422
|
-
|
|
423
|
-
### Official API -- Bitable (6 tools, v1.3.7 consolidation)
|
|
424
|
-
|
|
425
|
-
| Tool | Actions | Description |
|
|
426
|
-
|------|---------|-------------|
|
|
427
|
-
| `manage_bitable_app` | create / copy / get_meta | App-level operations (v1.3.7 consolidates create_bitable / copy_bitable / get_bitable_meta) |
|
|
428
|
-
| `manage_bitable_table` | list / create / update / delete | Table CRUD (rename via update) |
|
|
429
|
-
| `manage_bitable_field` | list / create / update / delete | Field (column) management. `type` required for both create AND update. |
|
|
430
|
-
| `manage_bitable_view` | list / create / delete | Views (grid, kanban, gallery, form, gantt, calendar) |
|
|
431
|
-
| `manage_bitable_record` | search / get / create / update / delete | Record CRUD. create/update/delete accept arrays — single record or up to 500/call. |
|
|
432
|
-
| `upload_bitable_attachment` | — | Upload a file into a Bitable Attachment-type field. Returns `file_token` to write into the field as `[{file_token}]`. v1.3.6 |
|
|
433
|
-
|
|
434
|
-
### Official API -- Calendar (8 tools, write tools v1.3.7)
|
|
435
|
-
|
|
436
|
-
| Tool | Description |
|
|
437
|
-
|------|-------------|
|
|
438
|
-
| `list_calendars` | List accessible calendars |
|
|
439
|
-
| `list_calendar_events` | List events in a calendar |
|
|
440
|
-
| `get_calendar_event` | Full event details |
|
|
441
|
-
| `create_calendar_event` | Create an event (v1.3.7). Requires `calendar:calendar.event:write`. |
|
|
442
|
-
| `update_calendar_event` | Patch event fields (v1.3.7) |
|
|
443
|
-
| `delete_calendar_event` | Delete an event, optionally dissolve its meeting chat (v1.3.7) |
|
|
444
|
-
| `respond_calendar_event` | RSVP as accept / decline / tentative (v1.3.7) |
|
|
445
|
-
| `get_freebusy` | Freebusy lookup for `user_ids` in a time range (v1.3.7) |
|
|
446
|
-
|
|
447
|
-
### Official API -- Tasks v2 (7 tools, v1.3.7 new domain)
|
|
448
|
-
|
|
449
|
-
Identifier is `task_guid` (not v1's numeric `task_id`). Requires `task:task` scope.
|
|
450
|
-
|
|
451
|
-
| Tool | Description |
|
|
452
|
-
|------|-------------|
|
|
453
|
-
| `list_tasks` | List the current user's tasks (filter by completed / type) |
|
|
454
|
-
| `get_task` | Full task detail |
|
|
455
|
-
| `create_task` | Create a task (summary required; due/members optional) |
|
|
456
|
-
| `update_task` | Patch fields. **`update_fields` is required** — Feishu only updates the listed keys. |
|
|
457
|
-
| `complete_task` | Mark complete (or uncomplete with `completed=false`) |
|
|
458
|
-
| `delete_task` | Permanent delete |
|
|
459
|
-
| `manage_task_members` | `action=add|remove`, members `[{id, role:"assignee"|"follower"}]` |
|
|
460
|
-
|
|
461
|
-
### Official API -- Drive (4 tools)
|
|
462
|
-
|
|
463
|
-
| Tool | Description |
|
|
464
|
-
|------|-------------|
|
|
465
|
-
| `list_files` | List files in a folder |
|
|
466
|
-
| `create_folder` | Create a new folder |
|
|
467
|
-
| `manage_drive_file` | Copy / move / delete a Drive file (`action=copy|move|delete`, `type` required). v1.3.7 consolidates v1.3.6 copy_file / move_file / delete_file. |
|
|
468
|
-
| `upload_drive_file` | Upload a local file into a Drive folder (`drive/v1/files/upload_all`). Optional `wiki_space_id` attaches the upload as a Wiki node atomically. v1.3.6 |
|
|
469
|
-
|
|
470
|
-
### Official API -- Wiki (8 tools)
|
|
471
|
-
|
|
472
|
-
| Tool | Description |
|
|
473
|
-
|------|-------------|
|
|
474
|
-
| `list_wiki_spaces` / `search_wiki` / `list_wiki_nodes` / `get_wiki_node` | Wiki spaces, search, browse + resolve a wiki node to underlying obj_token |
|
|
475
|
-
| `create_wiki_node` | Create a new wiki node (doc/sheet/bitable/mindnote/file/docx/slides) inside a space |
|
|
476
|
-
| `update_wiki_node` | Rename a wiki node (title only — content edits via docx/bitable tools) |
|
|
477
|
-
| `move_wiki_node` | Move a wiki node to a different parent or different space |
|
|
478
|
-
| `copy_wiki_node` | Deep-copy a wiki node to a different location (optionally to a different space) |
|
|
479
|
-
|
|
480
|
-
### Plugin -- Profiles (3 tools, v1.3.6 + v1.3.8)
|
|
481
|
-
|
|
482
|
-
| Tool | Description |
|
|
483
|
-
|------|-------------|
|
|
484
|
-
| `list_profiles` | List available identity profiles (default + extras from `LARK_PROFILES_JSON`) and the active one |
|
|
485
|
-
| `switch_profile` | Hot-swap active profile; cached client instances rebuild against new credentials |
|
|
486
|
-
| `manage_profile_hints` | Inspect/set/clear the resourceKey → profile cache used by the v1.3.8 auto-switch middleware |
|
|
487
|
-
|
|
488
|
-
### Multi-profile auto-switch (v1.3.8)
|
|
489
|
-
|
|
490
|
-
When `~/.feishu-user-plugin/credentials.json` has more than one profile, the plugin auto-switches between them on **read** paths when the active profile gets a permission-denied error. The winning profile is cached per resource so subsequent calls go straight to the right account.
|
|
491
|
-
|
|
492
|
-
**Whitelist** -- only `read_*`, `list_*`, `get_*`, `search_*`, `download_*` (and the read-action variants of `manage_bitable_*`) get auto-retry. Writes never auto-switch -- they fail loud so you don't accidentally create resources under the wrong account.
|
|
493
|
-
|
|
494
|
-
**Triggers** -- error codes 91403, 1254301, 1254000, 99991672, HTTP 403, plus message patterns `access_denied / permission_denied / docx_no_permission / no permission / forbidden`.
|
|
250
|
+
## Multi-account
|
|
495
251
|
|
|
496
|
-
|
|
252
|
+
`~/.feishu-user-plugin/credentials.json` supports multiple profiles (default + any number of additional), so one machine handles multiple Feishu accounts / multiple tenants.
|
|
497
253
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
254
|
+
```bash
|
|
255
|
+
npx feishu-user-plugin list-profiles
|
|
256
|
+
npx feishu-user-plugin switch-profile <name>
|
|
257
|
+
npx feishu-user-plugin keepalive --all # cross-profile keepalive
|
|
258
|
+
```
|
|
503
259
|
|
|
504
|
-
|
|
260
|
+
Read-path tools auto-retry across profiles on errors `91403` / `1254301` / `1254000` / `99991672` / `HTTP 403`. Writes never auto-switch (avoids creating resources under the wrong account). Per-call override: pass `via_profile: "<name>"` to pin to a specific profile.
|
|
505
261
|
|
|
506
|
-
|
|
507
|
-
|-------|-------|-------------|
|
|
508
|
-
| `/send` | `/send Alice: meeting at 3pm` | Send message as yourself |
|
|
509
|
-
| `/reply` | `/reply engineering-chat` | Read recent messages and reply |
|
|
510
|
-
| `/digest` | `/digest engineering-chat 7` | Summarize recent chat messages |
|
|
511
|
-
| `/search` | `/search engineering` | Search contacts and groups |
|
|
512
|
-
| `/doc` | `/doc search MCP` | Search, read, or create documents |
|
|
513
|
-
| `/table` | `/table query appXxx` | Query or create Bitable records |
|
|
514
|
-
| `/wiki` | `/wiki search protocol` | Search and browse wiki |
|
|
515
|
-
| `/drive` | `/drive list folderToken` | List files or create folders in Drive |
|
|
516
|
-
| `/status` | `/status` | Check login and auth status |
|
|
262
|
+
Details: [docs/TOOLS.md "Multi-profile auto-switch"](docs/TOOLS.md#多-profile-auto-switchv138).
|
|
517
263
|
|
|
518
|
-
|
|
264
|
+
## Realtime events
|
|
519
265
|
|
|
520
|
-
|
|
266
|
+
A single MCP process per machine holds the WS owner lock. All MCP processes share `events.jsonl`, every event delivered exactly once across the entire machine.
|
|
521
267
|
|
|
268
|
+
```bash
|
|
269
|
+
mcp call manage_ws_status --action info
|
|
270
|
+
mcp call manage_ws_status --action claim --force true
|
|
522
271
|
```
|
|
523
|
-
Cookie + Proto ┌──────────────────────────────────────┐
|
|
524
|
-
────────────────── >│ internal-api-lark-api.feishu.cn │
|
|
525
|
-
┌──────────────┐ │ /im/gateway/ (Protobuf over HTTP) │
|
|
526
|
-
│ MCP Client │ └──────────────────────────────────────┘
|
|
527
|
-
│ (Claude, │ App Token (REST) ┌──────────────────────────────────────┐
|
|
528
|
-
│ Cursor, │ ────────────────->│ open.feishu.cn/open-apis/ │
|
|
529
|
-
│ VS Code) │ │ (Official REST API) │
|
|
530
|
-
│ │ └──────────────────────────────────────┘
|
|
531
|
-
│ │ User OAuth (REST)┌──────────────────────────────────────┐
|
|
532
|
-
│ │ ────────────────->│ open.feishu.cn/open-apis/ │
|
|
533
|
-
└──────────────┘ │ (UAT -- P2P chat reading) │
|
|
534
|
-
└──────────────────────────────────────┘
|
|
535
|
-
```
|
|
536
|
-
|
|
537
|
-
## Session & Token Lifecycle
|
|
538
|
-
|
|
539
|
-
| Auth Layer | Token | Lifetime | Refresh |
|
|
540
|
-
|------------|-------|----------|---------|
|
|
541
|
-
| Cookie | `sl_session` | 12h max-age | Auto-refreshed every 4h via heartbeat |
|
|
542
|
-
| App Token | `tenant_access_token` | 2h | Auto-managed by SDK |
|
|
543
|
-
| User OAuth | `user_access_token` | ~2h | Auto-refreshed via `refresh_token`, saved to MCP config |
|
|
544
272
|
|
|
545
|
-
|
|
273
|
+
Default subscriptions: `["im.message.receive_v1"]`. To subscribe to other events (approval / calendar / vc / etc.), edit `credentials.json::profiles[<active>].events`, then call `manage_ws_status(action=reconfig)` to apply without restart.
|
|
546
274
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
## Project Structure
|
|
550
|
-
|
|
551
|
-
```
|
|
552
|
-
feishu-user-plugin/
|
|
553
|
-
├── .claude-plugin/
|
|
554
|
-
│ └── plugin.json # Plugin metadata
|
|
555
|
-
├── skills/
|
|
556
|
-
│ └── feishu-user-plugin/
|
|
557
|
-
│ ├── SKILL.md # Main skill definition (trigger, tools, auth)
|
|
558
|
-
│ └── references/ # 8 skill reference docs + CLAUDE.md
|
|
559
|
-
├── src/
|
|
560
|
-
│ ├── index.js # MCP server entry point (78 tools)
|
|
561
|
-
│ ├── client.js # User identity client (Protobuf gateway)
|
|
562
|
-
│ ├── official.js # Official API client (REST, UAT)
|
|
563
|
-
│ ├── utils.js # ID generators, cookie parser
|
|
564
|
-
│ ├── oauth.js # OAuth flow for user_access_token
|
|
565
|
-
│ ├── test-send.js # Quick CLI test
|
|
566
|
-
│ └── test-all.js # Full test suite
|
|
567
|
-
├── proto/
|
|
568
|
-
│ └── lark.proto # Protobuf message definitions
|
|
569
|
-
├── .mcp.json.example # MCP server config template
|
|
570
|
-
├── server.json # MCP Registry manifest
|
|
571
|
-
├── .env.example # Configuration template
|
|
572
|
-
└── package.json
|
|
573
|
-
```
|
|
275
|
+
Only `feishu.cn` is supported — Lark international (`lark.com`) WSClient is not available.
|
|
574
276
|
|
|
575
277
|
## Limitations
|
|
576
278
|
|
|
577
|
-
- Cookie
|
|
578
|
-
-
|
|
579
|
-
-
|
|
580
|
-
-
|
|
581
|
-
-
|
|
279
|
+
- **Cookie lifetime**: 12-24 hours without heartbeat; re-login at feishu.cn to get a fresh cookie
|
|
280
|
+
- **Protocol drift**: cookie + protobuf path depends on Feishu web client protocol; Feishu updates may break user-identity messaging (bot capabilities unaffected)
|
|
281
|
+
- **Cards**: cookie path's card sending is server-disabled; bot path works
|
|
282
|
+
- **Lark international**: realtime events WS not supported
|
|
283
|
+
- **Not implemented**: `search_messages`, md → wiki sync (see [ROADMAP.md](ROADMAP.md))
|
|
284
|
+
|
|
285
|
+
## Documentation
|
|
286
|
+
|
|
287
|
+
| Document | Role |
|
|
288
|
+
|----------|------|
|
|
289
|
+
| [docs/TOOLS.md](docs/TOOLS.md) | Tool reference + cross-domain caveats + usage patterns |
|
|
290
|
+
| [docs/AUTH-SETUP.md](docs/AUTH-SETUP.md) | Install / 3 auth layers / cookie capture / OAuth scopes |
|
|
291
|
+
| [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md) | Error codes & diagnosis |
|
|
292
|
+
| [docs/RELEASING.md](docs/RELEASING.md) | Release flow + team-skills sync + announcement rules |
|
|
293
|
+
| [docs/REFACTOR-NOTES.md](docs/REFACTOR-NOTES.md) | File responsibility matrix |
|
|
294
|
+
| [docs/CREDENTIALS-FORMAT.md](docs/CREDENTIALS-FORMAT.md) | Credentials schema |
|
|
295
|
+
| [docs/TESTING-METHODOLOGY.md](docs/TESTING-METHODOLOGY.md) | Testing playbook |
|
|
296
|
+
| [CONTRIBUTING.md](CONTRIBUTING.md) | Contribution flow (bilingual) |
|
|
297
|
+
| [ROADMAP.md](ROADMAP.md) | Roadmap (forward-only) |
|
|
298
|
+
| [CHANGELOG.md](CHANGELOG.md) | Version history |
|
|
299
|
+
|
|
300
|
+
Full docs/ index: [docs/README.md](docs/README.md).
|
|
582
301
|
|
|
583
302
|
## Contributing
|
|
584
303
|
|
|
585
|
-
Issues
|
|
586
|
-
|
|
587
|
-
If Feishu updates their protocol and something breaks, please [open an issue](https://github.com/EthanQC/feishu-user-plugin/issues/new?template=bug_report.md) with the error details.
|
|
588
|
-
|
|
589
|
-
### Automated sync hooks
|
|
304
|
+
Issues / PRs welcome. Read [CONTRIBUTING.md](CONTRIBUTING.md) first.
|
|
590
305
|
|
|
591
|
-
|
|
306
|
+
If a Feishu protocol change breaks a tool — open an issue with the error log.
|
|
592
307
|
|
|
593
|
-
|
|
594
|
-
- **Version triangle** — if `package.json`, `.claude-plugin/plugin.json`, or `skills/feishu-user-plugin/SKILL.md` are staged, all three `version` fields must agree or the commit is rejected.
|
|
595
|
-
- **Tool-count badge** — if `src/server.js` or any file under `src/tools/` is staged, the `N tools` badge in `README.md` must match the actual `TOOLS.length` exported by `src/server.js`.
|
|
596
|
-
- **Smoke test** — any change under `src/` triggers `npm run smoke` to catch schema regressions before commit.
|
|
308
|
+
## Privacy
|
|
597
309
|
|
|
598
|
-
|
|
310
|
+
A locally-run MCP server. Credentials stay on the user's machine; no telemetry, no phone-home. Full text: [PRIVACY.md](PRIVACY.md).
|
|
599
311
|
|
|
600
|
-
|
|
312
|
+
- **Collected**: nothing by the plugin itself; the five `LARK_*` envs are supplied by the user from their own Feishu / Lark account
|
|
313
|
+
- **Processed**: only the messages / docs / bitable / wiki / drive / calendar / tasks / OKR / contacts the user explicitly requests via MCP tool calls
|
|
314
|
+
- **Stored**: `~/.feishu-user-plugin/credentials.json` (mode 0600); optional event log at `~/.feishu-user-plugin/events.jsonl`
|
|
315
|
+
- **Third-party**: only the user's own Feishu tenant and the AI client the user runs (Claude Code / Codex / Cursor / etc.)
|
|
316
|
+
- **Retention**: entirely user-controlled; `rm -rf ~/.feishu-user-plugin && npm uninstall -g feishu-user-plugin` removes everything
|
|
317
|
+
- **Contact**: [GitHub Issues](https://github.com/EthanQC/feishu-user-plugin/issues); security disclosures with `[security]` prefix in the title
|
|
601
318
|
|
|
602
319
|
## License
|
|
603
320
|
|
|
@@ -605,6 +322,6 @@ On the maintainer's machine, a post-merge hook (`scripts/sync-team-skills.sh`) a
|
|
|
605
322
|
|
|
606
323
|
## Acknowledgments
|
|
607
324
|
|
|
608
|
-
- [cv-cat/LarkAgentX](https://github.com/cv-cat/LarkAgentX)
|
|
609
|
-
- [cv-cat/OpenFeiShuApis](https://github.com/cv-cat/OpenFeiShuApis)
|
|
610
|
-
- [Model Context Protocol](https://modelcontextprotocol.io)
|
|
325
|
+
- [cv-cat/LarkAgentX](https://github.com/cv-cat/LarkAgentX) — early Feishu web protocol research (Python)
|
|
326
|
+
- [cv-cat/OpenFeiShuApis](https://github.com/cv-cat/OpenFeiShuApis) — underlying API research
|
|
327
|
+
- [Model Context Protocol](https://modelcontextprotocol.io) — MCP spec + Anthropic / PulseMCP / GitHub / Stacklok joint registry
|