feishu-user-plugin 1.0.0 → 1.0.2
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/.env.example +3 -3
- package/.mcp.json.example +3 -1
- package/CHANGELOG.md +22 -0
- package/README.md +30 -19
- package/package.json +2 -2
- package/skills/feishu-user-plugin/SKILL.md +3 -2
- package/skills/feishu-user-plugin/references/CLAUDE.md +65 -27
- package/src/index.js +12 -3
- package/src/test-comprehensive.js +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "feishu-user-plugin",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "All-in-one Feishu plugin for Claude Code — send messages as yourself, read chats, manage docs/tables/wiki. 33 tools +
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "All-in-one Feishu plugin for Claude Code — send messages as yourself, read chats, manage docs/tables/wiki. 33 tools + 9 skills, 3 auth layers.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "EthanQC"
|
|
7
7
|
},
|
package/.env.example
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# === User Identity (reverse-engineered protocol) ===
|
|
2
2
|
# Required for: send_as_user, send_to_user, send_to_group, search_contacts, etc.
|
|
3
|
-
# How to get: Login to feishu.cn → Playwright context.cookies() or DevTools
|
|
3
|
+
# How to get: Login to feishu.cn → Playwright context.cookies() or DevTools Network tab
|
|
4
4
|
LARK_COOKIE=
|
|
5
5
|
|
|
6
6
|
# === Official API (Feishu Open Platform) ===
|
|
@@ -9,9 +9,9 @@ LARK_COOKIE=
|
|
|
9
9
|
LARK_APP_ID=
|
|
10
10
|
LARK_APP_SECRET=
|
|
11
11
|
|
|
12
|
-
# === User OAuth UAT (
|
|
12
|
+
# === User OAuth UAT (required for P2P chat reading) ===
|
|
13
13
|
# Required for: read_p2p_messages, list_user_chats
|
|
14
|
-
# How to get: Run "node src/oauth.js" after configuring App ID/Secret above
|
|
14
|
+
# How to get: Run "node src/oauth.js" after configuring Cookie + App ID/Secret above
|
|
15
15
|
# These are auto-populated by the OAuth flow and auto-refreshed at runtime
|
|
16
16
|
LARK_USER_ACCESS_TOKEN=
|
|
17
17
|
LARK_USER_REFRESH_TOKEN=
|
package/.mcp.json.example
CHANGED
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
"env": {
|
|
7
7
|
"LARK_COOKIE": "YOUR_FEISHU_COOKIE_HERE",
|
|
8
8
|
"LARK_APP_ID": "YOUR_APP_ID_HERE",
|
|
9
|
-
"LARK_APP_SECRET": "YOUR_APP_SECRET_HERE"
|
|
9
|
+
"LARK_APP_SECRET": "YOUR_APP_SECRET_HERE",
|
|
10
|
+
"LARK_USER_ACCESS_TOKEN": "YOUR_UAT_HERE",
|
|
11
|
+
"LARK_USER_REFRESH_TOKEN": "YOUR_REFRESH_TOKEN_HERE"
|
|
10
12
|
}
|
|
11
13
|
}
|
|
12
14
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,28 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/), and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## [1.0.2] - 2026-03-10
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
- `list_user_chats` description incorrectly claimed "including P2P" — actually only returns groups
|
|
11
|
+
- OAuth scope `contact:user.id:readonly` → `contact:user.base:readonly` in README
|
|
12
|
+
- Cookie length validation range (500-5000, was 1000-5000)
|
|
13
|
+
- Version inconsistency across `server.json`, `plugin.json`, `SKILL.md`, `src/index.js`
|
|
14
|
+
- Skill count: 8 → 9 (was missing `/drive`)
|
|
15
|
+
- README_CN.md Claude Desktop config missing `env` block
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
- Startup auth diagnostics in `src/index.js` (Cookie/App/UAT status logging)
|
|
19
|
+
- `LARK_USER_REFRESH_TOKEN` to all MCP config examples
|
|
20
|
+
- Troubleshooting for `invalid_grant` errors (28003/20003/20005)
|
|
21
|
+
- Troubleshooting for `oauth.js` requiring APP_ID/SECRET in `.env`
|
|
22
|
+
- Playwright cookie setup: two-step extraction, `clearCookies()`, ASCII validation
|
|
23
|
+
- `LARK_USER_REFRESH_TOKEN` to `server.json` environment_variables
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
- All 5 env vars marked as required for full functionality
|
|
27
|
+
- Improved `read_p2p_messages` chat_id description (numeric + oc_xxx both accepted)
|
|
28
|
+
|
|
7
29
|
## [1.0.0] - 2026-03-09
|
|
8
30
|
|
|
9
31
|
### Changed
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
[](#tools-33-total)
|
|
7
7
|
[](CONTRIBUTING.md)
|
|
8
8
|
|
|
9
|
-
**All-in-one Feishu/Lark MCP Server -- 33 tools,
|
|
9
|
+
**All-in-one Feishu/Lark MCP Server -- 33 tools, 9 skills, 3 auth layers for messaging, docs, tables, wiki, and drive.**
|
|
10
10
|
|
|
11
11
|
The only MCP server that lets you send messages as your **personal identity** (not a bot), while also integrating the full official Feishu API for documents, spreadsheets, wikis, and more.
|
|
12
12
|
|
|
@@ -15,7 +15,7 @@ The only MCP server that lets you send messages as your **personal identity** (n
|
|
|
15
15
|
- **Send as yourself** -- Messages show your real name, not a bot. Supports text, rich text, images, files, stickers, and audio.
|
|
16
16
|
- **Read everything** -- Group chats via bot API, P2P (direct messages) via OAuth UAT.
|
|
17
17
|
- **Full Feishu suite** -- Docs, Bitable (spreadsheets), Wiki, Drive, Contacts -- all in one plugin.
|
|
18
|
-
- **3 auth layers** -- Cookie-based user identity, app credentials (Official API), and OAuth UAT (P2P reading).
|
|
18
|
+
- **3 auth layers** -- Cookie-based user identity, app credentials (Official API), and OAuth UAT (P2P reading). All three are needed for full functionality.
|
|
19
19
|
- **8 slash commands** for Claude Code -- `/send`, `/reply`, `/search`, `/digest`, `/doc`, `/table`, `/wiki`, `/status`
|
|
20
20
|
- **Auto session management** -- Cookie heartbeat every 4h, UAT auto-refresh with token rotation.
|
|
21
21
|
- **Chat name resolution** -- Pass a group name instead of `oc_xxx` ID; it resolves automatically.
|
|
@@ -82,7 +82,7 @@ Go to **Permissions & Scopes** (权限管理) and add the following scopes:
|
|
|
82
82
|
| `bitable:record` | Read and write Bitable records |
|
|
83
83
|
| `wiki:wiki:readonly` | Read wiki spaces and nodes |
|
|
84
84
|
| `drive:drive:readonly` | List Drive files and folders |
|
|
85
|
-
| `contact:user.
|
|
85
|
+
| `contact:user.base:readonly` | Look up users by email/mobile |
|
|
86
86
|
|
|
87
87
|
> Add more scopes as needed depending on which tools you use.
|
|
88
88
|
|
|
@@ -110,11 +110,9 @@ Add your bot to the group chats where you want it to read messages. The bot can
|
|
|
110
110
|
| `LARK_APP_ID` | Official API tools | App ID from Feishu Open Platform. Needed for `read_messages`, docs, tables, wiki, drive. |
|
|
111
111
|
| `LARK_APP_SECRET` | Official API tools | App Secret from Feishu Open Platform. Used together with `LARK_APP_ID`. |
|
|
112
112
|
| `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`. |
|
|
113
|
+
| `LARK_USER_REFRESH_TOKEN` | UAT auto-refresh | Refresh token for automatic UAT renewal. Obtained together with UAT via OAuth flow. |
|
|
113
114
|
|
|
114
|
-
|
|
115
|
-
- **Cookie only** -- for sending messages as yourself
|
|
116
|
-
- **App credentials only** -- for reading docs, tables, wiki, group chats
|
|
117
|
-
- **All three** -- for the full feature set
|
|
115
|
+
All five variables are required for full functionality. Configure all of them during setup.
|
|
118
116
|
|
|
119
117
|
## How to Get Your Cookie
|
|
120
118
|
|
|
@@ -147,9 +145,9 @@ Claude Code will automatically:
|
|
|
147
145
|
|
|
148
146
|
> The server automatically refreshes the session via heartbeat every 4 hours. The `sl_session` cookie has a 12-hour max-age.
|
|
149
147
|
|
|
150
|
-
##
|
|
148
|
+
## Set Up OAuth (Required for P2P Chat Reading)
|
|
151
149
|
|
|
152
|
-
To
|
|
150
|
+
To enable `read_p2p_messages` and `list_user_chats`:
|
|
153
151
|
|
|
154
152
|
1. Your Feishu app must be a **Custom App** (自建应用), NOT marketplace/third-party
|
|
155
153
|
2. Add scopes: `im:message`, `im:message:readonly`, `im:chat:readonly`
|
|
@@ -166,7 +164,7 @@ cd $(npm root -g)/feishu-user-plugin && node src/oauth.js
|
|
|
166
164
|
# Or clone the repo just for the OAuth step, then use npx for daily use
|
|
167
165
|
```
|
|
168
166
|
|
|
169
|
-
A browser window will open for OAuth consent. The token is saved to `.env` automatically and auto-refreshes at runtime. Add
|
|
167
|
+
A browser window will open for OAuth consent. The token is saved to `.env` automatically and auto-refreshes at runtime. Add both `LARK_USER_ACCESS_TOKEN` and `LARK_USER_REFRESH_TOKEN` from `.env` to your MCP config's `env` section.
|
|
170
168
|
|
|
171
169
|
## MCP Client Configuration
|
|
172
170
|
|
|
@@ -185,7 +183,9 @@ Add to your project's `.mcp.json` (or `~/.claude/.mcp.json` for global):
|
|
|
185
183
|
"env": {
|
|
186
184
|
"LARK_COOKIE": "your-cookie-string",
|
|
187
185
|
"LARK_APP_ID": "cli_xxxxxxxxxxxx",
|
|
188
|
-
"LARK_APP_SECRET": "your-app-secret"
|
|
186
|
+
"LARK_APP_SECRET": "your-app-secret",
|
|
187
|
+
"LARK_USER_ACCESS_TOKEN": "your-uat",
|
|
188
|
+
"LARK_USER_REFRESH_TOKEN": "your-refresh-token"
|
|
189
189
|
}
|
|
190
190
|
}
|
|
191
191
|
}
|
|
@@ -203,7 +203,9 @@ Add to your project's `.mcp.json` (or `~/.claude/.mcp.json` for global):
|
|
|
203
203
|
"env": {
|
|
204
204
|
"LARK_COOKIE": "your-cookie-string",
|
|
205
205
|
"LARK_APP_ID": "cli_xxxxxxxxxxxx",
|
|
206
|
-
"LARK_APP_SECRET": "your-app-secret"
|
|
206
|
+
"LARK_APP_SECRET": "your-app-secret",
|
|
207
|
+
"LARK_USER_ACCESS_TOKEN": "your-uat",
|
|
208
|
+
"LARK_USER_REFRESH_TOKEN": "your-refresh-token"
|
|
207
209
|
}
|
|
208
210
|
}
|
|
209
211
|
}
|
|
@@ -228,7 +230,9 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
|
|
|
228
230
|
"env": {
|
|
229
231
|
"LARK_COOKIE": "your-cookie-string",
|
|
230
232
|
"LARK_APP_ID": "cli_xxxxxxxxxxxx",
|
|
231
|
-
"LARK_APP_SECRET": "your-app-secret"
|
|
233
|
+
"LARK_APP_SECRET": "your-app-secret",
|
|
234
|
+
"LARK_USER_ACCESS_TOKEN": "your-uat",
|
|
235
|
+
"LARK_USER_REFRESH_TOKEN": "your-refresh-token"
|
|
232
236
|
}
|
|
233
237
|
}
|
|
234
238
|
}
|
|
@@ -248,7 +252,9 @@ Add to `.cursor/mcp.json` in your project:
|
|
|
248
252
|
"env": {
|
|
249
253
|
"LARK_COOKIE": "your-cookie-string",
|
|
250
254
|
"LARK_APP_ID": "cli_xxxxxxxxxxxx",
|
|
251
|
-
"LARK_APP_SECRET": "your-app-secret"
|
|
255
|
+
"LARK_APP_SECRET": "your-app-secret",
|
|
256
|
+
"LARK_USER_ACCESS_TOKEN": "your-uat",
|
|
257
|
+
"LARK_USER_REFRESH_TOKEN": "your-refresh-token"
|
|
252
258
|
}
|
|
253
259
|
}
|
|
254
260
|
}
|
|
@@ -269,7 +275,9 @@ Add to `.vscode/mcp.json` in your project:
|
|
|
269
275
|
"env": {
|
|
270
276
|
"LARK_COOKIE": "your-cookie-string",
|
|
271
277
|
"LARK_APP_ID": "cli_xxxxxxxxxxxx",
|
|
272
|
-
"LARK_APP_SECRET": "your-app-secret"
|
|
278
|
+
"LARK_APP_SECRET": "your-app-secret",
|
|
279
|
+
"LARK_USER_ACCESS_TOKEN": "your-uat",
|
|
280
|
+
"LARK_USER_REFRESH_TOKEN": "your-refresh-token"
|
|
273
281
|
}
|
|
274
282
|
}
|
|
275
283
|
}
|
|
@@ -289,7 +297,9 @@ Add to `~/.codeium/windsurf/mcp_config.json`:
|
|
|
289
297
|
"env": {
|
|
290
298
|
"LARK_COOKIE": "your-cookie-string",
|
|
291
299
|
"LARK_APP_ID": "cli_xxxxxxxxxxxx",
|
|
292
|
-
"LARK_APP_SECRET": "your-app-secret"
|
|
300
|
+
"LARK_APP_SECRET": "your-app-secret",
|
|
301
|
+
"LARK_USER_ACCESS_TOKEN": "your-uat",
|
|
302
|
+
"LARK_USER_REFRESH_TOKEN": "your-refresh-token"
|
|
293
303
|
}
|
|
294
304
|
}
|
|
295
305
|
}
|
|
@@ -328,7 +338,7 @@ Send messages as yourself, not as a bot.
|
|
|
328
338
|
| Tool | Description |
|
|
329
339
|
|------|-------------|
|
|
330
340
|
| `read_p2p_messages` | Read P2P (direct message) history. Works for chats the bot cannot access. |
|
|
331
|
-
| `list_user_chats` | List
|
|
341
|
+
| `list_user_chats` | List group chats the user is in. Note: only returns groups, not P2P. |
|
|
332
342
|
|
|
333
343
|
### Official API -- IM (Bot Identity)
|
|
334
344
|
|
|
@@ -378,9 +388,9 @@ Send messages as yourself, not as a bot.
|
|
|
378
388
|
|------|-------------|
|
|
379
389
|
| `find_user` | Find user by email or mobile number |
|
|
380
390
|
|
|
381
|
-
## Claude Code Slash Commands (
|
|
391
|
+
## Claude Code Slash Commands (9 skills)
|
|
382
392
|
|
|
383
|
-
This plugin includes
|
|
393
|
+
This plugin includes 9 built-in skills in `skills/feishu-user-plugin/`:
|
|
384
394
|
|
|
385
395
|
| Skill | Usage | Description |
|
|
386
396
|
|-------|-------|-------------|
|
|
@@ -391,6 +401,7 @@ This plugin includes 8 built-in skills in `skills/feishu-user-plugin/`:
|
|
|
391
401
|
| `/doc` | `/doc search MCP` | Search, read, or create documents |
|
|
392
402
|
| `/table` | `/table query appXxx` | Query or create Bitable records |
|
|
393
403
|
| `/wiki` | `/wiki search protocol` | Search and browse wiki |
|
|
404
|
+
| `/drive` | `/drive list folderToken` | List files or create folders in Drive |
|
|
394
405
|
| `/status` | `/status` | Check login and auth status |
|
|
395
406
|
|
|
396
407
|
Skills are automatically available when the plugin is installed.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "feishu-user-plugin",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "All-in-one Feishu plugin for Claude Code — send messages as yourself, read chats, manage docs/tables/wiki. 33 tools +
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "All-in-one Feishu plugin for Claude Code — send messages as yourself, read chats, manage docs/tables/wiki. 33 tools + 9 skills, 3 auth layers.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"feishu-user-plugin": "src/index.js"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: feishu-user-plugin
|
|
3
|
-
version: "1.0.
|
|
3
|
+
version: "1.0.2"
|
|
4
4
|
description: "All-in-one Feishu plugin — send messages as yourself, read group/P2P chats, manage docs/tables/wiki. Replaces and extends the official Feishu MCP."
|
|
5
5
|
allowed-tools: send_to_user, send_to_group, send_as_user, send_image_as_user, send_file_as_user, send_post_as_user, send_sticker_as_user, send_audio_as_user, search_contacts, create_p2p_chat, get_chat_info, get_user_info, get_login_status, read_p2p_messages, list_user_chats, list_chats, read_messages, reply_message, forward_message, search_docs, read_doc, create_doc, list_bitable_tables, list_bitable_fields, search_bitable_records, create_bitable_record, update_bitable_record, list_wiki_spaces, search_wiki, list_wiki_nodes, list_files, create_folder, find_user
|
|
6
6
|
user_invocable: true
|
|
@@ -61,7 +61,8 @@ Check cookie / app credentials / UAT — all three auth layers at once.
|
|
|
61
61
|
| LARK_COOKIE | **You** | Send messages as yourself | Yes (for messaging) |
|
|
62
62
|
| LARK_APP_ID | **You** (create a Feishu app) | Official API access | Yes |
|
|
63
63
|
| LARK_APP_SECRET | **You** (from your Feishu app) | Official API access | Yes |
|
|
64
|
-
| LARK_USER_ACCESS_TOKEN | **You** (OAuth flow
|
|
64
|
+
| LARK_USER_ACCESS_TOKEN | **You** (OAuth flow) | Read P2P chat history | Yes (for P2P reading) |
|
|
65
|
+
| LARK_USER_REFRESH_TOKEN | **You** (OAuth flow) | UAT auto-refresh | Yes (for P2P reading) |
|
|
65
66
|
|
|
66
67
|
### Getting Your Cookie (Automated via Playwright)
|
|
67
68
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
All-in-one Feishu plugin for Claude Code with three auth layers:
|
|
5
5
|
- **User Identity** (cookie auth): Send messages (text, image, file, post, sticker, audio) as yourself
|
|
6
6
|
- **Official API** (app credentials): Read group messages, docs, tables, wiki, drive, contacts
|
|
7
|
-
- **User OAuth UAT** (user_access_token): Read P2P chat history
|
|
7
|
+
- **User OAuth UAT** (user_access_token): Read P2P chat history, list all user's chats
|
|
8
8
|
|
|
9
9
|
## Tool Categories
|
|
10
10
|
|
|
@@ -26,7 +26,7 @@ All-in-one Feishu plugin for Claude Code with three auth layers:
|
|
|
26
26
|
- `get_login_status` — Check cookie, app, and UAT status
|
|
27
27
|
|
|
28
28
|
### User OAuth UAT Tools (P2P chat reading)
|
|
29
|
-
- `read_p2p_messages` — Read P2P (direct message) chat history.
|
|
29
|
+
- `read_p2p_messages` — Read P2P (direct message) chat history. chat_id accepts both numeric IDs (from create_p2p_chat) and oc_xxx format.
|
|
30
30
|
- `list_user_chats` — List group chats the user is in. Note: API only returns groups, not P2P. For P2P, use: `search_contacts` → `create_p2p_chat` → `read_p2p_messages`.
|
|
31
31
|
|
|
32
32
|
### Official API Tools (app credentials)
|
|
@@ -43,7 +43,7 @@ All-in-one Feishu plugin for Claude Code with three auth layers:
|
|
|
43
43
|
- Send text as yourself → `send_to_user` or `send_to_group`
|
|
44
44
|
- Send rich content → `send_post_as_user` (formatted text), `send_image_as_user` (images)
|
|
45
45
|
- Read group chat history → `read_messages` with chat name or oc_ ID
|
|
46
|
-
- Read P2P chat history → `search_contacts` → `create_p2p_chat` → `read_p2p_messages`
|
|
46
|
+
- Read P2P chat history → `search_contacts` → `create_p2p_chat` → `read_p2p_messages`
|
|
47
47
|
- Reply as user in thread → `send_as_user` with root_id
|
|
48
48
|
- Reply as bot → `reply_message` (official API, text messages only)
|
|
49
49
|
- Diagnose issues → `get_login_status` first
|
|
@@ -51,44 +51,82 @@ All-in-one Feishu plugin for Claude Code with three auth layers:
|
|
|
51
51
|
## Auth & Session
|
|
52
52
|
- **LARK_COOKIE**: Required for user identity tools. Session auto-refreshed every 4h via heartbeat.
|
|
53
53
|
- **LARK_APP_ID + LARK_APP_SECRET**: Required for official API tools.
|
|
54
|
-
- **LARK_USER_ACCESS_TOKEN**: Required for P2P reading.
|
|
54
|
+
- **LARK_USER_ACCESS_TOKEN + LARK_USER_REFRESH_TOKEN**: Required for P2P reading. Auto-refreshed via refresh_token.
|
|
55
55
|
|
|
56
56
|
## Automated Cookie Setup via Playwright
|
|
57
57
|
|
|
58
|
-
When LARK_COOKIE is missing or expired,
|
|
59
|
-
Do NOT ask the user to manually copy cookies from DevTools.
|
|
58
|
+
When LARK_COOKIE is missing or expired, obtain it using Playwright MCP.
|
|
60
59
|
|
|
61
60
|
### Prerequisites
|
|
62
|
-
Playwright MCP must be available. If not
|
|
61
|
+
Playwright MCP must be available. If not:
|
|
63
62
|
> Run: `npx @anthropic-ai/claude-code mcp add playwright -- npx @anthropic-ai/mcp-server-playwright`
|
|
64
63
|
> Then restart Claude Code.
|
|
65
64
|
|
|
66
|
-
### Automated Flow
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
65
|
+
### Automated Flow — FOLLOW EXACTLY
|
|
66
|
+
|
|
67
|
+
**Step 1: Clear cookies first** (Playwright uses persistent browser profile that may have a DIFFERENT account cached):
|
|
68
|
+
```
|
|
69
|
+
browser_run_code: await context.clearCookies();
|
|
70
|
+
browser_navigate: https://www.feishu.cn/messenger/
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Step 2: Show QR code and wait for login**:
|
|
74
|
+
```
|
|
75
|
+
browser_take_screenshot
|
|
76
|
+
```
|
|
77
|
+
Poll `browser_snapshot` every 5s until URL changes from `/accounts/`.
|
|
78
|
+
|
|
79
|
+
**Step 3: Extract cookie — TWO-STEP approach** (NEVER use browser_run_code output directly as cookie):
|
|
80
|
+
|
|
81
|
+
Step 3a via `browser_run_code`:
|
|
82
|
+
```js
|
|
83
|
+
const cookies = await page.context().cookies('https://www.feishu.cn');
|
|
84
|
+
const str = cookies.map(c => c.name + '=' + c.value).join('; ');
|
|
85
|
+
await page.evaluate(s => { window.__COOKIE__ = s; }, str);
|
|
86
|
+
return 'Stored ' + cookies.length + ' cookies, length=' + str.length;
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Step 3b via `browser_evaluate`:
|
|
90
|
+
```js
|
|
91
|
+
window.__COOKIE__
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Step 4: Validate** — Must be pure ASCII, contain `session=` and `sl_session=`, length 500-5000. If >10000, it's contaminated.
|
|
95
|
+
|
|
96
|
+
**Step 5: Write config** using exact format (NO `"type": "stdio"`):
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"feishu-user-plugin": {
|
|
100
|
+
"command": "npx",
|
|
101
|
+
"args": ["-y", "feishu-user-plugin"],
|
|
102
|
+
"env": {
|
|
103
|
+
"LARK_COOKIE": "<cookie>",
|
|
104
|
+
"LARK_APP_ID": "<id>",
|
|
105
|
+
"LARK_APP_SECRET": "<secret>",
|
|
106
|
+
"LARK_USER_ACCESS_TOKEN": "<uat>",
|
|
107
|
+
"LARK_USER_REFRESH_TOKEN": "<refresh>"
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
```
|
|
81
112
|
|
|
82
113
|
## Troubleshooting
|
|
83
114
|
|
|
84
115
|
### If cookie authentication fails
|
|
85
|
-
- **Best method**: Playwright
|
|
86
|
-
- **Manual fallback**: Network tab →
|
|
116
|
+
- **Best method**: Playwright two-step extraction (see above)
|
|
117
|
+
- **Manual fallback**: Network tab → first request → Request Headers → Cookie → Copy value
|
|
87
118
|
- Do NOT use `document.cookie` or Application → Cookies (misses HttpOnly cookies)
|
|
88
119
|
|
|
120
|
+
### If Playwright logs into the wrong account
|
|
121
|
+
- Always `context.clearCookies()` BEFORE navigating to feishu.cn
|
|
122
|
+
- Verify account by checking URL domain after login
|
|
123
|
+
|
|
124
|
+
### If UAT refresh fails with "invalid_grant" (error 28003/20003/20005)
|
|
125
|
+
- Refresh token expired — re-run `node src/oauth.js` (needs LARK_APP_ID + LARK_APP_SECRET in `.env`)
|
|
126
|
+
- Copy new UAT + refresh token from `.env` to MCP config, then restart Claude Code
|
|
127
|
+
|
|
89
128
|
### If list_user_chats doesn't return P2P chats
|
|
90
|
-
-
|
|
91
|
-
- Use the P2P flow: `search_contacts` → `create_p2p_chat` → `read_p2p_messages`.
|
|
129
|
+
- Expected — API only returns groups. Use: `search_contacts` → `create_p2p_chat` → `read_p2p_messages`.
|
|
92
130
|
|
|
93
131
|
### If reply_message fails with error 230054
|
|
94
|
-
-
|
|
132
|
+
- Only text messages can be replied to via this API.
|
package/src/index.js
CHANGED
|
@@ -255,7 +255,7 @@ const TOOLS = [
|
|
|
255
255
|
inputSchema: {
|
|
256
256
|
type: 'object',
|
|
257
257
|
properties: {
|
|
258
|
-
chat_id: { type: 'string', description: 'Chat ID (oc_xxx
|
|
258
|
+
chat_id: { type: 'string', description: 'Chat ID (numeric from create_p2p_chat, or oc_xxx from list_user_chats). Both formats work.' },
|
|
259
259
|
page_size: { type: 'number', description: 'Messages to fetch (default 20, max 50)' },
|
|
260
260
|
start_time: { type: 'string', description: 'Start timestamp in seconds (optional)' },
|
|
261
261
|
end_time: { type: 'string', description: 'End timestamp in seconds (optional)' },
|
|
@@ -490,7 +490,7 @@ const TOOLS = [
|
|
|
490
490
|
// --- Server ---
|
|
491
491
|
|
|
492
492
|
const server = new Server(
|
|
493
|
-
{ name: 'feishu-user-plugin', version: '1.0.
|
|
493
|
+
{ name: 'feishu-user-plugin', version: '1.0.2' },
|
|
494
494
|
{ capabilities: { tools: {} } }
|
|
495
495
|
);
|
|
496
496
|
|
|
@@ -691,7 +691,16 @@ async function handleTool(name, args) {
|
|
|
691
691
|
async function main() {
|
|
692
692
|
const transport = new StdioServerTransport();
|
|
693
693
|
await server.connect(transport);
|
|
694
|
-
|
|
694
|
+
|
|
695
|
+
// Startup diagnostics
|
|
696
|
+
const hasCookie = !!process.env.LARK_COOKIE;
|
|
697
|
+
const hasApp = !!(process.env.LARK_APP_ID && process.env.LARK_APP_SECRET);
|
|
698
|
+
const hasUAT = !!process.env.LARK_USER_ACCESS_TOKEN;
|
|
699
|
+
console.error(`[feishu-user-plugin] MCP Server v1.0.2 — ${TOOLS.length} tools`);
|
|
700
|
+
console.error(`[feishu-user-plugin] Auth: Cookie=${hasCookie ? 'YES' : 'NO'} App=${hasApp ? 'YES' : 'NO'} UAT=${hasUAT ? 'YES' : 'NO'}`);
|
|
701
|
+
if (!hasCookie) console.error('[feishu-user-plugin] WARNING: LARK_COOKIE not set — user identity tools (send_to_user, etc.) will fail');
|
|
702
|
+
if (!hasApp) console.error('[feishu-user-plugin] WARNING: LARK_APP_ID/SECRET not set — official API tools (read_messages, docs, etc.) will fail');
|
|
703
|
+
if (!hasUAT) console.error('[feishu-user-plugin] WARNING: LARK_USER_ACCESS_TOKEN not set — P2P chat reading (read_p2p_messages) will fail');
|
|
695
704
|
}
|
|
696
705
|
|
|
697
706
|
main().catch(console.error);
|
|
@@ -274,7 +274,7 @@ async function testUAT() {
|
|
|
274
274
|
}
|
|
275
275
|
|
|
276
276
|
async function main() {
|
|
277
|
-
console.log('=== feishu-user-plugin v1.0.
|
|
277
|
+
console.log('=== feishu-user-plugin v1.0.2 — Comprehensive Test ===\n');
|
|
278
278
|
|
|
279
279
|
await testUserIdentity();
|
|
280
280
|
console.log('');
|