daguands-mcp 1.0.21 → 1.0.23

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/config.js ADDED
@@ -0,0 +1,56 @@
1
+ /**
2
+ * 守护进程和MCP服务器配置
3
+ */
4
+ /**
5
+ * 默认配置
6
+ */
7
+ export const defaultConfig = {
8
+ timeouts: {
9
+ httpRequest: 900000, // 15分钟 (MCP Server → daemon)
10
+ wsRequest: 900000, // 15分钟 (daemon → 扩展)
11
+ extensionMessage: 900000, // 15分钟 (扩展 → content script)
12
+ },
13
+ ports: {
14
+ ws: 28765, // WebSocket端口
15
+ http: 28766, // HTTP API端口
16
+ },
17
+ logging: {
18
+ enableDataSizeLog: true, // 记录数据大小
19
+ enableDataPreview: true, // 记录数据预览
20
+ },
21
+ };
22
+ /**
23
+ * 从环境变量加载配置
24
+ */
25
+ export function loadConfig() {
26
+ const config = { ...defaultConfig };
27
+ // 从环境变量覆盖超时配置
28
+ if (process.env.DAGUAN_HTTP_TIMEOUT) {
29
+ config.timeouts.httpRequest = parseInt(process.env.DAGUAN_HTTP_TIMEOUT);
30
+ }
31
+ if (process.env.DAGUAN_WS_TIMEOUT) {
32
+ config.timeouts.wsRequest = parseInt(process.env.DAGUAN_WS_TIMEOUT);
33
+ }
34
+ if (process.env.DAGUAN_EXT_TIMEOUT) {
35
+ config.timeouts.extensionMessage = parseInt(process.env.DAGUAN_EXT_TIMEOUT);
36
+ }
37
+ // 从环境变量覆盖端口配置
38
+ if (process.env.DAGUAN_WS_PORT) {
39
+ config.ports.ws = parseInt(process.env.DAGUAN_WS_PORT);
40
+ }
41
+ if (process.env.DAGUAN_HTTP_PORT) {
42
+ config.ports.http = parseInt(process.env.DAGUAN_HTTP_PORT);
43
+ }
44
+ // 日志配置
45
+ if (process.env.DAGUAN_LOG_DATA_SIZE === 'false') {
46
+ config.logging.enableDataSizeLog = false;
47
+ }
48
+ if (process.env.DAGUAN_LOG_DATA_PREVIEW === 'false') {
49
+ config.logging.enableDataPreview = false;
50
+ }
51
+ return config;
52
+ }
53
+ /**
54
+ * 全局配置实例
55
+ */
56
+ export const config = loadConfig();
package/dist/daemon.js CHANGED
@@ -3,8 +3,9 @@ import express from 'express';
3
3
  import { createServer } from 'http';
4
4
  import { getAllTools } from './tools/index.js';
5
5
  import { daemonLog as log } from './logger.js';
6
- const WS_PORT = 28765;
7
- const HTTP_PORT = 28766;
6
+ import { config } from './config.js';
7
+ const WS_PORT = config.ports.ws;
8
+ const HTTP_PORT = config.ports.http;
8
9
  /**
9
10
  * 扩展连接管理
10
11
  */
@@ -43,22 +44,40 @@ class ExtensionManager {
43
44
  }
