核心模块详解 - cso1z/Feishu-MCP GitHub Wiki

核心模块详解

目录

模块概览

项目采用分层架构,主要模块如下:

src/
├── index.ts              # 应用入口
├── server.ts             # HTTP 服务器
├── cli.ts                # CLI 入口
├── mcp/                  # MCP 协议实现
│   ├── feishuMcp.ts      # MCP 服务器核心
│   └── tools/            # 工具函数注册
├── services/             # 服务层
│   ├── baseService.ts    # 基础 API 服务
│   ├── feishuApiService.ts # 飞书 API 服务
│   ├── blockFactory.ts   # 文档块工厂
│   └── feishuAuthService.ts # 认证服务
└── utils/                # 工具层
    ├── config.ts         # 配置管理
    ├── logger.ts         # 日志系统
    ├── cache.ts          # 缓存管理
    └── auth/             # 认证工具

MCP 服务器模块

FeishuMcp 类

位置: src/mcp/feishuMcp.ts

这是 MCP 服务器的核心类,继承自 McpServer

核心功能

export class FeishuMcp extends McpServer {
  private feishuService: FeishuApiService | null = null;

  constructor() {
    super(serverInfo, serverOptions);
    this.initFeishuService();
    this.registerAllTools();
  }

  private initFeishuService(): void {
    this.feishuService = FeishuApiService.getInstance();
  }

  private registerAllTools(): void {
    registerFeishuTools(this, this.feishuService);
    registerFeishuBlockTools(this, this.feishuService);
    registerFeishuFolderTools(this, this.feishuService);
  }
}

工具注册

工具函数分为三类:

  1. 基础工具 (feishuTools.ts)

    • 文档创建和查询
    • 文档信息获取
    • Wiki 链接转换
    • 搜索功能
  2. 文档块工具 (feishuBlockTools.ts)

    • 文档块创建(文本、代码、标题等)
    • 文档块更新
    • 文档块删除
    • 批量操作
  3. 文件夹工具 (feishuFolderTools.ts)

    • 文件夹列表获取
    • 文件夹创建
    • 根文件夹获取

服务层模块

BaseApiService (基础 API 服务)

位置: src/services/baseService.ts

抽象基类,提供通用的 HTTP 请求处理能力。

核心方法

export abstract class BaseApiService {
  // 执行 HTTP 请求的核心方法
  protected async request<T>(
    endpoint: string,
    method: string = 'GET',
    data?: any,
    needsAuth: boolean = true,
    additionalHeaders?: Record<string, string>,
    responseType?: 'json' | 'arraybuffer' | 'blob' | 'document' | 'text' | 'stream',
    retry: boolean = false
  ): Promise<T>

  // HTTP 方法封装
  protected async get<T>(endpoint: string, params?: any, needsAuth?: boolean): Promise<T>
  protected async post<T>(endpoint: string, data?: any, needsAuth?: boolean): Promise<T>
  protected async patch<T>(endpoint: string, data?: any, needsAuth?: boolean): Promise<T>
  protected async delete<T>(endpoint: string, data?: any, needsAuth?: boolean): Promise<T>
}

错误处理机制

// Token 过期自动刷新
private async handleTenantTokenExpired<T>(...): Promise<T> {
  // 清除过期 token
  tokenCacheManager.removeTenantToken(clientKey);
  // 重试请求(会自动获取新 token)
  return await this.request<T>(endpoint, method, data, needsAuth, additionalHeaders, responseType, true);
}

private async handleUserTokenExpired<T>(...): Promise<T> {
  // 检查是否可以刷新
  if (tokenStatus.canRefresh && !tokenStatus.isExpired) {
    // 设置 token 为过期状态,触发刷新
    tokenInfo.expires_at = Math.floor(Date.now() / 1000) - 1;
    // 重试请求
    return await this.request<T>(...);
  }
}

FeishuApiService (飞书 API 服务)

位置: src/services/feishuApiService.ts

单例模式,提供所有飞书 API 操作的封装。

文档操作

// 创建文档
public async createDocument(title: string, folderToken: string): Promise<any>

// 获取文档信息
public async getDocumentInfo(documentId: string): Promise<any>

// 获取文档内容
public async getDocumentContent(documentId: string, lang: number = 0): Promise<string>

// 获取文档块结构
public async getDocumentBlocks(documentId: string, pageSize: number = 500): Promise<any[]>

文档块操作

// 创建文本块
public async createTextBlock(
  documentId: string,
  parentBlockId: string,
  textContents: Array<{text?: string, equation?: string, style?: any}>,
  align: number = 1,
  index: number = 0
): Promise<any>

// 创建代码块
public async createCodeBlock(
  documentId: string,
  parentBlockId: string,
  code: string,
  language: number = 0,
  wrap: boolean = false,
  index: number = 0
): Promise<any>

// 批量创建文档块
public async createDocumentBlocks(
  documentId: string,
  parentBlockId: string,
  blockContents: any[],
  index: number = 0
): Promise<any>

图片处理

// 创建图片块(完整流程)
public async createImageBlock(
  documentId: string,
  parentBlockId: string,
  imagePathOrUrl: string,
  options: ImageBlockOptions
): Promise<any>

