wechaty-web-panel 1.6.112 → 1.6.113

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.
Files changed (109) hide show
  1. package/dist/bot/chatgpt/index.js +235 -0
  2. package/dist/bot/coze/sdk/index.js +110 -0
  3. package/dist/bot/dify/sdk/index.js +461 -0
  4. package/dist/bot/dify/sdk/office.js +319 -0
  5. package/dist/bot/fastgpt/index.js +98 -0
  6. package/dist/bot/qanything/index.js +136 -0
  7. package/dist/botInstance/coze.js +167 -0
  8. package/dist/botInstance/cozev3.js +157 -0
  9. package/dist/botInstance/dify.js +160 -0
  10. package/dist/botInstance/fastgpt.js +130 -0
  11. package/dist/botInstance/gpt4v.js +95 -0
  12. package/dist/botInstance/officialOpenAi.js +186 -0
  13. package/dist/botInstance/qany.js +144 -0
  14. package/dist/botInstance/sdk/chatGPT4V.js +89 -0
  15. package/dist/botInstance/sdk/coze.js +200 -0
  16. package/dist/botInstance/sdk/difyClient.js +354 -0
  17. package/dist/botInstance/sdk/pTimeout.js +97 -0
  18. package/dist/botInstance/sdk/qanything.js +137 -0
  19. package/dist/botInstance/sdk/quick-lru.js +237 -0
  20. package/dist/common/hook.js +66 -0
  21. package/dist/common/index.js +513 -0
  22. package/dist/common/multiReply.js +158 -0
  23. package/dist/common/reply.js +23 -0
  24. package/dist/const/puppet-type.js +71 -0
  25. package/dist/db/aiDb.js +27 -0
  26. package/dist/db/aichatDb.js +84 -0
  27. package/dist/db/chatHistory.js +137 -0
  28. package/dist/db/configDb.js +97 -0
  29. package/dist/db/global.js +62 -0
  30. package/dist/db/gptConfig.js +85 -0
  31. package/dist/db/nedb.js +88 -0
  32. package/dist/db/puppetDb.js +58 -0
  33. package/dist/db/roomDb.js +83 -0
  34. package/dist/db/rssConfig.js +82 -0
  35. package/dist/db/rssHistory.js +88 -0
  36. package/dist/db/userDb.js +27 -0
  37. package/dist/handlers/on-callback-message.js +183 -0
  38. package/dist/handlers/on-error.js +5 -0
  39. package/dist/handlers/on-friend.js +62 -0
  40. package/dist/handlers/on-heartbeat.js +20 -0
  41. package/dist/handlers/on-login.js +58 -0
  42. package/dist/handlers/on-logout.js +17 -0
  43. package/dist/handlers/on-message.js +644 -0
  44. package/dist/handlers/on-ready.js +36 -0
  45. package/dist/handlers/on-record-message.js +56 -0
  46. package/dist/handlers/on-roomjoin.js +42 -0
  47. package/dist/handlers/on-roomleave.js +12 -0
  48. package/dist/handlers/on-roomtopic.js +16 -0
  49. package/dist/handlers/on-scan.js +64 -0
  50. package/dist/handlers/on-verifycode.js +42 -0
  51. package/dist/index.js +81 -69306
  52. package/dist/lib/contentCensor.js +23 -0
  53. package/dist/lib/index.js +562 -0
  54. package/dist/lib/oss.js +43 -0
  55. package/dist/lib/s3oss.js +33 -0
  56. package/dist/mcp/mcp-server.js +26 -0
  57. package/dist/mcp/src/config/database.js +51 -0
  58. package/dist/mcp/src/index.js +238 -0
  59. package/dist/mcp/src/mcp/schemas.js +178 -0
  60. package/dist/mcp/src/mcp/server.js +421 -0
  61. package/dist/mcp/src/mcp/streamable-server.js +690 -0
  62. package/dist/mcp/src/models/ChatMessage.js +151 -0
  63. package/dist/mcp/src/models/Friend.js +64 -0
  64. package/dist/mcp/src/models/Group.js +55 -0
  65. package/dist/mcp/src/models/GroupMember.js +67 -0
  66. package/dist/mcp/src/models/index.js +27 -0
  67. package/dist/mcp/src/scripts/migrate.js +21 -0
  68. package/dist/mcp/src/services/ChatDataService.js +284 -0
  69. package/dist/mcp/src/services/McpService.js +521 -0
  70. package/dist/mcp/src/services/McpTools.js +504 -0
  71. package/dist/mcp/streamable-examples.js +283 -0
  72. package/dist/mcp/streamable-server.js +79 -0
  73. package/dist/mcp/test-mcp.js +64 -0
  74. package/dist/mcp/test-streamable-server.js +86 -0
  75. package/dist/package-json.js +89 -0
  76. package/dist/proxy/aibotk.js +829 -0
  77. package/dist/proxy/api.js +431 -0
  78. package/dist/proxy/apib.js +587 -0
  79. package/dist/proxy/bot/chatgpt.js +38 -0
  80. package/dist/proxy/bot/coze.js +38 -0
  81. package/dist/proxy/bot/cozev3.js +38 -0
  82. package/dist/proxy/bot/dify.js +38 -0
  83. package/dist/proxy/bot/dispatch.js +81 -0
  84. package/dist/proxy/bot/fastgpt.js +27 -0
  85. package/dist/proxy/bot/qany.js +27 -0
  86. package/dist/proxy/config.js +14 -0
  87. package/dist/proxy/cozeAi.js +60 -0
  88. package/dist/proxy/cozeV3Ai.js +60 -0
  89. package/dist/proxy/difyAi.js +58 -0
  90. package/dist/proxy/fastgpt.js +55 -0
  91. package/dist/proxy/mqtt.js +275 -0
  92. package/dist/proxy/multimodal.js +122 -0
  93. package/dist/proxy/openAi.js +63 -0
  94. package/dist/proxy/outapi.js +62 -0
  95. package/dist/proxy/qAnyAi.js +57 -0
  96. package/dist/proxy/superagent.js +200 -0
  97. package/dist/proxy/tencent-open.js +255 -0
  98. package/dist/service/event-dispatch-service.js +309 -0
  99. package/dist/service/gpt4vService.js +45 -0
  100. package/dist/service/msg-filter-service.js +121 -0
  101. package/dist/service/msg-filters.js +645 -0
  102. package/dist/service/room-async-service.js +455 -0
  103. package/dist/task/index.js +535 -0
  104. package/dist/task/rss.js +174 -0
  105. package/package.json +2 -2
  106. package/src/package-json.js +2 -2
  107. package/tsconfig.json +3 -12
  108. package/dist/index.d.ts +0 -9
  109. package/tsconfig.cjs.json +0 -12
