ppxc-leads-mcp 0.1.3 → 0.1.5
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/main.js +5 -3
- package/dist/mcp/diagnostics.js +3 -0
- package/dist/mcp/server.js +16 -2
- package/package.json +3 -2
- package/scripts/launch-mcp.cjs +29 -1
- package/skills/ppxc-find-customers/SKILL.md +1 -1
package/dist/main.js
CHANGED
|
@@ -36,8 +36,10 @@ function quitAfterStdioClose(reason) {
|
|
|
36
36
|
});
|
|
37
37
|
setTimeout(() => electron_1.app.exit(0), 1500).unref();
|
|
38
38
|
}
|
|
39
|
-
process.
|
|
40
|
-
process.stdin.on("
|
|
39
|
+
if (!process.env.PPXC_MCP_STDIN_FD) {
|
|
40
|
+
process.stdin.on("end", () => quitAfterStdioClose("end"));
|
|
41
|
+
process.stdin.on("close", () => quitAfterStdioClose("close"));
|
|
42
|
+
}
|
|
41
43
|
const gotLock = electron_1.app.requestSingleInstanceLock();
|
|
42
44
|
if (!gotLock) {
|
|
43
45
|
log.error("another PPXC Leads MCP instance is already running, exiting");
|
|
@@ -53,7 +55,7 @@ else {
|
|
|
53
55
|
.whenReady()
|
|
54
56
|
.then(async () => {
|
|
55
57
|
log.info(`electron ready, starting MCP stdio server (ppxc-leads-mcp v${version_1.OWN_VERSION})`);
|
|
56
|
-
await (0, server_1.startMcpServer)();
|
|
58
|
+
await (0, server_1.startMcpServer)(quitAfterStdioClose);
|
|
57
59
|
log.info("MCP server connected over stdio");
|
|
58
60
|
})
|
|
59
61
|
.catch((err) => {
|
package/dist/mcp/diagnostics.js
CHANGED
|
@@ -27,6 +27,9 @@ function readLogTail() {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
function pickOutputDir() {
|
|
30
|
+
const override = process.env.PPXC_MCP_DIAGNOSTICS_DIR?.trim();
|
|
31
|
+
if (override)
|
|
32
|
+
return override;
|
|
30
33
|
for (const name of ["desktop", "downloads"]) {
|
|
31
34
|
try {
|
|
32
35
|
const dir = electron_1.app.getPath(name);
|
package/dist/mcp/server.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.createMcpServer = createMcpServer;
|
|
|
4
4
|
exports.startMcpServer = startMcpServer;
|
|
5
5
|
const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
6
6
|
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
7
|
+
const node_fs_1 = require("node:fs");
|
|
7
8
|
const zod_1 = require("zod");
|
|
8
9
|
const platform_runner_1 = require("../browser/platform-runner");
|
|
9
10
|
const detect_platform_1 = require("../browser/platforms/detect-platform");
|
|
@@ -822,9 +823,22 @@ function createMcpServer() {
|
|
|
822
823
|
});
|
|
823
824
|
return server;
|
|
824
825
|
}
|
|
825
|
-
|
|
826
|
+
function mcpInputStream(onInputClosed) {
|
|
827
|
+
const fdRaw = process.env.PPXC_MCP_STDIN_FD?.trim();
|
|
828
|
+
if (!fdRaw)
|
|
829
|
+
return process.stdin;
|
|
830
|
+
const fd = Number(fdRaw);
|
|
831
|
+
if (!Number.isInteger(fd) || fd < 0) {
|
|
832
|
+
throw new Error(`invalid PPXC_MCP_STDIN_FD: ${fdRaw}`);
|
|
833
|
+
}
|
|
834
|
+
const stream = (0, node_fs_1.createReadStream)("", { fd, autoClose: false });
|
|
835
|
+
stream.on("end", () => onInputClosed?.(`fd${fd}-end`));
|
|
836
|
+
stream.on("close", () => onInputClosed?.(`fd${fd}-close`));
|
|
837
|
+
return stream;
|
|
838
|
+
}
|
|
839
|
+
async function startMcpServer(onInputClosed) {
|
|
826
840
|
const server = createMcpServer();
|
|
827
|
-
const transport = new stdio_js_1.StdioServerTransport();
|
|
841
|
+
const transport = new stdio_js_1.StdioServerTransport(mcpInputStream(onInputClosed), process.stdout);
|
|
828
842
|
await server.connect(transport);
|
|
829
843
|
}
|
|
830
844
|
//# sourceMappingURL=server.js.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ppxc-leads-mcp",
|
|
3
3
|
"productName": "PPXC Leads MCP",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.5",
|
|
5
5
|
"description": "PPXC 找客户能力的 MCP 工具包:智能体可调用的抖音/小红书/快手评论客户发现工具",
|
|
6
6
|
"license": "UNLICENSED",
|
|
7
7
|
"homepage": "https://opc1.me/download/mcp",
|
|
@@ -34,7 +34,8 @@
|
|
|
34
34
|
"smoke:e2e": "npm run build && electron dist/scripts/smoke-e2e-main.js",
|
|
35
35
|
"smoke:backend": "npm run build && electron dist/scripts/smoke-backend-tools-main.js",
|
|
36
36
|
"regression:static": "npm run build && node dist/scripts/regression-static-main.js",
|
|
37
|
-
"spike:probe": "npm run build && PPXC_MCP_PAGE_VISIBLE=${PPXC_MCP_PAGE_VISIBLE:-1} electron dist/scripts/spike-platform-probe-main.js"
|
|
37
|
+
"spike:probe": "npm run build && PPXC_MCP_PAGE_VISIBLE=${PPXC_MCP_PAGE_VISIBLE:-1} electron dist/scripts/spike-platform-probe-main.js",
|
|
38
|
+
"smoke:published-mcp": "node scripts/smoke-published-mcp.cjs"
|
|
38
39
|
},
|
|
39
40
|
"devDependencies": {
|
|
40
41
|
"@types/node": "^25.5.0",
|
package/scripts/launch-mcp.cjs
CHANGED
|
@@ -88,11 +88,39 @@ if (!existsSync(mainJs)) {
|
|
|
88
88
|
const env = { ...process.env };
|
|
89
89
|
delete env.ELECTRON_RUN_AS_NODE;
|
|
90
90
|
|
|
91
|
+
const useAuxStdinPipe = process.platform === "win32";
|
|
92
|
+
if (useAuxStdinPipe) {
|
|
93
|
+
env.PPXC_MCP_STDIN_FD = "3";
|
|
94
|
+
}
|
|
95
|
+
|
|
91
96
|
const child = spawn(electronBin, [mainJs], {
|
|
92
|
-
|
|
97
|
+
// Windows 上 GUI 形态的 Electron 读取 fd0 可能立刻收到 EOF,导致 MCP server
|
|
98
|
+
// 启动后马上退出。Windows 改用额外 fd3 承载 MCP 输入;stdout/stderr 仍
|
|
99
|
+
// 直接继承,stdout 完整保留给 MCP 协议输出。
|
|
100
|
+
stdio: useAuxStdinPipe ? ["ignore", "inherit", "inherit", "pipe"] : ["pipe", "inherit", "inherit"],
|
|
93
101
|
env,
|
|
94
102
|
});
|
|
95
103
|
|
|
104
|
+
const mcpInput = useAuxStdinPipe ? child.stdio[3] : child.stdin;
|
|
105
|
+
if (!mcpInput) {
|
|
106
|
+
process.stderr.write("[ppxc-leads-mcp] 启动失败:无法建立 MCP 输入管道。\n");
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
process.stdin.resume();
|
|
111
|
+
process.stdin.on("data", (chunk) => {
|
|
112
|
+
mcpInput.write(chunk);
|
|
113
|
+
});
|
|
114
|
+
process.stdin.on("end", () => {
|
|
115
|
+
mcpInput.end();
|
|
116
|
+
});
|
|
117
|
+
process.stdin.on("close", () => {
|
|
118
|
+
mcpInput.end();
|
|
119
|
+
});
|
|
120
|
+
mcpInput.on("error", () => {
|
|
121
|
+
/* child 已退出或 stdin 已关闭,忽略 EPIPE 等清理期错误 */
|
|
122
|
+
});
|
|
123
|
+
|
|
96
124
|
let exiting = false;
|
|
97
125
|
|
|
98
126
|
function exitWithChild(code, signal) {
|
|
@@ -31,7 +31,7 @@ description: 用 PPXC 找客户小组件(MCP)从抖音/小红书/快手评
|
|
|
31
31
|
|
|
32
32
|
3. **告诉用户**:「我把 PPXC 找客户小组件的配置加好了,重启/刷新一下智能体就能用。首次使用会自动下载运行环境(约一两分钟,取决于网络)。」
|
|
33
33
|
4. **重启后验证**:调 `check_status_and_login` 确认工具就位,然后从第 1 步继续。
|
|
34
|
-
5. **你没有文件编辑能力时**:把上面那段配置原样发给用户,告诉他贴进自己智能体的 MCP 设置里,并附 PPXC
|
|
34
|
+
5. **你没有文件编辑能力时**:把上面那段配置原样发给用户,告诉他贴进自己智能体的 MCP 设置里,并附 PPXC 官网接入页 https://opc1.me/download/mcp(有逐家图文步骤)。
|
|
35
35
|
|
|
36
36
|
## 标准流程(按顺序)
|
|
37
37
|
|