@lujoai/lujo-mcp 0.4.0-beta.4
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/bin/check.js +76 -0
- package/bin/cli.js +82 -0
- package/package.json +39 -0
package/bin/check.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// postinstall check — verifies the platform-specific companion package landed.
|
|
3
|
+
// If optionalDependencies resolution failed (e.g. npm without --os or a very
|
|
4
|
+
// old npm that skips platform-matched optionals), fail loudly with a clear fix.
|
|
5
|
+
'use strict';
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
|
|
9
|
+
const platform =
|
|
10
|
+
process.platform === 'win32' ? 'win32' : process.platform === 'darwin' ? 'osx' : process.platform === 'linux' ? 'linux' : process.platform;
|
|
11
|
+
const arch = process.arch === 'x64' ? 'x64' : process.arch === 'arm64' ? 'arm64' : process.arch;
|
|
12
|
+
const pkg = `lujo-mcp-${platform}-${arch}`;
|
|
13
|
+
const binFile = `lujo-mcp-server${process.platform === 'win32' ? '.exe' : ''}`;
|
|
14
|
+
|
|
15
|
+
function pkgVersionAt(pkgDir) {
|
|
16
|
+
try {
|
|
17
|
+
return JSON.parse(fs.readFileSync(path.join(pkgDir, 'package.json'), 'utf8')).version || null;
|
|
18
|
+
} catch {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let metaV = null;
|
|
24
|
+
try {
|
|
25
|
+
metaV = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8')).version || null;
|
|
26
|
+
} catch {
|
|
27
|
+
metaV = null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let exe = null;
|
|
31
|
+
const mismatches = [];
|
|
32
|
+
let dir = __dirname;
|
|
33
|
+
for (;;) {
|
|
34
|
+
for (const sub of [path.join('node_modules', '@lujoai', pkg), path.join('node_modules', pkg)]) {
|
|
35
|
+
const pkgDir = path.join(dir, sub);
|
|
36
|
+
const candidate = path.join(pkgDir, 'bin', binFile);
|
|
37
|
+
if (fs.existsSync(candidate)) {
|
|
38
|
+
const v = pkgVersionAt(pkgDir);
|
|
39
|
+
if (!metaV || !v || v === metaV) {
|
|
40
|
+
exe = candidate;
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
mismatches.push(`${pkgDir} (platform ${v} ≠ meta ${metaV})`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (exe) break;
|
|
47
|
+
const parent = path.dirname(dir);
|
|
48
|
+
if (parent === dir) break;
|
|
49
|
+
dir = parent;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (exe) {
|
|
53
|
+
process.exit(0); // good
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (mismatches.length) {
|
|
57
|
+
console.error(`[lujo-mcp-server] platform package '${pkg}' was found but its version does not match the meta package @${metaV}:`);
|
|
58
|
+
for (const m of mismatches) console.error(` - ${m}`);
|
|
59
|
+
console.error('');
|
|
60
|
+
console.error('The install is corrupt or version-mismatched. Reinstall to fix:');
|
|
61
|
+
console.error('');
|
|
62
|
+
console.error(' npm install -g @lujoai/lujo-mcp');
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
console.error(`[lujo-mcp-server] platform package '${pkg}' was not installed (binary missing at ${binFile}).`);
|
|
67
|
+
console.error('');
|
|
68
|
+
console.error('This usually happens when npm did not resolve platform-matched optionalDependencies.');
|
|
69
|
+
console.error('Fix by installing the platform package explicitly:');
|
|
70
|
+
console.error('');
|
|
71
|
+
console.error(` npm install -g @lujoai/${pkg}`);
|
|
72
|
+
console.error('');
|
|
73
|
+
console.error('Or reinstall with a fresh lockfile:');
|
|
74
|
+
console.error('');
|
|
75
|
+
console.error(' npm install -g @lujoai/lujo-mcp --force');
|
|
76
|
+
process.exit(1);
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// lujo-mcp-server launcher — locates the platform-specific binary in the companion
|
|
3
|
+
// lujo-mcp-<platform>-<arch> package and spawns it as the MCP stdio server.
|
|
4
|
+
//
|
|
5
|
+
// Mirrors the pattern used by esbuild/@biomejs/@nuphus: the root package is a thin
|
|
6
|
+
// meta package whose optionalDependencies install only the binary for the current
|
|
7
|
+
// platform. This file is the `bin` entry npm exposes as `lujo-mcp-server`.
|
|
8
|
+
'use strict';
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const { spawn } = require('child_process');
|
|
12
|
+
|
|
13
|
+
// Map Node's process.platform/arch → our platform package suffix.
|
|
14
|
+
function platformPackageName() {
|
|
15
|
+
const platform =
|
|
16
|
+
process.platform === 'win32' ? 'win32' : process.platform === 'darwin' ? 'osx' : process.platform === 'linux' ? 'linux' : process.platform;
|
|
17
|
+
const arch = process.arch === 'x64' ? 'x64' : process.arch === 'arm64' ? 'arm64' : process.arch;
|
|
18
|
+
return `lujo-mcp-${platform}-${arch}`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function binaryInDir(pkgDir, pkg, binFile) {
|
|
22
|
+
// The platform package always lays the binary at bin/lujo-mcp-server(.exe).
|
|
23
|
+
const candidate = path.join(pkgDir, 'bin', binFile);
|
|
24
|
+
if (fs.existsSync(candidate)) return candidate;
|
|
25
|
+
// Fall back to reading the platform package's package.json bin field.
|
|
26
|
+
const metaPath = path.join(pkgDir, 'package.json');
|
|
27
|
+
if (fs.existsSync(metaPath)) {
|
|
28
|
+
const meta = JSON.parse(fs.readFileSync(metaPath, 'utf8'));
|
|
29
|
+
if (meta && meta.bin) {
|
|
30
|
+
const binTarget = typeof meta.bin === 'string' ? meta.bin : meta.bin['lujo-mcp-server'] || meta.bin[pkg];
|
|
31
|
+
if (binTarget) {
|
|
32
|
+
const p = path.join(pkgDir, binTarget);
|
|
33
|
+
if (fs.existsSync(p)) return p;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function binaryNameFor(pkg) {
|
|
41
|
+
const binFile = 'lujo-mcp-server' + (process.platform === 'win32' ? '.exe' : '');
|
|
42
|
+
// npm can lay out the optional platform packages two ways:
|
|
43
|
+
// hoisted sibling or nested under the meta package. Walk up the
|
|
44
|
+
// directory tree checking node_modules at each level, like `require` does.
|
|
45
|
+
let dir = __dirname;
|
|
46
|
+
for (;;) {
|
|
47
|
+
for (const sub of [path.join('node_modules', '@lujoai', pkg), path.join('node_modules', pkg)]) {
|
|
48
|
+
const found = binaryInDir(path.join(dir, sub), pkg, binFile);
|
|
49
|
+
if (found) return found;
|
|
50
|
+
}
|
|
51
|
+
const parent = path.dirname(dir);
|
|
52
|
+
if (parent === dir) return null;
|
|
53
|
+
dir = parent;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function run() {
|
|
58
|
+
const pkg = platformPackageName();
|
|
59
|
+
const bin = binaryNameFor(pkg);
|
|
60
|
+
if (!bin) {
|
|
61
|
+
console.error(`[lujo-mcp-server] could not locate the ${pkg} binary.
|
|
62
|
+
This usually means the platform package was not installed. Install it explicitly:
|
|
63
|
+
npm install -g @lujoai/${pkg}
|
|
64
|
+
or reinstall the meta package:
|
|
65
|
+
npm install -g @lujoai/lujo-mcp`);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
const child = spawn(bin, process.argv.slice(2), {
|
|
69
|
+
stdio: 'inherit',
|
|
70
|
+
windowsHide: true,
|
|
71
|
+
});
|
|
72
|
+
child.on('error', (err) => {
|
|
73
|
+
console.error(`[lujo-mcp-server] failed to spawn ${bin}: ${err.message}`);
|
|
74
|
+
process.exit(1);
|
|
75
|
+
});
|
|
76
|
+
child.on('exit', (code, signal) => {
|
|
77
|
+
if (signal) process.kill(process.pid, signal);
|
|
78
|
+
else process.exit(code == null ? 0 : code);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
run();
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lujoai/lujo-mcp",
|
|
3
|
+
"version": "0.4.0-beta.4",
|
|
4
|
+
"description": "Lujo-MCP — AI 智能调试 MCP Server(桌面/浏览器自动化无关)。平台二进制通过 optionalDependencies 自动选择,开箱即用。",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/Ljj041120/Lujo-MCP.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/Ljj041120/Lujo-MCP",
|
|
11
|
+
"keywords": [
|
|
12
|
+
"mcp",
|
|
13
|
+
"model-context-protocol",
|
|
14
|
+
"debug",
|
|
15
|
+
"ai-debug",
|
|
16
|
+
"debugging",
|
|
17
|
+
"lujo"
|
|
18
|
+
],
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=16"
|
|
21
|
+
},
|
|
22
|
+
"bin": {
|
|
23
|
+
"lujo-mcp-server": "bin/cli.js"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"bin"
|
|
27
|
+
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"postinstall": "node bin/check.js",
|
|
30
|
+
"prepublishOnly": "node ./scripts/check-clean-bin.js"
|
|
31
|
+
},
|
|
32
|
+
"optionalDependencies": {
|
|
33
|
+
"@lujoai/lujo-mcp-win32-x64": "0.4.0-beta.4",
|
|
34
|
+
"@lujoai/lujo-mcp-win32-arm64": "0.4.0-beta.4",
|
|
35
|
+
"@lujoai/lujo-mcp-linux-x64": "0.4.0-beta.4",
|
|
36
|
+
"@lujoai/lujo-mcp-linux-arm64": "0.4.0-beta.4",
|
|
37
|
+
"@lujoai/lujo-mcp-osx-arm64": "0.4.0-beta.4"
|
|
38
|
+
}
|
|
39
|
+
}
|