@@ -0,0 +1,690 @@
1
+ import express from "express";
2
+ import cors from "cors";
3
+ import { randomUUID } from "node:crypto";
4
+ import { z } from "zod";
5
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
7
+ import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
8
+ // 导入我们的业务服务
9
+ import ChatMCP from "../index.js";
10
+ /**
11
+ * 基于 Streamable HTTP 的微信聊天数据 MCP 服务器
12
+ *
13
+ * 这是一个现代化的 MCP 服务器实现,使用最新的 Streamable HTTP 传输协议
14
+ * 替代了已弃用的 SSE (Server-Sent Events) 传输方式
15
+ */
16
+ class ChatMcpStreamableServer {
17
+ constructor(port = 3001, options = {}) {
18
+ this.port = port;
19
+ this.options = {
20
+ stateful: true, // 是否启用有状态模式
21
+ enableJsonResponse: true, // 启用 JSON 响应模式
22
+ enableCors: true, // 启用 CORS
23
+ maxMessageSize: "10mb", // 最大消息大小
24
+ ...options,
25
+ };
26
+ this.app = express();
27
+ this.chatMCP = null;
28
+ this.transports = {}; // 存储传输实例(有状态模式)
29
+ this.setupExpress();
30
+ }
31
+ /**
32
+ * 设置 Express 应用
33
+ */
34
+ setupExpress() {
35
+ // 解析 JSON 请求体
36
+ this.app.use(express.json({ limit: this.options.maxMessageSize }));
37
+ this.app.use(express.urlencoded({ extended: true, limit: this.options.maxMessageSize }));
38
+ // 配置 CORS
39
+ if (this.options.enableCors) {
40
+ this.app.use(cors({
41
+ origin: "*", // 生产环境中应该限制为特定域名
42
+ exposedHeaders: ["Mcp-Session-Id"], // 暴露会话ID头部
43
+ methods: ["GET", "POST", "DELETE", "OPTIONS"],
44
+ allowedHeaders: ["Content-Type", "Mcp-Session-Id"],
45
+ }));
46
+ }
47
+ // Authorization middleware
48
+ const authenticateToken = (req, res, next) => {
49
+ const authHeader = req.headers["authorization"];
50
+ const token = authHeader && authHeader.split(" ")[1]; // Bearer TOKEN
51
+ if (!token) {
52
+ res.status(401).json({
53
+ jsonrpc: "2.0",
54
+ error: {
55
+ code: -32001,
56
+ message: "Unauthorized: Missing bearer token",
57
+ },
58
+ id: null,
59
+ });
60
+ return;
61
+ }
62
+ if (token !== this.options.authToken) {
63
+ res.status(403).json({
64
+ jsonrpc: "2.0",
65
+ error: {
66
+ code: -32002,
67
+ message: "Forbidden: Invalid bearer token",
68
+ },
69
+ id: null,
70
+ });
71
+ return;
72
+ }
73
+ next();
74
+ };
75
+ // 错误处理中间件
76
+ this.app.use((err, req, res, next) => {
77
+ console.error("Express错误:", err);
78
+ res.status(500).json({
79
+ jsonrpc: "2.0",
80
+ error: {
81
+ code: -32603,
82
+ message: "服务器内部错误",
83
+ data: err.message,
84
+ },
85
+ id: req.body?.id || null,
86
+ });
87
+ });
88
+ if (this.options.authToken) {
89
+ this.app.use("/mcp", authenticateToken);
90
+ }
91
+ }
92
+ /**
93
+ * 初始化聊天MCP服务
94
+ */
95
+ async initializeChatMCP() {
96
+ if (!this.chatMCP) {
97
+ this.chatMCP = new ChatMCP();
98
+ await this.chatMCP.init();
99
+ console.log("✅ ChatMCP 服务已初始化");
100
+ }
101
+ return this.chatMCP;
102
+ }
103
+ /**
104
+ * 创建并配置 MCP 服务器
105
+ */
106
+ createMcpServer() {
107
+ const server = new McpServer({
108
+ name: "chat-mcp-streamable-server",
109
+ version: "1.0.0",
110
+ }, {
111
+ capabilities: {
112
+ tools: {},
113
+ logging: {},
114
+ },
115
+ });
116
+ this.registerTools(server);
117
+ return server;
118
+ }
119
+ /**
120
+ * 注册所有 MCP 工具
121
+ */
122
+ registerTools(server) {
123
+ // === 查询工具 ===
124
+ // 搜索好友
125
+ server.tool("search_friends", "搜索好友信息,支持关键词、标签等多种搜索条件", {
126
+ robotId: z.string().describe("机器人账号ID"),
127
+ keyword: z
128
+ .string()
129
+ .optional()
130
+ .describe("搜索关键词(姓名、备注、别名、微信号)"),
131
+ tags: z.string().optional().describe("标签筛选"),
132
+ limit: z.number().default(50).describe("返回结果数量限制"),
133
+ offset: z.number().default(0).describe("结果偏移量"),
134
+ orderBy: z.string().default("createdAt").describe("排序字段"),
135
+ orderDirection: z
136
+ .enum(["ASC", "DESC"])
137
+ .default("DESC")
138
+ .describe("排序方向"),
139
+ }, async (params) => {
140
+ await this.initializeChatMCP();
141
+ const result = await this.chatMCP.searchFriends(params);
142
+ return {
143
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
144
+ };
145
+ });
146
+ // 搜索群组
147
+ server.tool("search_groups", "搜索群组信息,支持群名、成员数等搜索条件", {
148
+ robotId: z.string().describe("机器人账号ID"),
149
+ keyword: z.string().optional().describe("群名关键词"),
150
+ includeMembers: z.boolean().default(false).describe("是否包含成员信息"),
151
+ minMemberCount: z.number().default(0).describe("最小成员数"),
152
+ maxMemberCount: z.number().optional().describe("最大成员数"),
153
+ limit: z.number().default(50).describe("返回结果数量限制"),
154
+ offset: z.number().default(0).describe("结果偏移量"),
155
+ }, async (params) => {
156
+ await this.initializeChatMCP();
157
+ const result = await this.chatMCP.searchGroups(params);
158
+ return {
159
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
160
+ };
161
+ });
162
+ // 搜索聊天消息
163
+ server.tool("search_messages", "搜索聊天消息,支持内容、时间范围等搜索条件", {
164
+ robotId: z.string().describe("机器人账号ID"),
165
+ conversationId: z.string().optional().describe("会话ID"),
166
+ keyword: z.string().optional().describe("消息内容关键词"),
167
+ contentType: z
168
+ .string()
169
+ .optional()
170
+ .describe("内容类型(文字、图片、文件等)"),
171
+ recordType: z
172
+ .enum(["contact", "room"])
173
+ .optional()
174
+ .describe("记录类型(contact私聊/room群聊)"),
175
+ chatUserId: z.string().optional().describe("聊天用户ID"),
176
+ isRobotAnswer: z.boolean().optional().describe("是否机器人回复"),
177
+ startTime: z.number().optional().describe("开始时间戳"),
178
+ endTime: z.number().optional().describe("结束时间戳"),
179
+ limit: z.number().default(100).describe("返回结果数量限制"),
180
+ offset: z.number().default(0).describe("结果偏移量"),
181
+ }, async (params) => {
182
+ await this.initializeChatMCP();
183
+ const result = await this.chatMCP.searchChatMessages(params);
184
+ return {
185
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
186
+ };
187
+ });
188
+ // 全文搜索
189
+ server.tool("full_text_search", "全文搜索,同时搜索好友、群组和消息", {
190
+ robotId: z.string().describe("机器人账号ID"),
191
+ keyword: z.string().describe("搜索关键词"),
192
+ searchTypes: z
193
+ .array(z.enum(["friends", "groups", "messages"]))
194
+ .default(["friends", "groups", "messages"])
195
+ .describe("搜索类型"),
196
+ limit: z.number().default(20).describe("每种类型的返回结果数量限制"),
197
+ }, async (params) => {
198
+ await this.initializeChatMCP();
199
+ const result = await this.chatMCP.fullTextSearch(params);
200
+ return {
201
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
202
+ };
203
+ });
204
+ // 获取机器人统计信息
205
+ server.tool("get_robot_statistics", "获取机器人的统计信息,包括好友数、群组数、消息数等", {
206
+ robotId: z.string().describe("机器人账号ID"),
207
+ }, async (params) => {
208
+ await this.initializeChatMCP();
209
+ const result = await this.chatMCP.getRobotStatistics(params.robotId);
210
+ return {
211
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
212
+ };
213
+ });
214
+ // 获取会话详情
215
+ server.tool("get_conversation_details", "获取会话的详细信息和统计数据", {
216
+ robotId: z.string().describe("机器人账号ID"),
217
+ conversationId: z.string().describe("会话ID"),
218
+ }, async (params) => {
219
+ await this.initializeChatMCP();
220
+ const result = await this.chatMCP.getConversationDetails(params);
221
+ return {
222
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
223
+ };
224
+ });
225
+ // 获取群组成员详情
226
+ server.tool("get_group_members_detail", "获取群组成员的详细信息和活跃度统计", {
227
+ robotId: z.string().describe("机器人账号ID"),
228
+ roomWxid: z.string().describe("群微信ID"),
229
+ includeMessageStats: z
230
+ .boolean()
231
+ .default(true)
232
+ .describe("是否包含消息统计"),
233
+ }, async (params) => {
234
+ await this.initializeChatMCP();
235
+ const result = await this.chatMCP.getGroupMembersDetail(params);
236
+ return {
237
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
238
+ };
239
+ });
240
+ // 获取消息热力图
241
+ server.tool("get_message_heatmap", "获取消息活动热力图数据,分析时间分布模式", {
242
+ robotId: z.string().describe("机器人账号ID"),
243
+ conversationId: z.string().optional().describe("会话ID"),
244
+ startDate: z.string().optional().describe("开始日期(YYYY-MM-DD格式)"),
245
+ endDate: z.string().optional().describe("结束日期(YYYY-MM-DD格式)"),
246
+ granularity: z
247
+ .enum(["hour", "day", "week", "month"])
248
+ .default("hour")
249
+ .describe("时间粒度"),
250
+ }, async (params) => {
251
+ await this.initializeChatMCP();
252
+ const result = await this.chatMCP.getMessageHeatmap(params);
253
+ return {
254
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
255
+ };
256
+ });
257
+ // 获取系统信息
258
+ server.tool("get_system_info", "获取系统信息,包括数据库状态、系统性能等", {}, async () => {
259
+ await this.initializeChatMCP();
260
+ const result = await this.chatMCP.getSystemInfo();
261
+ return {
262
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
263
+ };
264
+ });
265
+ // === 分析工具 ===
266
+ // 快速查找
267
+ server.tool("quick_find", "快速查找工具,智能识别并搜索用户、群组或成员", {
268
+ robotId: z.string().describe("机器人账号ID"),
269
+ query: z.string().describe("查询内容"),
270
+ type: z
271
+ .enum(["auto", "friend", "group", "member"])
272
+ .default("auto")
273
+ .describe("查找类型"),
274
+ }, async (params) => {
275
+ await this.initializeChatMCP();
276
+ const result = await this.chatMCP.quickFind(params);
277
+ return {
278
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
279
+ };
280
+ });
281
+ // 关系分析
282
+ server.tool("analyze_relationships", "分析用户关系,包括好友关系、共同群组等", {
283
+ robotId: z.string().describe("机器人账号ID"),
284
+ userId: z.string().describe("目标用户ID"),
285
+ analysisType: z
286
+ .enum(["basic", "comprehensive"])
287
+ .default("comprehensive")
288
+ .describe("分析类型"),
289
+ }, async (params) => {
290
+ await this.initializeChatMCP();
291
+ const result = await this.chatMCP.analyzeRelationships(params);
292
+ return {
293
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
294
+ };
295
+ });
296
+ // 活动分析
297
+ server.tool("analyze_activity", "分析用户或群组的活动模式和频率", {
298
+ robotId: z.string().describe("机器人账号ID"),
299
+ targetId: z.string().describe("目标ID(用户或群组)"),
300
+ targetType: z
301
+ .enum(["auto", "user", "group"])
302
+ .default("auto")
303
+ .describe("目标类型"),
304
+ timeRange: z.number().default(30).describe("分析时间范围(天数)"),
305
+ granularity: z
306
+ .enum(["hour", "day", "week"])
307
+ .default("day")
308
+ .describe("时间粒度"),
309
+ }, async (params) => {
310
+ await this.initializeChatMCP();
311
+ const result = await this.chatMCP.analyzeActivity(params);
312
+ return {
313
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
314
+ };
315
+ });
316
+ // 内容分析
317
+ server.tool("analyze_content", "分析聊天内容,包括关键词提取、情感分析等", {
318
+ robotId: z.string().describe("机器人账号ID"),
319
+ conversationId: z.string().optional().describe("会话ID"),
320
+ timeRange: z.number().default(30).describe("分析时间范围(天数)"),
321
+ analysisTypes: z
322
+ .array(z.enum(["contentType", "keywords", "sentiment"]))
323
+ .default(["contentType", "keywords", "sentiment"])
324
+ .describe("分析类型"),
325
+ }, async (params) => {
326
+ await this.initializeChatMCP();
327
+ const result = await this.chatMCP.analyzeContent(params);
328
+ return {
329
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
330
+ };
331
+ });
332
+ // 数据导出
333
+ server.tool("export_data", "导出数据到指定格式(JSON、CSV、TXT)", {
334
+ robotId: z.string().describe("机器人账号ID"),
335
+ exportType: z
336
+ .enum(["messages", "friends", "groups", "statistics"])
337
+ .default("messages")
338
+ .describe("导出类型"),
339
+ conversationId: z
340
+ .string()
341
+ .optional()
342
+ .describe("会话ID(仅导出消息时需要)"),
343
+ format: z
344
+ .enum(["json", "csv", "txt"])
345
+ .default("json")
346
+ .describe("导出格式"),
347
+ timeRange: z.number().default(30).describe("时间范围(天数)"),
348
+ includeMetadata: z.boolean().default(true).describe("是否包含元数据"),
349
+ }, async (params) => {
350
+ await this.initializeChatMCP();
351
+ const result = await this.chatMCP.exportData(params);
352
+ return {
353
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
354
+ };
355
+ });
356
+ // === 数据写入工具 ===
357
+ // 批量创建好友
358
+ server.tool("batch_create_friends", "批量创建或更新好友信息", {
359
+ robotId: z.string().describe("机器人账号ID"),
360
+ friends: z
361
+ .array(z.object({
362
+ robotId: z.string().describe("机器人账号ID"),
363
+ wxid: z.string().describe("好友微信ID"),
364
+ wxNumber: z.string().optional().describe("好友微信号"),
365
+ name: z.string().optional().describe("昵称"),
366
+ avatar: z.string().optional().describe("头像URL"),
367
+ alias: z.string().optional().describe("别名"),
368
+ remark: z.string().optional().describe("备注"),
369
+ tags: z.string().optional().describe("标签"),
370
+ }))
371
+ .describe("好友信息数组"),
372
+ updateOnDuplicate: z.boolean().default(true).describe("重复时是否更新"),
373
+ }, async (params) => {
374
+ await this.initializeChatMCP();
375
+ const result = await this.chatMCP.batchCreateFriends(params.friends, {
376
+ updateOnDuplicate: params.updateOnDuplicate,
377
+ });
378
+ return {
379
+ content: [
380
+ {
381
+ type: "text",
382
+ text: JSON.stringify({
383
+ success: true,
384
+ message: `成功批量创建/更新 ${result.length} 条好友记录`,
385
+ recordCount: result.length,
386
+ }, null, 2),
387
+ },
388
+ ],
389
+ };
390
+ });
391
+ // 批量创建群组
392
+ server.tool("batch_create_groups", "批量创建或更新群组信息", {
393
+ robotId: z.string().describe("机器人账号ID"),
394
+ groups: z
395
+ .array(z.object({
396
+ robotId: z.string().describe("机器人账号ID"),
397
+ wxid: z.string().describe("群微信ID"),
398
+ adminId: z.string().optional().describe("群管理员微信ID"),
399
+ name: z.string().optional().describe("群名"),
400
+ avatar: z.string().optional().describe("群头像URL"),
401
+ memberCount: z.number().optional().describe("群成员数"),
402
+ }))
403
+ .describe("群组信息数组"),
404
+ updateOnDuplicate: z.boolean().default(true).describe("重复时是否更新"),
405
+ }, async (params) => {
406
+ await this.initializeChatMCP();
407
+ const result = await this.chatMCP.batchCreateGroups(params.groups, {
408
+ updateOnDuplicate: params.updateOnDuplicate,
409
+ });
410
+ return {
411
+ content: [
412
+ {
413
+ type: "text",
414
+ text: JSON.stringify({
415
+ success: true,
416
+ message: `成功批量创建/更新 ${result.length} 条群组记录`,
417
+ recordCount: result.length,
418
+ }, null, 2),
419
+ },
420
+ ],
421
+ };
422
+ });
423
+ // 批量创建群成员
424
+ server.tool("batch_create_group_members", "批量创建或更新群成员信息", {
425
+ robotId: z.string().describe("机器人账号ID"),
426
+ members: z
427
+ .array(z.object({
428
+ robotId: z.string().describe("机器人账号ID"),
429
+ roomWxid: z.string().describe("群微信ID"),
430
+ wxid: z.string().describe("群成员微信ID"),
431
+ wxNumber: z.string().optional().describe("群成员微信号"),
432
+ name: z.string().optional().describe("群成员昵称"),
433
+ avatar: z.string().optional().describe("群成员头像URL"),
434
+ alias: z.string().optional().describe("群成员别名"),
435
+ remark: z.string().optional().describe("群成员备注"),
436
+ }))
437
+ .describe("群成员信息数组"),
438
+ updateOnDuplicate: z.boolean().default(true).describe("重复时是否更新"),
439
+ }, async (params) => {
440
+ await this.initializeChatMCP();
441
+ const result = await this.chatMCP.batchCreateGroupMembers(params.members, { updateOnDuplicate: params.updateOnDuplicate });
442
+ return {
443
+ content: [
444
+ {
445
+ type: "text",
446
+ text: JSON.stringify({
447
+ success: true,
448
+ message: `成功批量创建/更新 ${result.length} 条群成员记录`,
449
+ recordCount: result.length,
450
+ }, null, 2),
451
+ },
452
+ ],
453
+ };
454
+ });
455
+ // 创建聊天消息
456
+ server.tool("create_chat_message", "创建聊天消息记录", {
457
+ robotId: z.string().describe("机器人账号ID"),
458
+ message: z
459
+ .object({
460
+ robotId: z.string().describe("机器人账号ID"),
461
+ robotName: z.string().optional().describe("机器人昵称"),
462
+ conversationId: z.string().describe("会话ID"),
463
+ conversationName: z.string().optional().describe("会话名"),
464
+ conversationAvatar: z.string().optional().describe("会话头像"),
465
+ isRobotAnswer: z
466
+ .boolean()
467
+ .default(false)
468
+ .describe("是否机器人回复"),
469
+ realUser: z.number().default(0).describe("是否真人回复"),
470
+ msgId: z.string().optional().describe("消息ID"),
471
+ contentType: z.string().default("文字").describe("内容类型"),
472
+ recordType: z.enum(["contact", "room"]).describe("记录类型"),
473
+ chatUserName: z.string().optional().describe("聊天用户昵称"),
474
+ chatUserAlias: z.string().optional().describe("聊天用户备注"),
475
+ chatUserId: z.string().optional().describe("聊天用户ID"),
476
+ chatUserAvatar: z.string().optional().describe("聊天用户头像"),
477
+ roomName: z.string().optional().describe("群聊名称"),
478
+ roomId: z.string().optional().describe("群聊ID"),
479
+ content: z.string().optional().describe("聊天内容"),
480
+ url: z.string().optional().describe("H5链接"),
481
+ fileName: z.string().optional().describe("文件名称"),
482
+ isImage: z.boolean().default(false).describe("是否图片"),
483
+ description: z.string().optional().describe("H5描述"),
484
+ imageUrl: z.string().optional().describe("H5图片链接"),
485
+ title: z.string().optional().describe("H5标题"),
486
+ timestamp: z.number().describe("聊天时间戳"),
487
+ })
488
+ .describe("消息信息"),
489
+ }, async (params) => {
490
+ await this.initializeChatMCP();
491
+ const result = await this.chatMCP.createChatMessage(params.message);
492
+ return {
493
+ content: [
494
+ {
495
+ type: "text",
496
+ text: JSON.stringify({
497
+ success: true,
498
+ message: "成功创建聊天消息记录",
499
+ messageId: result.id,
500
+ }, null, 2),
501
+ },
502
+ ],
503
+ };
504
+ });
505
+ // 工具注册完成提示(工具数量可能无法直接访问)
506
+ console.log(`✅ MCP 工具注册完成`);
507
+ }
508
+ /**
509
+ * 设置路由
510
+ */
511
+ setupRoutes() {
512
+ // 健康检查端点
513
+ this.app.get("/health", (req, res) => {
514
+ res.json({
515
+ success: true,
516
+ message: "微信聊天数据 MCP Streamable HTTP 服务运行正常",
517
+ version: "1.0.0",
518
+ protocol: "Streamable HTTP",
519
+ timestamp: new Date().toISOString(),
520
+ });
521
+ });
522
+ // MCP Streamable HTTP 主端点
523
+ this.app.post("/mcp", async (req, res) => {
524
+ try {
525
+ const sessionId = req.headers["mcp-session-id"];
526
+ let transport;
527
+ if (this.options.stateful) {
528
+ // 有状态模式:管理会话
529
+ if (sessionId && this.transports[sessionId]) {
530
+ // 重用现有传输
531
+ transport = this.transports[sessionId];
532
+ }
533
+ else if (!sessionId && isInitializeRequest(req.body)) {
534
+ // 新的初始化请求
535
+ transport = new StreamableHTTPServerTransport({
536
+ sessionIdGenerator: () => randomUUID(),
537
+ enableJsonResponse: this.options.enableJsonResponse,
538
+ onsessioninitialized: (newSessionId) => {
539
+ console.log(`✅ 会话已初始化: ${newSessionId}`);
540
+ this.transports[newSessionId] = transport;
541
+ },
542
+ });
543
+ // 连接传输到 MCP 服务器
544
+ const mcpServer = this.createMcpServer();
545
+ await mcpServer.connect(transport);
546
+ await transport.handleRequest(req, res, req.body);
547
+ return;
548
+ }
549
+ else {
550
+ // 无效请求
551
+ return res.status(400).json({
552
+ jsonrpc: "2.0",
553
+ error: {
554
+ code: -32600,
555
+ message: "无效请求:缺少会话ID或非初始化请求",
556
+ },
557
+ id: req.body?.id || null,
558
+ });
559
+ }
560
+ }
561
+ else {
562
+ // 无状态模式:每个请求独立处理
563
+ transport = new StreamableHTTPServerTransport({
564
+ sessionIdGenerator: undefined, // 无状态模式
565
+ enableJsonResponse: this.options.enableJsonResponse,
566
+ });
567
+ const mcpServer = this.createMcpServer();
568
+ await mcpServer.connect(transport);
569
+ await transport.handleRequest(req, res, req.body);
570
+ return;
571
+ }
572
+ // 处理现有会话的请求
573
+ await transport.handleRequest(req, res, req.body);
574
+ }
575
+ catch (error) {
576
+ console.error("MCP 请求处理失败:", error);
577
+ res.status(500).json({
578
+ jsonrpc: "2.0",
579
+ error: {
580
+ code: -32603,
581
+ message: "内部服务器错误",
582
+ data: error.message,
583
+ },
584
+ id: req.body?.id || null,
585
+ });
586
+ }
587
+ });
588
+ // 删除会话端点(仅有状态模式)
589
+ if (this.options.stateful) {
590
+ this.app.delete("/mcp", (req, res) => {
591
+ const sessionId = req.headers["mcp-session-id"];
592
+ if (sessionId && this.transports[sessionId]) {
593
+ try {
594
+ this.transports[sessionId].close();
595
+ delete this.transports[sessionId];
596
+ console.log(`✅ 会话已删除: ${sessionId}`);
597
+ res.json({ success: true, message: "会话已删除" });
598
+ }
599
+ catch (error) {
600
+ console.error(`删除会话失败 ${sessionId}:`, error);
601
+ res.status(500).json({
602
+ success: false,
603
+ error: "删除会话失败",
604
+ message: error.message,
605
+ });
606
+ }
607
+ }
608
+ else {
609
+ res.status(404).json({
610
+ success: false,
611
+ error: "会话不存在",
612
+ });
613
+ }
614
+ });
615
+ }
616
+ // API 信息端点
617
+ this.app.get("/", (req, res) => {
618
+ res.json({
619
+ name: "微信聊天数据 MCP Streamable HTTP 服务",
620
+ version: "1.0.0",
621
+ protocol: "MCP Streamable HTTP",
622
+ endpoints: {
623
+ health: `${req.protocol}://${req.get("host")}/health`,
624
+ mcp: `${req.protocol}://${req.get("host")}/mcp`,
625
+ ...(this.options.stateful && {
626
+ deleteSession: `${req.protocol}://${req.get("host")}/mcp (DELETE)`,
627
+ }),
628
+ },
629
+ features: {
630
+ stateful: this.options.stateful,
631
+ jsonResponse: this.options.enableJsonResponse,
632
+ cors: this.options.enableCors,
633
+ toolCount: 18,
634
+ },
635
+ });
636
+ });
637
+ }
638
+ /**
639
+ * 启动服务器
640
+ */
641
+ async start() {
642
+ this.setupRoutes();
643
+ return new Promise((resolve, reject) => {
644
+ try {
645
+ const server = this.app.listen(this.port, () => {
646
+ console.log("🚀 微信聊天数据 MCP Streamable HTTP 服务器已启动");
647
+ console.log(`📍 服务地址: http://localhost:${this.port}`);
648
+ console.log(`🔗 MCP 端点: http://localhost:${this.port}/mcp`);
649
+ console.log(`🏥 健康检查: http://localhost:${this.port}/health`);
650
+ console.log(`📋 协议: MCP Streamable HTTP`);
651
+ console.log(`🔄 模式: ${this.options.stateful ? "有状态" : "无状态"}`);
652
+ console.log(`🛠️ 工具数量: 18`);
653
+ console.log("");
654
+ resolve(server);
655
+ });
656
+ server.on("error", (err) => {
657
+ console.error("服务器启动失败:", err);
658
+ reject(err);
659
+ });
660
+ // 优雅关闭
661
+ process.on("SIGINT", async () => {
662
+ console.log("\n正在关闭服务器...");
663
+ // 关闭所有活动传输
664
+ if (this.options.stateful) {
665
+ for (const sessionId in this.transports) {
666
+ try {
667
+ console.log(`关闭会话传输: ${sessionId}`);
668
+ await this.transports[sessionId].close();
669
+ delete this.transports[sessionId];
670
+ }
671
+ catch (error) {
672
+ console.error(`关闭会话传输失败 ${sessionId}:`, error);
673
+ }
674
+ }
675
+ }
676
+ server.close(() => {
677
+ console.log("✅ 服务器已关闭");
678
+ process.exit(0);
679
+ });
680
+ });
681
+ }
682
+ catch (error) {
683
+ console.error("启动服务器时发生错误:", error);
684
+ reject(error);
685
+ }
686
+ });
687
+ }
688
+ }
689
+ export default ChatMcpStreamableServer;
690
+ //# sourceMappingURL=streamable-server.js.map