// 流程:
// 1. 获取图片 Base64 (本地文件或网络 URL)
// 2. 创建空图片块
// 3. 上传图片素材到飞书
// 4. 设置图片块内容

BlockFactory (文档块工厂)

位置: src/services/blockFactory.ts

工厂类,用于创建符合飞书 API 规范的文档块对象。

支持的块类型

export enum BlockType {
  TEXT = 'text',
  CODE = 'code',
  HEADING = 'heading',
  LIST = 'list',
  IMAGE = 'image',
  MERMAID = 'mermaid'
}

创建方法

// 创建文本块
createTextBlock(options: {
  textContents: Array<{text: string, style?: any}>,
  align: number
}): any

// 创建代码块
createCodeBlock(options: {
  code: string,
  language: number,
  wrap: boolean
}): any

// 创建标题块
createHeadingBlock(options: {
  text: string,
  level: number,
  align: number
}): any

样式处理

// 应用默认文本样式
public static applyDefaultTextStyle(style?: any): any {
  const defaultStyle = {
    bold: false,
    italic: false,
    strikethrough: false,
    underline: false,
    code_inline: false,
    background_color: 0,
    text_color: 0,
    link: undefined
  };
  
  return { ...defaultStyle, ...style };
}

工具层模块

Config (配置管理)

位置: src/utils/config.ts

负责加载和管理应用配置。

配置来源

  1. 环境变量 (.env 文件)
  2. 命令行参数
  3. 默认值

优先级:命令行参数 > 环境变量 > 默认值

配置项

interface Config {
  feishu: {
    appId: string;
    appSecret: string;
    baseUrl: string;
    authType: 'tenant' | 'user';
  };
  server: {
    port: number;
  };
}

Logger (日志系统)

位置: src/utils/logger.ts

统一的日志接口,支持集成 MCP 日志系统。

日志级别

Logger.info('信息日志');
Logger.warn('警告日志');
Logger.error('错误日志');
Logger.debug('调试日志');

MCP 集成

// 在 stdio 模式下,日志会通过 MCP 协议发送
Logger.info = (...args: any[]) => {
  server.server.sendLoggingMessage({ level: 'info', data: args });
};

CacheManager (缓存管理)

位置: src/utils/cache.ts

提供内存缓存功能,主要用于 Wiki 到文档 ID 的转换缓存。

export class CacheManager {
  // 缓存 Wiki 转换结果
  cacheWikiToDocId(wikiToken: string, documentId: string): void
  
  // 获取缓存的转换结果
  getWikiToDocId(wikiToken: string): string | null
}

认证模块

TokenCacheManager (Token 缓存管理器)

位置: src/utils/auth/tokenCacheManager.ts

管理用户 token 和租户 token 的缓存,支持文件持久化。

功能特性

  1. 内存缓存:快速访问
  2. 文件持久化:服务重启后保留 token
  3. 自动清理:定期清理过期 token
  4. 状态检查:检查 token 是否有效、是否需要刷新

核心方法

// 缓存用户 token
cacheUserToken(key: string, tokenInfo: UserTokenInfo, customTtl?: number): boolean

// 获取用户 token
getUserToken(key: string): string | null

// 检查用户 token 状态
checkUserTokenStatus(key: string): TokenStatus

// 缓存租户 token
cacheTenantToken(key: string, tokenInfo: TenantTokenInfo, customTtl?: number): boolean

// 获取租户 token
getTenantToken(key: string): string | null

UserAuthManager (用户认证管理器)

位置: src/utils/auth/userAuthManager.ts

管理用户会话映射,将 SSE sessionId 映射到 userKey。

export class UserAuthManager {
  // 创建会话映射
  createSession(sessionId: string, userKey: string): void
  
  // 获取用户标识
  getUserKeyBySessionId(sessionId: string): string | null
  
  // 移除会话映射
  removeSession(sessionId: string): void
}

UserContextManager (用户上下文管理器)

位置: src/utils/auth/userContextManager.ts

使用 AsyncLocalStorage 管理请求级别的用户上下文。

export class UserContextManager {
  // 在用户上下文中执行函数
  run(context: {userKey: string, baseUrl: string}, fn: () => Promise<void>): void
  
  // 获取当前用户标识
  getUserKey(): string | null
  
  // 获取当前基础 URL
  getBaseUrl(): string | null
}

TokenRefreshManager (Token 刷新管理器)

位置: src/utils/auth/tokenRefreshManager.ts

后台定时任务,自动刷新即将过期的用户 token。

export class TokenRefreshManager {
  start(): void {
    // 每 5 分钟检查一次所有用户 token
    setInterval(() => {
      this.refreshExpiringTokens();
    }, 5 * 60 * 1000);
  }
}

文档块处理模块

ParamUtils (参数工具)

位置: src/utils/paramUtils.ts

处理各种参数格式,统一转换为 API 需要的格式。

// 处理文档 ID(支持 URL 和纯 ID)
processDocumentId(documentId: string): string

// 处理块 ID
processBlockId(blockId: string): string

// 处理 Wiki Token
processWikiToken(wikiUrl: string): string

// 处理画板 ID
processWhiteboardId(whiteboardId: string): string

Document Utils (文档工具)

位置: src/utils/document.ts

提供文档内容处理的工具函数。


相关文档:

⚠️ **GitHub.com Fallback** ⚠️