feishu-mcp 0.0.10 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,166 @@
1
+ import { z } from 'zod';
2
+ import { formatErrorMessage } from '../../utils/error.js';
3
+ import { Logger } from '../../utils/logger.js';
4
+ import { DocumentIdSchema, BlockIdSchema, SearchKeySchema, } from '../../types/feishuSchema.js';
5
+ /**
6
+ * 注册飞书相关的MCP工具
7
+ * @param server MCP服务器实例
8
+ * @param feishuService 飞书API服务实例
9
+ */
10
+ export function registerFeishuTools(server, feishuService) {
11
+ // 添加创建飞书文档工具
12
+ server.tool('create_feishu_document', 'Creates a new Feishu document and returns its information. Use this tool when you need to create a document from scratch with a specific title and folder location.', {
13
+ title: z.string().describe('Document title (required). This will be displayed in the Feishu document list and document header.'),
14
+ folderToken: z.string().describe('Folder token (required). Specifies where to create the document. Format is an alphanumeric string like "doxcnOu1ZKYH4RtX1Y5XwL5WGRh".'),
15
+ }, async ({ title, folderToken }) => {
16
+ try {
17
+ Logger.info(`开始创建飞书文档,标题: ${title}${folderToken ? `,文件夹Token: ${folderToken}` : ',使用默认文件夹'}`);
18
+ const newDoc = await feishuService?.createDocument(title, folderToken);
19
+ if (!newDoc) {
20
+ throw new Error('创建文档失败,未返回文档信息');
21
+ }
22
+ Logger.info(`飞书文档创建成功,文档ID: ${newDoc.objToken || newDoc.document_id}`);
23
+ return {
24
+ content: [{ type: 'text', text: JSON.stringify(newDoc, null, 2) }],
25
+ };
26
+ }
27
+ catch (error) {
28
+ Logger.error(`创建飞书文档失败:`, error);
29
+ const errorMessage = formatErrorMessage(error);
30
+ return {
31
+ content: [{ type: 'text', text: `创建飞书文档失败: ${errorMessage}` }],
32
+ };
33
+ }
34
+ });
35
+ // 添加获取飞书文档信息工具
36
+ server.tool('get_feishu_document_info', 'Retrieves basic information about a Feishu document. Use this to verify a document exists, check access permissions, or get metadata like title, type, and creation information.', {
37
+ documentId: DocumentIdSchema,
38
+ }, async ({ documentId }) => {
39
+ try {
40
+ if (!feishuService) {
41
+ return {
42
+ content: [{ type: 'text', text: '飞书服务未初始化,请检查配置' }],
43
+ };
44
+ }
45
+ Logger.info(`开始获取飞书文档信息,文档ID: ${documentId}`);
46
+ const docInfo = await feishuService.getDocumentInfo(documentId);
47
+ Logger.info(`飞书文档信息获取成功,标题: ${docInfo.title}`);
48
+ return {
49
+ content: [{ type: 'text', text: JSON.stringify(docInfo, null, 2) }],
50
+ };
51
+ }
52
+ catch (error) {
53
+ Logger.error(`获取飞书文档信息失败:`, error);
54
+ const errorMessage = formatErrorMessage(error, '获取飞书文档信息失败');
55
+ return {
56
+ content: [{ type: 'text', text: errorMessage }],
57
+ };
58
+ }
59
+ });
60
+ // 添加获取飞书文档内容工具
61
+ server.tool('get_feishu_document_content', 'Retrieves the plain text content of a Feishu document. Ideal for content analysis, processing, or when you need to extract text without formatting. The content maintains the document structure but without styling. Note: For Feishu wiki links (https://xxx.feishu.cn/wiki/xxx) you must first use convert_feishu_wiki_to_document_id tool to obtain a compatible document ID.', {
62
+ documentId: DocumentIdSchema,
63
+ lang: z.number().optional().default(0).describe('Language code (optional). Default is 0 (Chinese). Use 1 for English if available.'),
64
+ }, async ({ documentId, lang }) => {
65
+ try {
66
+ if (!feishuService) {
67
+ return {
68
+ content: [{ type: 'text', text: 'Feishu service is not initialized. Please check the configuration' }],
69
+ };
70
+ }
71
+ Logger.info(`开始获取飞书文档内容,文档ID: ${documentId},语言: ${lang}`);
72
+ const content = await feishuService.getDocumentContent(documentId, lang);
73
+ Logger.info(`飞书文档内容获取成功,内容长度: ${content.length}字符`);
74
+ return {
75
+ content: [{ type: 'text', text: content }],
76
+ };
77
+ }
78
+ catch (error) {
79
+ Logger.error(`获取飞书文档内容失败:`, error);
80
+ const errorMessage = formatErrorMessage(error);
81
+ return {
82
+ content: [{ type: 'text', text: `获取飞书文档内容失败: ${errorMessage}` }],
83
+ };
84
+ }
85
+ });
86
+ // 添加获取飞书文档块工具
87
+ server.tool('get_feishu_document_blocks', 'Retrieves the block structure information of a Feishu document. Essential to use before inserting content to understand document structure and determine correct insertion positions. Returns a detailed hierarchy of blocks with their IDs, types, and content. Note: For Feishu wiki links (https://xxx.feishu.cn/wiki/xxx) you must first use convert_feishu_wiki_to_document_id tool to obtain a compatible document ID.', {
88
+ documentId: DocumentIdSchema,
89
+ }, async ({ documentId }) => {
90
+ try {
91
+ if (!feishuService) {
92
+ return {
93
+ content: [{ type: 'text', text: 'Feishu service is not initialized. Please check the configuration' }],
94
+ };
95
+ }
96
+ Logger.info(`开始获取飞书文档块,文档ID: ${documentId}`);
97
+ const blocks = await feishuService.getDocumentBlocks(documentId);
98
+ Logger.info(`飞书文档块获取成功,共 ${blocks.length} 个块`);
99
+ return {
100
+ content: [{ type: 'text', text: JSON.stringify(blocks, null, 2) }],
101
+ };
102
+ }
103
+ catch (error) {
104
+ Logger.error(`获取飞书文档块失败:`, error);
105
+ const errorMessage = formatErrorMessage(error);
106
+ return {
107
+ content: [{ type: 'text', text: `获取飞书文档块失败: ${errorMessage}` }],
108
+ };
109
+ }
110
+ });
111
+ // 添加获取块内容工具
112
+ server.tool('get_feishu_block_content', 'Retrieves the detailed content and structure of a specific block in a Feishu document. Useful for inspecting block properties, formatting, and content, especially before making updates or for debugging purposes. Note: For Feishu wiki links (https://xxx.feishu.cn/wiki/xxx) you must first use convert_feishu_wiki_to_document_id tool to obtain a compatible document ID.', {
113
+ documentId: DocumentIdSchema,
114
+ blockId: BlockIdSchema,
115
+ }, async ({ documentId, blockId }) => {
116
+ try {
117
+ if (!feishuService) {
118
+ return {
119
+ content: [{ type: 'text', text: '飞书服务未初始化,请检查配置' }],
120
+ };
121
+ }
122
+ Logger.info(`开始获取飞书块内容,文档ID: ${documentId},块ID: ${blockId}`);
123
+ const blockContent = await feishuService.getBlockContent(documentId, blockId);
124
+ Logger.info(`飞书块内容获取成功,块类型: ${blockContent.block_type}`);
125
+ return {
126
+ content: [{ type: 'text', text: JSON.stringify(blockContent, null, 2) }],
127
+ };
128
+ }
129
+ catch (error) {
130
+ Logger.error(`获取飞书块内容失败:`, error);
131
+ const errorMessage = formatErrorMessage(error);
132
+ return {
133
+ content: [{ type: 'text', text: `获取飞书块内容失败: ${errorMessage}` }],
134
+ };
135
+ }
136
+ });
137
+ // 添加搜索文档工具
138
+ server.tool('search_feishu_documents', 'Searches for documents in Feishu. Supports keyword-based search and returns document information including title, type, and owner. Use this tool to find specific content or related documents in your document library.', {
139
+ searchKey: SearchKeySchema,
140
+ }, async ({ searchKey }) => {
141
+ try {
142
+ if (!feishuService) {
143
+ return {
144
+ content: [{ type: 'text', text: 'Feishu service is not initialized. Please check the configuration.' }],
145
+ };
146
+ }
147
+ Logger.info(`开始搜索飞书文档,关键字: ${searchKey},`);
148
+ const searchResult = await feishuService.searchDocuments(searchKey);
149
+ Logger.info(`文档搜索完成,找到 ${searchResult.size} 个结果`);
150
+ return {
151
+ content: [
152
+ { type: 'text', text: JSON.stringify(searchResult, null, 2) },
153
+ ],
154
+ };
155
+ }
156
+ catch (error) {
157
+ Logger.error(`搜索飞书文档失败:`, error);
158
+ const errorMessage = formatErrorMessage(error);
159
+ return {
160
+ content: [
161
+ { type: 'text', text: `搜索飞书文档失败: ${errorMessage}` },
162
+ ],
163
+ };
164
+ }
165
+ });
166
+ }