@wecom/wecom-openclaw-plugin 2026.7.2 → 2026.8.17
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/README.md +33 -4
- package/dist/index.js +14 -21
- package/dist/src/cli/argv.d.ts +36 -0
- package/dist/src/cli/argv.js +155 -0
- package/dist/src/cli/const.d.ts +94 -0
- package/dist/src/cli/const.js +107 -0
- package/dist/src/cli/credentials.d.ts +54 -0
- package/dist/src/cli/credentials.js +342 -0
- package/dist/src/cli/index.d.ts +5 -0
- package/dist/src/cli/index.js +5 -0
- package/dist/src/cli/legacy-tool-warning.d.ts +12 -0
- package/dist/src/cli/legacy-tool-warning.js +20 -0
- package/dist/src/cli/locate.d.ts +32 -0
- package/dist/src/cli/locate.js +196 -0
- package/dist/src/cli/process-launcher.d.ts +1 -0
- package/dist/src/cli/process-launcher.js +1 -0
- package/dist/src/cli/process-output.d.ts +14 -0
- package/dist/src/cli/process-output.js +43 -0
- package/dist/src/cli/tool.d.ts +46 -0
- package/dist/src/cli/tool.js +363 -0
- package/dist/src/const.d.ts +0 -8
- package/dist/src/const.js +0 -14
- package/dist/src/monitor.js +1 -12
- package/dist/src/state-manager.d.ts +0 -19
- package/dist/src/state-manager.js +1 -34
- package/dist/src/utils.d.ts +27 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +3 -3
- package/skills/wecom-send-media/SKILL.md +2 -0
- package/skills/wecom-send-template-card/SKILL.md +1 -1
- package/skills/wecomcli-calendar/SKILL.md +302 -0
- package/skills/wecomcli-calendar/references/calendar-agenda.md +228 -0
- package/skills/wecomcli-calendar/references/calendar-cancel.md +110 -0
- package/skills/wecomcli-calendar/references/calendar-create.md +240 -0
- package/skills/wecomcli-calendar/references/calendar-freebusy.md +209 -0
- package/skills/wecomcli-calendar/references/calendar-meeting-room.md +172 -0
- package/skills/wecomcli-calendar/references/calendar-search.md +208 -0
- package/skills/wecomcli-calendar/references/calendar-update.md +274 -0
- package/skills/wecomcli-contact/SKILL.md +59 -0
- package/skills/wecomcli-disk/SKILL.md +401 -0
- package/skills/wecomcli-doc/SKILL.md +140 -0
- package/skills/wecomcli-doc/references/doc-contents-append.md +22 -0
- package/skills/wecomcli-doc/references/doc-contents-overwrite.md +29 -0
- package/skills/wecomcli-doc/references/doc-create.md +161 -0
- package/skills/wecomcli-doc/scripts/build_docx.py +1375 -0
- package/skills/wecomcli-doc-manage/SKILL.md +135 -0
- package/skills/wecomcli-doc-manage/references/doc-members-update.md +26 -0
- package/skills/wecomcli-doc-manage/references/doc-names-update.md +22 -0
- package/skills/wecomcli-doc-manage/references/doc-rules-update.md +24 -0
- package/skills/wecomcli-email/SKILL.md +216 -0
- package/skills/wecomcli-email/references/forward-mail.md +131 -0
- package/skills/wecomcli-email/references/get-mail.md +168 -0
- package/skills/wecomcli-email/references/reply-mail.md +140 -0
- package/skills/wecomcli-email/references/search-mail.md +113 -0
- package/skills/wecomcli-email/references/security.md +53 -0
- package/skills/wecomcli-email/references/send-mail.md +186 -0
- package/skills/wecomcli-email/references/send-schedule.md +83 -0
- package/skills/wecomcli-media/SKILL.md +100 -0
- package/skills/wecomcli-meeting/SKILL.md +374 -0
- package/skills/wecomcli-meeting/references/meeting-cancel.md +115 -0
- package/skills/wecomcli-meeting/references/meeting-create.md +169 -0
- package/skills/wecomcli-meeting/references/meeting-list.md +228 -0
- package/skills/wecomcli-meeting/references/meeting-original-get.md +100 -0
- package/skills/wecomcli-meeting/references/meeting-search.md +175 -0
- package/skills/wecomcli-meeting/references/meeting-update.md +219 -0
- package/skills/wecomcli-message/SKILL.md +213 -0
- package/skills/wecomcli-preflight/SKILL.md +147 -0
- package/skills/wecomcli-sheet/SKILL.md +177 -0
- package/skills/wecomcli-sheet/references/sheet-contents-update.md +49 -0
- package/skills/wecomcli-sheet/references/sheet-ranges-get.md +47 -0
- package/skills/wecomcli-sheet/references/sheet-rows-append.md +47 -0
- package/skills/wecomcli-sheet/references/sheet-subsheets-add.md +28 -0
- package/skills/wecomcli-sheet/references/sheet-subsheets-delete.md +22 -0
- package/skills/wecomcli-smartpage/SKILL.md +172 -0
- package/skills/wecomcli-smartpage/references/data-driven-pages.md +50 -0
- package/skills/wecomcli-smartpage/references/formula/arraylist.md +369 -0
- package/skills/wecomcli-smartpage/references/formula/datetime.md +283 -0
- package/skills/wecomcli-smartpage/references/formula/logic.md +247 -0
- package/skills/wecomcli-smartpage/references/formula/math.md +362 -0
- package/skills/wecomcli-smartpage/references/formula/operators.md +246 -0
- package/skills/wecomcli-smartpage/references/formula/pageblock.md +76 -0
- package/skills/wecomcli-smartpage/references/formula/templates.md +410 -0
- package/skills/wecomcli-smartpage/references/formula/text.md +377 -0
- package/skills/wecomcli-smartpage/references/formula/user.md +22 -0
- package/skills/wecomcli-smartpage/references/formula-reference.md +192 -0
- package/skills/wecomcli-smartpage/references/mdx-syntax.md +739 -0
- package/skills/wecomcli-smartpage/references/smartpage-edit.md +519 -0
- package/skills/wecomcli-smartsheet/SKILL.md +153 -0
- package/skills/wecomcli-smartsheet/assets/templates/README.md +53 -0
- package/skills/wecomcli-smartsheet/assets/templates/ai_efficiency.md +709 -0
- package/skills/wecomcli-smartsheet/assets/templates/connect_to_app.md +380 -0
- package/skills/wecomcli-smartsheet/assets/templates/financial_accounting.md +369 -0
- package/skills/wecomcli-smartsheet/assets/templates/hr_and_administration.md +475 -0
- package/skills/wecomcli-smartsheet/assets/templates/ledger_records.md +156 -0
- package/skills/wecomcli-smartsheet/assets/templates/manufacturing.md +395 -0
- package/skills/wecomcli-smartsheet/assets/templates/marketing.md +186 -0
- package/skills/wecomcli-smartsheet/assets/templates/office_essentials.md +299 -0
- package/skills/wecomcli-smartsheet/assets/templates/personal_efficiency.md +70 -0
- package/skills/wecomcli-smartsheet/assets/templates/procurement_logistics.md +325 -0
- package/skills/wecomcli-smartsheet/assets/templates/project_management.md +564 -0
- package/skills/wecomcli-smartsheet/assets/templates/rd_process_customer.md +222 -0
- package/skills/wecomcli-smartsheet/assets/templates/rd_process_ops.md +105 -0
- package/skills/wecomcli-smartsheet/assets/templates/rd_process_project.md +109 -0
- package/skills/wecomcli-smartsheet/assets/templates/rd_process_research.md +92 -0
- package/skills/wecomcli-smartsheet/assets/templates/sales_and_operations.md +446 -0
- package/skills/wecomcli-smartsheet/assets/templates/store_management.md +431 -0
- package/skills/wecomcli-smartsheet/assets/templates/team_tasks.md +274 -0
- package/skills/wecomcli-smartsheet/assets/templates/wechat_customer.md +384 -0
- package/skills/wecomcli-smartsheet/assets/templates/work_report.md +100 -0
- package/skills/wecomcli-smartsheet/references/common.md +145 -0
- package/skills/wecomcli-smartsheet/references/smart-sheet-chart-types.md +95 -0
- package/skills/wecomcli-smartsheet/references/smart-sheet-edit.md +611 -0
- package/skills/wecomcli-smartsheet/references/smart-sheet-field-types.md +438 -0
- package/skills/wecomcli-smartsheet/references/smart-sheet-formula.md +845 -0
- package/skills/wecomcli-smartsheet/references/smart-sheet-read.md +411 -0
- package/skills/wecomcli-smartsheet/references/smart-sheet-record-values.md +203 -0
- package/skills/wecomcli-smartsheet/references/smart-sheet-view-types.md +356 -0
- package/skills/{wecom-smartsheet/references/webhook-examples.md → wecomcli-smartsheet/references/smart-sheet-webhook-examples.md} +23 -32
- package/skills/wecomcli-smartsheet/references/smart-sheet-webhook.md +169 -0
- package/skills/wecomcli-todo/SKILL.md +75 -0
- package/skills/wecomcli-todo/references/todo-create.md +139 -0
- package/skills/wecomcli-todo/references/todo-delete.md +65 -0
- package/skills/wecomcli-todo/references/todo-finish.md +74 -0
- package/skills/wecomcli-todo/references/todo-get.md +68 -0
- package/skills/wecomcli-todo/references/todo-list.md +135 -0
- package/skills/wecomcli-todo/references/todo-update.md +114 -0
- package/dist/src/mcp/index.d.ts +0 -6
- package/dist/src/mcp/index.js +0 -10
- package/dist/src/mcp/interceptors/biz-error.d.ts +0 -11
- package/dist/src/mcp/interceptors/biz-error.js +0 -69
- package/dist/src/mcp/interceptors/doc-auth-error.d.ts +0 -10
- package/dist/src/mcp/interceptors/doc-auth-error.js +0 -171
- package/dist/src/mcp/interceptors/index.d.ts +0 -35
- package/dist/src/mcp/interceptors/index.js +0 -70
- package/dist/src/mcp/interceptors/msg-media.d.ts +0 -11
- package/dist/src/mcp/interceptors/msg-media.js +0 -133
- package/dist/src/mcp/interceptors/smartpage-create.d.ts +0 -30
- package/dist/src/mcp/interceptors/smartpage-create.js +0 -132
- package/dist/src/mcp/interceptors/smartpage-export.d.ts +0 -17
- package/dist/src/mcp/interceptors/smartpage-export.js +0 -87
- package/dist/src/mcp/interceptors/smartsheet-upload.d.ts +0 -22
- package/dist/src/mcp/interceptors/smartsheet-upload.js +0 -263
- package/dist/src/mcp/interceptors/types.d.ts +0 -64
- package/dist/src/mcp/interceptors/types.js +0 -7
- package/dist/src/mcp/schema.d.ts +0 -11
- package/dist/src/mcp/schema.js +0 -99
- package/dist/src/mcp/tool.d.ts +0 -63
- package/dist/src/mcp/tool.js +0 -224
- package/dist/src/mcp/transport.d.ts +0 -94
- package/dist/src/mcp/transport.js +0 -549
- package/skills/wecom-contact/SKILL.md +0 -162
- package/skills/wecom-doc/SKILL.md +0 -127
- package/skills/wecom-meeting/SKILL.md +0 -441
- package/skills/wecom-meeting/references/example-full.md +0 -30
- package/skills/wecom-meeting/references/example-reminder.md +0 -46
- package/skills/wecom-meeting/references/example-security.md +0 -22
- package/skills/wecom-meeting/references/response-get-meeting-info.md +0 -148
- package/skills/wecom-msg/SKILL.md +0 -157
- package/skills/wecom-msg/references/api-get-messages.md +0 -93
- package/skills/wecom-msg/references/api-get-msg-chat-list.md +0 -58
- package/skills/wecom-msg/references/api-get-msg-media.md +0 -44
- package/skills/wecom-msg/references/api-send-message.md +0 -39
- package/skills/wecom-preflight/SKILL.md +0 -141
- package/skills/wecom-schedule/SKILL.md +0 -161
- package/skills/wecom-schedule/references/api-check-availability.md +0 -56
- package/skills/wecom-schedule/references/api-create-schedule.md +0 -38
- package/skills/wecom-schedule/references/api-get-schedule-detail.md +0 -81
- package/skills/wecom-schedule/references/api-update-schedule.md +0 -32
- package/skills/wecom-schedule/references/ref-reminders.md +0 -24
- package/skills/wecom-sheet/SKILL.md +0 -131
- package/skills/wecom-sheet/references/sheet-add-sub.md +0 -54
- package/skills/wecom-sheet/references/sheet-append-data.md +0 -64
- package/skills/wecom-sheet/references/sheet-delete-sub.md +0 -38
- package/skills/wecom-sheet/references/sheet-update-range-data.md +0 -95
- package/skills/wecom-smartpage/SKILL.md +0 -119
- package/skills/wecom-smartpage/references/smartpage-create.md +0 -130
- package/skills/wecom-smartpage/references/smartpage-export.md +0 -168
- package/skills/wecom-smartsheet/SKILL.md +0 -241
- package/skills/wecom-smartsheet/references/smartsheet-cell-value-formats.md +0 -163
- package/skills/wecom-smartsheet/references/smartsheet-field-types.md +0 -44
- package/skills/wecom-smartsheet/references/smartsheet-get-records.md +0 -187
- package/skills/wecom-smartsheet/references/webhook-fallback.md +0 -183
- package/skills/wecom-todo/SKILL.md +0 -392
- package/skills/wecom-todo/examples/workflows.md +0 -163
package/dist/src/mcp/schema.js
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MCP Schema 清洗模块
|
|
3
|
-
*
|
|
4
|
-
* 负责内联 $ref/$defs 引用并移除 Gemini 不支持的 JSON Schema 关键词,
|
|
5
|
-
* 防止 Gemini 模型解析 function response 时报 400 错误。
|
|
6
|
-
*/
|
|
7
|
-
/** Gemini 不支持的 JSON Schema 关键词 */
|
|
8
|
-
const GEMINI_UNSUPPORTED_KEYWORDS = new Set([
|
|
9
|
-
"patternProperties", "additionalProperties", "$schema", "$id", "$ref", "$defs",
|
|
10
|
-
"definitions", "examples", "minLength", "maxLength", "minimum", "maximum",
|
|
11
|
-
"multipleOf", "pattern", "format", "minItems", "maxItems", "uniqueItems",
|
|
12
|
-
"minProperties", "maxProperties",
|
|
13
|
-
]);
|
|
14
|
-
/**
|
|
15
|
-
* 清洗 JSON Schema,内联 $ref 引用并移除 Gemini 不支持的关键词,
|
|
16
|
-
* 防止 Gemini 模型解析 function response 时报 400 错误。
|
|
17
|
-
*/
|
|
18
|
-
export function cleanSchemaForGemini(schema) {
|
|
19
|
-
if (!schema || typeof schema !== "object")
|
|
20
|
-
return schema;
|
|
21
|
-
if (Array.isArray(schema))
|
|
22
|
-
return schema.map(cleanSchemaForGemini);
|
|
23
|
-
const obj = schema;
|
|
24
|
-
// 收集 $defs/definitions 用于后续 $ref 内联解析
|
|
25
|
-
const defs = {
|
|
26
|
-
...(obj.$defs && typeof obj.$defs === "object" ? obj.$defs : {}),
|
|
27
|
-
...(obj.definitions && typeof obj.definitions === "object" ? obj.definitions : {}),
|
|
28
|
-
};
|
|
29
|
-
return cleanWithDefs(obj, defs, new Set());
|
|
30
|
-
}
|
|
31
|
-
function cleanWithDefs(schema, defs, refStack) {
|
|
32
|
-
if (!schema || typeof schema !== "object")
|
|
33
|
-
return schema;
|
|
34
|
-
if (Array.isArray(schema))
|
|
35
|
-
return schema.map((item) => cleanWithDefs(item, defs, refStack));
|
|
36
|
-
const obj = schema;
|
|
37
|
-
// 合并当前层级的 $defs/definitions 到 defs 中
|
|
38
|
-
if (obj.$defs && typeof obj.$defs === "object") {
|
|
39
|
-
Object.assign(defs, obj.$defs);
|
|
40
|
-
}
|
|
41
|
-
if (obj.definitions && typeof obj.definitions === "object") {
|
|
42
|
-
Object.assign(defs, obj.definitions);
|
|
43
|
-
}
|
|
44
|
-
// 处理 $ref 引用:尝试内联解析
|
|
45
|
-
if (typeof obj.$ref === "string") {
|
|
46
|
-
const ref = obj.$ref;
|
|
47
|
-
if (refStack.has(ref))
|
|
48
|
-
return {}; // 防止循环引用
|
|
49
|
-
const match = ref.match(/^#\/(?:\$defs|definitions)\/(.+)$/);
|
|
50
|
-
if (match && match[1] && defs[match[1]]) {
|
|
51
|
-
const nextStack = new Set(refStack);
|
|
52
|
-
nextStack.add(ref);
|
|
53
|
-
return cleanWithDefs(defs[match[1]], defs, nextStack);
|
|
54
|
-
}
|
|
55
|
-
return {}; // 无法解析的 $ref,返回空对象
|
|
56
|
-
}
|
|
57
|
-
const cleaned = {};
|
|
58
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
59
|
-
if (GEMINI_UNSUPPORTED_KEYWORDS.has(key))
|
|
60
|
-
continue;
|
|
61
|
-
if (key === "const") {
|
|
62
|
-
cleaned.enum = [value];
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
if (key === "properties" && value && typeof value === "object" && !Array.isArray(value)) {
|
|
66
|
-
cleaned[key] = Object.fromEntries(Object.entries(value).map(([k, v]) => [
|
|
67
|
-
k, cleanWithDefs(v, defs, refStack),
|
|
68
|
-
]));
|
|
69
|
-
}
|
|
70
|
-
else if (key === "items" && value) {
|
|
71
|
-
cleaned[key] = Array.isArray(value)
|
|
72
|
-
? value.map((item) => cleanWithDefs(item, defs, refStack))
|
|
73
|
-
: cleanWithDefs(value, defs, refStack);
|
|
74
|
-
}
|
|
75
|
-
else if ((key === "anyOf" || key === "oneOf" || key === "allOf") && Array.isArray(value)) {
|
|
76
|
-
// 过滤掉 null 类型的变体
|
|
77
|
-
const nonNull = value.filter((v) => {
|
|
78
|
-
if (!v || typeof v !== "object")
|
|
79
|
-
return true;
|
|
80
|
-
const r = v;
|
|
81
|
-
return r.type !== "null";
|
|
82
|
-
});
|
|
83
|
-
if (nonNull.length === 1) {
|
|
84
|
-
// 只剩一个变体时直接内联
|
|
85
|
-
const single = cleanWithDefs(nonNull[0], defs, refStack);
|
|
86
|
-
if (single && typeof single === "object" && !Array.isArray(single)) {
|
|
87
|
-
Object.assign(cleaned, single);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
cleaned[key] = nonNull.map((v) => cleanWithDefs(v, defs, refStack));
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
cleaned[key] = value;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
return cleaned;
|
|
99
|
-
}
|
package/dist/src/mcp/tool.d.ts
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* wecom_mcp — 模拟 MCP 调用的 Agent Tool
|
|
3
|
-
*
|
|
4
|
-
* 通过 MCP Streamable HTTP 传输协议调用企业微信 MCP Server,
|
|
5
|
-
* 提供 list(列出所有工具)和 call(调用工具)两个操作。
|
|
6
|
-
*
|
|
7
|
-
* 在 skills 中的使用方式:
|
|
8
|
-
* wecom_mcp list <category>
|
|
9
|
-
* wecom_mcp call <category> <method> '<jsonArgs>'
|
|
10
|
-
*
|
|
11
|
-
* 示例:
|
|
12
|
-
* wecom_mcp list contact
|
|
13
|
-
* wecom_mcp call contact getContact '{}'
|
|
14
|
-
*/
|
|
15
|
-
interface CreateWeComMcpToolOptions {
|
|
16
|
-
/** 当前会话可信的企业微信 userid */
|
|
17
|
-
requesterUserId?: string;
|
|
18
|
-
/** 当前会话对应的账户 ID(来自 ctx.agentAccountId) */
|
|
19
|
-
accountId?: string;
|
|
20
|
-
/** 当前会话的 chatId(群组 ID 或用户 ID),用于 aibot_send_biz_msg 等命令 */
|
|
21
|
-
chatId?: string;
|
|
22
|
-
/** 当前会话的聊天类型:single(单聊)或 group(群聊) */
|
|
23
|
-
chatType?: "single" | "group";
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* 创建 wecom_mcp Agent Tool 定义
|
|
27
|
-
*/
|
|
28
|
-
export declare function createWeComMcpTool(options?: CreateWeComMcpToolOptions): {
|
|
29
|
-
name: string;
|
|
30
|
-
label: string;
|
|
31
|
-
description: string;
|
|
32
|
-
parameters: {
|
|
33
|
-
type: "object";
|
|
34
|
-
properties: {
|
|
35
|
-
action: {
|
|
36
|
-
type: string;
|
|
37
|
-
enum: string[];
|
|
38
|
-
description: string;
|
|
39
|
-
};
|
|
40
|
-
category: {
|
|
41
|
-
type: string;
|
|
42
|
-
description: string;
|
|
43
|
-
};
|
|
44
|
-
method: {
|
|
45
|
-
type: string;
|
|
46
|
-
description: string;
|
|
47
|
-
};
|
|
48
|
-
args: {
|
|
49
|
-
type: string[];
|
|
50
|
-
description: string;
|
|
51
|
-
};
|
|
52
|
-
};
|
|
53
|
-
required: string[];
|
|
54
|
-
};
|
|
55
|
-
execute(_toolCallId: string, params: unknown): Promise<{
|
|
56
|
-
content: {
|
|
57
|
-
type: "text";
|
|
58
|
-
text: string;
|
|
59
|
-
}[];
|
|
60
|
-
details: unknown;
|
|
61
|
-
}>;
|
|
62
|
-
};
|
|
63
|
-
export {};
|
package/dist/src/mcp/tool.js
DELETED
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* wecom_mcp — 模拟 MCP 调用的 Agent Tool
|
|
3
|
-
*
|
|
4
|
-
* 通过 MCP Streamable HTTP 传输协议调用企业微信 MCP Server,
|
|
5
|
-
* 提供 list(列出所有工具)和 call(调用工具)两个操作。
|
|
6
|
-
*
|
|
7
|
-
* 在 skills 中的使用方式:
|
|
8
|
-
* wecom_mcp list <category>
|
|
9
|
-
* wecom_mcp call <category> <method> '<jsonArgs>'
|
|
10
|
-
*
|
|
11
|
-
* 示例:
|
|
12
|
-
* wecom_mcp list contact
|
|
13
|
-
* wecom_mcp call contact getContact '{}'
|
|
14
|
-
*/
|
|
15
|
-
import { sendJsonRpc } from "./transport.js";
|
|
16
|
-
import { cleanSchemaForGemini } from "./schema.js";
|
|
17
|
-
import { resolveBeforeCall, runAfterCall } from "./interceptors/index.js";
|
|
18
|
-
// ============================================================================
|
|
19
|
-
// 响应构造辅助
|
|
20
|
-
// ============================================================================
|
|
21
|
-
/** 构造统一的文本响应结构 */
|
|
22
|
-
const textResult = (data) => ({
|
|
23
|
-
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
24
|
-
details: data,
|
|
25
|
-
});
|
|
26
|
-
const normalizeOptionalString = (value) => {
|
|
27
|
-
const trimmed = value?.trim();
|
|
28
|
-
return trimmed ? trimmed : undefined;
|
|
29
|
-
};
|
|
30
|
-
/** 构造错误响应 */
|
|
31
|
-
const errorResult = (err) => {
|
|
32
|
-
// 适配企业微信 API 返回的 { errcode, errmsg } 结构
|
|
33
|
-
if (err && typeof err === "object" && "errcode" in err) {
|
|
34
|
-
const { errcode, errmsg } = err;
|
|
35
|
-
return textResult({ error: errmsg ?? `错误码: ${errcode}`, errcode });
|
|
36
|
-
}
|
|
37
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
38
|
-
return textResult({ error: message });
|
|
39
|
-
};
|
|
40
|
-
// ============================================================================
|
|
41
|
-
// list 操作:列出某品类的所有 MCP 工具
|
|
42
|
-
// ============================================================================
|
|
43
|
-
const handleList = async (ctx) => {
|
|
44
|
-
const result = await sendJsonRpc(ctx.category, "tools/list", undefined, {
|
|
45
|
-
requesterUserId: ctx.requesterUserId,
|
|
46
|
-
accountId: ctx.accountId,
|
|
47
|
-
});
|
|
48
|
-
const tools = result?.tools ?? [];
|
|
49
|
-
if (tools.length === 0) {
|
|
50
|
-
return { message: `品类 "${ctx.category}" 下暂无可用工具`, tools: [] };
|
|
51
|
-
}
|
|
52
|
-
return {
|
|
53
|
-
category: ctx.category,
|
|
54
|
-
count: tools.length,
|
|
55
|
-
tools: tools.map((t) => ({
|
|
56
|
-
name: t.name,
|
|
57
|
-
description: t.description ?? "",
|
|
58
|
-
// 清洗 inputSchema,内联 $ref/$defs 引用并移除 Gemini 不支持的关键词,
|
|
59
|
-
// 避免 Gemini 模型解析 function response 时报 400 错误
|
|
60
|
-
inputSchema: t.inputSchema ? cleanSchemaForGemini(t.inputSchema) : undefined,
|
|
61
|
-
})),
|
|
62
|
-
};
|
|
63
|
-
};
|
|
64
|
-
// ============================================================================
|
|
65
|
-
// call 操作:调用某品类的某个 MCP 工具
|
|
66
|
-
// ============================================================================
|
|
67
|
-
const handleCall = async (ctx) => {
|
|
68
|
-
const { category, method, args, requesterUserId, accountId } = ctx;
|
|
69
|
-
const callStart = performance.now();
|
|
70
|
-
console.log(`[mcp] handleCall ${category}/${method} 入参: ${JSON.stringify(args)}`);
|
|
71
|
-
// 1. 收集拦截器的 beforeCall 配置(如超时时间、替换 args)
|
|
72
|
-
const { options, args: resolvedArgs } = await resolveBeforeCall(ctx);
|
|
73
|
-
const finalArgs = resolvedArgs ?? args;
|
|
74
|
-
const requestOptions = { ...options, ...(requesterUserId ? { requesterUserId } : {}), ...(accountId ? { accountId } : {}) };
|
|
75
|
-
if (resolvedArgs) {
|
|
76
|
-
console.log(`[mcp] handleCall ${category}/${method} 拦截器替换 args: ${JSON.stringify(resolvedArgs).slice(0, 500)}` +
|
|
77
|
-
(JSON.stringify(resolvedArgs).length > 500 ? "...(truncated)" : ""));
|
|
78
|
-
}
|
|
79
|
-
if (options) {
|
|
80
|
-
console.log(`[mcp] handleCall ${category}/${method} 拦截器选项: ${JSON.stringify(options)}`);
|
|
81
|
-
}
|
|
82
|
-
// 2. 执行 MCP 调用
|
|
83
|
-
const result = await sendJsonRpc(category, "tools/call", {
|
|
84
|
-
name: method,
|
|
85
|
-
arguments: finalArgs,
|
|
86
|
-
}, requestOptions);
|
|
87
|
-
const rpcDone = performance.now();
|
|
88
|
-
const rpcMs = (rpcDone - callStart).toFixed(1);
|
|
89
|
-
const resultStr = JSON.stringify(result);
|
|
90
|
-
console.log(`[mcp] handleCall ${category}/${method} MCP 响应 (${rpcMs}ms): ${resultStr.slice(0, 800)}` +
|
|
91
|
-
(resultStr.length > 800 ? "...(truncated)" : ""));
|
|
92
|
-
// 3. 管道式执行 afterCall 拦截器(业务错误码检查、响应变换等)
|
|
93
|
-
const finalResult = await runAfterCall(ctx, result);
|
|
94
|
-
const totalMs = (performance.now() - callStart).toFixed(1);
|
|
95
|
-
const interceptMs = (performance.now() - rpcDone).toFixed(1);
|
|
96
|
-
// 有拦截器处理时打印详细耗时,否则只打印 RPC 耗时
|
|
97
|
-
if (finalResult !== result) {
|
|
98
|
-
const finalStr = JSON.stringify(finalResult);
|
|
99
|
-
console.log(`[mcp] handleCall ${category}/${method} afterCall 变换后 (${interceptMs}ms): ${finalStr.slice(0, 500)}` +
|
|
100
|
-
(finalStr.length > 500 ? "...(truncated)" : ""));
|
|
101
|
-
console.log(`[mcp] handleCall ${category}/${method} 总耗时: ${totalMs}ms` +
|
|
102
|
-
` (MCP请求: ${rpcMs}ms, 拦截处理: ${interceptMs}ms)`);
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
console.log(`[mcp] handleCall ${category}/${method} 耗时: ${rpcMs}ms`);
|
|
106
|
-
}
|
|
107
|
-
return finalResult;
|
|
108
|
-
};
|
|
109
|
-
// ============================================================================
|
|
110
|
-
// 参数解析
|
|
111
|
-
// ============================================================================
|
|
112
|
-
/**
|
|
113
|
-
* 解析 args 参数:支持 JSON 字符串或直接的对象
|
|
114
|
-
*/
|
|
115
|
-
const parseArgs = (args) => {
|
|
116
|
-
if (!args)
|
|
117
|
-
return {};
|
|
118
|
-
if (typeof args === "object")
|
|
119
|
-
return args;
|
|
120
|
-
try {
|
|
121
|
-
return JSON.parse(args);
|
|
122
|
-
}
|
|
123
|
-
catch (err) {
|
|
124
|
-
const detail = err instanceof SyntaxError ? err.message : String(err);
|
|
125
|
-
throw new Error(`args 参数不是合法的 JSON: ${args} (${detail})`);
|
|
126
|
-
}
|
|
127
|
-
};
|
|
128
|
-
// ============================================================================
|
|
129
|
-
// 工具定义 & 导出
|
|
130
|
-
// ============================================================================
|
|
131
|
-
/**
|
|
132
|
-
* 创建 wecom_mcp Agent Tool 定义
|
|
133
|
-
*/
|
|
134
|
-
export function createWeComMcpTool(options = {}) {
|
|
135
|
-
const requesterUserId = normalizeOptionalString(options.requesterUserId);
|
|
136
|
-
const accountId = normalizeOptionalString(options.accountId);
|
|
137
|
-
const chatId = normalizeOptionalString(options.chatId);
|
|
138
|
-
const chatType = options.chatType;
|
|
139
|
-
return {
|
|
140
|
-
name: "wecom_mcp",
|
|
141
|
-
label: "企业微信 MCP 工具",
|
|
142
|
-
description: [
|
|
143
|
-
"通过 HTTP 直接调用企业微信 MCP Server。",
|
|
144
|
-
"支持两种操作:",
|
|
145
|
-
" - list: 列出指定品类的所有 MCP 工具",
|
|
146
|
-
" - call: 调用指定品类的某个 MCP 工具",
|
|
147
|
-
"",
|
|
148
|
-
"使用方式:",
|
|
149
|
-
" wecom_mcp list <category>",
|
|
150
|
-
" wecom_mcp call <category> <method> '<jsonArgs>'",
|
|
151
|
-
"",
|
|
152
|
-
"示例:",
|
|
153
|
-
" 列出 contact 品类所有工具:wecom_mcp list contact",
|
|
154
|
-
" 调用 contact 的 getContact:wecom_mcp call contact getContact '{}'",
|
|
155
|
-
].join("\n"),
|
|
156
|
-
parameters: {
|
|
157
|
-
type: "object",
|
|
158
|
-
properties: {
|
|
159
|
-
action: {
|
|
160
|
-
type: "string",
|
|
161
|
-
enum: ["list", "call"],
|
|
162
|
-
description: "操作类型:list(列出工具)或 call(调用工具)",
|
|
163
|
-
},
|
|
164
|
-
category: {
|
|
165
|
-
type: "string",
|
|
166
|
-
description: "MCP 品类名称,如 doc、contact 等,对应 mcpConfig 中的 key",
|
|
167
|
-
},
|
|
168
|
-
method: {
|
|
169
|
-
type: "string",
|
|
170
|
-
description: "要调用的 MCP 方法名(action=call 时必填)",
|
|
171
|
-
},
|
|
172
|
-
args: {
|
|
173
|
-
type: ["string", "object"],
|
|
174
|
-
description: "调用 MCP 方法的参数,可以是 JSON 字符串或对象(action=call 时使用,默认 {})",
|
|
175
|
-
},
|
|
176
|
-
},
|
|
177
|
-
required: ["action", "category"],
|
|
178
|
-
},
|
|
179
|
-
async execute(_toolCallId, params) {
|
|
180
|
-
const p = params;
|
|
181
|
-
console.log(`[mcp] execute: action=${p.action}, category=${p.category}` +
|
|
182
|
-
(p.method ? `, method=${p.method}` : "") +
|
|
183
|
-
(p.args ? `, args=${typeof p.args === "string" ? p.args : JSON.stringify(p.args)}` : ""));
|
|
184
|
-
try {
|
|
185
|
-
let result;
|
|
186
|
-
const ctx = {
|
|
187
|
-
category: p.category,
|
|
188
|
-
method: p.method ?? "",
|
|
189
|
-
args: {},
|
|
190
|
-
requesterUserId,
|
|
191
|
-
accountId,
|
|
192
|
-
chatId,
|
|
193
|
-
chatType,
|
|
194
|
-
};
|
|
195
|
-
switch (p.action) {
|
|
196
|
-
case "list":
|
|
197
|
-
result = textResult(await handleList(ctx));
|
|
198
|
-
break;
|
|
199
|
-
case "call": {
|
|
200
|
-
if (!p.method) {
|
|
201
|
-
result = textResult({ error: "action 为 call 时必须提供 method 参数" });
|
|
202
|
-
break;
|
|
203
|
-
}
|
|
204
|
-
ctx.args = parseArgs(p.args);
|
|
205
|
-
result = textResult(await handleCall(ctx));
|
|
206
|
-
break;
|
|
207
|
-
}
|
|
208
|
-
default:
|
|
209
|
-
result = textResult({ error: `未知操作类型: ${String(p.action)},支持 list 和 call` });
|
|
210
|
-
}
|
|
211
|
-
console.log(`[mcp] execute: action=${p.action}, category=${p.category}` +
|
|
212
|
-
(p.method ? `, method=${p.method}` : "") +
|
|
213
|
-
` → 响应长度=${result.content[0].text.length} chars`);
|
|
214
|
-
return result;
|
|
215
|
-
}
|
|
216
|
-
catch (err) {
|
|
217
|
-
console.error(`[mcp] execute: action=${p.action}, category=${p.category}` +
|
|
218
|
-
(p.method ? `, method=${p.method}` : "") +
|
|
219
|
-
` → 异常: ${err instanceof Error ? err.message : JSON.stringify(err)}`);
|
|
220
|
-
return errorResult(err);
|
|
221
|
-
}
|
|
222
|
-
},
|
|
223
|
-
};
|
|
224
|
-
}
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MCP Streamable HTTP 传输层模块
|
|
3
|
-
*
|
|
4
|
-
* 负责:
|
|
5
|
-
* - MCP JSON-RPC over HTTP 通信(发送请求、解析响应)
|
|
6
|
-
* - Streamable HTTP session 生命周期管理(initialize 握手 → Mcp-Session-Id 维护 → 失效重建)
|
|
7
|
-
* - 自动检测无状态 Server:如果 initialize 响应未返回 Mcp-Session-Id,
|
|
8
|
-
* 则标记为无状态模式,后续请求跳过握手和 session 管理
|
|
9
|
-
* - SSE 流式响应解析
|
|
10
|
-
* - MCP 配置运行时缓存(通过 WSClient 拉取 URL 并缓存在内存中)
|
|
11
|
-
*/
|
|
12
|
-
/** 媒体下载请求超时时间(毫秒),base64 编码的媒体文件最大可达 ~27MB */
|
|
13
|
-
export declare const MEDIA_DOWNLOAD_TIMEOUT_MS = 120000;
|
|
14
|
-
/** 请求 MCP Server 时透传可信企业微信 userid 的 header 名 */
|
|
15
|
-
export declare const WECOM_USERID_HEADER = "x-openclaw-wecom-userid";
|
|
16
|
-
/**
|
|
17
|
-
* MCP JSON-RPC 错误
|
|
18
|
-
*
|
|
19
|
-
* 携带服务端返回的 JSON-RPC error.code,
|
|
20
|
-
* 用于上层按错误码进行差异化处理(如特定错误码触发缓存清理)。
|
|
21
|
-
*/
|
|
22
|
-
export declare class McpRpcError extends Error {
|
|
23
|
-
readonly code: number;
|
|
24
|
-
readonly data?: unknown | undefined;
|
|
25
|
-
constructor(code: number, message: string, data?: unknown | undefined);
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* MCP HTTP 错误
|
|
29
|
-
*
|
|
30
|
-
* 携带 HTTP 状态码,用于精确判断 session 失效(404)等场景,
|
|
31
|
-
* 避免通过字符串匹配 "404" 导致的误判。
|
|
32
|
-
*/
|
|
33
|
-
export declare class McpHttpError extends Error {
|
|
34
|
-
readonly statusCode: number;
|
|
35
|
-
constructor(statusCode: number, message: string);
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* 根据配置解析当前用于 MCP 的账户 ID
|
|
39
|
-
*
|
|
40
|
-
* 通过 PluginRuntime 读取全局配置,按以下优先级选择账户:
|
|
41
|
-
* 1. 默认账户(如果配置了 botId + secret)
|
|
42
|
-
* 2. 第一个配置了 botId + secret 的长连接账户
|
|
43
|
-
* 3. 无可用长连接账户时回退到默认账户(会导致后续 WSClient 获取失败)
|
|
44
|
-
*/
|
|
45
|
-
export declare function resolveCurrentAccountId(): string;
|
|
46
|
-
/**
|
|
47
|
-
* 清理指定账户+品类的所有 MCP 缓存(配置、会话、无状态标记)
|
|
48
|
-
*
|
|
49
|
-
* 当 MCP Server 返回特定错误码时调用,确保下次请求重新拉取配置并重建会话。
|
|
50
|
-
*
|
|
51
|
-
* @param accountId - 账户 ID
|
|
52
|
-
* @param category - MCP 品类名称
|
|
53
|
-
*/
|
|
54
|
-
export declare function clearCategoryCache(accountId: string, category: string): void;
|
|
55
|
-
/**
|
|
56
|
-
* 清理指定账户下所有品类的 MCP 缓存
|
|
57
|
-
*
|
|
58
|
-
* 适用于账户掉线、凭据变更等需要整体清理的场景。
|
|
59
|
-
*
|
|
60
|
-
* @param accountId - 账户 ID
|
|
61
|
-
*/
|
|
62
|
-
export declare function clearAccountCache(accountId: string): void;
|
|
63
|
-
/** tools/list 返回的工具描述 */
|
|
64
|
-
export interface McpToolInfo {
|
|
65
|
-
name: string;
|
|
66
|
-
description?: string;
|
|
67
|
-
inputSchema?: Record<string, unknown>;
|
|
68
|
-
}
|
|
69
|
-
/** sendJsonRpc 的可选配置 */
|
|
70
|
-
export interface SendJsonRpcOptions {
|
|
71
|
-
/** 自定义 HTTP 请求超时时间(毫秒),默认使用 HTTP_REQUEST_TIMEOUT_MS */
|
|
72
|
-
timeoutMs?: number;
|
|
73
|
-
/** 当前会话可信的企业微信 userid,有值时会注入自定义 header */
|
|
74
|
-
requesterUserId?: string;
|
|
75
|
-
/** 指定使用的账户 ID,有值时优先使用,否则 fallback 到 resolveCurrentAccountId() */
|
|
76
|
-
accountId?: string;
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* 发送 JSON-RPC 请求到 MCP Server(Streamable HTTP 协议)
|
|
80
|
-
*
|
|
81
|
-
* 自动管理 session 生命周期:
|
|
82
|
-
* - 无状态 Server:跳过 session 管理,直接发送请求
|
|
83
|
-
* - 有状态 Server:首次调用先执行 initialize 握手,session 失效(404)时自动重建并重试
|
|
84
|
-
*
|
|
85
|
-
* accountId 优先使用 options.accountId(由工具工厂从 ctx.agentAccountId 传入),
|
|
86
|
-
* 未提供时 fallback 到 resolveCurrentAccountId()。解析结果贯穿整条调用链,避免跨账号污染。
|
|
87
|
-
*
|
|
88
|
-
* @param category - MCP 品类名称
|
|
89
|
-
* @param method - JSON-RPC 方法名
|
|
90
|
-
* @param params - JSON-RPC 参数
|
|
91
|
-
* @param options - 可选配置(如自定义超时、指定账户)
|
|
92
|
-
* @returns JSON-RPC result
|
|
93
|
-
*/
|
|
94
|
-
export declare function sendJsonRpc(category: string, method: string, params?: Record<string, unknown>, options?: SendJsonRpcOptions): Promise<unknown>;
|