daguands-mcp 1.0.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 ADDED
@@ -0,0 +1,167 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * 本地 MCP 服务器 - 使用 STDIO 与 OpenClaw 通信
4
+ *
5
+ * 架构:
6
+ * OpenClaw (STDIO) <-> Local Server (WebSocket) <-> Chrome Extension
7
+ *
8
+ * 本服务器作为中间层:
9
+ * 1. 通过 STDIO 与 OpenClaw 通信 (MCP 协议)
10
+ * 2. 通过 WebSocket 与 Chrome 扩展通信
11
+ * 3. 转发工具调用请求到扩展
12
+ */
13
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
14
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
15
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
16
+ import { WebSocketServer, WebSocket } from 'ws';
17
+ import { getAllTools } from './tools/index.js';
18
+ // 使用较高端口号,减少冲突(18765 = 1 + 8765)
19
+ const WS_PORT = parseInt(process.env.DAGUAN_WS_PORT || '18765');
20
+ // 日志函数 (写入到 stderr,不影响 STDIO 通信)
21
+ function log(message, ...args) {
22
+ console.error(`[Local Server] ${message}`, ...args);
23
+ }
24
+ /**
25
+ * 扩展连接管理
26
+ */
27
+ class ExtensionManager {
28
+ constructor(wss) {
29
+ this.wss = wss;
30
+ this.ws = null;
31
+ this.pendingRequests = new Map();
32
+ this.setupWebSocket();
33
+ }
34
+ setupWebSocket() {
35
+ log(`🌐 WebSocket 服务器启动在端口 ${WS_PORT}`);
36
+ this.wss.on('connection', (ws) => {
37
+ log('✅ Chrome 扩展已连接');
38
+ this.ws = ws;
39
+ ws.on('message', (data) => {
40
+ try {
41
+ const message = JSON.parse(data.toString());
42
+ this.handleExtensionMessage(message);
43
+ }
44
+ catch (error) {
45
+ log('解析消息失败:', error);
46
+ }
47
+ });
48
+ ws.on('close', () => {
49
+ log('❌ Chrome 扩展断开连接');
50
+ this.ws = null;
51
+ });
52
+ ws.on('error', (error) => {
53
+ log('WebSocket 错误:', error);
54
+ });
55
+ });
56
+ }
57
+ handleExtensionMessage(message) {
58
+ const { requestId, type, data, error } = message;
59
+ if (type === 'response') {
60
+ const pending = this.pendingRequests.get(requestId);
61
+ if (pending) {
62
+ this.pendingRequests.delete(requestId);
63
+ if (error) {
64
+ pending.reject(new Error(error));
65
+ }
66
+ else {
67
+ pending.resolve(data);
68
+ }
69
+ }
70
+ }
71
+ }
72
+ /**
73
+ * 向扩展发送请求
74
+ */
75
+ async sendRequest(type, params) {
76
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
77
+ throw new Error('Chrome 扩展未连接');
78
+ }
79
+ const requestId = `req-${Date.now()}-${Math.random()}`;
80
+ return new Promise((resolve, reject) => {
81
+ this.pendingRequests.set(requestId, { resolve, reject });
82
+ this.ws.send(JSON.stringify({
83
+ requestId,
84
+ type,
85
+ params,
86
+ }));
87
+ // 30秒超时
88
+ setTimeout(() => {
89
+ if (this.pendingRequests.has(requestId)) {
90
+ this.pendingRequests.delete(requestId);
91
+ reject(new Error('请求超时'));
92
+ }
93
+ }, 30000);
94
+ });
95
+ }
96
+ isConnected() {
97
+ return this.ws !== null && this.ws.readyState === WebSocket.OPEN;
98
+ }
99
+ }
100
+ /**
101
+ * 主函数
102
+ */
103
+ async function main() {
104
+ log('🚀 达观AI MCP 本地服务器启动中...');
105
+ // 创建 WebSocket 服务器
106
+ const wss = new WebSocketServer({ port: WS_PORT });
107
+ const extensionManager = new ExtensionManager(wss);
108
+ // 创建 MCP Server
109
+ const server = new Server({
110
+ name: 'daguan-ai-standalone',
111
+ version: '2.0.0',
112
+ }, {
113
+ capabilities: {
114
+ tools: {},
115
+ },
116
+ });
117
+ // 处理工具列表请求
118
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
119
+ log('📋 处理 tools/list 请求');
120
+ // 直接返回本地定义的工具(不需要扩展连接)
121
+ const tools = getAllTools();
122
+ log(`返回 ${tools.length} 个工具`);
123
+ return { tools };
124
+ });
125
+ // 处理工具调用请求
126
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
127
+ const { name, arguments: args } = request.params;
128
+ log(`🔧 处理工具调用: ${name}`, args);
129
+ if (!extensionManager.isConnected()) {
130
+ throw new Error('Chrome 扩展未连接,请确保已安装并启用扩展');
131
+ }
132
+ try {
133
+ // 转发执行请求到扩展
134
+ const result = await extensionManager.sendRequest('tool_call', {
135
+ name,
136
+ arguments: args,
137
+ });
138
+ log(`✅ 工具 ${name} 执行成功`);
139
+ return result;
140
+ }
141
+ catch (error) {
142
+ log(`❌ 工具 ${name} 执行失败:`, error);
143
+ throw error;
144
+ }
145
+ });
146
+ // 使用 STDIO Transport 连接 OpenClaw
147
+ const transport = new StdioServerTransport();
148
+ await server.connect(transport);
149
+ log('✅ MCP 服务器已就绪');
150
+ log(`等待连接:`);
151
+ log(` - OpenClaw: 通过 STDIO`);
152
+ log(` - Chrome 扩展: ws://127.0.0.1:${WS_PORT}`);
153
+ }
154
+ // 错误处理
155
+ process.on('uncaughtException', (error) => {
156
+ log('❌ 未捕获的异常:', error);
157
+ process.exit(1);
158
+ });
159
+ process.on('unhandledRejection', (reason) => {
160
+ log('❌ 未处理的 Promise 拒绝:', reason);
161
+ process.exit(1);
162
+ });
163
+ // 启动
164
+ main().catch((error) => {
165
+ log('❌ 启动失败:', error);
166
+ process.exit(1);
167
+ });
@@ -0,0 +1,54 @@
1
+ /**
2
+ * 抖音平台工具
3
+ */
4
+ export const DOUYIN_TOOLS = [
5
+ {
6
+ name: 'fetch_douyin_video_info',
7
+ description: '获取抖音视频基本信息(标题、作者、点赞数、评论数)',
8
+ platform: 'douyin',
9
+ inputSchema: {
10
+ type: 'object',
11
+ properties: {
12
+ videoUrl: {
13
+ type: 'string',
14
+ description: '视频页面URL',
15
+ },
16
+ },
17
+ required: ['videoUrl'],
18
+ },
19
+ },
20
+ {
21
+ name: 'fetch_douyin_comments',
22
+ description: '获取抖音视频评论',
23
+ platform: 'douyin',
24
+ inputSchema: {
25
+ type: 'object',
26
+ properties: {
27
+ videoUrl: {
28
+ type: 'string',
29
+ description: '视频页面URL(可选,不提供则使用当前页面)',
30
+ },
31
+ maxCount: {
32
+ type: 'number',
33
+ description: '最大评论数量',
34
+ default: 50,
35
+ },
36
+ },
37
+ },
38
+ },
39
+ {
40
+ name: 'fetch_douyin_product_info',
41
+ description: '获取抖音小店商品信息',
42
+ platform: 'douyin',
43
+ inputSchema: {
44
+ type: 'object',
45
+ properties: {
46
+ productUrl: {
47
+ type: 'string',
48
+ description: '商品页面URL',
49
+ },
50
+ },
51
+ required: ['productUrl'],
52
+ },
53
+ },
54
+ ];
@@ -0,0 +1,51 @@
1
+ /**
2
+ * 工具注册中心
3
+ * 统一管理所有平台的工具
4
+ */
5
+ import { TAOBAO_TOOLS } from './taobao.js';
6
+ /**
7
+ * 所有平台的工具
8
+ */
9
+ export const PLATFORMS = [
10
+ {
11
+ platform: 'taobao',
12
+ description: '淘宝/天猫',
13
+ tools: TAOBAO_TOOLS,
14
+ },
15
+ // 未来可以添加更多平台:
16
+ // {
17
+ // platform: 'jd',
18
+ // description: '京东电商数据采集',
19
+ // tools: JD_TOOLS,
20
+ // },
21
+ // {
22
+ // platform: 'xiaohongshu',
23
+ // description: '小红书内容数据采集',
24
+ // tools: XIAOHONGSHU_TOOLS,
25
+ // },
26
+ ];
27
+ /**
28
+ * 获取所有工具(扁平化列表)
29
+ */
30
+ export function getAllTools() {
31
+ return PLATFORMS.flatMap((platform) => platform.tools);
32
+ }
33
+ /**
34
+ * 根据平台获取工具
35
+ */
36
+ export function getToolsByPlatform(platform) {
37
+ const platformTools = PLATFORMS.find((p) => p.platform === platform);
38
+ return platformTools?.tools || [];
39
+ }
40
+ /**
41
+ * 根据名称获取工具
42
+ */
43
+ export function getToolByName(name) {
44
+ return getAllTools().find((tool) => tool.name === name);
45
+ }
46
+ /**
47
+ * 获取所有平台信息
48
+ */
49
+ export function getAllPlatforms() {
50
+ return PLATFORMS;
51
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * 淘宝/天猫平台工具
3
+ */
4
+ export const TAOBAO_TOOLS = [
5
+ {
6
+ name: 'fetch_product_info',
7
+ description: '获取淘宝商品的基本信息(标题、价格、主图)',
8
+ platform: 'taobao',
9
+ inputSchema: {
10
+ type: 'object',
11
+ properties: {
12
+ productUrl: {
13
+ type: 'string',
14
+ description: '商品页面URL',
15
+ },
16
+ },
17
+ required: ['productUrl'],
18
+ },
19
+ },
20
+ {
21
+ name: 'fetch_taobao_reviews',
22
+ description: '获取淘宝商品评价数据,支持过滤和数量限制',
23
+ platform: 'taobao',
24
+ inputSchema: {
25
+ type: 'object',
26
+ properties: {
27
+ productUrl: {
28
+ type: 'string',
29
+ description: '商品页面URL(可选,不提供则使用当前激活的标签页)',
30
+ },
31
+ maxCount: {
32
+ type: 'number',
33
+ description: '最大评价数量,默认20条',
34
+ default: 20,
35
+ },
36
+ filterType: {
37
+ type: 'string',
38
+ enum: ['all', 'good', 'medium', 'bad'],
39
+ description: '评价类型过滤:all=全部, good=好评, medium=中评, bad=差评',
40
+ default: 'all',
41
+ },
42
+ },
43
+ },
44
+ },
45
+ {
46
+ name: 'fetch_taobao_shop_info',
47
+ description: '获取淘宝店铺信息(店铺名称、评分、关注数)',
48
+ platform: 'taobao',
49
+ inputSchema: {
50
+ type: 'object',
51
+ properties: {
52
+ shopUrl: {
53
+ type: 'string',
54
+ description: '店铺页面URL',
55
+ },
56
+ },
57
+ required: ['shopUrl'],
58
+ },
59
+ },
60
+ ];
@@ -0,0 +1,4 @@
1
+ /**
2
+ * 工具定义类型
3
+ */
4
+ export {};
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "daguands-mcp",
3
+ "version": "1.0.0",
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
+ "ws": "^8.14.2"
22
+ },
23
+ "devDependencies": {
24
+ "@types/node": "^20.10.5",
25
+ "@types/ws": "^8.5.10",
26
+ "typescript": "^5.3.3"
27
+ },
28
+ "keywords": [
29
+ "mcp",
30
+ "openclaw",
31
+ "taobao",
32
+ "ecommerce",
33
+ "chrome-extension"
34
+ ],
35
+ "author": "Daguands",
36
+ "license": "MIT"
37
+ }