44
45
  handleExtensionMessage(message) {
45
46
  const { requestId, type, data, error } = message;
46
- log('收到扩展消息:', JSON.stringify(message).substring(0, 200) + '...');
47
+ // 计算数据大小
48
+ let dataSize = 0;
49
+ if (data !== undefined && data !== null) {
50
+ try {
51
+ dataSize = JSON.stringify(data).length;
52
+ }
53
+ catch (e) {
54
+ log('⚠️ 无法计算数据大小:', e);
55
+ }
56
+ }
57
+ if (config.logging.enableDataSizeLog) {
58
+ log(`收到扩展消息: requestId=${requestId}, type=${type}, dataSize=${dataSize}bytes`);
59
+ }
60
+ if (config.logging.enableDataPreview && dataSize > 0) {
61
+ const preview = JSON.stringify(data).substring(0, 100);
62
+ log(`数据预览: ${preview}${dataSize > 100 ? '...' : ''}`);
63
+ }
47
64
  if (type === 'response') {
48
65
  const pending = this.pendingRequests.get(requestId);
49
66
  if (pending) {
50
67
  this.pendingRequests.delete(requestId);
51
68
  if (error) {
52
- log(`请求 ${requestId} 失败:`, error);
69
+ log(`❌ 请求 ${requestId} 失败:`, error);
53
70
  pending.reject(new Error(error));
54
71
  }
55
72
  else {
56
- log(`请求 ${requestId} 成功,返回数据:`, JSON.stringify(data).substring(0, 100) + '...');
73
+ log(`✅ 请求 ${requestId} 成功,数据大小: ${dataSize}bytes`);
74
+ // 直接传递data对象,不要再次序列化
75
+ // data已经是从JSON.parse解析出来的对象
57
76
  pending.resolve(data);
58
77
  }
59
78
  }
60
79
  else {
61
- log(`警告:收到未知请求的响应: ${requestId}`);
80
+ log(`⚠️ 警告:收到未知请求的响应: ${requestId}`);
62
81
  }
63
82
  }
64
83
  }
@@ -88,14 +107,14 @@ class ExtensionManager {
88
107
  log('发送消息内容:', message.substring(0, 200));
89
108
  this.ws.send(message);
90
109
  log('✅ 消息已发送,等待响应...');
91
- // 超时
110
+ // 使用配置的超时时间
92
111
  setTimeout(() => {
93
112
  if (this.pendingRequests.has(requestId)) {
94
- log('⏰ 请求超时:', requestId);
113
+ log(`⏰ 请求超时: ${requestId} (${config.timeouts.wsRequest}ms)`);
95
114
  this.pendingRequests.delete(requestId);
96
- reject(new Error('请求超时'));
115
+ reject(new Error(`请求超时 (${config.timeouts.wsRequest / 1000}秒)`));
97
116
  }
98
- }, 600000);
117
+ }, config.timeouts.wsRequest);
99
118
  });
100
119
  }
