npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

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-lark

Or install globally to use the CLI:

pnpm add -g mcphero-lark

Setup

1. Create a Lark App

  1. Go to the Lark Open Platform and create a new app
  2. Note your App ID and App Secret
  3. 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-lark

As 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:

  1. Generate auth URL -- call AuthenAuthorize to get the OAuth URL
  2. User authorizes -- redirect the user to the URL; Lark redirects back with a code
  3. Exchange code for tokens -- call AuthenOauthToken with the code
  4. 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 clean

Publishing

This is a private scoped package. Publish with restricted access:

pnpm publish --no-git-checks --access restricted

License

MIT