feishu-mcp 0.0.16 → 0.0.18

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/dist/cli.js CHANGED
File without changes
@@ -2,7 +2,16 @@ 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, AlignSchema, AlignSchemaWithValidation, TextElementsArraySchema, CodeLanguageSchema, CodeWrapSchema, BlockConfigSchema, MediaIdSchema, MediaExtraSchema, ImagePathOrUrlSchema, ImageFileNameSchema, ImageWidthSchema, ImageHeightSchema } from '../../types/feishuSchema.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';
6
15
  /**
7
16
  * 注册飞书块相关的MCP工具
8
17
  * @param server MCP服务器实例
@@ -227,137 +236,166 @@ export function registerFeishuBlockTools(server, feishuService) {
227
236
  }
228
237
  });
229
238
  // 添加创建飞书文本块工具
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
- });
239
+ // server.tool(
240
+ // "create_feishu_text_block",
241
+ // "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.",
242
+ // {
243
+ // documentId: DocumentIdSchema,
244
+ // parentBlockId: ParentBlockIdSchema,
245
+ // textContents: TextElementsArraySchema,
246
+ // align: AlignSchema,
247
+ // index: IndexSchema
248
+ // },
249
+ // async ({ documentId, parentBlockId, textContents, align = 1, index }) => {
250
+ // try {
251
+ // if (!feishuService) {
252
+ // return {
253
+ // content: [{ type: "text", text: "Feishu service is not initialized. Please check the configuration" }],
254
+ // };
255
+ // }
256
+ //
257
+ // Logger.info(`开始创建飞书文本块,文档ID: ${documentId},父块ID: ${parentBlockId},对齐方式: ${align},插入位置: ${index}`);
258
+ // const result = await feishuService.createTextBlock(documentId, parentBlockId, textContents, align, index);
259
+ // Logger.info(`飞书文本块创建成功`);
260
+ //
261
+ // return {
262
+ // content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
263
+ // };
264
+ // } catch (error) {
265
+ // Logger.error(`创建飞书文本块失败:`, error);
266
+ // const errorMessage = formatErrorMessage(error);
267
+ // return {
268
+ // content: [{ type: "text", text: `创建飞书文本块失败: ${errorMessage}` }],
269
+ // };
270
+ // }
271
+ // },
272
+ // );
273
+ //
274
+ // // 添加创建飞书代码块工具
275
+ // server.tool(
276
+ // "create_feishu_code_block",
277
+ // "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.",
278
+ // {
279
+ // documentId: DocumentIdSchema,
280
+ // parentBlockId: ParentBlockIdSchema,
281
+ // code: z.string().describe("Code content (required). The complete code text to display."),
282
+ // language: CodeLanguageSchema,
283
+ // wrap: CodeWrapSchema,
284
+ // index: IndexSchema
285
+ // },
286
+ // async ({ documentId, parentBlockId, code, language = 1, wrap = false, index = 0 }) => {
287
+ // try {
288
+ // if (!feishuService) {
289
+ // return {
290
+ // content: [{ type: "text", text: "Feishu service is not initialized. Please check the configuration" }],
291
+ // };
292
+ // }
293
+ //
294
+ // Logger.info(`开始创建飞书代码块,文档ID: ${documentId},父块ID: ${parentBlockId},语言: ${language},自动换行: ${wrap},插入位置: ${index}`);
295
+ // const result = await feishuService.createCodeBlock(documentId, parentBlockId, code, language, wrap, index);
296
+ // Logger.info(`飞书代码块创建成功`);
297
+ //
298
+ // return {
299
+ // content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
300
+ // };
301
+ // } catch (error) {
302
+ // Logger.error(`创建飞书代码块失败:`, error);
303
+ // const errorMessage = formatErrorMessage(error);
304
+ // return {
305
+ // content: [{ type: "text", text: `创建飞书代码块失败: ${errorMessage}` }],
306
+ // };
307
+ // }
308
+ // },
309
+ // );
310
+ //
311
+ // // 添加创建飞书标题块工具
312
+ // server.tool(
313
+ // "create_feishu_heading_block",
314
+ // "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.",
315
+ // {
316
+ // documentId: DocumentIdSchema,
317
+ // parentBlockId: ParentBlockIdSchema,
318
+ // 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)."),
319
+ // content: z.string().describe("Heading text content (required). The actual text of the heading."),
320
+ // align: AlignSchemaWithValidation,
321
+ // index: IndexSchema
322
+ // },
323
+ // async ({ documentId, parentBlockId, level, content, align = 1, index = 0 }) => {
324
+ // try {
325
+ // if (!feishuService) {
326
+ // return {
327
+ // content: [{ type: "text", text: "Feishu service is not initialized. Please check the configuration" }],
328
+ // };
329
+ // }
330
+ //
331
+ // // 确保align值在合法范围内(1-3)
332
+ // if (align !== 1 && align !== 2 && align !== 3) {
333
+ // return {
334
+ // content: [{ type: "text", text: "错误: 对齐方式(align)参数必须是1(居左)、2(居中)或3(居右)中的一个值。" }],
335
+ // };
336
+ // }
337
+ //
338
+ // Logger.info(`开始创建飞书标题块,文档ID: ${documentId},父块ID: ${parentBlockId},标题级别: ${level},对齐方式: ${align},插入位置: ${index}`);
339
+ // const result = await feishuService.createHeadingBlock(documentId, parentBlockId, content, level, index, align);
340
+ // Logger.info(`飞书标题块创建成功`);
341
+ //
342
+ // return {
343
+ // content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
344
+ // };
345
+ // } catch (error) {
346
+ // Logger.error(`创建飞书标题块失败:`, error);
347
+ // const errorMessage = formatErrorMessage(error);
348
+ // return {
349
+ // content: [{ type: "text", text: `创建飞书标题块失败: ${errorMessage}` }],
350
+ // };
351
+ // }
352
+ // },
353
+ // );
354
+ //
355
+ // // 添加创建飞书列表块工具
356
+ // server.tool(
357
+ // "create_feishu_list_block",
358
+ // "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.",
359
+ // {
360
+ // documentId: DocumentIdSchema,
361
+ // parentBlockId: ParentBlockIdSchema,
362
+ // content: z.string().describe("List item content (required). The actual text of the list item."),
363
+ // isOrdered: z.boolean().optional().default(false).describe("Whether this is an ordered (numbered) list item. Default is false (bullet point/unordered)."),
364
+ // align: AlignSchemaWithValidation,
365
+ // index: IndexSchema
366
+ // },
367
+ // async ({ documentId, parentBlockId, content, isOrdered = false, align = 1, index = 0 }) => {
368
+ // try {
369
+ // if (!feishuService) {
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
+ // );
361
399
  // 添加飞书Wiki文档ID转换工具
362
400
  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.', {
363
401
  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'),
@@ -447,91 +485,103 @@ export function registerFeishuBlockTools(server, feishuService) {
447
485
  }
448
486
  });
449
487
  // 添加创建飞书图片块工具
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
- });
488
+ // server.tool(
489
+ // 'create_feishu_image_block',
490
+ // '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.',
491
+ // {
492
+ // documentId: DocumentIdSchema,
493
+ // parentBlockId: ParentBlockIdSchema,
494
+ // imagePathOrUrl: ImagePathOrUrlSchema,
495
+ // fileName: ImageFileNameSchema,
496
+ // width: ImageWidthSchema,
497
+ // height: ImageHeightSchema,
498
+ // index: IndexSchema
499
+ // },
500
+ // async ({ documentId, parentBlockId, imagePathOrUrl, fileName, width, height, index = 0 }) => {
501
+ // try {
502
+ // if (!feishuService) {
503
+ // return {
504
+ // content: [{ type: 'text', text: 'Feishu service is not initialized. Please check the configuration' }],
505
+ // };
506
+ // }
507
+ //
508
+ // Logger.info(`开始创建飞书图片块,文档ID: ${documentId},父块ID: ${parentBlockId},图片源: ${imagePathOrUrl},插入位置: ${index}`);
509
+ //
510
+ // const result = await feishuService.createImageBlock(documentId, parentBlockId, imagePathOrUrl, {
511
+ // fileName,
512
+ // width,
513
+ // height,
514
+ // index
515
+ // });
516
+ //
517
+ // Logger.info(`飞书图片块创建成功,块ID: ${result.imageBlockId}`);
518
+ //
519
+ // return {
520
+ // content: [{
521
+ // type: 'text',
522
+ // text: `图片块创建成功!\n\n块ID: ${result.imageBlockId}\n文件Token: ${result.fileToken}\n文档修订ID: ${result.documentRevisionId}\n\n完整结果:\n${JSON.stringify(result, null, 2)}`
523
+ // }],
524
+ // };
525
+ // } catch (error) {
526
+ // Logger.error(`创建飞书图片块失败:`, error);
527
+ // const errorMessage = formatErrorMessage(error);
528
+ // return {
529
+ // content: [{ type: 'text', text: `创建飞书图片块失败: ${errorMessage}` }],
530
+ // };
531
+ // }
532
+ // },
533
+ // );
488
534
  // 添加图片上传绑定工具
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.', {
535
+ server.tool('upload_and_bind_image_to_block', 'Uploads images from local paths or URLs and binds them to existing empty image blocks. 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 IDs. Supports local file paths and HTTP/HTTPS URLs. Each image upload and binding is processed independently, and all results are returned in order.', {
490
536
  documentId: DocumentIdSchema,
491
- blockId: BlockIdSchema,
492
- imagePathOrUrl: ImagePathOrUrlSchema,
493
- fileName: ImageFileNameSchema,
494
- }, async ({ documentId, blockId, imagePathOrUrl, fileName }) => {
537
+ images: ImagesArraySchema,
538
+ }, async ({ documentId, images }) => {
495
539
  try {
496
540
  if (!feishuService) {
497
541
  return {
498
542
  content: [{ type: 'text', text: 'Feishu service is not initialized. Please check the configuration' }],
499
543
  };
500
544
  }
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');
545
+ const results = [];
546
+ for (const { blockId, imagePathOrUrl, fileName } of images) {
547
+ Logger.info(`开始上传图片并绑定到块,文档ID: ${documentId},块ID: ${blockId},图片源: ${imagePathOrUrl}`);
548
+ try {
549
+ const { base64: imageBase64, fileName: detectedFileName } = await feishuService.getImageBase64FromPathOrUrl(imagePathOrUrl);
550
+ const finalFileName = fileName || detectedFileName;
551
+ Logger.info('第1步:上传图片素材');
552
+ const uploadResult = await feishuService.uploadImageMedia(imageBase64, finalFileName, blockId);
553
+ if (!uploadResult?.file_token) {
554
+ throw new Error('上传图片素材失败:无法获取file_token');
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
+ }
511
575
  }
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('图片上传并绑定完成');
517
576
  return {
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
- }],
577
+ content: [{ type: 'text', text: `批量图片上传绑定结果:\n${JSON.stringify(results, null, 2)}` }],
528
578
  };
529
579
  }
530
580
  catch (error) {
531
- Logger.error(`上传图片并绑定到块失败:`, error);
581
+ Logger.error(`批量上传图片并绑定到块失败:`, error);
532
582
  const errorMessage = formatErrorMessage(error);
533
583
  return {
534
- content: [{ type: 'text', text: `上传图片并绑定到块失败: ${errorMessage}` }],
584
+ content: [{ type: 'text', text: `批量上传图片并绑定到块失败: ${errorMessage}` }],
535
585
  };
536
586
  }
537
587
  });
@@ -1,35 +1,39 @@
1
1
  import { formatErrorMessage } from '../../utils/error.js';
2
2
  import { Logger } from '../../utils/logger.js';
3
3
  import { FolderTokenSchema, FolderNameSchema, } from '../../types/feishuSchema.js';
4
+ import { Config } from '../../utils/config';
4
5
  /**
5
6
  * 注册飞书文件夹相关的MCP工具
6
7
  * @param server MCP服务器实例
7
8
  * @param feishuService 飞书API服务实例
8
9
  */
9
10
  export function registerFeishuFolderTools(server, feishuService) {
11
+ const config = Config.getInstance();
10
12
  // 添加获取根文件夹信息工具
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) {
13
+ if (config.feishu.authType === 'user') {
14
+ 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 () => {
15
+ try {
16
+ if (!feishuService) {
17
+ return {
18
+ content: [{ type: 'text', text: '飞书服务未初始化,请检查配置' }],
19
+ };
20
+ }
21
+ Logger.info(`开始获取飞书根文件夹信息`);
22
+ const folderInfo = await feishuService.getRootFolderInfo();
23
+ Logger.info(`飞书根文件夹信息获取成功,token: ${folderInfo.token}`);
14
24
  return {
15
- content: [{ type: 'text', text: '飞书服务未初始化,请检查配置' }],
25
+ content: [{ type: 'text', text: JSON.stringify(folderInfo, null, 2) }],
16
26
  };
17
27
  }
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
- });
28
+ catch (error) {
29
+ Logger.error(`获取飞书根文件夹信息失败:`, error);
30
+ const errorMessage = formatErrorMessage(error, '获取飞书根文件夹信息失败');
31
+ return {
32
+ content: [{ type: 'text', text: errorMessage }],
33
+ };
34
+ }
35
+ });
36
+ }
33
37
  // 添加获取文件夹中的文件清单工具
34
38
  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.', {
35
39
  folderToken: FolderTokenSchema,