101
120
  isConnected() {
@@ -107,6 +126,15 @@ class ExtensionManager {
107
126
  */
108
127
  export async function startDaemon() {
109
128
  log('🚀 守护进程启动中...');
129
+ log('='.repeat(60));
130
+ log('配置信息:');
131
+ log(` WebSocket端口: ${WS_PORT}`);
132
+ log(` HTTP API端口: ${HTTP_PORT}`);
133
+ log(` HTTP请求超时: ${config.timeouts.httpRequest}ms (${config.timeouts.httpRequest / 1000}秒)`);
134
+ log(` WebSocket请求超时: ${config.timeouts.wsRequest}ms (${config.timeouts.wsRequest / 1000}秒)`);
135
+ log(` 记录数据大小: ${config.logging.enableDataSizeLog ? '是' : '否'}`);
136
+ log(` 记录数据预览: ${config.logging.enableDataPreview ? '是' : '否'}`);
137
+ log('='.repeat(60));
110
138
  // 创建WebSocket服务器
111
139
  const wss = new WebSocketServer({ port: WS_PORT });
112
140
  log(`🌐 WebSocket服务器启动在端口 ${WS_PORT}`);
package/dist/index.js CHANGED
@@ -7,7 +7,8 @@ import { fileURLToPath } from 'url';
7
7
  import { dirname, join } from 'path';
8
8
  import { getAllTools } from './tools/index.js';
9
9
  import { mcpLog as log } from './logger.js';
10
- const DAEMON_HTTP_PORT = 28766;
10
+ import { config } from './config.js';
11
+ const DAEMON_HTTP_PORT = config.ports.http;
11
12
  const __filename = fileURLToPath(import.meta.url);
12
13
  const __dirname = dirname(__filename);
13
14
  async function checkDaemon() {
@@ -44,11 +45,19 @@ async function startDaemon() {
44
45
  throw new Error('守护进程启动超时');
45
46
  }
46
47
  async function callDaemonTool(name, args) {
48
+ // 计算参数大小
49
+ const argsSize = JSON.stringify(args).length;
47
50
  log(`📤 调用守护进程工具: ${name}`);
48
- log(`参数:`, JSON.stringify(args).substring(0, 200));
51
+ if (config.logging.enableDataSizeLog) {
52
+ log(`参数大小: ${argsSize}bytes`);
53
+ }
54
+ if (config.logging.enableDataPreview) {
55
+ log(`参数预览:`, JSON.stringify(args).substring(0, 100) + (argsSize > 100 ? '...' : ''));
56
+ }
49
57
  try {
50
58
  const url = `http://127.0.0.1:${DAEMON_HTTP_PORT}/tool_call`;
51
59
  log(`发送HTTP请求到: ${url}`);
60
+ log(`使用超时: ${config.timeouts.httpRequest}ms (${config.timeouts.httpRequest / 1000}秒)`);
52
61
  const response = await fetch(url, {
53
62
  method: 'POST',
54
63
  headers: {
@@ -58,7 +67,7 @@ async function callDaemonTool(name, args) {
58
67
  name,
59
68
  arguments: args,
60
69
  }),
61
- signal: AbortSignal.timeout(30000),
70
+ signal: AbortSignal.timeout(config.timeouts.httpRequest),
62
71
  });
63
72
  log(`收到HTTP响应: status=${response.status} ${response.statusText}`);
64
73
  if (!response.ok) {
@@ -67,18 +76,25 @@ async function callDaemonTool(name, args) {
67
76
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
68
77
  }
69
78
  const result = await response.json();
70
- log(`守护进程返回:`, JSON.stringify(result).substring(0, 200));
79
+ // 计算返回结果大小
80
+ const resultSize = JSON.stringify(result.result || {}).length;
81
+ if (config.logging.enableDataSizeLog) {
82
+ log(`守护进程返回数据大小: ${resultSize}bytes`);
83
+ }
84
+ if (config.logging.enableDataPreview) {
85
+ log(`返回数据预览:`, JSON.stringify(result).substring(0, 200) + (resultSize > 200 ? '...' : ''));
86
+ }
71
87
  if (!result.success) {
72
88
  log(`❌ 工具调用失败:`, result.error);
73
89
  throw new Error(result.error || '工具调用失败');
74
90
  }
75
- log(`✅ 工具调用成功`);
91
+ log(`✅ 工具调用成功,数据大小: ${resultSize}bytes`);
76
92
  return result.result;
77
93
  }
78
94
  catch (error) {
79
95
  if (error instanceof Error && error.name === 'AbortError') {
80
- log(`⏰ 请求超时`);
81
- throw new Error('请求超时');
96
+ log(`⏰ HTTP请求超时 (${config.timeouts.httpRequest / 1000}秒)`);
97
+ throw new Error(`请求超时 (${config.timeouts.httpRequest / 1000}秒)`);
82
98
  }
83
99
  log(`❌ 调用守护进程失败:`, error);
84
100
  throw error;
@@ -89,6 +105,13 @@ async function callDaemonTool(name, args) {
89
105
  */
90
106
  async function main() {
91
107
  log('🚀 MCP Server启动中...');
108
+ log('='.repeat(60));
109
+ log('配置信息:');
110
+ log(` 守护进程地址: http://127.0.0.1:${DAEMON_HTTP_PORT}`);
111
+ log(` HTTP请求超时: ${config.timeouts.httpRequest}ms (${config.timeouts.httpRequest / 1000}秒)`);
112
+ log(` 记录数据大小: ${config.logging.enableDataSizeLog ? '是' : '否'}`);
113
+ log(` 记录数据预览: ${config.logging.enableDataPreview ? '是' : '否'}`);
114
+ log('='.repeat(60));
92
115
  // 检查守护进程
93
116
  let daemonRunning = await checkDaemon();
94
117
  if (!daemonRunning) {
@@ -149,8 +172,24 @@ async function main() {
149
172
  }
150
173
  // 错误处理
151
174
  process.on('uncaughtException', (error) => {
152
- log('❌ 未捕获的异常:', error);
153
- process.exit(1);
175
+ // 检查是否是客户端断连相关的错误
176
+ const isClientDisconnect = error.code === 'EPIPE' ||
177
+ error.code === 'ECONNRESET' ||
178
+ (error.errno === -4047 && error.syscall === 'write');
179
+ if (isClientDisconnect) {
180
+ // 客户端断连是正常情况,不退出
181
+ log('⚠️ 客户端断开连接:', JSON.stringify({
182
+ code: error.code,
183
+ errno: error.errno,
184
+ syscall: error.syscall
185
+ }));
186
+ log('这通常表示客户端已获取结果并关闭连接,服务继续运行');
187
+ }
188
+ else {
189
+ // 其他异常才退出
190
+ log('❌ 未捕获的异常:', error);
191
+ process.exit(1);
192
+ }
154
193
  });
155
194
  process.on('unhandledRejection', (reason) => {
156
195
  log('❌ 未处理的Promise拒绝:', reason);
@@ -54,15 +54,6 @@ export const TAOBAO_TOOLS = [
54
54
  goodsId: {
55
55
  type: 'string',
56
56
  description: '淘宝商品Id',
57
- },
58
- pageCount: {
59
- type: 'string',
60
- default: '30',
61
- description: '要获取的总页数',
62
- },
63
- filterRate: {
64
- type: 'boolean',
65
- description: '是否过滤掉无效评价',
66
57
  }
67
58
  },
68
59
  required: ['productUrl'],
package/package.json CHANGED
@@ -1,39 +1,39 @@
1
- {
2
- "name": "daguands-mcp",
3
- "version": "1.0.21",
4
- "description": "daguands mcp",
5
- "type": "module",
6
- "main": "dist/index.js",
7
- "bin": {
8
- "daguan-mcp": "dist/index.js"
9
- },
10
- "files": [
11
- "dist"
12
- ],
13
- "scripts": {
14
- "build": "tsc",
15
- "dev": "tsc --watch",
16
- "start": "node dist/index.js",
17
- "prepublishOnly": "npm run build"
18
- },
19
- "dependencies": {
20
- "@modelcontextprotocol/sdk": "^1.0.4",
21
- "@types/express": "^5.0.6",
22
- "express": "^5.2.1",
23
- "ws": "^8.14.2"
24
- },
25
- "devDependencies": {
26
- "@types/node": "^20.10.5",
27
- "@types/ws": "^8.5.10",
28
- "typescript": "^5.3.3"
29
- },
30
- "keywords": [
31
- "mcp",
32
- "openclaw",
33
- "taobao",
34
- "ecommerce",
35
- "chrome-extension"
36
- ],
37
- "author": "Daguands",
38
- "license": "MIT"
39
- }
1
+ {
2
+ "name": "daguands-mcp",
3
+ "version": "1.0.23",
4
+ "description": "daguands mcp",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "daguan-mcp": "dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "dev": "tsc --watch",
16
+ "start": "node dist/index.js",
17
+ "prepublishOnly": "npm run build"
18
+ },
19
+ "dependencies": {
20
+ "@modelcontextprotocol/sdk": "^1.0.4",
21
+ "@types/express": "^5.0.6",
22
+ "express": "^5.2.1",
23
+ "ws": "^8.14.2"
24
+ },
25
+ "devDependencies": {
26
+ "@types/node": "^20.10.5",
27
+ "@types/ws": "^8.5.10",
28
+ "typescript": "^5.3.3"
29
+ },
30
+ "keywords": [
31
+ "mcp",
32
+ "openclaw",
33
+ "taobao",
34
+ "ecommerce",
35
+ "chrome-extension"
36
+ ],
37
+ "author": "Daguands",
38
+ "license": "MIT"
39
+ }