Skip to main content
Glama
README.md
# 飞书 MCP 服务器

[![TypeScript](https://img.shields.io/badge/TypeScript-5.8-blue.svg)](https://www.typescriptlang.org/)
[![Node.js](https://img.shields.io/badge/Node.js->=23-green.svg)](https://nodejs.org/)
[![License](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![MCP](https://img.shields.io/badge/MCP-Compatible-purple.svg)](https://modelcontextprotocol.ai/)

飞书 MCP 服务器是一个基于 [Model Context Protocol](https://modelcontextprotocol.ai/) 的服务,提供飞书 API 集成,使 AI 模型能够轻松与飞书服务交互。

## 目录

- [功能特点](#功能特点)
- [支持的工具](#支持的工具)
- [项目架构](#项目架构)
- [快速开始](#快速开始)
- [配置说明](#配置说明)
- [API 文档](#api-文档)
- [开发指南](#开发指南)
- [常见问题](#常见问题)
- [许可证](#许可证)
- [贡献指南](#贡献指南)

## 功能特点

- **文档服务**:读取、创建飞书文档,支持内容块操作和权限管理
- **机器人服务**:发送文本消息和交互卡片到飞书聊天
- **聊天服务**:搜索和管理群组会话
- **多维表格服务**:完整的 Bitable CRUD 操作,支持批量创建记录
- **多模式支持**:
  - **STDIO 模式**:通过标准输入/输出通信,适用于 CLI 环境和集成到其他应用
  - **HTTP 模式**:提供 REST API 和 SSE 连接,适用于 Web 服务和分布式部署
- **完善的错误处理**:统一的错误处理机制,提供详细的错误信息
- **类型安全**:基于 TypeScript,提供完整的类型定义
- **模块化架构**:易于扩展新功能和集成其他飞书 API

## 支持的工具

### 文档操作 (6 个工具)
| 工具名称 | 描述 |
|---------|------|
| `get_feishu_document_raw` | 获取文档原始内容 |
| `get_feishu_document` | 获取文档元数据 |
| `create_feishu_document` | 创建新文档 |
| `create_feishu_document_block` | 在文档中创建内容块 |
| `set_feishu_document_permission` | 设置文档分享权限 |
| `create_feishu_document_password` | 创建文档分享密码 |

### 机器人操作 (2 个工具)
| 工具名称 | 描述 |
|---------|------|
| `send_feishu_text_message` | 发送文本消息 |
| `send_feishu_card` | 发送交互卡片 |

### 聊天操作 (2 个工具)
| 工具名称 | 描述 |
|---------|------|
| `search_feishu_chats` | 搜索群组 |
| `get_feishu_chats` | 获取群组列表 |

### 多维表格操作 (10 个工具)
| 工具名称 | 描述 |
|---------|------|
| `get_feishu_sheet_meta` | 获取多维表格元数据 |
| `get_feishu_sheet_tables` | 获取数据表列表 |
| `get_feishu_sheet_views` | 获取视图列表 |
| `get_feishu_sheet_view` | 获取视图详情 |
| `get_feishu_sheet_records` | 获取记录列表 |
| `get_feishu_sheet_record` | 获取单条记录 |
| `create_feishu_sheet_record` | 创建记录 |
| `update_feishu_sheet_record` | 更新记录 |
| `delete_feishu_sheet_record` | 删除记录 |
| `batch_create_feishu_sheet_records` | 批量创建记录 |

## 项目架构

### 代码结构

```
/src
  /client        # API客户端实现(底层API请求封装)
    /documents   # 文档相关API客户端
    /bots        # 机器人API客户端
    /chats       # 聊天相关API客户端
  /services      # 服务层实现(业务逻辑和错误处理)
    /documents   # 文档相关服务
    /bots        # 机器人相关服务
    /chats       # 聊天相关服务
  /server        # MCP服务器实现
    /tools       # MCP工具注册和实现
  /typings       # 类型定义
  /utils         # 通用工具函数
  /http          # HTTP服务器实现
  /logger        # 日志服务
  /consts        # 常量定义
  config.ts      # 配置管理
  index.ts       # 入口点
```

### 设计原则

项目采用分层架构设计,确保关注点分离和职责明确:

#### 1. 分层职责

- **客户端层(Client)**
  - 封装HTTP请求的细节
  - 处理底层API参数和响应格式
  - 管理认证和令牌刷新
  - 不包含业务逻辑

- **服务层(Service)**
  - 使用客户端执行API操作
  - 实现业务逻辑
  - 处理和转换错误
  - 提供友好的接口给上层使用

- **工具层(Tools)**
  - 实现MCP协议定义的工具
  - 处理参数验证和格式转换
  - 调用服务层完成实际操作
  - 格式化返回结果

#### 2. 依赖方向

- 服务层依赖客户端层
- 工具层依赖服务层
- 严格避免循环依赖

#### 3. 错误处理策略

- 使用 `FeiShuApiError` 统一处理API错误
- 客户端层返回原始错误
- 服务层捕获并转换为业务相关错误
- 工具层处理所有异常并返回用户友好消息

### 工作流程

1. MCP服务器接收请求(STDIO或HTTP)
2. 工具层验证参数并调用相应服务
3. 服务层实现业务逻辑并调用客户端
4. 客户端执行实际API请求并返回结果
5. 结果经由服务层处理后返回给工具层
6. 工具层格式化结果并返回给MCP服务器

## 快速开始

### 前提条件

- Node.js 23.0或更高版本
- pnpm包管理器
- 有效的飞书开发者账号和已创建的自建应用

### 安装步骤

1. 克隆仓库

```bash
git clone https://github.com/opsworld30/feishu-mcp-server.git
cd feishu-mcp-server
```

2. 安装依赖

```bash
pnpm install
```

3. 创建`.env`文件

```
# 飞书应用凭证(必填)
FEISHU_APP_ID=your_app_id
FEISHU_APP_SECRET=your_app_secret

# 服务器配置(可选)
PORT=3344
LOG_LEVEL=info
```

### 运行服务

#### 开发模式

```bash
# 开发模式(自动重启)
pnpm dev

# 或使用普通启动
pnpm start
```

#### 生产模式

```bash
# 构建项目
pnpm build

# 运行编译后的代码
node dist/index.js
```

#### STDIO模式

```bash
# 方法1:使用环境变量
NODE_ENV=cli node dist/index.js

# 方法2:使用命令行参数
node dist/index.js --stdio
```

## 配置说明

| 选项 | 环境变量 | 命令行参数 | 默认值 | 描述 |
|------|----------|------------|--------|------|
| 飞书应用ID | `FEISHU_APP_ID` | `--feishu-app-id` | - | 飞书自建应用的App ID |
| 飞书应用密钥 | `FEISHU_APP_SECRET` | `--feishu-app-secret` | - | 飞书自建应用的App Secret |
| 服务器端口 | `PORT` | `--port` | 3344 | HTTP服务器端口号 |
| 日志级别 | `LOG_LEVEL` | `--log-level` | info | 日志级别(debug/info/warn/error) |
| 令牌缓存时间 | `TOKEN_CACHE_DURATION` | - | 7100 | 访问令牌缓存时间(秒) |

## API文档

### 文档操作

#### `get_feishu_document_raw`
获取飞书文档的原始内容。
- **参数**:`docId` - 文档ID (例如:feishu.cn/docx/\<documentId\>)
- **返回**:文档的文本内容

#### `get_feishu_document`
获取飞书文档的元数据信息。
- **参数**:`docId` - 文档ID
- **返回**:文档的元数据(JSON格式)

#### `create_feishu_document`
创建新的飞书文档。
- **参数**:
  - `title` - 文档标题(可选)
  - `folderToken` - 目标文件夹Token(可选,不指定则创建在根目录)
- **返回**:新文档的ID和URL

#### `create_feishu_document_block`
在文档中创建内容块。
- **参数**:
  - `documentId` - 文档ID
  - `blockId` - 父块ID(可选,默认为文档根节点)
  - `blocks` - 块数组,支持类型:text, heading1-6, bullet, ordered, code, quote, todo, divider
  - `index` - 插入位置(可选,-1表示末尾)
- **返回**:创建的块信息

#### `set_feishu_document_permission`
设置文档的公开分享权限。
- **参数**:
  - `documentId` - 文档ID
  - `linkShareEntity` - 权限类型:tenant_readable, tenant_editable, anyone_readable, anyone_editable, closed
- **返回**:设置结果

#### `create_feishu_document_password`
为文档创建分享密码。
- **参数**:`documentId` - 文档ID
- **返回**:分享密码

### 机器人操作

#### `send_feishu_text_message`
发送文本消息到飞书聊天。
- **参数**:
  - `chatId` - 聊天ID
  - `text` - 要发送的文本内容
- **返回**:消息ID

#### `send_feishu_card`
发送交互卡片到飞书聊天。
- **参数**:
  - `chatId` - 聊天ID
  - `cardContent` - 卡片内容(JSON字符串)
- **返回**:消息ID

### 聊天操作

#### `search_feishu_chats`
搜索用户或机器人可见的群组。
- **参数**:
  - `query` - 搜索关键词(可选)
  - `page_token` - 分页标记(可选)
  - `page_size` - 每页数量,默认10,最大100(可选)
  - `user_id_type` - 用户ID类型:open_id, union_id, user_id(可选)
- **返回**:群组列表

#### `get_feishu_chats`
获取用户或机器人所在的群组列表。
- **参数**:
  - `page_token` - 分页标记(可选)
  - `page_size` - 每页数量,默认10,最大100(可选)
  - `user_id_type` - 用户ID类型(可选)
- **返回**:群组列表

### 多维表格操作

#### `get_feishu_sheet_meta`
获取多维表格的元数据信息。
- **参数**:`appToken` - 多维表格ID (例如:feishu.cn/base/\<appToken\>)
- **返回**:表格元数据(JSON格式)

#### `get_feishu_sheet_tables`
获取多维表格中的数据表列表。
- **参数**:
  - `appToken` - 多维表格ID
  - `pageSize` - 每页数量,默认20,最大100(可选)
  - `pageToken` - 分页标记(可选)
- **返回**:数据表列表

#### `get_feishu_sheet_views`
获取数据表的视图列表。
- **参数**:
  - `appToken` - 多维表格ID
  - `tableId` - 数据表ID
  - `pageSize` - 每页数量(可选)
  - `pageToken` - 分页标记(可选)
- **返回**:视图列表

#### `get_feishu_sheet_view`
获取特定视图的详细信息。
- **参数**:
  - `appToken` - 多维表格ID
  - `tableId` - 数据表ID
  - `viewId` - 视图ID
- **返回**:视图详情

#### `get_feishu_sheet_records`
获取数据表记录列表。
- **参数**:
  - `appToken` - 多维表格ID
  - `tableId` - 数据表ID
  - `viewId` - 视图ID(可选)
  - `fieldIds` - 字段ID列表(可选)
  - `filter` - FQL格式过滤条件(可选)
  - `sort` - JSON格式排序条件(可选)
  - `pageSize` - 每页数量(可选)
  - `pageToken` - 分页标记(可选)
- **返回**:记录列表

#### `get_feishu_sheet_record`
获取单条记录。
- **参数**:
  - `appToken` - 多维表格ID
  - `tableId` - 数据表ID
  - `recordId` - 记录ID
  - `fieldIds` - 字段ID列表(可选)
- **返回**:单条记录

#### `create_feishu_sheet_record`
创建新记录。
- **参数**:
  - `appToken` - 多维表格ID
  - `tableId` - 数据表ID
  - `fields` - 字段键值对
- **返回**:新记录信息

#### `update_feishu_sheet_record`
更新现有记录。
- **参数**:
  - `appToken` - 多维表格ID
  - `tableId` - 数据表ID
  - `recordId` - 记录ID
  - `fields` - 要更新的字段键值对
- **返回**:更新后的记录

#### `delete_feishu_sheet_record`
删除记录。
- **参数**:
  - `appToken` - 多维表格ID
  - `tableId` - 数据表ID
  - `recordId` - 记录ID
- **返回**:删除结果

#### `batch_create_feishu_sheet_records`
批量创建记录。
- **参数**:
  - `appToken` - 多维表格ID
  - `tableId` - 数据表ID
  - `records` - 记录数组,每条记录包含 `fields` 对象
- **返回**:创建的记录列表

## 开发指南

### 代码规范

项目使用严格的TypeScript规范和ESLint配置:

- 使用TypeScript接口和类型定义
- 避免使用 `any` 类型
- 使用 `Record<string, unknown>` 替代 `object` 类型
- 所有代码文件、注释和错误消息使用英文

运行代码检查:

```bash
# 运行代码检查
pnpm lint

# 运行代码检查并修复
pnpm lint:fix

# 运行代码格式化
pnpm format
```

### 错误处理

所有与飞书API相关的错误应使用 `FeiShuApiError` 类处理:

```typescript
try {
  // API操作
} catch (error) {
  if (error instanceof FeiShuApiError) {
    // 处理特定的API错误
    logger.error(`FeiShu API Error (${error.code}): ${error.message}`);
  } else {
    // 处理通用错误
    logger.error('Unexpected error:', error);
  }
  // 转换为用户友好消息
  throw new FeiShuApiError('操作失败', { cause: error });
}
```

### 提交规范

提交消息必须遵循以下格式:
```
<type>(<scope>): <subject>
```

例如:
- `feat(bot): 添加发送卡片功能`
- `fix(documents): 修复文档内容获取错误`

支持的类型:
- `feat`: 新功能
- `fix`: 修复Bug
- `docs`: 文档变更
- `style`: 代码格式调整
- `refactor`: 代码重构
- `perf`: 性能优化
- `test`: 测试相关
- `chore`: 构建过程或辅助工具的变动

### 扩展指南

添加新功能的步骤:

1. **创建客户端类**
   - 在 `src/client/<feature>/` 目录下创建
   - 继承 `ApiClient` 基类
   - 实现API请求方法

   ```typescript
   // src/client/feature/feature-client.ts
   export class FeatureClient extends ApiClient {
     async getFeatureData(id: string): Promise<FeatureData> {
       return this.request<FeatureResponse>('/feature/get', { id });
     }
   }
   ```

2. **创建服务类**
   - 在 `src/services/<feature>/` 目录下创建
   - 使用相应的客户端类
   - 实现业务逻辑和错误处理

   ```typescript
   // src/services/feature/feature-service.ts
   export class FeatureService {
     private client: FeatureClient;
     
     constructor(config: ApiClientConfig) {
       this.client = new FeatureClient(config);
     }
     
     async getFeature(id: string): Promise<Feature> {
       try {
         const data = await this.client.getFeatureData(id);
         return this.transformData(data);
       } catch (error) {
         handleError(error);
       }
     }
   }
   ```

3. **注册服务**
   - 在 `src/services/index.ts` 中导出新服务
   - 将服务添加到 `FeiShuServices` 类

4. **创建MCP工具**
   - 在 `src/server/tools/feature-tools.ts` 中创建
   - 使用Zod进行参数验证
   - 调用服务层方法

   ```typescript
   // src/server/tools/feature-tools.ts
   export function registerFeatureTools(params: ToolRegistryParams): void {
     const { server, services, logger } = params;
     
     server.tool(
       'get_feishu_feature',
       'Get feature from FeiShu',
       {
         id: z.string().describe('Feature ID'),
       },
       async ({ id }) => {
         try {
           const feature = await services.feature.getFeature(id);
           return { content: [{ type: 'text', text: JSON.stringify(feature) }] };
         } catch (error) {
           return handleToolError(error, logger);
         }
       }
     );
   }
   ```

5. **注册工具**
   - 在 `src/server/tools/index.ts` 中引入并注册新工具

## 常见问题

### 认证失败

**问题**:API请求返回认证错误

**解决方案**:
- 检查应用ID和密钥是否正确
- 确认应用具有所需的权限范围
- 检查服务器时间是否正确同步

### 令牌刷新问题

**问题**:令牌刷新失败

**解决方案**:
- 设置更短的令牌缓存时间
- 检查网络连接稳定性
- 查看飞书开发者平台的应用状态

## 许可证

MIT

## 贡献指南

欢迎贡献!请遵循以下步骤:

1. Fork仓库
2. 创建功能分支(`git checkout -b feature/amazing-feature`)
3. 提交更改(`git commit -m 'feat: add some amazing feature'`)
4. 推送到分支(`git push origin feature/amazing-feature`)
5. 开启Pull Request

提交PR前请确保:
- 代码通过所有测试
- 更新了相关文档
- 遵循项目的代码风格和命名约定
- 添加必要的单元测试