开发者指南 - cso1z/Feishu-MCP GitHub Wiki
- Node.js: >= 20.17.0
- 包管理器: pnpm (推荐) 或 npm
- TypeScript: ^5.7.3
- 克隆项目
git clone https://github.com/cso1z/Feishu-MCP.git
cd Feishu-MCP- 安装依赖
pnpm install
# 或
npm install- 配置环境变量
# 复制示例文件
cp .env.example .env
# 编辑 .env 文件
FEISHU_APP_ID=your_app_id
FEISHU_APP_SECRET=your_app_secret
FEISHU_AUTH_TYPE=tenant # 或 user
PORT=3333- 构建项目
pnpm run build- 启动开发服务器
pnpm run dev- VS Code 或 Cursor
- TypeScript 扩展
- ESLint 扩展
- Prettier 扩展
Feishu-MCP/
├── src/ # 源代码目录
│ ├── index.ts # 应用入口(HTTP/SSE 模式)
│ ├── cli.ts # CLI 入口
│ ├── server.ts # HTTP 服务器实现
│ ├── mcp/ # MCP 协议实现
│ │ ├── feishuMcp.ts # MCP 服务器核心
│ │ └── tools/ # 工具函数
│ ├── services/ # 服务层
│ │ ├── baseService.ts # 基础 API 服务
│ │ ├── feishuApiService.ts # 飞书 API 服务
│ │ ├── blockFactory.ts # 文档块工厂
│ │ ├── feishuAuthService.ts # 认证服务
│ │ └── callbackService.ts # OAuth 回调处理
│ ├── utils/ # 工具层
│ │ ├── config.ts # 配置管理
│ │ ├── logger.ts # 日志系统
│ │ ├── cache.ts # 缓存管理
│ │ ├── auth/ # 认证工具
│ │ └── ...
│ └── types/ # 类型定义
├── dist/ # 编译输出
├── doc/ # 文档
├── .env.example # 环境变量示例
└── package.json # 项目配置
- 在对应的工具文件中添加工具函数
// 文件位置: src/mcp/tools/feishuTools.ts
import { z } from 'zod';
export function registerFeishuTools(server: McpServer, feishuService: FeishuApiService) {
server.tool(
'new_feishu_tool',
'工具描述,说明工具的功能和使用场景',
{
param1: z.string().describe('参数1的说明'),
param2: z.number().optional().describe('参数2的说明(可选)'),
},
async ({ param1, param2 }) => {
try {
// 调用 feishuService 的方法
const result = await feishuService.someMethod(param1, param2);
return {
content: [
{
type: 'text',
text: JSON.stringify(result, null, 2)
}
]
};
} catch (error) {
Logger.error('工具执行失败:', error);
const errorMessage = formatErrorMessage(error);
return {
content: [
{
type: 'text',
text: `工具执行失败: ${errorMessage}`
}
]
};
}
}
);
}- 在 FeishuApiService 中添加对应的 API 方法(如需要)
// 文件位置: src/services/feishuApiService.ts
public async someMethod(param1: string, param2?: number): Promise<any> {
try {
const endpoint = '/some/endpoint';
const params = { param1, param2 };
const response = await this.get(endpoint, params);
return response;
} catch (error) {
this.handleApiError(error, '操作失败');
}
}-
更新文档
- 在
README.md的工具功能表中添加新工具 - 在
doc/api-reference.md中添加详细的 API 文档
- 在
- 在 BlockFactory 中添加创建方法
// 文件位置: src/services/blockFactory.ts
export enum BlockType {
// ... 现有类型
NEW_TYPE = 'new_type'
}
export class BlockFactory {
createNewTypeBlock(options: NewTypeOptions): any {
return {
block_type: BlockTypeMap[BlockType.NEW_TYPE],
// ... 块内容结构
};
}
}- 在 FeishuApiService 中添加创建方法
// 文件位置: src/services/feishuApiService.ts
public async createNewTypeBlock(
documentId: string,
parentBlockId: string,
options: NewTypeOptions,
index: number = 0
): Promise<any> {
const blockContent = this.blockFactory.createNewTypeBlock(options);
return this.createDocumentBlock(documentId, parentBlockId, blockContent, index);
}- 添加对应的工具函数
- 使用 严格模式 (
strict: true) - 优先使用 interface 而非 type(除非需要联合类型)
- 函数参数和返回值必须有类型注解
- 避免使用
any,优先使用unknown
// ✅ 好的做法
interface UserInfo {
id: string;
name: string;
}
function getUserInfo(id: string): Promise<UserInfo> {
// ...
}
// ❌ 不好的做法
function getUserInfo(id: any): any {
// ...
}-
类名: PascalCase,如
FeishuApiService -
函数名: camelCase,如
getUserToken -
常量: UPPER_SNAKE_CASE,如
MAX_RETRY_COUNT -
文件名: camelCase,如
feishuApiService.ts
- 类和方法: 使用 JSDoc 注释
- 复杂逻辑: 添加行内注释说明
/**
* 获取用户访问令牌
* @param clientKey 客户端缓存键
* @param appId 应用ID(可选,如果tokenInfo中没有则使用此参数)
* @returns 用户访问令牌
* @throws 如果无法获取有效的token则抛出AuthRequiredError
*/
public async getUserAccessToken(
clientKey: string,
appId?: string,
appSecret?: string
): Promise<string> {
// ...
}- 使用
try-catch捕获异步错误 - 使用
formatErrorMessage统一格式化错误信息 - 记录详细的错误日志
try {
const result = await someAsyncOperation();
return result;
} catch (error) {
Logger.error('操作失败:', error);
const errorMessage = formatErrorMessage(error);
throw new Error(`操作失败: ${errorMessage}`);
}- 启动开发服务器
pnpm run dev-
使用 VS Code 调试
- 创建
.vscode/launch.json - 配置调试参数
- 创建
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Debug Server",
"runtimeExecutable": "pnpm",
"runtimeArgs": ["run", "dev"],
"console": "integratedTerminal"
}
]
}-
查看日志
- 开发模式下,日志会输出到控制台
- HTTP 模式下,可以通过浏览器访问日志端点(如实现)
使用 MCP Inspector 调试 MCP 协议通信:
pnpm run inspect在工具函数中添加日志:
server.tool('some_tool', '...', {...}, async (params) => {
Logger.debug('工具调用参数:', params);
try {
const result = await feishuService.someMethod(params);
Logger.debug('工具执行结果:', result);
return { content: [{ type: 'text', text: JSON.stringify(result) }] };
} catch (error) {
Logger.error('工具执行失败:', error);
throw error;
}
});# 运行所有测试
pnpm test
# 运行特定测试文件
pnpm test src/services/feishuApiService.test.ts
# 监视模式
pnpm test --watch// 文件位置: src/services/feishuApiService.test.ts
import { describe, it, expect, beforeEach } from '@jest/globals';
import { FeishuApiService } from './feishuApiService';
describe('FeishuApiService', () => {
let service: FeishuApiService;
beforeEach(() => {
service = FeishuApiService.getInstance();
});
it('should create document', async () => {
const result = await service.createDocument('Test', 'folder_token');
expect(result).toBeDefined();
expect(result.objToken).toBeDefined();
});
});使用 Conventional Commits 规范:
<type>(<scope>): <subject>
<body>
<footer>
类型 (type):
-
feat: 新功能 -
fix: 修复 bug -
docs: 文档更新 -
style: 代码格式(不影响功能) -
refactor: 重构 -
test: 测试相关 -
chore: 构建/工具相关
示例:
feat(tools): 添加批量创建文档块工具
- 支持一次性创建多个文档块
- 优化批量操作的性能
- 添加错误处理机制
Closes #123
- 创建功能分支
git checkout -b feat/new-feature- 提交更改
git add .
git commit -m "feat: 添加新功能"- 推送并创建 Pull Request
git push origin feat/new-feature- 代码符合规范
- 添加了必要的注释
- 更新了相关文档
- 通过了测试
- 没有引入新的警告或错误
相关文档: