@dasaying/feishu-doc-mcp 1.0.0 → 1.1.0
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/index.js +645 -87
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -21,7 +21,7 @@ import { InMemoryTaskMessageQueue, InMemoryTaskStore, isTerminal } from '@modelc
|
|
|
21
21
|
import '@modelcontextprotocol/sdk/server/auth/errors.js';
|
|
22
22
|
import { Hono } from 'hono';
|
|
23
23
|
import { cors } from 'hono/cors';
|
|
24
|
-
import * as
|
|
24
|
+
import * as z18 from 'zod/v4';
|
|
25
25
|
import '@modelcontextprotocol/sdk/shared/auth.js';
|
|
26
26
|
import 'hono/bearer-auth';
|
|
27
27
|
import { ErrorCode, JSONRPCMessageSchema, isInitializeRequest, isJSONRPCRequest, DEFAULT_NEGOTIATED_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, isJSONRPCResultResponse, isJSONRPCErrorResponse } from '@modelcontextprotocol/sdk/types.js';
|
|
@@ -47,7 +47,7 @@ var __decorateParam = (index, decorator) => (target, key) => decorator(target, k
|
|
|
47
47
|
// package.json
|
|
48
48
|
var package_default = {
|
|
49
49
|
name: "@dasaying/feishu-doc-mcp",
|
|
50
|
-
version: "1.
|
|
50
|
+
version: "1.1.0",
|
|
51
51
|
description: "\u98DE\u4E66\u4E91\u6587\u6863 MCP \u670D\u52A1\u5668 - \u652F\u6301 Markdown \u6587\u6863\u4E0A\u4F20\u3001\u8BFB\u53D6\u548C\u6279\u91CF\u64CD\u4F5C\u3002Feishu (Lark) Document MCP Server - Support Markdown upload, read and batch operations."};
|
|
52
52
|
var JsonRpcErrorCode = /* @__PURE__ */ ((JsonRpcErrorCode2) => {
|
|
53
53
|
JsonRpcErrorCode2[JsonRpcErrorCode2["ParseError"] = -32700] = "ParseError";
|
|
@@ -3918,6 +3918,7 @@ var FileSystemProvider = class {
|
|
|
3918
3918
|
}
|
|
3919
3919
|
getTenantPath(tenantId) {
|
|
3920
3920
|
const sanitizedTenantId = sanitization.sanitizePath(tenantId, {
|
|
3921
|
+
rootDir: this.storagePath,
|
|
3921
3922
|
toPosix: true
|
|
3922
3923
|
}).sanitizedPath;
|
|
3923
3924
|
if (sanitizedTenantId.includes("/") || sanitizedTenantId.includes("..")) {
|
|
@@ -6197,7 +6198,7 @@ var FEISHU_CONFIG = {
|
|
|
6197
6198
|
TOKEN_URL: "https://open.feishu.cn/open-apis/authen/v2/oauth/token",
|
|
6198
6199
|
REFRESH_TOKEN_URL: "https://open.feishu.cn/open-apis/authen/v2/oauth/token",
|
|
6199
6200
|
// API 权限范围(包含 offline_access 以支持 refresh_token)
|
|
6200
|
-
SCOPES: "contact:user.base:readonly docx:document wiki:wiki drive:drive offline_access",
|
|
6201
|
+
SCOPES: "contact:user.base:readonly docx:document wiki:wiki drive:drive bitable:app offline_access",
|
|
6201
6202
|
// 文件上传相关(使用素材上传 API,导入后自动删除源文件)
|
|
6202
6203
|
UPLOAD_URL: "https://open.feishu.cn/open-apis/drive/v1/medias/upload_all",
|
|
6203
6204
|
// 文档创建相关
|
|
@@ -6943,12 +6944,14 @@ var FeishuService = class {
|
|
|
6943
6944
|
const content = await this.apiProvider.getDocumentContent(
|
|
6944
6945
|
auth.accessToken,
|
|
6945
6946
|
documentId,
|
|
6946
|
-
options.documentType
|
|
6947
|
+
options.documentType,
|
|
6948
|
+
options.wikiSpaceId
|
|
6947
6949
|
);
|
|
6948
6950
|
const metadata = await this.apiProvider.getDocumentMetadata(
|
|
6949
6951
|
auth.accessToken,
|
|
6950
6952
|
documentId,
|
|
6951
|
-
options.documentType
|
|
6953
|
+
options.documentType,
|
|
6954
|
+
options.wikiSpaceId
|
|
6952
6955
|
);
|
|
6953
6956
|
const conversionResult = this.convertToMarkdown(content, options);
|
|
6954
6957
|
let downloadedImages = 0;
|
|
@@ -6980,7 +6983,7 @@ var FeishuService = class {
|
|
|
6980
6983
|
downloadedImages,
|
|
6981
6984
|
downloadedAttachments
|
|
6982
6985
|
};
|
|
6983
|
-
if (outputFile) result.outputFile = outputFile;
|
|
6986
|
+
if (outputFile !== void 0) result.outputFile = outputFile;
|
|
6984
6987
|
return result;
|
|
6985
6988
|
} catch (error) {
|
|
6986
6989
|
logger.error(
|
|
@@ -7051,6 +7054,157 @@ var FeishuService = class {
|
|
|
7051
7054
|
results
|
|
7052
7055
|
};
|
|
7053
7056
|
}
|
|
7057
|
+
/**
|
|
7058
|
+
* readBitable method 读取多维表格.
|
|
7059
|
+
*/
|
|
7060
|
+
async readBitable(bitableToken, options, context) {
|
|
7061
|
+
logger.info("\u8BFB\u53D6\u591A\u7EF4\u8868\u683C", { ...context, bitableToken, options });
|
|
7062
|
+
try {
|
|
7063
|
+
const finalAppId = options.appId || FEISHU_CONFIG.DEFAULT_APP_ID;
|
|
7064
|
+
if (!finalAppId) {
|
|
7065
|
+
throw new McpError(-32602 /* InvalidParams */, "\u672A\u914D\u7F6E\u5E94\u7528 ID");
|
|
7066
|
+
}
|
|
7067
|
+
const auth = await this.getAuth(finalAppId, context);
|
|
7068
|
+
if (!auth) {
|
|
7069
|
+
throw new McpError(
|
|
7070
|
+
-32602 /* InvalidParams */,
|
|
7071
|
+
"\u672A\u627E\u5230\u6709\u6548\u7684\u8BA4\u8BC1\u4FE1\u606F"
|
|
7072
|
+
);
|
|
7073
|
+
}
|
|
7074
|
+
const validAuth = await this.ensureValidToken(auth, context);
|
|
7075
|
+
const metadata = await this.apiProvider.getBitableMetadata(
|
|
7076
|
+
validAuth.accessToken,
|
|
7077
|
+
bitableToken
|
|
7078
|
+
);
|
|
7079
|
+
const tables = await this.apiProvider.getBitableTables(
|
|
7080
|
+
validAuth.accessToken,
|
|
7081
|
+
bitableToken
|
|
7082
|
+
);
|
|
7083
|
+
const tableResults = [];
|
|
7084
|
+
for (const table of tables) {
|
|
7085
|
+
const fields = await this.apiProvider.getBitableFields(
|
|
7086
|
+
validAuth.accessToken,
|
|
7087
|
+
bitableToken,
|
|
7088
|
+
table.tableId
|
|
7089
|
+
);
|
|
7090
|
+
const allRecords = [];
|
|
7091
|
+
let pageToken;
|
|
7092
|
+
let hasMore = true;
|
|
7093
|
+
while (hasMore) {
|
|
7094
|
+
const recordsResult = await this.apiProvider.getBitableRecords(
|
|
7095
|
+
validAuth.accessToken,
|
|
7096
|
+
bitableToken,
|
|
7097
|
+
table.tableId,
|
|
7098
|
+
100,
|
|
7099
|
+
pageToken
|
|
7100
|
+
);
|
|
7101
|
+
allRecords.push(...recordsResult.records);
|
|
7102
|
+
hasMore = recordsResult.hasMore;
|
|
7103
|
+
pageToken = recordsResult.pageToken;
|
|
7104
|
+
}
|
|
7105
|
+
let markdown2 = "";
|
|
7106
|
+
if (options.outputFormat === "markdown" || !options.outputFormat) {
|
|
7107
|
+
markdown2 = this.convertBitableToMarkdown(
|
|
7108
|
+
table.name,
|
|
7109
|
+
fields,
|
|
7110
|
+
allRecords
|
|
7111
|
+
);
|
|
7112
|
+
}
|
|
7113
|
+
tableResults.push({
|
|
7114
|
+
tableId: table.tableId,
|
|
7115
|
+
name: table.name,
|
|
7116
|
+
markdown: markdown2,
|
|
7117
|
+
records: allRecords
|
|
7118
|
+
});
|
|
7119
|
+
}
|
|
7120
|
+
let fullMarkdown = "";
|
|
7121
|
+
if (options.outputFormat === "markdown" || !options.outputFormat) {
|
|
7122
|
+
fullMarkdown = `# ${metadata.name}
|
|
7123
|
+
|
|
7124
|
+
`;
|
|
7125
|
+
for (const table of tableResults) {
|
|
7126
|
+
fullMarkdown += table.markdown + "\n\n";
|
|
7127
|
+
}
|
|
7128
|
+
}
|
|
7129
|
+
logger.info("\u591A\u7EF4\u8868\u683C\u8BFB\u53D6\u6210\u529F", {
|
|
7130
|
+
...context,
|
|
7131
|
+
bitableToken,
|
|
7132
|
+
name: metadata.name,
|
|
7133
|
+
tableCount: tables.length
|
|
7134
|
+
});
|
|
7135
|
+
return {
|
|
7136
|
+
success: true,
|
|
7137
|
+
bitableToken,
|
|
7138
|
+
name: metadata.name,
|
|
7139
|
+
content: fullMarkdown,
|
|
7140
|
+
tables: tableResults
|
|
7141
|
+
};
|
|
7142
|
+
} catch (error) {
|
|
7143
|
+
logger.error(
|
|
7144
|
+
"\u8BFB\u53D6\u591A\u7EF4\u8868\u683C\u5931\u8D25",
|
|
7145
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
7146
|
+
context
|
|
7147
|
+
);
|
|
7148
|
+
return {
|
|
7149
|
+
success: false,
|
|
7150
|
+
bitableToken,
|
|
7151
|
+
error: error instanceof Error ? error.message : String(error)
|
|
7152
|
+
};
|
|
7153
|
+
}
|
|
7154
|
+
}
|
|
7155
|
+
/**
|
|
7156
|
+
* convertBitableToMarkdown method 将多维表格转换为 Markdown.
|
|
7157
|
+
*/
|
|
7158
|
+
convertBitableToMarkdown(tableName, fields, records) {
|
|
7159
|
+
if (records.length === 0) {
|
|
7160
|
+
return `## ${tableName}
|
|
7161
|
+
|
|
7162
|
+
*\uFF08\u7A7A\u8868\u683C\uFF09*
|
|
7163
|
+
`;
|
|
7164
|
+
}
|
|
7165
|
+
let markdown2 = `## ${tableName}
|
|
7166
|
+
|
|
7167
|
+
`;
|
|
7168
|
+
const headers = fields.map((f) => f.fieldName);
|
|
7169
|
+
markdown2 += "| " + headers.join(" | ") + " |\n";
|
|
7170
|
+
markdown2 += "| " + headers.map(() => "---").join(" | ") + " |\n";
|
|
7171
|
+
for (const record of records) {
|
|
7172
|
+
const row = fields.map((field) => {
|
|
7173
|
+
const value = record.fields[field.fieldName];
|
|
7174
|
+
if (value === null || value === void 0) {
|
|
7175
|
+
return "";
|
|
7176
|
+
}
|
|
7177
|
+
if (Array.isArray(value)) {
|
|
7178
|
+
return value.map((v) => this.formatCellValue(v)).join(", ");
|
|
7179
|
+
}
|
|
7180
|
+
return this.formatCellValue(value);
|
|
7181
|
+
});
|
|
7182
|
+
markdown2 += "| " + row.join(" | ") + " |\n";
|
|
7183
|
+
}
|
|
7184
|
+
return markdown2;
|
|
7185
|
+
}
|
|
7186
|
+
/**
|
|
7187
|
+
* formatCellValue method 格式化单元格值.
|
|
7188
|
+
*/
|
|
7189
|
+
formatCellValue(value) {
|
|
7190
|
+
if (value === null || value === void 0) {
|
|
7191
|
+
return "";
|
|
7192
|
+
}
|
|
7193
|
+
if (typeof value === "object") {
|
|
7194
|
+
if ("text" in value && typeof value.text === "string") {
|
|
7195
|
+
return value.text;
|
|
7196
|
+
}
|
|
7197
|
+
if ("name" in value && typeof value.name === "string") {
|
|
7198
|
+
return value.name;
|
|
7199
|
+
}
|
|
7200
|
+
if ("link" in value && typeof value.link === "string") {
|
|
7201
|
+
return value.link;
|
|
7202
|
+
}
|
|
7203
|
+
return JSON.stringify(value);
|
|
7204
|
+
}
|
|
7205
|
+
const primitiveValue = value;
|
|
7206
|
+
return String(primitiveValue).replace(/\|/g, "\\|").replace(/\n/g, " ");
|
|
7207
|
+
}
|
|
7054
7208
|
/**
|
|
7055
7209
|
* readWikiRecursive method 递归读取知识库.
|
|
7056
7210
|
*/
|
|
@@ -7165,6 +7319,9 @@ var FeishuService = class {
|
|
|
7165
7319
|
async downloadResources(resources, options, accessToken) {
|
|
7166
7320
|
let images = 0;
|
|
7167
7321
|
let attachments = 0;
|
|
7322
|
+
if (!options.downloadImages && !options.downloadAttachments) {
|
|
7323
|
+
return { images, attachments };
|
|
7324
|
+
}
|
|
7168
7325
|
for (const resource of resources) {
|
|
7169
7326
|
if (resource.type === "image" && options.downloadImages) {
|
|
7170
7327
|
const savePath = `${options.assetsPath ?? "./assets"}/${resource.fileToken}`;
|
|
@@ -7917,7 +8074,7 @@ var FeishuApiProvider = class {
|
|
|
7917
8074
|
async createDocument(accessToken, title, content, targetType, targetId, parentNodeToken) {
|
|
7918
8075
|
const ctx = requestContextService.createRequestContext({
|
|
7919
8076
|
operation: "feishu.createDocument",
|
|
7920
|
-
tenantId: "
|
|
8077
|
+
tenantId: "feishu_service"
|
|
7921
8078
|
});
|
|
7922
8079
|
logger.info("\u5F00\u59CB\u521B\u5EFA\u98DE\u4E66\u6587\u6863", {
|
|
7923
8080
|
...ctx,
|
|
@@ -8251,6 +8408,140 @@ var FeishuApiProvider = class {
|
|
|
8251
8408
|
return result;
|
|
8252
8409
|
});
|
|
8253
8410
|
}
|
|
8411
|
+
/**
|
|
8412
|
+
* getBitableMetadata method 获取多维表格元数据.
|
|
8413
|
+
*/
|
|
8414
|
+
async getBitableMetadata(accessToken, bitableToken) {
|
|
8415
|
+
const ctx = requestContextService.createRequestContext({
|
|
8416
|
+
operation: "feishu.getBitableMetadata",
|
|
8417
|
+
tenantId: "feishu_service"
|
|
8418
|
+
});
|
|
8419
|
+
logger.info("\u83B7\u53D6\u591A\u7EF4\u8868\u683C\u5143\u6570\u636E", { ...ctx, bitableToken });
|
|
8420
|
+
try {
|
|
8421
|
+
const url2 = `${FEISHU_CONFIG.BASE_URL}/bitable/v1/apps/${bitableToken}`;
|
|
8422
|
+
const response = await this.requestWithAuth(url2, accessToken, { method: "GET" });
|
|
8423
|
+
if (response.code !== 0 || !response.data) {
|
|
8424
|
+
throw new McpError(
|
|
8425
|
+
-32603 /* InternalError */,
|
|
8426
|
+
response.msg ?? "\u83B7\u53D6\u591A\u7EF4\u8868\u683C\u5143\u6570\u636E\u5931\u8D25"
|
|
8427
|
+
);
|
|
8428
|
+
}
|
|
8429
|
+
return {
|
|
8430
|
+
name: response.data.app.name,
|
|
8431
|
+
revision: response.data.app.revision,
|
|
8432
|
+
isAdvanced: response.data.app.is_advanced
|
|
8433
|
+
};
|
|
8434
|
+
} catch (error) {
|
|
8435
|
+
logger.error("\u83B7\u53D6\u591A\u7EF4\u8868\u683C\u5143\u6570\u636E\u5931\u8D25", error instanceof Error ? error : new Error(String(error)), ctx);
|
|
8436
|
+
throw error instanceof McpError ? error : new McpError(
|
|
8437
|
+
-32603 /* InternalError */,
|
|
8438
|
+
`\u83B7\u53D6\u591A\u7EF4\u8868\u683C\u5143\u6570\u636E\u5931\u8D25: ${String(error)}`
|
|
8439
|
+
);
|
|
8440
|
+
}
|
|
8441
|
+
}
|
|
8442
|
+
/**
|
|
8443
|
+
* getBitableTables method 获取多维表格的所有数据表.
|
|
8444
|
+
*/
|
|
8445
|
+
async getBitableTables(accessToken, bitableToken) {
|
|
8446
|
+
const ctx = requestContextService.createRequestContext({
|
|
8447
|
+
operation: "feishu.getBitableTables",
|
|
8448
|
+
tenantId: "feishu_service"
|
|
8449
|
+
});
|
|
8450
|
+
logger.info("\u83B7\u53D6\u591A\u7EF4\u8868\u683C\u6570\u636E\u8868\u5217\u8868", { ...ctx, bitableToken });
|
|
8451
|
+
try {
|
|
8452
|
+
const url2 = `${FEISHU_CONFIG.BASE_URL}/bitable/v1/apps/${bitableToken}/tables?page_size=100`;
|
|
8453
|
+
const response = await this.requestWithAuth(url2, accessToken, { method: "GET" });
|
|
8454
|
+
if (response.code !== 0 || !response.data) {
|
|
8455
|
+
throw new McpError(
|
|
8456
|
+
-32603 /* InternalError */,
|
|
8457
|
+
response.msg ?? "\u83B7\u53D6\u6570\u636E\u8868\u5217\u8868\u5931\u8D25"
|
|
8458
|
+
);
|
|
8459
|
+
}
|
|
8460
|
+
return response.data.items.map((table) => ({
|
|
8461
|
+
tableId: table.table_id,
|
|
8462
|
+
name: table.name,
|
|
8463
|
+
revision: table.revision
|
|
8464
|
+
}));
|
|
8465
|
+
} catch (error) {
|
|
8466
|
+
logger.error("\u83B7\u53D6\u6570\u636E\u8868\u5217\u8868\u5931\u8D25", error instanceof Error ? error : new Error(String(error)), ctx);
|
|
8467
|
+
throw error instanceof McpError ? error : new McpError(
|
|
8468
|
+
-32603 /* InternalError */,
|
|
8469
|
+
`\u83B7\u53D6\u6570\u636E\u8868\u5217\u8868\u5931\u8D25: ${String(error)}`
|
|
8470
|
+
);
|
|
8471
|
+
}
|
|
8472
|
+
}
|
|
8473
|
+
/**
|
|
8474
|
+
* getBitableFields method 获取数据表的字段信息.
|
|
8475
|
+
*/
|
|
8476
|
+
async getBitableFields(accessToken, bitableToken, tableId) {
|
|
8477
|
+
const ctx = requestContextService.createRequestContext({
|
|
8478
|
+
operation: "feishu.getBitableFields",
|
|
8479
|
+
tenantId: "feishu_service"
|
|
8480
|
+
});
|
|
8481
|
+
logger.info("\u83B7\u53D6\u6570\u636E\u8868\u5B57\u6BB5", { ...ctx, bitableToken, tableId });
|
|
8482
|
+
try {
|
|
8483
|
+
const url2 = `${FEISHU_CONFIG.BASE_URL}/bitable/v1/apps/${bitableToken}/tables/${tableId}/fields?page_size=100`;
|
|
8484
|
+
const response = await this.requestWithAuth(url2, accessToken, { method: "GET" });
|
|
8485
|
+
if (response.code !== 0 || !response.data) {
|
|
8486
|
+
throw new McpError(
|
|
8487
|
+
-32603 /* InternalError */,
|
|
8488
|
+
response.msg ?? "\u83B7\u53D6\u5B57\u6BB5\u4FE1\u606F\u5931\u8D25"
|
|
8489
|
+
);
|
|
8490
|
+
}
|
|
8491
|
+
return response.data.items.map((field) => ({
|
|
8492
|
+
fieldId: field.field_id,
|
|
8493
|
+
fieldName: field.field_name,
|
|
8494
|
+
type: field.type,
|
|
8495
|
+
property: field.property
|
|
8496
|
+
}));
|
|
8497
|
+
} catch (error) {
|
|
8498
|
+
logger.error("\u83B7\u53D6\u5B57\u6BB5\u4FE1\u606F\u5931\u8D25", error instanceof Error ? error : new Error(String(error)), ctx);
|
|
8499
|
+
throw error instanceof McpError ? error : new McpError(
|
|
8500
|
+
-32603 /* InternalError */,
|
|
8501
|
+
`\u83B7\u53D6\u5B57\u6BB5\u4FE1\u606F\u5931\u8D25: ${String(error)}`
|
|
8502
|
+
);
|
|
8503
|
+
}
|
|
8504
|
+
}
|
|
8505
|
+
/**
|
|
8506
|
+
* getBitableRecords method 获取数据表的记录.
|
|
8507
|
+
*/
|
|
8508
|
+
async getBitableRecords(accessToken, bitableToken, tableId, pageSize = 100, pageToken) {
|
|
8509
|
+
const ctx = requestContextService.createRequestContext({
|
|
8510
|
+
operation: "feishu.getBitableRecords",
|
|
8511
|
+
tenantId: "feishu_service"
|
|
8512
|
+
});
|
|
8513
|
+
logger.info("\u83B7\u53D6\u6570\u636E\u8868\u8BB0\u5F55", { ...ctx, bitableToken, tableId, pageSize });
|
|
8514
|
+
try {
|
|
8515
|
+
let url2 = `${FEISHU_CONFIG.BASE_URL}/bitable/v1/apps/${bitableToken}/tables/${tableId}/records?page_size=${pageSize}`;
|
|
8516
|
+
if (pageToken) {
|
|
8517
|
+
url2 += `&page_token=${pageToken}`;
|
|
8518
|
+
}
|
|
8519
|
+
const response = await this.requestWithAuth(url2, accessToken, { method: "GET" });
|
|
8520
|
+
if (response.code !== 0 || !response.data) {
|
|
8521
|
+
throw new McpError(
|
|
8522
|
+
-32603 /* InternalError */,
|
|
8523
|
+
response.msg ?? "\u83B7\u53D6\u8BB0\u5F55\u5931\u8D25"
|
|
8524
|
+
);
|
|
8525
|
+
}
|
|
8526
|
+
const result = {
|
|
8527
|
+
records: response.data.items.map((record) => ({
|
|
8528
|
+
recordId: record.record_id,
|
|
8529
|
+
fields: record.fields
|
|
8530
|
+
})),
|
|
8531
|
+
hasMore: response.data.has_more
|
|
8532
|
+
};
|
|
8533
|
+
if (response.data.page_token) {
|
|
8534
|
+
result.pageToken = response.data.page_token;
|
|
8535
|
+
}
|
|
8536
|
+
return result;
|
|
8537
|
+
} catch (error) {
|
|
8538
|
+
logger.error("\u83B7\u53D6\u8BB0\u5F55\u5931\u8D25", error instanceof Error ? error : new Error(String(error)), ctx);
|
|
8539
|
+
throw error instanceof McpError ? error : new McpError(
|
|
8540
|
+
-32603 /* InternalError */,
|
|
8541
|
+
`\u83B7\u53D6\u8BB0\u5F55\u5931\u8D25: ${String(error)}`
|
|
8542
|
+
);
|
|
8543
|
+
}
|
|
8544
|
+
}
|
|
8254
8545
|
/**
|
|
8255
8546
|
* healthCheck method 健康检查.
|
|
8256
8547
|
*/
|
|
@@ -8402,7 +8693,7 @@ var FeishuApiProvider = class {
|
|
|
8402
8693
|
async uploadMarkdownFile(accessToken, fileName, content) {
|
|
8403
8694
|
const ctx = requestContextService.createRequestContext({
|
|
8404
8695
|
operation: "feishu.uploadMarkdownFile",
|
|
8405
|
-
tenantId: "
|
|
8696
|
+
tenantId: "feishu_service"
|
|
8406
8697
|
});
|
|
8407
8698
|
try {
|
|
8408
8699
|
logger.debug("\u5F00\u59CB\u4E0A\u4F20Markdown\u6587\u4EF6", {
|
|
@@ -8510,7 +8801,7 @@ var FeishuApiProvider = class {
|
|
|
8510
8801
|
async createImportTask(accessToken, fileToken, title, targetFolderId) {
|
|
8511
8802
|
const ctx = requestContextService.createRequestContext({
|
|
8512
8803
|
operation: "feishu.createImportTask",
|
|
8513
|
-
tenantId: "
|
|
8804
|
+
tenantId: "feishu_service"
|
|
8514
8805
|
});
|
|
8515
8806
|
try {
|
|
8516
8807
|
const url2 = `${FEISHU_CONFIG.BASE_URL}/drive/v1/import_tasks`;
|
|
@@ -8590,7 +8881,7 @@ var FeishuApiProvider = class {
|
|
|
8590
8881
|
const maxAttempts = 30;
|
|
8591
8882
|
const ctx = requestContextService.createRequestContext({
|
|
8592
8883
|
operation: "feishu.waitForImportCompletion",
|
|
8593
|
-
tenantId: "
|
|
8884
|
+
tenantId: "feishu_service"
|
|
8594
8885
|
});
|
|
8595
8886
|
logger.info("\u5F00\u59CB\u7B49\u5F85\u5BFC\u5165\u4EFB\u52A1\u5B8C\u6210", {
|
|
8596
8887
|
...ctx,
|
|
@@ -8773,18 +9064,18 @@ var FeishuApiProvider = class {
|
|
|
8773
9064
|
/**
|
|
8774
9065
|
* getDocumentContent method 获取文档内容.
|
|
8775
9066
|
*/
|
|
8776
|
-
async getDocumentContent(accessToken, documentId, documentType) {
|
|
9067
|
+
async getDocumentContent(accessToken, documentId, documentType, wikiSpaceId) {
|
|
8777
9068
|
const ctx = requestContextService.createRequestContext({
|
|
8778
9069
|
operation: "feishu.getDocumentContent",
|
|
8779
|
-
tenantId: "
|
|
9070
|
+
tenantId: "feishu_service"
|
|
8780
9071
|
});
|
|
8781
|
-
logger.info("\u83B7\u53D6\u6587\u6863\u5185\u5BB9", { ...ctx, documentId, documentType });
|
|
9072
|
+
logger.info("\u83B7\u53D6\u6587\u6863\u5185\u5BB9", { ...ctx, documentId, documentType, wikiSpaceId });
|
|
8782
9073
|
try {
|
|
8783
9074
|
let url2;
|
|
8784
9075
|
if (documentType === "drive") {
|
|
8785
9076
|
url2 = `${FEISHU_CONFIG.BASE_URL}/docx/v1/documents/${documentId}/blocks`;
|
|
8786
9077
|
} else {
|
|
8787
|
-
url2 = `${FEISHU_CONFIG.BASE_URL}/
|
|
9078
|
+
url2 = `${FEISHU_CONFIG.BASE_URL}/docx/v1/documents/${documentId}/blocks`;
|
|
8788
9079
|
}
|
|
8789
9080
|
const response = await this.requestWithAuth(url2, accessToken, { method: "GET" });
|
|
8790
9081
|
if (response.code !== 0 || !response.data) {
|
|
@@ -8794,6 +9085,16 @@ var FeishuApiProvider = class {
|
|
|
8794
9085
|
);
|
|
8795
9086
|
}
|
|
8796
9087
|
const blocks = response.data.blocks ?? response.data.items ?? [];
|
|
9088
|
+
logger.debug("\u98DE\u4E66 API \u8FD4\u56DE\u7684 blocks \u6570\u636E", {
|
|
9089
|
+
...ctx,
|
|
9090
|
+
blockCount: blocks.length,
|
|
9091
|
+
sampleBlocks: blocks.slice(0, 5).map((b) => ({
|
|
9092
|
+
block_id: b.block_id,
|
|
9093
|
+
block_type: b.block_type,
|
|
9094
|
+
keys: Object.keys(b),
|
|
9095
|
+
data: JSON.stringify(b).substring(0, 500)
|
|
9096
|
+
}))
|
|
9097
|
+
});
|
|
8797
9098
|
return {
|
|
8798
9099
|
documentId,
|
|
8799
9100
|
title: "",
|
|
@@ -8820,19 +9121,14 @@ var FeishuApiProvider = class {
|
|
|
8820
9121
|
/**
|
|
8821
9122
|
* getDocumentMetadata method 获取文档元数据.
|
|
8822
9123
|
*/
|
|
8823
|
-
async getDocumentMetadata(accessToken, documentId, documentType) {
|
|
9124
|
+
async getDocumentMetadata(accessToken, documentId, documentType, wikiSpaceId) {
|
|
8824
9125
|
const ctx = requestContextService.createRequestContext({
|
|
8825
9126
|
operation: "feishu.getDocumentMetadata",
|
|
8826
|
-
tenantId: "
|
|
9127
|
+
tenantId: "feishu_service"
|
|
8827
9128
|
});
|
|
8828
|
-
logger.info("\u83B7\u53D6\u6587\u6863\u5143\u6570\u636E", { ...ctx, documentId, documentType });
|
|
9129
|
+
logger.info("\u83B7\u53D6\u6587\u6863\u5143\u6570\u636E", { ...ctx, documentId, documentType, wikiSpaceId });
|
|
8829
9130
|
try {
|
|
8830
|
-
|
|
8831
|
-
if (documentType === "drive") {
|
|
8832
|
-
url2 = `${FEISHU_CONFIG.BASE_URL}/docx/v1/documents/${documentId}`;
|
|
8833
|
-
} else {
|
|
8834
|
-
url2 = `${FEISHU_CONFIG.BASE_URL}/wiki/v2/spaces/${documentId}`;
|
|
8835
|
-
}
|
|
9131
|
+
const url2 = `${FEISHU_CONFIG.BASE_URL}/docx/v1/documents/${documentId}`;
|
|
8836
9132
|
const response = await this.requestWithAuth(url2, accessToken, { method: "GET" });
|
|
8837
9133
|
if (response.code !== 0 || !response.data) {
|
|
8838
9134
|
throw new McpError(
|
|
@@ -8873,7 +9169,7 @@ var FeishuApiProvider = class {
|
|
|
8873
9169
|
async downloadFile(accessToken, fileToken, savePath) {
|
|
8874
9170
|
const ctx = requestContextService.createRequestContext({
|
|
8875
9171
|
operation: "feishu.downloadFile",
|
|
8876
|
-
tenantId: "
|
|
9172
|
+
tenantId: "feishu_service"
|
|
8877
9173
|
});
|
|
8878
9174
|
logger.info("\u4E0B\u8F7D\u6587\u4EF6", { ...ctx, fileToken, savePath });
|
|
8879
9175
|
try {
|
|
@@ -9103,7 +9399,7 @@ var ContentConverterProvider = class {
|
|
|
9103
9399
|
convert(content, _options) {
|
|
9104
9400
|
const ctx = requestContextService.createRequestContext({
|
|
9105
9401
|
operation: "contentConverter.convert",
|
|
9106
|
-
tenantId: "
|
|
9402
|
+
tenantId: "feishu_service"
|
|
9107
9403
|
});
|
|
9108
9404
|
logger.info("\u5F00\u59CB\u8F6C\u6362\u6587\u6863\u5185\u5BB9", {
|
|
9109
9405
|
...ctx,
|
|
@@ -9188,6 +9484,13 @@ var ContentConverterProvider = class {
|
|
|
9188
9484
|
const block = blockMap.get(blockId);
|
|
9189
9485
|
if (!block) return "";
|
|
9190
9486
|
const result = [];
|
|
9487
|
+
if (block.blockType === "table") {
|
|
9488
|
+
const tableMarkdown = this.convertTableWithCells(block, blockMap);
|
|
9489
|
+
if (tableMarkdown) {
|
|
9490
|
+
result.push(tableMarkdown);
|
|
9491
|
+
}
|
|
9492
|
+
return result.join("\n\n");
|
|
9493
|
+
}
|
|
9191
9494
|
const markdown2 = this.convertBlock(block, depth);
|
|
9192
9495
|
if (markdown2) {
|
|
9193
9496
|
result.push(markdown2);
|
|
@@ -9247,12 +9550,14 @@ var ContentConverterProvider = class {
|
|
|
9247
9550
|
return this.convertFileBlock(block);
|
|
9248
9551
|
case "table":
|
|
9249
9552
|
return this.convertTableBlock(block);
|
|
9553
|
+
case "table_cell":
|
|
9554
|
+
return this.convertTableCellBlock(block);
|
|
9250
9555
|
case "page":
|
|
9251
9556
|
return "";
|
|
9252
9557
|
default:
|
|
9253
9558
|
const ctx = requestContextService.createRequestContext({
|
|
9254
9559
|
operation: "contentConverter.convertBlock",
|
|
9255
|
-
tenantId: "
|
|
9560
|
+
tenantId: "feishu_service"
|
|
9256
9561
|
});
|
|
9257
9562
|
logger.warning("\u4E0D\u652F\u6301\u7684\u5757\u7C7B\u578B", {
|
|
9258
9563
|
...ctx,
|
|
@@ -9266,18 +9571,78 @@ var ContentConverterProvider = class {
|
|
|
9266
9571
|
* extractText method 提取块中的文本内容.
|
|
9267
9572
|
*/
|
|
9268
9573
|
extractText(block) {
|
|
9269
|
-
if (!block.content
|
|
9270
|
-
|
|
9271
|
-
|
|
9272
|
-
|
|
9273
|
-
|
|
9274
|
-
|
|
9275
|
-
|
|
9276
|
-
|
|
9277
|
-
|
|
9278
|
-
|
|
9279
|
-
|
|
9280
|
-
}
|
|
9574
|
+
if (!block.content) return "";
|
|
9575
|
+
const blockContent = block.content;
|
|
9576
|
+
let elements;
|
|
9577
|
+
if (blockContent.page && typeof blockContent.page === "object") {
|
|
9578
|
+
elements = blockContent.page.elements;
|
|
9579
|
+
} else if (blockContent.heading1 && typeof blockContent.heading1 === "object") {
|
|
9580
|
+
elements = blockContent.heading1.elements;
|
|
9581
|
+
} else if (blockContent.heading2 && typeof blockContent.heading2 === "object") {
|
|
9582
|
+
elements = blockContent.heading2.elements;
|
|
9583
|
+
} else if (blockContent.heading3 && typeof blockContent.heading3 === "object") {
|
|
9584
|
+
elements = blockContent.heading3.elements;
|
|
9585
|
+
} else if (blockContent.heading4 && typeof blockContent.heading4 === "object") {
|
|
9586
|
+
elements = blockContent.heading4.elements;
|
|
9587
|
+
} else if (blockContent.heading5 && typeof blockContent.heading5 === "object") {
|
|
9588
|
+
elements = blockContent.heading5.elements;
|
|
9589
|
+
} else if (blockContent.heading6 && typeof blockContent.heading6 === "object") {
|
|
9590
|
+
elements = blockContent.heading6.elements;
|
|
9591
|
+
} else if (blockContent.heading7 && typeof blockContent.heading7 === "object") {
|
|
9592
|
+
elements = blockContent.heading7.elements;
|
|
9593
|
+
} else if (blockContent.heading8 && typeof blockContent.heading8 === "object") {
|
|
9594
|
+
elements = blockContent.heading8.elements;
|
|
9595
|
+
} else if (blockContent.heading9 && typeof blockContent.heading9 === "object") {
|
|
9596
|
+
elements = blockContent.heading9.elements;
|
|
9597
|
+
} else if (blockContent.text && typeof blockContent.text === "object") {
|
|
9598
|
+
elements = blockContent.text.elements;
|
|
9599
|
+
} else if (blockContent.bullet && typeof blockContent.bullet === "object") {
|
|
9600
|
+
elements = blockContent.bullet.elements;
|
|
9601
|
+
} else if (blockContent.ordered && typeof blockContent.ordered === "object") {
|
|
9602
|
+
elements = blockContent.ordered.elements;
|
|
9603
|
+
} else if (blockContent.code && typeof blockContent.code === "object") {
|
|
9604
|
+
elements = blockContent.code.elements;
|
|
9605
|
+
} else if (blockContent.quote && typeof blockContent.quote === "object") {
|
|
9606
|
+
elements = blockContent.quote.elements;
|
|
9607
|
+
} else if (blockContent.todo && typeof blockContent.todo === "object") {
|
|
9608
|
+
elements = blockContent.todo.elements;
|
|
9609
|
+
} else if (blockContent.callout && typeof blockContent.callout === "object") {
|
|
9610
|
+
elements = blockContent.callout.elements;
|
|
9611
|
+
} else if (blockContent.elements && Array.isArray(blockContent.elements)) {
|
|
9612
|
+
elements = blockContent.elements;
|
|
9613
|
+
}
|
|
9614
|
+
if (elements && Array.isArray(elements)) {
|
|
9615
|
+
return elements.map((element) => {
|
|
9616
|
+
if (!element.text_run?.content) return "";
|
|
9617
|
+
let text = element.text_run.content;
|
|
9618
|
+
const style = element.text_run.text_element_style;
|
|
9619
|
+
if (style) {
|
|
9620
|
+
if (style.bold) text = `**${text}**`;
|
|
9621
|
+
if (style.italic) text = `*${text}*`;
|
|
9622
|
+
if (style.strikethrough) text = `~~${text}~~`;
|
|
9623
|
+
if (style.inline_code) text = `\`${text}\``;
|
|
9624
|
+
if (style.link?.url) text = `[${text}](${style.link.url})`;
|
|
9625
|
+
}
|
|
9626
|
+
return text;
|
|
9627
|
+
}).join("");
|
|
9628
|
+
}
|
|
9629
|
+
if (blockContent.text && Array.isArray(blockContent.text)) {
|
|
9630
|
+
return blockContent.text.map((run2) => {
|
|
9631
|
+
let text = run2.text;
|
|
9632
|
+
if (run2.style) {
|
|
9633
|
+
if (run2.style.bold) text = `**${text}**`;
|
|
9634
|
+
if (run2.style.italic) text = `*${text}*`;
|
|
9635
|
+
if (run2.style.strikethrough) text = `~~${text}~~`;
|
|
9636
|
+
if (run2.style.inlineCode) text = `\`${text}\``;
|
|
9637
|
+
if (run2.style.link) text = `[${text}](${run2.style.link.url})`;
|
|
9638
|
+
}
|
|
9639
|
+
return text;
|
|
9640
|
+
}).join("");
|
|
9641
|
+
}
|
|
9642
|
+
if (typeof blockContent.text === "string") {
|
|
9643
|
+
return blockContent.text;
|
|
9644
|
+
}
|
|
9645
|
+
return "";
|
|
9281
9646
|
}
|
|
9282
9647
|
/**
|
|
9283
9648
|
* convertCodeBlock method 转换代码块.
|
|
@@ -9328,13 +9693,74 @@ ${text}
|
|
|
9328
9693
|
/**
|
|
9329
9694
|
* convertTableBlock method 转换表格块.
|
|
9330
9695
|
*/
|
|
9331
|
-
convertTableBlock(
|
|
9332
|
-
|
|
9333
|
-
|
|
9334
|
-
|
|
9335
|
-
|
|
9336
|
-
|
|
9337
|
-
|
|
9696
|
+
convertTableBlock(_block) {
|
|
9697
|
+
return "";
|
|
9698
|
+
}
|
|
9699
|
+
/**
|
|
9700
|
+
* convertTableCellBlock method 转换表格单元格块.
|
|
9701
|
+
*/
|
|
9702
|
+
convertTableCellBlock(block) {
|
|
9703
|
+
return this.extractText(block);
|
|
9704
|
+
}
|
|
9705
|
+
/**
|
|
9706
|
+
* convertTableWithCells method 转换表格及其所有单元格.
|
|
9707
|
+
*/
|
|
9708
|
+
convertTableWithCells(tableBlock, blockMap) {
|
|
9709
|
+
if (!tableBlock.children || tableBlock.children.length === 0) {
|
|
9710
|
+
return "<!-- Empty table -->";
|
|
9711
|
+
}
|
|
9712
|
+
const tableContent = tableBlock.content;
|
|
9713
|
+
const rowSize = tableContent?.table?.property?.row_size ?? 0;
|
|
9714
|
+
const columnSize = tableContent?.table?.property?.column_size ?? 0;
|
|
9715
|
+
if (rowSize === 0 || columnSize === 0) {
|
|
9716
|
+
return "<!-- Invalid table -->";
|
|
9717
|
+
}
|
|
9718
|
+
const rows = [];
|
|
9719
|
+
for (let i = 0; i < rowSize; i++) {
|
|
9720
|
+
rows.push(new Array(columnSize).fill(""));
|
|
9721
|
+
}
|
|
9722
|
+
let cellIndex = 0;
|
|
9723
|
+
for (const cellId of tableBlock.children) {
|
|
9724
|
+
const cell = blockMap.get(cellId);
|
|
9725
|
+
if (!cell || cell.blockType !== "table_cell") continue;
|
|
9726
|
+
const rowIndex = Math.floor(cellIndex / columnSize);
|
|
9727
|
+
const columnIndex = cellIndex % columnSize;
|
|
9728
|
+
cellIndex++;
|
|
9729
|
+
if (rowIndex < rowSize && columnIndex < columnSize) {
|
|
9730
|
+
let cellText = "";
|
|
9731
|
+
if (cell.children && cell.children.length > 0) {
|
|
9732
|
+
const childTexts = [];
|
|
9733
|
+
for (const childId of cell.children) {
|
|
9734
|
+
const childBlock = blockMap.get(childId);
|
|
9735
|
+
if (childBlock) {
|
|
9736
|
+
const text = this.extractText(childBlock);
|
|
9737
|
+
if (text) {
|
|
9738
|
+
childTexts.push(text);
|
|
9739
|
+
}
|
|
9740
|
+
}
|
|
9741
|
+
}
|
|
9742
|
+
cellText = childTexts.join(" ");
|
|
9743
|
+
} else {
|
|
9744
|
+
cellText = this.extractText(cell);
|
|
9745
|
+
}
|
|
9746
|
+
if (rows[rowIndex] && columnIndex < columnSize) {
|
|
9747
|
+
rows[rowIndex][columnIndex] = cellText;
|
|
9748
|
+
}
|
|
9749
|
+
}
|
|
9750
|
+
}
|
|
9751
|
+
const lines = [];
|
|
9752
|
+
if (rows.length === 0 || !rows[0]) {
|
|
9753
|
+
return "<!-- Empty table -->";
|
|
9754
|
+
}
|
|
9755
|
+
lines.push("| " + rows[0].join(" | ") + " |");
|
|
9756
|
+
lines.push("| " + rows[0].map(() => "---").join(" | ") + " |");
|
|
9757
|
+
for (let i = 1; i < rows.length; i++) {
|
|
9758
|
+
const row = rows[i];
|
|
9759
|
+
if (row) {
|
|
9760
|
+
lines.push("| " + row.join(" | ") + " |");
|
|
9761
|
+
}
|
|
9762
|
+
}
|
|
9763
|
+
return lines.join("\n");
|
|
9338
9764
|
}
|
|
9339
9765
|
};
|
|
9340
9766
|
ContentConverterProvider = __decorateClass([
|
|
@@ -9522,9 +9948,9 @@ ResourceRegistry = __decorateClass([
|
|
|
9522
9948
|
injectable(),
|
|
9523
9949
|
__decorateParam(0, injectAll(ResourceDefinitions, { isOptional: true }))
|
|
9524
9950
|
], ResourceRegistry);
|
|
9525
|
-
var registerResources = (
|
|
9951
|
+
var registerResources = (container26) => {
|
|
9526
9952
|
for (const resource of allResourceDefinitions) {
|
|
9527
|
-
|
|
9953
|
+
container26.register(ResourceDefinitions, { useValue: resource });
|
|
9528
9954
|
}
|
|
9529
9955
|
};
|
|
9530
9956
|
|
|
@@ -9759,7 +10185,7 @@ async function authCallbackLogic(input, appContext, _sdkContext) {
|
|
|
9759
10185
|
try {
|
|
9760
10186
|
const context = requestContextService.createRequestContext({
|
|
9761
10187
|
operation: "feishu.handleAuthCallback",
|
|
9762
|
-
tenantId: "
|
|
10188
|
+
tenantId: "feishu_service"
|
|
9763
10189
|
});
|
|
9764
10190
|
const result = await feishuService.handleAuthCallback(
|
|
9765
10191
|
input.code,
|
|
@@ -9907,7 +10333,7 @@ async function uploadLogic(input, appContext, _sdkContext) {
|
|
|
9907
10333
|
});
|
|
9908
10334
|
const context = requestContextService.createRequestContext({
|
|
9909
10335
|
operation: "feishu.uploadMarkdown",
|
|
9910
|
-
tenantId: "
|
|
10336
|
+
tenantId: "feishu_service"
|
|
9911
10337
|
});
|
|
9912
10338
|
let content;
|
|
9913
10339
|
let documentTitle = input.title;
|
|
@@ -10073,7 +10499,7 @@ async function updateLogic(input, appContext, _sdkContext) {
|
|
|
10073
10499
|
});
|
|
10074
10500
|
const context = requestContextService.createRequestContext({
|
|
10075
10501
|
operation: "feishu.updateDocument",
|
|
10076
|
-
tenantId: "
|
|
10502
|
+
tenantId: "feishu_service"
|
|
10077
10503
|
});
|
|
10078
10504
|
let content;
|
|
10079
10505
|
let workingDirectory = input.workingDirectory;
|
|
@@ -10215,7 +10641,7 @@ async function listFoldersLogic(input, appContext, _sdkContext) {
|
|
|
10215
10641
|
);
|
|
10216
10642
|
const ctx = requestContextService.createRequestContext({
|
|
10217
10643
|
operation: "feishu.listFolders",
|
|
10218
|
-
tenantId: "
|
|
10644
|
+
tenantId: "feishu_service"
|
|
10219
10645
|
});
|
|
10220
10646
|
try {
|
|
10221
10647
|
const folders = await feishuService.listFolders(
|
|
@@ -10311,7 +10737,7 @@ async function listWikisLogic(input, appContext, _sdkContext) {
|
|
|
10311
10737
|
);
|
|
10312
10738
|
const ctx = requestContextService.createRequestContext({
|
|
10313
10739
|
operation: "feishu.listWikis",
|
|
10314
|
-
tenantId: "
|
|
10740
|
+
tenantId: "feishu_service"
|
|
10315
10741
|
});
|
|
10316
10742
|
try {
|
|
10317
10743
|
const wikis = await feishuService.listWikis(ctx, input.appId);
|
|
@@ -10430,7 +10856,7 @@ async function listWikiNodesLogic(input, appContext, _sdkContext) {
|
|
|
10430
10856
|
);
|
|
10431
10857
|
const ctx = requestContextService.createRequestContext({
|
|
10432
10858
|
operation: "feishu.listWikiNodes",
|
|
10433
|
-
tenantId: "
|
|
10859
|
+
tenantId: "feishu_service"
|
|
10434
10860
|
});
|
|
10435
10861
|
const nodes = await feishuService.getWikiNodes(
|
|
10436
10862
|
ctx,
|
|
@@ -10518,7 +10944,7 @@ async function getUserInfoLogic(input, appContext, _sdkContext) {
|
|
|
10518
10944
|
const storage = container.resolve(StorageService);
|
|
10519
10945
|
const ctx = requestContextService.createRequestContext({
|
|
10520
10946
|
operation: "feishu.getUserInfo",
|
|
10521
|
-
tenantId: "
|
|
10947
|
+
tenantId: "feishu_service"
|
|
10522
10948
|
});
|
|
10523
10949
|
const appId = input.appId || "cli_a9e211f948381bdf";
|
|
10524
10950
|
const auth = await storage.get(`feishu/auth/${appId}`, ctx);
|
|
@@ -10592,7 +11018,7 @@ async function setDefaultAppLogic(input, appContext, _sdkContext) {
|
|
|
10592
11018
|
const storage = container.resolve(StorageService);
|
|
10593
11019
|
const ctx = requestContextService.createRequestContext({
|
|
10594
11020
|
operation: "feishu.setDefaultApp",
|
|
10595
|
-
tenantId: "
|
|
11021
|
+
tenantId: "feishu_service"
|
|
10596
11022
|
});
|
|
10597
11023
|
const auth = await storage.get(
|
|
10598
11024
|
`feishu/auth/${input.appId}`,
|
|
@@ -10676,7 +11102,7 @@ async function listAppsLogic(_input, appContext, _sdkContext) {
|
|
|
10676
11102
|
const storage = container.resolve(StorageService);
|
|
10677
11103
|
const ctx = requestContextService.createRequestContext({
|
|
10678
11104
|
operation: "feishu.listApps",
|
|
10679
|
-
tenantId: "
|
|
11105
|
+
tenantId: "feishu_service"
|
|
10680
11106
|
});
|
|
10681
11107
|
const defaultAppId = await storage.get(
|
|
10682
11108
|
"feishu/config/default_app",
|
|
@@ -10871,7 +11297,7 @@ async function batchUploadLogic(input, appContext, _sdkContext) {
|
|
|
10871
11297
|
);
|
|
10872
11298
|
const context = requestContextService.createRequestContext({
|
|
10873
11299
|
operation: "feishu.batchUploadMarkdown",
|
|
10874
|
-
tenantId: "
|
|
11300
|
+
tenantId: "feishu_service"
|
|
10875
11301
|
});
|
|
10876
11302
|
const baseWorkingDirectory = input.workingDirectory || process.cwd();
|
|
10877
11303
|
const uploadDocument = async (doc, index) => {
|
|
@@ -11090,7 +11516,7 @@ async function readLogic(input, appContext, _sdkContext) {
|
|
|
11090
11516
|
});
|
|
11091
11517
|
const context = requestContextService.createRequestContext({
|
|
11092
11518
|
operation: "feishu.readDocument",
|
|
11093
|
-
tenantId: "
|
|
11519
|
+
tenantId: "feishu_service"
|
|
11094
11520
|
});
|
|
11095
11521
|
if (input.documentType === "wiki" && !input.wikiSpaceId) {
|
|
11096
11522
|
throw new McpError(
|
|
@@ -11270,7 +11696,7 @@ async function batchReadLogic(input, appContext, _sdkContext) {
|
|
|
11270
11696
|
});
|
|
11271
11697
|
const context = requestContextService.createRequestContext({
|
|
11272
11698
|
operation: "feishu.batchReadDocuments",
|
|
11273
|
-
tenantId: "
|
|
11699
|
+
tenantId: "feishu_service"
|
|
11274
11700
|
});
|
|
11275
11701
|
const feishuService = container.resolve(
|
|
11276
11702
|
FeishuServiceToken
|
|
@@ -11413,7 +11839,7 @@ async function recursiveReadLogic(input, appContext, _sdkContext) {
|
|
|
11413
11839
|
});
|
|
11414
11840
|
const context = requestContextService.createRequestContext({
|
|
11415
11841
|
operation: "feishu.readWikiRecursive",
|
|
11416
|
-
tenantId: "
|
|
11842
|
+
tenantId: "feishu_service"
|
|
11417
11843
|
});
|
|
11418
11844
|
const feishuService = container.resolve(
|
|
11419
11845
|
FeishuServiceToken
|
|
@@ -11502,6 +11928,136 @@ var feishuReadWikiRecursiveTool = {
|
|
|
11502
11928
|
logic: withToolAuth(["tool:feishu:read"], recursiveReadLogic),
|
|
11503
11929
|
responseFormatter: responseFormatter14
|
|
11504
11930
|
};
|
|
11931
|
+
var TOOL_NAME15 = "feishu_read_bitable";
|
|
11932
|
+
var TOOL_TITLE15 = "\u8BFB\u53D6\u98DE\u4E66\u591A\u7EF4\u8868\u683C";
|
|
11933
|
+
var TOOL_DESCRIPTION15 = `\u8BFB\u53D6\u98DE\u4E66\u591A\u7EF4\u8868\u683C\uFF08Bitable\uFF09\uFF0C\u5E76\u8F6C\u6362\u4E3A Markdown \u683C\u5F0F\u3002
|
|
11934
|
+
|
|
11935
|
+
\u591A\u7EF4\u8868\u683C\u662F\u98DE\u4E66\u7684\u4E00\u79CD\u6570\u636E\u7BA1\u7406\u5DE5\u5177\uFF0C\u7C7B\u4F3C\u4E8E\u7535\u5B50\u8868\u683C\uFF0C\u4F46\u529F\u80FD\u66F4\u5F3A\u5927\u3002
|
|
11936
|
+
|
|
11937
|
+
\u529F\u80FD\u7279\u6027\uFF1A
|
|
11938
|
+
- \u8BFB\u53D6\u591A\u7EF4\u8868\u683C\u7684\u6240\u6709\u6570\u636E\u8868\uFF08Sheet\uFF09
|
|
11939
|
+
- \u81EA\u52A8\u8F6C\u6362\u4E3A Markdown \u8868\u683C\u683C\u5F0F
|
|
11940
|
+
- \u652F\u6301\u5206\u9875\u8BFB\u53D6\u5927\u91CF\u6570\u636E
|
|
11941
|
+
- \u5904\u7406\u591A\u79CD\u5B57\u6BB5\u7C7B\u578B\uFF08\u6587\u672C\u3001\u6570\u5B57\u3001\u65E5\u671F\u3001\u94FE\u63A5\u7B49\uFF09
|
|
11942
|
+
|
|
11943
|
+
**\u6CE8\u610F\u4E8B\u9879\uFF1A**
|
|
11944
|
+
- \u9700\u8981\u5148\u5B8C\u6210\u98DE\u4E66 OAuth \u6388\u6743
|
|
11945
|
+
- \u9700\u8981\u5E94\u7528\u5177\u6709 bitable:bitable \u6743\u9650
|
|
11946
|
+
- \u591A\u7EF4\u8868\u683C token \u53EF\u4EE5\u4ECE\u6587\u6863 URL \u4E2D\u83B7\u53D6
|
|
11947
|
+
`.trim();
|
|
11948
|
+
var TOOL_ANNOTATIONS15 = {
|
|
11949
|
+
readOnlyHint: true,
|
|
11950
|
+
destructiveHint: false,
|
|
11951
|
+
idempotentHint: true,
|
|
11952
|
+
openWorldHint: true
|
|
11953
|
+
};
|
|
11954
|
+
var InputSchema15 = z.object({
|
|
11955
|
+
bitableToken: z.string().min(1).describe("\u591A\u7EF4\u8868\u683C token\u3002\u53EF\u4EE5\u4ECE\u591A\u7EF4\u8868\u683C URL \u4E2D\u83B7\u53D6\u3002"),
|
|
11956
|
+
outputFormat: z.enum(["markdown", "json"]).default("markdown").describe("\u8F93\u51FA\u683C\u5F0F\uFF1Amarkdown\uFF08Markdown \u8868\u683C\uFF09\u6216 json\uFF08JSON \u6570\u636E\uFF09\u3002"),
|
|
11957
|
+
appId: z.string().optional().describe("\u98DE\u4E66\u5E94\u7528 ID\u3002\u5982\u679C\u4E0D\u63D0\u4F9B\uFF0C\u5C06\u4F7F\u7528\u9ED8\u8BA4\u914D\u7F6E\u7684\u5E94\u7528\u3002")
|
|
11958
|
+
}).describe("\u8BFB\u53D6\u98DE\u4E66\u591A\u7EF4\u8868\u683C\u7684\u53C2\u6570\u3002");
|
|
11959
|
+
var OutputSchema15 = z.object({
|
|
11960
|
+
success: z.boolean().describe("\u8BFB\u53D6\u662F\u5426\u6210\u529F\u3002"),
|
|
11961
|
+
bitableToken: z.string().describe("\u591A\u7EF4\u8868\u683C token\u3002"),
|
|
11962
|
+
name: z.string().optional().describe("\u591A\u7EF4\u8868\u683C\u540D\u79F0\u3002"),
|
|
11963
|
+
content: z.string().optional().describe("Markdown \u5185\u5BB9\uFF08\u6240\u6709\u8868\u683C\uFF09\u3002"),
|
|
11964
|
+
tables: z.array(
|
|
11965
|
+
z.object({
|
|
11966
|
+
tableId: z.string().describe("\u6570\u636E\u8868 ID\u3002"),
|
|
11967
|
+
name: z.string().describe("\u6570\u636E\u8868\u540D\u79F0\u3002"),
|
|
11968
|
+
markdown: z.string().optional().describe("Markdown \u8868\u683C\u5185\u5BB9\u3002"),
|
|
11969
|
+
records: z.array(
|
|
11970
|
+
z.object({
|
|
11971
|
+
recordId: z.string().describe("\u8BB0\u5F55 ID\u3002"),
|
|
11972
|
+
fields: z.record(z.string(), z.unknown()).describe("\u5B57\u6BB5\u6570\u636E\u3002")
|
|
11973
|
+
})
|
|
11974
|
+
).optional().describe("\u8BB0\u5F55\u5217\u8868\u3002")
|
|
11975
|
+
})
|
|
11976
|
+
).optional().describe("\u6570\u636E\u8868\u5217\u8868\u3002"),
|
|
11977
|
+
error: z.string().optional().describe("\u9519\u8BEF\u4FE1\u606F\u3002")
|
|
11978
|
+
}).describe("\u591A\u7EF4\u8868\u683C\u8BFB\u53D6\u7ED3\u679C\u3002");
|
|
11979
|
+
async function readBitableLogic(input, appContext, _sdkContext) {
|
|
11980
|
+
logger.debug("\u5F00\u59CB\u8BFB\u53D6\u98DE\u4E66\u591A\u7EF4\u8868\u683C", {
|
|
11981
|
+
...appContext,
|
|
11982
|
+
bitableToken: input.bitableToken,
|
|
11983
|
+
outputFormat: input.outputFormat
|
|
11984
|
+
});
|
|
11985
|
+
const context = requestContextService.createRequestContext({
|
|
11986
|
+
operation: "feishu.readBitable",
|
|
11987
|
+
tenantId: "feishu_service"
|
|
11988
|
+
});
|
|
11989
|
+
const feishuService = container.resolve(
|
|
11990
|
+
FeishuServiceToken
|
|
11991
|
+
);
|
|
11992
|
+
const options = {
|
|
11993
|
+
outputFormat: input.outputFormat
|
|
11994
|
+
};
|
|
11995
|
+
if (input.appId) options.appId = input.appId;
|
|
11996
|
+
const result = await feishuService.readBitable(
|
|
11997
|
+
input.bitableToken,
|
|
11998
|
+
options,
|
|
11999
|
+
context
|
|
12000
|
+
);
|
|
12001
|
+
if (result.success) {
|
|
12002
|
+
logger.info("\u98DE\u4E66\u591A\u7EF4\u8868\u683C\u8BFB\u53D6\u6210\u529F", {
|
|
12003
|
+
...context,
|
|
12004
|
+
bitableToken: result.bitableToken,
|
|
12005
|
+
name: result.name,
|
|
12006
|
+
tableCount: result.tables?.length
|
|
12007
|
+
});
|
|
12008
|
+
} else {
|
|
12009
|
+
logger.warning("\u98DE\u4E66\u591A\u7EF4\u8868\u683C\u8BFB\u53D6\u5931\u8D25", {
|
|
12010
|
+
...context,
|
|
12011
|
+
error: result.error
|
|
12012
|
+
});
|
|
12013
|
+
}
|
|
12014
|
+
return {
|
|
12015
|
+
success: result.success,
|
|
12016
|
+
bitableToken: result.bitableToken,
|
|
12017
|
+
name: result.name,
|
|
12018
|
+
content: result.content,
|
|
12019
|
+
tables: result.tables,
|
|
12020
|
+
error: result.error
|
|
12021
|
+
};
|
|
12022
|
+
}
|
|
12023
|
+
function responseFormatter15(result) {
|
|
12024
|
+
const md = markdown();
|
|
12025
|
+
if (result.success) {
|
|
12026
|
+
md.h2("\u2705 \u591A\u7EF4\u8868\u683C\u8BFB\u53D6\u6210\u529F").keyValue("\u8868\u683C\u540D\u79F0", result.name ?? "\u672A\u77E5").keyValue("\u591A\u7EF4\u8868\u683C Token", result.bitableToken).keyValue("\u6570\u636E\u8868\u6570\u91CF", String(result.tables?.length ?? 0));
|
|
12027
|
+
if (result.tables && result.tables.length > 0) {
|
|
12028
|
+
md.blankLine().h3("\u{1F4CA} \u6570\u636E\u8868\u5217\u8868");
|
|
12029
|
+
for (const table of result.tables) {
|
|
12030
|
+
md.text(`- **${table.name}** (${table.records?.length ?? 0} \u6761\u8BB0\u5F55)`);
|
|
12031
|
+
}
|
|
12032
|
+
}
|
|
12033
|
+
if (result.content) {
|
|
12034
|
+
md.blankLine().h3("\u{1F4DD} \u8868\u683C\u5185\u5BB9").blankLine().text(
|
|
12035
|
+
result.content.length > 2e3 ? result.content.substring(0, 2e3) + "\n\n... (\u5185\u5BB9\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD)" : result.content
|
|
12036
|
+
);
|
|
12037
|
+
}
|
|
12038
|
+
} else {
|
|
12039
|
+
md.h2("\u274C \u591A\u7EF4\u8868\u683C\u8BFB\u53D6\u5931\u8D25").paragraph(result.error ?? "\u672A\u77E5\u9519\u8BEF");
|
|
12040
|
+
md.blankLine().blockquote(
|
|
12041
|
+
"\u8BF7\u68C0\u67E5\u9519\u8BEF\u4FE1\u606F\uFF0C\u786E\u4FDD\u5DF2\u5B8C\u6210 OAuth \u8BA4\u8BC1\u4E14\u6709\u6743\u9650\u8BBF\u95EE\u8BE5\u591A\u7EF4\u8868\u683C\u3002"
|
|
12042
|
+
);
|
|
12043
|
+
}
|
|
12044
|
+
return [
|
|
12045
|
+
{
|
|
12046
|
+
type: "text",
|
|
12047
|
+
text: md.build()
|
|
12048
|
+
}
|
|
12049
|
+
];
|
|
12050
|
+
}
|
|
12051
|
+
var feishuReadBitableTool = {
|
|
12052
|
+
name: TOOL_NAME15,
|
|
12053
|
+
title: TOOL_TITLE15,
|
|
12054
|
+
description: TOOL_DESCRIPTION15,
|
|
12055
|
+
inputSchema: InputSchema15,
|
|
12056
|
+
outputSchema: OutputSchema15,
|
|
12057
|
+
annotations: TOOL_ANNOTATIONS15,
|
|
12058
|
+
logic: withToolAuth(["tool:feishu:read"], readBitableLogic),
|
|
12059
|
+
responseFormatter: responseFormatter15
|
|
12060
|
+
};
|
|
11505
12061
|
|
|
11506
12062
|
// src/mcp-server/tools/definitions/index.ts
|
|
11507
12063
|
var allToolDefinitions = [
|
|
@@ -11523,6 +12079,8 @@ var allToolDefinitions = [
|
|
|
11523
12079
|
// 飞书文档:批量读取
|
|
11524
12080
|
feishuReadWikiRecursiveTool,
|
|
11525
12081
|
// 飞书文档:递归读取知识库
|
|
12082
|
+
feishuReadBitableTool,
|
|
12083
|
+
// 飞书文档:读取多维表格
|
|
11526
12084
|
// 飞书管理工具
|
|
11527
12085
|
feishuListFoldersTool,
|
|
11528
12086
|
// 飞书管理:列出文件夹
|
|
@@ -11547,7 +12105,7 @@ function createMcpToolHandler({
|
|
|
11547
12105
|
inputSchema: _inputSchema,
|
|
11548
12106
|
// Captured for type inference, not used at runtime
|
|
11549
12107
|
logic,
|
|
11550
|
-
responseFormatter:
|
|
12108
|
+
responseFormatter: responseFormatter16 = defaultResponseFormatter2
|
|
11551
12109
|
}) {
|
|
11552
12110
|
return async (input, callContext) => {
|
|
11553
12111
|
const sdkContext = callContext;
|
|
@@ -11569,7 +12127,7 @@ function createMcpToolHandler({
|
|
|
11569
12127
|
);
|
|
11570
12128
|
return {
|
|
11571
12129
|
structuredContent: result,
|
|
11572
|
-
content:
|
|
12130
|
+
content: responseFormatter16(result)
|
|
11573
12131
|
};
|
|
11574
12132
|
} catch (error) {
|
|
11575
12133
|
const mcpError = ErrorHandler.handleError(error, {
|
|
@@ -12021,9 +12579,9 @@ ToolRegistry = __decorateClass([
|
|
|
12021
12579
|
injectable(),
|
|
12022
12580
|
__decorateParam(0, injectAll(ToolDefinitions, { isOptional: true }))
|
|
12023
12581
|
], ToolRegistry);
|
|
12024
|
-
var registerTools = (
|
|
12582
|
+
var registerTools = (container26) => {
|
|
12025
12583
|
for (const tool of allToolDefinitions) {
|
|
12026
|
-
|
|
12584
|
+
container26.register(ToolDefinitions, { useValue: tool });
|
|
12027
12585
|
}
|
|
12028
12586
|
};
|
|
12029
12587
|
|
|
@@ -12084,33 +12642,33 @@ async function createMcpServerInstance() {
|
|
|
12084
12642
|
globalThis.crypto?.webcrypto ?? // Node.js [18-16] REPL
|
|
12085
12643
|
globalThis.crypto ?? // Node.js >18
|
|
12086
12644
|
import('crypto').then((m) => m.webcrypto);
|
|
12087
|
-
|
|
12088
|
-
client_id:
|
|
12089
|
-
redirect_uri:
|
|
12645
|
+
z18.object({
|
|
12646
|
+
client_id: z18.string(),
|
|
12647
|
+
redirect_uri: z18.string().optional().refine((value) => value === void 0 || URL.canParse(value), { message: "redirect_uri must be a valid URL" })
|
|
12090
12648
|
});
|
|
12091
|
-
|
|
12092
|
-
response_type:
|
|
12093
|
-
code_challenge:
|
|
12094
|
-
code_challenge_method:
|
|
12095
|
-
scope:
|
|
12096
|
-
state:
|
|
12097
|
-
resource:
|
|
12649
|
+
z18.object({
|
|
12650
|
+
response_type: z18.literal("code"),
|
|
12651
|
+
code_challenge: z18.string(),
|
|
12652
|
+
code_challenge_method: z18.literal("S256"),
|
|
12653
|
+
scope: z18.string().optional(),
|
|
12654
|
+
state: z18.string().optional(),
|
|
12655
|
+
resource: z18.url().optional()
|
|
12098
12656
|
});
|
|
12099
|
-
|
|
12100
|
-
|
|
12101
|
-
code:
|
|
12102
|
-
code_verifier:
|
|
12103
|
-
redirect_uri:
|
|
12104
|
-
resource:
|
|
12657
|
+
z18.object({ grant_type: z18.string() });
|
|
12658
|
+
z18.object({
|
|
12659
|
+
code: z18.string(),
|
|
12660
|
+
code_verifier: z18.string(),
|
|
12661
|
+
redirect_uri: z18.string().optional(),
|
|
12662
|
+
resource: z18.url().optional()
|
|
12105
12663
|
});
|
|
12106
|
-
|
|
12107
|
-
refresh_token:
|
|
12108
|
-
scope:
|
|
12109
|
-
resource:
|
|
12664
|
+
z18.object({
|
|
12665
|
+
refresh_token: z18.string(),
|
|
12666
|
+
scope: z18.string().optional(),
|
|
12667
|
+
resource: z18.url().optional()
|
|
12110
12668
|
});
|
|
12111
|
-
|
|
12112
|
-
client_id:
|
|
12113
|
-
client_secret:
|
|
12669
|
+
z18.object({
|
|
12670
|
+
client_id: z18.string(),
|
|
12671
|
+
client_secret: z18.string().optional()
|
|
12114
12672
|
});
|
|
12115
12673
|
var isOldBunVersion = () => {
|
|
12116
12674
|
const version = typeof Bun !== "undefined" ? Bun.version : void 0;
|