mcphero-lark
v2.3.0
Published
MCP Hero Lark Integration
Downloads
915
Readme
mcphero-lark
Lark/Feishu document parser and API client exposed as both an MCP server and a CLI. Built with mcphero and the official @larksuiteoapi/node-sdk.
Features
- Export Lark documents to Markdown
- Import Markdown into existing Lark documents
- Manage Wiki spaces, nodes, and search
- Send messages to users and group chats
- List organization contacts
- OAuth authentication flow for user-scoped API access
- Pluggable block parser system for Lark document types
Installation
pnpm add mcphero-larkOr install globally to use the CLI:
pnpm add -g mcphero-larkSetup
1. Create a Lark App
- Go to the Lark Open Platform and create a new app
- Note your App ID and App Secret
- Configure a Redirect URI for OAuth (default:
http://localhost:3000/callback)
2. Required Scopes
When configuring your Lark app, enable the following OAuth scopes:
| Category | Scopes |
|----------|--------|
| Contact | contact:contact, contact:contact.base:readonly, contact:department.base:readonly, contact:user.base:readonly, contact:user.email:readonly, contact:user.phone:readonly |
| Documents | docs:doc, docs:document.content:read, docs:document:export, docx:document, docx:document:create, docx:document:readonly, docx:document.block:convert |
| Drive | drive:drive, drive:export:readonly |
| Wiki | wiki:wiki, wiki:node:read, wiki:node:retrieve, wiki:space:retrieve |
| Messaging | im:chat, im:chat:read, im:chat:readonly, im:message |
| Other | offline_access, admin:app.info:readonly, bitable:app, sheets:spreadsheet |
Usage
As an MCP Server
Add to your MCP client configuration (e.g. .mcp.json for Claude Code):
{
"mcpServers": {
"larkMcp": {
"command": "pnpm",
"args": ["tsx", "src/mcp.ts"]
}
}
}Or with the published package:
{
"mcpServers": {
"larkMcp": {
"command": "mcphero-lark"
}
}
}As a CLI
# Run directly from source
pnpm tsx src/cli.ts
# Or use the installed binary
mcphero-larkAs a Library
import { TokenClient, DocxParser } from 'mcphero-lark'
// Export a document to Markdown
const client = new TokenClient('default')
const parser = new DocxParser(client, { includeTitle: true })
const markdown = await parser.process('document_id')Authentication
mcphero-lark supports two authentication modes:
App-level (Tenant Token)
Used automatically by TokenClient for bot-level API calls (e.g. sending messages). Tokens are refreshed automatically before expiry.
User-level (OAuth)
Required for user-scoped operations (documents, wiki, contacts). Follow this flow:
- Generate auth URL -- call
AuthenAuthorizeto get the OAuth URL - User authorizes -- redirect the user to the URL; Lark redirects back with a
code - Exchange code for tokens -- call
AuthenOauthTokenwith the code - Tokens are stored -- access and refresh tokens are persisted in
lark.json
Subsequent API calls use the stored tokens automatically via TokenClient.
Tools Reference
All tools accept an optional userId parameter (default: 'default') to select which stored OAuth token to use for the request.
Authentication
AuthenAuthorize
Generate an OAuth authorization URL for user login.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| userId | string | No | Token store key (default: 'default') |
Returns: { authUrl: string }
AuthenOauthToken
Exchange an OAuth authorization code for access and refresh tokens.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| code | string | Yes | Authorization code from OAuth callback |
| userId | string | No | Token store key (default: 'default') |
Returns: { accessToken: { token, expiresAt }, refreshToken: { token, expiresAt } }
AuthenUserInfo
Get information about the currently authenticated user.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| userId | string | No | Token store key (default: 'default') |
Returns: User info object (name, email, avatar, etc.)
Contacts
ContactUserList
List users in the organization by department.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| departmentId | string | No | Department ID ('0' for root/all users) |
| pageSize | number | No | Results per page (max 50) |
| pageToken | string | No | Pagination token |
| userId | string | No | Token store key |
Returns: { items: [{ openId, userId, name, enName, email, mobile }], hasMore, pageToken }
Documents
DocxDocumentExport
Export a Lark document to Markdown.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| documentId | string | Yes | Lark document ID |
| includeTitle | boolean | No | Include document title as H1 (default: true) |
| path | string | No | Write to file path instead of returning content |
| userId | string | No | Token store key |
Returns: Node metadata + markdown content (or file path if path is provided)
DocxDocumentImport
Import Markdown content into an existing Lark document. Replaces all existing content.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| documentId | string | Yes | Target document ID |
| path | string | Yes | Local path to Markdown file |
| userIdType | 'user_id' | 'union_id' | 'open_id' | No | User ID type |
| userId | string | No | Token store key |
Returns: { documentId, spaceId, title, blocksDeleted, blocksCreated }
DocxDocumentBlockList
List all blocks in a Lark document.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| documentId | string | Yes | Document ID |
| userIdType | 'user_id' | 'union_id' | 'open_id' | No | User ID type |
| documentRevisionId | number | No | Specific document revision |
| pageSize | number | No | Results per page |
| pageToken | string | No | Pagination token |
| userId | string | No | Token store key |
Returns: Block list with pagination
Wiki
WikiSpaceList
List all wiki spaces accessible to the user.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| pageSize | number | No | Results per page |
| pageToken | string | No | Pagination token |
| userId | string | No | Token store key |
Returns: List of wiki spaces with pagination
WikiSpaceNodeList
List nodes in a wiki space.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| spaceId | string | Yes | Wiki space ID |
| parentNodeToken | string | No | Filter to children of this node |
| pageSize | number | No | Results per page |
| pageToken | string | No | Pagination token |
| userId | string | No | Token store key |
Returns: List of wiki nodes with pagination
WikiSpaceGetNode
Get details of a specific wiki node.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| token | string | Yes | Wiki node token |
| objType | 'doc' | 'docx' | 'sheet' | 'mindnote' | 'bitable' | 'file' | 'slides' | 'wiki' | No | Object type filter |
| userId | string | No | Token store key |
Returns: Full node details
WikiSpaceNodeCreate
Create a new document node in a wiki space.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| spaceId | string | Yes | Wiki space ID |
| parentNodeToken | string | No | Parent node (omit for top-level) |
| title | string | No | Document title |
| userId | string | No | Token store key |
Returns: { spaceId, nodeToken, objToken, title, parentNodeToken }
WikiSpaceNodeMove
Move a wiki node (and its children) to a different parent or space.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| spaceId | string | Yes | Source wiki space ID |
| nodeToken | string | Yes | Node to move |
| targetParentToken | string | No | Target parent node |
| targetSpaceId | string | No | Target space for cross-space moves |
| userId | string | No | Token store key |
Returns: { spaceId, nodeToken, objToken, objType, parentNodeToken, title, hasChild }
WikiSearch
Full-text search across wiki spaces.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| query | string | Yes | Search query |
| spaceId | string | No | Filter to a specific space |
| nodeId | string | No | Filter to descendants of a node (requires spaceId) |
| pageSize | number | No | Results per page (max 50, default 20) |
| pageToken | string | No | Pagination token |
| userId | string | No | Token store key |
Returns: { items: [{ nodeId, spaceId, objType, title, url, objToken }], hasMore, pageToken }
Messaging
ImChatList
List chats that the user or bot is in (excludes P2P chats).
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| sortType | 'ByCreateTimeAsc' | 'ByActiveTimeDesc' | No | Sort order |
| pageSize | number | No | Results per page |
| pageToken | string | No | Pagination token |
| userId | string | No | Token store key |
Returns: { items: [{ chatId, name, description, ownerId, external, labels }], hasMore, pageToken }
ImChatSearch
Search for chats by keyword.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| query | string | Yes | Search keyword |
| pageSize | number | No | Results per page |
| pageToken | string | No | Pagination token |
| userId | string | No | Token store key |
Returns: { items: [{ chatId, name, description, ownerId, external, labels }], hasMore, pageToken }
ImMessageSend
Send a message to a user or group chat. Messages are sent as the bot (uses app credentials, not user tokens).
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| receiveId | string | Yes | Recipient ID (user or chat) |
| receiveIdType | 'open_id' | 'user_id' | 'union_id' | 'email' | 'chat_id' | Yes | Type of receiveId |
| msgType | 'text' | 'post' | 'interactive' | Yes | Message type |
| content | string | Yes | Message content (JSON string) |
| uuid | string | No | Idempotency key |
Returns: { messageId, chatId, createTime, msgType, senderId, senderType }
Example -- send a text message:
{
"receiveId": "oc_xxx",
"receiveIdType": "chat_id",
"msgType": "text",
"content": "{\"text\": \"Hello from mcphero-lark!\"}"
}Server Management
McpHealth
Check MCP server health and uptime.
Returns: { status: 'ok', uptime, pid }
McpRestart
Restart the MCP server to pick up code changes.
Returns: { status: 'restarting' }
Architecture
src/
index.ts # Library exports
mcp.ts # MCP server (stdio transport)
cli.ts # CLI (interactive transport)
actions/ # Tool definitions (createAction + zod schemas)
Authen/ # OAuth flow
Contact/ # Organization users
Docx/ # Document export/import
Im/ # Chat and messaging
Mcp/ # Server management
Wiki/ # Wiki spaces and nodes
classes/
TokenClient.ts # User and tenant agnostic token persistence client (lark.json)
DocxParser.ts # Lark blocks -> Markdown converter
parser/ # Block type parsers (text, heading, list, table, etc.)
types/ # TypeScript type definitions
lib/ # Shared utilities (API helpers, env, scopes)Development
# Install dependencies
pnpm install
# Run MCP server in dev mode
pnpm tsx src/mcp.ts
# Run CLI in dev mode
pnpm tsx src/cli.ts
# Build
pnpm build
# Lint
pnpm lint
# Clean build artifacts
pnpm cleanPublishing
This is a private scoped package. Publish with restricted access:
pnpm publish --no-git-checks --access restrictedLicense
MIT
