feishu-mcp 0.0.15 → 0.0.16
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.
- package/LICENSE +21 -21
- package/README.md +257 -251
- package/dist/cli.js +0 -0
- package/dist/config.js +26 -0
- package/dist/mcp/tools/feishuBlockTools.js +202 -252
- package/dist/mcp/tools/feishuFolderTools.js +22 -28
- package/dist/mcp/tools/feishuTools.js +54 -68
- package/dist/services/feishu.js +495 -0
- package/dist/services/feishuBlockService.js +179 -0
- package/dist/services/feishuBlocks.js +135 -0
- package/dist/services/feishuService.js +475 -0
- package/dist/types/feishuSchema.js +6 -15
- package/package.json +75 -75
|
@@ -2,16 +2,7 @@ import { z } from 'zod';
|
|
|
2
2
|
import { formatErrorMessage } from '../../utils/error.js';
|
|
3
3
|
import { Logger } from '../../utils/logger.js';
|
|
4
4
|
import { detectMimeType } from '../../utils/document.js';
|
|
5
|
-
import { DocumentIdSchema, ParentBlockIdSchema, BlockIdSchema, IndexSchema, StartIndexSchema, EndIndexSchema,
|
|
6
|
-
// AlignSchema,
|
|
7
|
-
// AlignSchemaWithValidation,
|
|
8
|
-
TextElementsArraySchema,
|
|
9
|
-
// CodeLanguageSchema,
|
|
10
|
-
// CodeWrapSchema,
|
|
11
|
-
BlockConfigSchema, MediaIdSchema, MediaExtraSchema, ImagesArraySchema,
|
|
12
|
-
// ImageWidthSchema,
|
|
13
|
-
// ImageHeightSchema
|
|
14
|
-
} from '../../types/feishuSchema.js';
|
|
5
|
+
import { DocumentIdSchema, ParentBlockIdSchema, BlockIdSchema, IndexSchema, StartIndexSchema, EndIndexSchema, AlignSchema, AlignSchemaWithValidation, TextElementsArraySchema, CodeLanguageSchema, CodeWrapSchema, BlockConfigSchema, MediaIdSchema, MediaExtraSchema, ImagePathOrUrlSchema, ImageFileNameSchema, ImageWidthSchema, ImageHeightSchema } from '../../types/feishuSchema.js';
|
|
15
6
|
/**
|
|
16
7
|
* 注册飞书块相关的MCP工具
|
|
17
8
|
* @param server MCP服务器实例
|
|
@@ -236,166 +227,137 @@ export function registerFeishuBlockTools(server, feishuService) {
|
|
|
236
227
|
}
|
|
237
228
|
});
|
|
238
229
|
// 添加创建飞书文本块工具
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
//
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
//
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
//
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
// return {
|
|
371
|
-
// content: [{ type: "text", text: "Feishu service is not initialized. Please check the configuration" }],
|
|
372
|
-
// };
|
|
373
|
-
// }
|
|
374
|
-
//
|
|
375
|
-
// // 确保align值在合法范围内(1-3)
|
|
376
|
-
// if (align !== 1 && align !== 2 && align !== 3) {
|
|
377
|
-
// return {
|
|
378
|
-
// content: [{ type: "text", text: "错误: 对齐方式(align)参数必须是1(居左)、2(居中)或3(居右)中的一个值。" }],
|
|
379
|
-
// };
|
|
380
|
-
// }
|
|
381
|
-
//
|
|
382
|
-
// const listType = isOrdered ? "有序" : "无序";
|
|
383
|
-
// Logger.info(`开始创建飞书${listType}列表块,文档ID: ${documentId},父块ID: ${parentBlockId},对齐方式: ${align},插入位置: ${index}`);
|
|
384
|
-
// const result = await feishuService.createListBlock(documentId, parentBlockId, content, isOrdered, index, align);
|
|
385
|
-
// Logger.info(`飞书${listType}列表块创建成功`);
|
|
386
|
-
//
|
|
387
|
-
// return {
|
|
388
|
-
// content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
389
|
-
// };
|
|
390
|
-
// } catch (error) {
|
|
391
|
-
// Logger.error(`创建飞书列表块失败:`, error);
|
|
392
|
-
// const errorMessage = formatErrorMessage(error);
|
|
393
|
-
// return {
|
|
394
|
-
// content: [{ type: "text", text: `创建飞书列表块失败: ${errorMessage}` }],
|
|
395
|
-
// };
|
|
396
|
-
// }
|
|
397
|
-
// },
|
|
398
|
-
// );
|
|
230
|
+
server.tool("create_feishu_text_block", "Creates a new text block with precise style control. Unlike markdown-based formatting, this tool lets you explicitly set text styles for each text segment. Ideal for formatted documents where exact styling control is needed. NOTE: If creating multiple blocks at once, use batch_create_feishu_blocks tool instead for better efficiency. 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.", {
|
|
231
|
+
documentId: DocumentIdSchema,
|
|
232
|
+
parentBlockId: ParentBlockIdSchema,
|
|
233
|
+
textContents: TextElementsArraySchema,
|
|
234
|
+
align: AlignSchema,
|
|
235
|
+
index: IndexSchema
|
|
236
|
+
}, async ({ documentId, parentBlockId, textContents, align = 1, index }) => {
|
|
237
|
+
try {
|
|
238
|
+
if (!feishuService) {
|
|
239
|
+
return {
|
|
240
|
+
content: [{ type: "text", text: "Feishu service is not initialized. Please check the configuration" }],
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
Logger.info(`开始创建飞书文本块,文档ID: ${documentId},父块ID: ${parentBlockId},对齐方式: ${align},插入位置: ${index}`);
|
|
244
|
+
const result = await feishuService.createTextBlock(documentId, parentBlockId, textContents, align, index);
|
|
245
|
+
Logger.info(`飞书文本块创建成功`);
|
|
246
|
+
return {
|
|
247
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
catch (error) {
|
|
251
|
+
Logger.error(`创建飞书文本块失败:`, error);
|
|
252
|
+
const errorMessage = formatErrorMessage(error);
|
|
253
|
+
return {
|
|
254
|
+
content: [{ type: "text", text: `创建飞书文本块失败: ${errorMessage}` }],
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
// 添加创建飞书代码块工具
|
|
259
|
+
server.tool("create_feishu_code_block", "Creates a new code block with syntax highlighting and formatting options. Ideal for technical documentation, tutorials, or displaying code examples with proper formatting and language-specific highlighting. NOTE: If creating multiple blocks at once, use batch_create_feishu_blocks tool instead for better efficiency. 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.", {
|
|
260
|
+
documentId: DocumentIdSchema,
|
|
261
|
+
parentBlockId: ParentBlockIdSchema,
|
|
262
|
+
code: z.string().describe("Code content (required). The complete code text to display."),
|
|
263
|
+
language: CodeLanguageSchema,
|
|
264
|
+
wrap: CodeWrapSchema,
|
|
265
|
+
index: IndexSchema
|
|
266
|
+
}, async ({ documentId, parentBlockId, code, language = 1, wrap = false, index = 0 }) => {
|
|
267
|
+
try {
|
|
268
|
+
if (!feishuService) {
|
|
269
|
+
return {
|
|
270
|
+
content: [{ type: "text", text: "Feishu service is not initialized. Please check the configuration" }],
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
Logger.info(`开始创建飞书代码块,文档ID: ${documentId},父块ID: ${parentBlockId},语言: ${language},自动换行: ${wrap},插入位置: ${index}`);
|
|
274
|
+
const result = await feishuService.createCodeBlock(documentId, parentBlockId, code, language, wrap, index);
|
|
275
|
+
Logger.info(`飞书代码块创建成功`);
|
|
276
|
+
return {
|
|
277
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
catch (error) {
|
|
281
|
+
Logger.error(`创建飞书代码块失败:`, error);
|
|
282
|
+
const errorMessage = formatErrorMessage(error);
|
|
283
|
+
return {
|
|
284
|
+
content: [{ type: "text", text: `创建飞书代码块失败: ${errorMessage}` }],
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
// 添加创建飞书标题块工具
|
|
289
|
+
server.tool("create_feishu_heading_block", "Creates a heading block with customizable level and alignment. Use this tool to add section titles, chapter headings, or any hierarchical structure elements to your document. Supports nine heading levels for different emphasis needs. NOTE: If creating multiple blocks at once, use batch_create_feishu_blocks tool instead for better efficiency. 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.", {
|
|
290
|
+
documentId: DocumentIdSchema,
|
|
291
|
+
parentBlockId: ParentBlockIdSchema,
|
|
292
|
+
level: z.number().min(1).max(9).describe("Heading level (required). Integer between 1 and 9, where 1 is the largest heading (h1) and 9 is the smallest (h9)."),
|
|
293
|
+
content: z.string().describe("Heading text content (required). The actual text of the heading."),
|
|
294
|
+
align: AlignSchemaWithValidation,
|
|
295
|
+
index: IndexSchema
|
|
296
|
+
}, async ({ documentId, parentBlockId, level, content, align = 1, index = 0 }) => {
|
|
297
|
+
try {
|
|
298
|
+
if (!feishuService) {
|
|
299
|
+
return {
|
|
300
|
+
content: [{ type: "text", text: "Feishu service is not initialized. Please check the configuration" }],
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
// 确保align值在合法范围内(1-3)
|
|
304
|
+
if (align !== 1 && align !== 2 && align !== 3) {
|
|
305
|
+
return {
|
|
306
|
+
content: [{ type: "text", text: "错误: 对齐方式(align)参数必须是1(居左)、2(居中)或3(居右)中的一个值。" }],
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
Logger.info(`开始创建飞书标题块,文档ID: ${documentId},父块ID: ${parentBlockId},标题级别: ${level},对齐方式: ${align},插入位置: ${index}`);
|
|
310
|
+
const result = await feishuService.createHeadingBlock(documentId, parentBlockId, content, level, index, align);
|
|
311
|
+
Logger.info(`飞书标题块创建成功`);
|
|
312
|
+
return {
|
|
313
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
catch (error) {
|
|
317
|
+
Logger.error(`创建飞书标题块失败:`, error);
|
|
318
|
+
const errorMessage = formatErrorMessage(error);
|
|
319
|
+
return {
|
|
320
|
+
content: [{ type: "text", text: `创建飞书标题块失败: ${errorMessage}` }],
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
// 添加创建飞书列表块工具
|
|
325
|
+
server.tool("create_feishu_list_block", "Creates a list item block (either ordered or unordered). Perfect for creating hierarchical and structured content with bullet points or numbered lists. NOTE: If creating multiple blocks at once, use batch_create_feishu_blocks tool instead for better efficiency. 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.", {
|
|
326
|
+
documentId: DocumentIdSchema,
|
|
327
|
+
parentBlockId: ParentBlockIdSchema,
|
|
328
|
+
content: z.string().describe("List item content (required). The actual text of the list item."),
|
|
329
|
+
isOrdered: z.boolean().optional().default(false).describe("Whether this is an ordered (numbered) list item. Default is false (bullet point/unordered)."),
|
|
330
|
+
align: AlignSchemaWithValidation,
|
|
331
|
+
index: IndexSchema
|
|
332
|
+
}, async ({ documentId, parentBlockId, content, isOrdered = false, align = 1, index = 0 }) => {
|
|
333
|
+
try {
|
|
334
|
+
if (!feishuService) {
|
|
335
|
+
return {
|
|
336
|
+
content: [{ type: "text", text: "Feishu service is not initialized. Please check the configuration" }],
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
// 确保align值在合法范围内(1-3)
|
|
340
|
+
if (align !== 1 && align !== 2 && align !== 3) {
|
|
341
|
+
return {
|
|
342
|
+
content: [{ type: "text", text: "错误: 对齐方式(align)参数必须是1(居左)、2(居中)或3(居右)中的一个值。" }],
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
const listType = isOrdered ? "有序" : "无序";
|
|
346
|
+
Logger.info(`开始创建飞书${listType}列表块,文档ID: ${documentId},父块ID: ${parentBlockId},对齐方式: ${align},插入位置: ${index}`);
|
|
347
|
+
const result = await feishuService.createListBlock(documentId, parentBlockId, content, isOrdered, index, align);
|
|
348
|
+
Logger.info(`飞书${listType}列表块创建成功`);
|
|
349
|
+
return {
|
|
350
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
catch (error) {
|
|
354
|
+
Logger.error(`创建飞书列表块失败:`, error);
|
|
355
|
+
const errorMessage = formatErrorMessage(error);
|
|
356
|
+
return {
|
|
357
|
+
content: [{ type: "text", text: `创建飞书列表块失败: ${errorMessage}` }],
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
});
|
|
399
361
|
// 添加飞书Wiki文档ID转换工具
|
|
400
362
|
server.tool('convert_feishu_wiki_to_document_id', 'Converts a Feishu Wiki document link to a compatible document ID. This conversion is required before using wiki links with any other Feishu document tools.', {
|
|
401
363
|
wikiUrl: z.string().describe('Wiki URL or Token (required). Supports complete URL formats like https://xxx.feishu.cn/wiki/xxxxx or direct use of the Token portion'),
|
|
@@ -485,103 +447,91 @@ export function registerFeishuBlockTools(server, feishuService) {
|
|
|
485
447
|
}
|
|
486
448
|
});
|
|
487
449
|
// 添加创建飞书图片块工具
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
// Logger.error(`创建飞书图片块失败:`, error);
|
|
527
|
-
// const errorMessage = formatErrorMessage(error);
|
|
528
|
-
// return {
|
|
529
|
-
// content: [{ type: 'text', text: `创建飞书图片块失败: ${errorMessage}` }],
|
|
530
|
-
// };
|
|
531
|
-
// }
|
|
532
|
-
// },
|
|
533
|
-
// );
|
|
450
|
+
server.tool('create_feishu_image_block', 'Creates a complete image block in a Feishu document by uploading an image from a local path or URL and setting it to the block. This tool handles the entire 3-step process: (1) Creates an empty image block, (2) Downloads/reads the image and uploads it as media resource, (3) Sets the image content to the block. Supports local file paths and HTTP/HTTPS URLs. Use this when you want to insert images into Feishu documents. 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.', {
|
|
451
|
+
documentId: DocumentIdSchema,
|
|
452
|
+
parentBlockId: ParentBlockIdSchema,
|
|
453
|
+
imagePathOrUrl: ImagePathOrUrlSchema,
|
|
454
|
+
fileName: ImageFileNameSchema,
|
|
455
|
+
width: ImageWidthSchema,
|
|
456
|
+
height: ImageHeightSchema,
|
|
457
|
+
index: IndexSchema
|
|
458
|
+
}, async ({ documentId, parentBlockId, imagePathOrUrl, fileName, width, height, index = 0 }) => {
|
|
459
|
+
try {
|
|
460
|
+
if (!feishuService) {
|
|
461
|
+
return {
|
|
462
|
+
content: [{ type: 'text', text: 'Feishu service is not initialized. Please check the configuration' }],
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
Logger.info(`开始创建飞书图片块,文档ID: ${documentId},父块ID: ${parentBlockId},图片源: ${imagePathOrUrl},插入位置: ${index}`);
|
|
466
|
+
const result = await feishuService.createImageBlock(documentId, parentBlockId, imagePathOrUrl, {
|
|
467
|
+
fileName,
|
|
468
|
+
width,
|
|
469
|
+
height,
|
|
470
|
+
index
|
|
471
|
+
});
|
|
472
|
+
Logger.info(`飞书图片块创建成功,块ID: ${result.imageBlockId}`);
|
|
473
|
+
return {
|
|
474
|
+
content: [{
|
|
475
|
+
type: 'text',
|
|
476
|
+
text: `图片块创建成功!\n\n块ID: ${result.imageBlockId}\n文件Token: ${result.fileToken}\n文档修订ID: ${result.documentRevisionId}\n\n完整结果:\n${JSON.stringify(result, null, 2)}`
|
|
477
|
+
}],
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
catch (error) {
|
|
481
|
+
Logger.error(`创建飞书图片块失败:`, error);
|
|
482
|
+
const errorMessage = formatErrorMessage(error);
|
|
483
|
+
return {
|
|
484
|
+
content: [{ type: 'text', text: `创建飞书图片块失败: ${errorMessage}` }],
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
});
|
|
534
488
|
// 添加图片上传绑定工具
|
|
535
|
-
server.tool('upload_and_bind_image_to_block', 'Uploads
|
|
489
|
+
server.tool('upload_and_bind_image_to_block', 'Uploads an image from a local path or URL and binds it to an existing empty image block. This tool is used after creating image blocks with batch_create_feishu_blocks tool. It handles uploading the image media and setting the image content to the specified block ID. Supports local file paths and HTTP/HTTPS URLs.', {
|
|
536
490
|
documentId: DocumentIdSchema,
|
|
537
|
-
|
|
538
|
-
|
|
491
|
+
blockId: BlockIdSchema,
|
|
492
|
+
imagePathOrUrl: ImagePathOrUrlSchema,
|
|
493
|
+
fileName: ImageFileNameSchema,
|
|
494
|
+
}, async ({ documentId, blockId, imagePathOrUrl, fileName }) => {
|
|
539
495
|
try {
|
|
540
496
|
if (!feishuService) {
|
|
541
497
|
return {
|
|
542
498
|
content: [{ type: 'text', text: 'Feishu service is not initialized. Please check the configuration' }],
|
|
543
499
|
};
|
|
544
500
|
}
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
}
|
|
556
|
-
Logger.info(`图片素材上传成功,file_token: ${uploadResult.file_token}`);
|
|
557
|
-
Logger.info('第2步:设置图片块内容');
|
|
558
|
-
const setContentResult = await feishuService.setImageBlockContent(documentId, blockId, uploadResult.file_token);
|
|
559
|
-
Logger.info('图片上传并绑定完成');
|
|
560
|
-
results.push({
|
|
561
|
-
blockId,
|
|
562
|
-
fileToken: uploadResult.file_token,
|
|
563
|
-
uploadResult,
|
|
564
|
-
setContentResult,
|
|
565
|
-
documentRevisionId: setContentResult.document_revision_id
|
|
566
|
-
});
|
|
567
|
-
}
|
|
568
|
-
catch (err) {
|
|
569
|
-
Logger.error(`上传图片并绑定到块失败:`, err);
|
|
570
|
-
results.push({
|
|
571
|
-
blockId,
|
|
572
|
-
error: err instanceof Error ? err.message : String(err)
|
|
573
|
-
});
|
|
574
|
-
}
|
|
501
|
+
Logger.info(`开始上传图片并绑定到块,文档ID: ${documentId},块ID: ${blockId},图片源: ${imagePathOrUrl}`);
|
|
502
|
+
// 从路径或URL获取图片的Base64编码
|
|
503
|
+
const { base64: imageBase64, fileName: detectedFileName } = await feishuService.getImageBase64FromPathOrUrl(imagePathOrUrl);
|
|
504
|
+
// 使用提供的文件名或检测到的文件名
|
|
505
|
+
const finalFileName = fileName || detectedFileName;
|
|
506
|
+
// 第1步:上传图片素材
|
|
507
|
+
Logger.info('第1步:上传图片素材');
|
|
508
|
+
const uploadResult = await feishuService.uploadImageMedia(imageBase64, finalFileName, blockId);
|
|
509
|
+
if (!uploadResult?.file_token) {
|
|
510
|
+
throw new Error('上传图片素材失败:无法获取file_token');
|
|
575
511
|
}
|
|
512
|
+
Logger.info(`图片素材上传成功,file_token: ${uploadResult.file_token}`);
|
|
513
|
+
// 第2步:设置图片块内容
|
|
514
|
+
Logger.info('第2步:设置图片块内容');
|
|
515
|
+
const setContentResult = await feishuService.setImageBlockContent(documentId, blockId, uploadResult.file_token);
|
|
516
|
+
Logger.info('图片上传并绑定完成');
|
|
576
517
|
return {
|
|
577
|
-
content: [{
|
|
518
|
+
content: [{
|
|
519
|
+
type: 'text',
|
|
520
|
+
text: `图片上传并绑定成功!\n\n块ID: ${blockId}\n文件Token: ${uploadResult.file_token}\n文档修订ID: ${setContentResult.document_revision_id}\n\n完整结果:\n${JSON.stringify({
|
|
521
|
+
blockId: blockId,
|
|
522
|
+
fileToken: uploadResult.file_token,
|
|
523
|
+
uploadResult: uploadResult,
|
|
524
|
+
setContentResult: setContentResult,
|
|
525
|
+
documentRevisionId: setContentResult.document_revision_id
|
|
526
|
+
}, null, 2)}`
|
|
527
|
+
}],
|
|
578
528
|
};
|
|
579
529
|
}
|
|
580
530
|
catch (error) {
|
|
581
|
-
Logger.error(
|
|
531
|
+
Logger.error(`上传图片并绑定到块失败:`, error);
|
|
582
532
|
const errorMessage = formatErrorMessage(error);
|
|
583
533
|
return {
|
|
584
|
-
content: [{ type: 'text', text:
|
|
534
|
+
content: [{ type: 'text', text: `上传图片并绑定到块失败: ${errorMessage}` }],
|
|
585
535
|
};
|
|
586
536
|
}
|
|
587
537
|
});
|
|
@@ -8,34 +8,28 @@ import { FolderTokenSchema, FolderNameSchema, } from '../../types/feishuSchema.j
|
|
|
8
8
|
*/
|
|
9
9
|
export function registerFeishuFolderTools(server, feishuService) {
|
|
10
10
|
// 添加获取根文件夹信息工具
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
// return {
|
|
34
|
-
// content: [{ type: 'text', text: errorMessage }],
|
|
35
|
-
// };
|
|
36
|
-
// }
|
|
37
|
-
// },
|
|
38
|
-
// );
|
|
11
|
+
server.tool('get_feishu_root_folder_info', 'Retrieves basic information about the root folder in Feishu Drive. Returns the token, ID and user ID of the root folder, which can be used for subsequent folder operations.', {}, async () => {
|
|
12
|
+
try {
|
|
13
|
+
if (!feishuService) {
|
|
14
|
+
return {
|
|
15
|
+
content: [{ type: 'text', text: '飞书服务未初始化,请检查配置' }],
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
Logger.info(`开始获取飞书根文件夹信息`);
|
|
19
|
+
const folderInfo = await feishuService.getRootFolderInfo();
|
|
20
|
+
Logger.info(`飞书根文件夹信息获取成功,token: ${folderInfo.token}`);
|
|
21
|
+
return {
|
|
22
|
+
content: [{ type: 'text', text: JSON.stringify(folderInfo, null, 2) }],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
Logger.error(`获取飞书根文件夹信息失败:`, error);
|
|
27
|
+
const errorMessage = formatErrorMessage(error, '获取飞书根文件夹信息失败');
|
|
28
|
+
return {
|
|
29
|
+
content: [{ type: 'text', text: errorMessage }],
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
});
|
|
39
33
|
// 添加获取文件夹中的文件清单工具
|
|
40
34
|
server.tool('get_feishu_folder_files', 'Retrieves a list of files and subfolders in a specified folder. Use this to explore folder contents, view file metadata, and get URLs and tokens for further operations.', {
|
|
41
35
|
folderToken: FolderTokenSchema,
|