@leadbay/mcp 0.23.10 → 0.23.11
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/CHANGELOG.md +9 -2
- package/MIGRATION.md +2 -2
- package/dist/bin.js +53 -13
- package/dist/http-server.js +5 -5
- package/dist/installer-electron.js +47 -7
- package/dist/installer-gui.js +47 -7
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog — @leadbay/mcp
|
|
2
2
|
|
|
3
|
+
## 0.23.11 — 2026-07-02
|
|
4
|
+
|
|
5
|
+
Windows `.dxt` sign-in now opens the browser reliably (product#3839).
|
|
6
|
+
|
|
7
|
+
- **`openInBrowser` (Windows)** — the auto-open resolved the moment `cmd.exe` was *created*, before its internal `start` builtin actually handed the URL to the default browser. So a silent no-op (no default-browser protocol association, a locked-down shell / AppLocker, a corrupt `HKCR\http\shell\open`) went undetected: `browserOpenFailedAtBootstrap` stayed false and the user was told "a browser may have opened" when nothing did. On Windows we now wait (bounded — 800ms for `cmd start`, 1200ms otherwise) for the launcher's **exit code**, treat a non-zero exit as failure, and fall through to `rundll32 url.dll,FileProtocolHandler` (no command interpreter — the same ShellExecute path Explorer uses, with an honest exit code) and finally PowerShell `Start-Process`. When every launcher fails, the `AUTH_REQUIRED` envelope honestly says the browser couldn't be opened and shows the clickable sign-in link. The #3801 `&`-quoting `cmd start` candidate is unchanged and still tried first. macOS/Linux keep resolve-on-`spawn` (the #3805 headless-hang fix — those launchers are the hand-off).
|
|
8
|
+
- **`bin.ts` shutdown** — the `browserOpenInFlight` teardown wait rose 1.5s → 3s so the multi-launcher Windows walk can finish dispatching before exit (the sibling bootstrap wait already allows 4s; the surfaced sign-in link is the fallback either way).
|
|
9
|
+
|
|
3
10
|
## 0.23.10 — 2026-07-01
|
|
4
11
|
|
|
5
12
|
A freshly-created lens no longer reads as "empty" (product#3833).
|
|
@@ -467,7 +474,7 @@ Every tool invocation now fires an `mcp tool called` event to PostHog (same proj
|
|
|
467
474
|
|
|
468
475
|
## 0.6.1 — 2026-05-10
|
|
469
476
|
|
|
470
|
-
**Distribution**: listed in the official MCP Registry as `io.github.leadbay/leadbay-mcp` (auto-published from CI via GitHub OIDC); installable as a Claude Code plugin via `/plugin marketplace add leadbay/
|
|
477
|
+
**Distribution**: listed in the official MCP Registry as `io.github.leadbay/leadbay-mcp` (auto-published from CI via GitHub OIDC); installable as a Claude Code plugin via `/plugin marketplace add leadbay/mcp` then `/plugin install leadbay@leadbay-mcp`; submission packets prepared for the Claude.ai connector directory and Anthropic's curated MCPB extension directory.
|
|
471
478
|
|
|
472
479
|
**Registry verification**: adds `mcpName` to the npm package metadata so the MCP Registry can verify ownership of `io.github.leadbay/leadbay-mcp` against the published `@leadbay/mcp` package.
|
|
473
480
|
|
|
@@ -649,7 +656,7 @@ New `leadbay_import_leads` composite write tool.
|
|
|
649
656
|
Claude Desktop 2026 compatibility + install UX polish. Also publishes the `refine_prompt` `/user_prompt` wire-key fix that landed on `main` in 0.2.3 but never reached npm.
|
|
650
657
|
|
|
651
658
|
- **Fix [product#3504](https://github.com/leadbay/product/issues/3504)** — `install --target claude-desktop` no longer silently no-ops on Claude Desktop 2026. The app moved to the DXT (Desktop Extension) system; the legacy `claude_desktop_config.json` is UI-prefs-only there and gets overwritten on every prefs save, so a block written to it disappears a few minutes later. `install` now detects DXT (via `Claude Extensions/`, `extensions-installations.json`, or `dxt:*` keys in `config.json`), prints a loud warning pointing at the `.dxt` bundle, and default-skips the legacy write. Pass `--force-legacy` to override.
|
|
652
|
-
- **New: shipping a `.dxt` bundle** — drag-drop into Claude Desktop 2026 → Settings → Extensions. Uploaded to each [GitHub Release](https://github.com/leadbay/
|
|
659
|
+
- **New: shipping a `.dxt` bundle** — drag-drop into Claude Desktop 2026 → Settings → Extensions. Uploaded to each [GitHub Release](https://github.com/leadbay/mcp/releases). Dialog asks for token + region + write-toggle; no terminal required. Manifest is DXT 0.2 (`dxt_version: "0.2"`, `user_config.leadbay_token.sensitive: true`). Source for the build lives in `packages/dxt/`.
|
|
653
660
|
- **Fix**: `login` 401 errors no longer end with a dangling `:` when the backend returns an empty body. Messages now read `login failed (401) at <url> (wrong email or password?)`. 429/5xx get their own hints too. The core helper `formatLoginError` is exported from `@leadbay/core` so the MCP and ClawHub surfaces stay in sync.
|
|
654
661
|
- **README**: new section on `npm install -g` EACCES (sudo / npx / nvm workarounds — common on the official nodejs.org `.pkg`), and a pointer to the `.dxt` install for Claude Desktop 2026.
|
|
655
662
|
- **Also shipping** (previously merged but not yet published to npm) — `leadbay_refine_prompt` / `leadbay_set_user_prompt` now send `{ user_prompt }` instead of `{ prompt }` to `POST /user_prompt` ([product#3508](https://github.com/leadbay/product/issues/3508)). Fixes the JSON deserialization 400 Ludo hit during the 0.2.2 install session.
|
package/MIGRATION.md
CHANGED
|
@@ -166,7 +166,7 @@ The legacy `leadbay-mcp install --include-write` flag is accepted but a no-op
|
|
|
166
166
|
|
|
167
167
|
---
|
|
168
168
|
|
|
169
|
-
# Migration:
|
|
169
|
+
# Migration: leadbay-mcp 0.1.x → 0.2.0
|
|
170
170
|
|
|
171
171
|
This release is the autoplan-reviewed agent-experience overhaul. The OpenClaw
|
|
172
172
|
plugin and MCP server gain a coherent composite-tool surface so an AI agent
|
|
@@ -277,7 +277,7 @@ additionally exposes the granular tools; most users don't need it.
|
|
|
277
277
|
|
|
278
278
|
### OpenClaw plugin
|
|
279
279
|
|
|
280
|
-
In the plugin config (e.g. `openclaw config set plugins.entries.
|
|
280
|
+
In the plugin config (e.g. `openclaw config set plugins.entries.leadbay-mcp.exposeWrite true`):
|
|
281
281
|
|
|
282
282
|
```json
|
|
283
283
|
{
|
package/dist/bin.js
CHANGED
|
@@ -9407,12 +9407,12 @@ var init_login = __esm({
|
|
|
9407
9407
|
execute: async (client, params, ctx) => {
|
|
9408
9408
|
const cleanPassword = params.password.replace(/\\(.)/g, "$1");
|
|
9409
9409
|
const startWith = client.region === "fr" ? "fr" : "us";
|
|
9410
|
-
ctx?.logger?.info?.(`
|
|
9410
|
+
ctx?.logger?.info?.(`Leadbay login: email=${params.email} startRegion=${startWith}`);
|
|
9411
9411
|
try {
|
|
9412
9412
|
const result = await resolveRegion(params.email, cleanPassword, startWith);
|
|
9413
9413
|
if (client.baseUrl !== result.baseUrl) {
|
|
9414
9414
|
client.setBaseUrl(result.baseUrl, result.region);
|
|
9415
|
-
ctx?.logger?.info?.(`
|
|
9415
|
+
ctx?.logger?.info?.(`Leadbay login: switched to region=${result.region} (account is in the ${result.region.toUpperCase()} backend)`);
|
|
9416
9416
|
}
|
|
9417
9417
|
client.setToken(result.token);
|
|
9418
9418
|
client.prefetchOrgData().catch(() => {
|
|
@@ -9424,7 +9424,7 @@ var init_login = __esm({
|
|
|
9424
9424
|
verified: result.verified
|
|
9425
9425
|
};
|
|
9426
9426
|
} catch (err) {
|
|
9427
|
-
ctx?.logger?.error?.(`
|
|
9427
|
+
ctx?.logger?.error?.(`Leadbay login: failed: ${err?.message}`);
|
|
9428
9428
|
return {
|
|
9429
9429
|
error: true,
|
|
9430
9430
|
code: "LOGIN_FAILED",
|
|
@@ -25800,7 +25800,7 @@ function buildServer(client, opts = {}) {
|
|
|
25800
25800
|
}
|
|
25801
25801
|
const exposedNames = new Set(toolByName.keys());
|
|
25802
25802
|
const server = new Server(
|
|
25803
|
-
{ name: "leadbay", version: opts.version ?? "0.0.0-dev" },
|
|
25803
|
+
{ name: "leadbay-mcp", version: opts.version ?? "0.0.0-dev" },
|
|
25804
25804
|
{
|
|
25805
25805
|
capabilities: {
|
|
25806
25806
|
tools: {},
|
|
@@ -27582,6 +27582,17 @@ function browserOpenCandidates(url) {
|
|
|
27582
27582
|
{ cmd: "xdg-open", args: [url] }
|
|
27583
27583
|
];
|
|
27584
27584
|
}
|
|
27585
|
+
function windowsFallbackCandidates(url) {
|
|
27586
|
+
const sysRoot = process.env.SystemRoot || process.env.windir || "C:\\Windows";
|
|
27587
|
+
const psLiteral = `'${url.replace(/'/g, "''")}'`;
|
|
27588
|
+
return [
|
|
27589
|
+
{ cmd: `${sysRoot}\\System32\\rundll32.exe`, args: ["url.dll,FileProtocolHandler", url] },
|
|
27590
|
+
{
|
|
27591
|
+
cmd: `${sysRoot}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`,
|
|
27592
|
+
args: ["-NoProfile", "-NonInteractive", "-Command", "Start-Process", psLiteral]
|
|
27593
|
+
}
|
|
27594
|
+
];
|
|
27595
|
+
}
|
|
27585
27596
|
function browserLaunchEnv(debug) {
|
|
27586
27597
|
const env = { ...process.env };
|
|
27587
27598
|
if (process.platform !== "linux") return env;
|
|
@@ -27646,7 +27657,7 @@ function browserLaunchEnv(debug) {
|
|
|
27646
27657
|
return env;
|
|
27647
27658
|
}
|
|
27648
27659
|
async function openInBrowser(url, debug) {
|
|
27649
|
-
const candidates = browserOpenCandidates(url);
|
|
27660
|
+
const candidates = process.platform === "win32" ? [...browserOpenCandidates(url), ...windowsFallbackCandidates(url)] : browserOpenCandidates(url);
|
|
27650
27661
|
const launchEnv = browserLaunchEnv(debug);
|
|
27651
27662
|
debug?.(
|
|
27652
27663
|
`openInBrowser: platform=${process.platform} DISPLAY=${launchEnv.DISPLAY ?? "<unset>"} WAYLAND=${launchEnv.WAYLAND_DISPLAY ?? "<unset>"} DBUS=${launchEnv.DBUS_SESSION_BUS_ADDRESS ? "set" : "<unset>"} candidates=[${candidates.map((c) => c.cmd).join(", ")}]`
|
|
@@ -27655,14 +27666,43 @@ async function openInBrowser(url, debug) {
|
|
|
27655
27666
|
for (const { cmd, args } of candidates) {
|
|
27656
27667
|
try {
|
|
27657
27668
|
await new Promise((resolve, reject) => {
|
|
27658
|
-
const
|
|
27659
|
-
|
|
27669
|
+
const isWin = process.platform === "win32";
|
|
27670
|
+
const spawnOpts = { stdio: "ignore", detached: !isWin, env: launchEnv };
|
|
27671
|
+
if (isWin) spawnOpts.windowsVerbatimArguments = true;
|
|
27660
27672
|
const child = spawn3(cmd, args, spawnOpts);
|
|
27661
27673
|
child.on("error", reject);
|
|
27662
|
-
|
|
27663
|
-
|
|
27674
|
+
if (!isWin) {
|
|
27675
|
+
child.on("spawn", () => {
|
|
27676
|
+
debug?.(`spawn OK: ${cmd} (pid=${child.pid})`);
|
|
27677
|
+
child.unref();
|
|
27678
|
+
resolve();
|
|
27679
|
+
});
|
|
27680
|
+
return;
|
|
27681
|
+
}
|
|
27682
|
+
const isCmd = /cmd(\.exe)?$/i.test(cmd);
|
|
27683
|
+
const budgetMs = isCmd ? 800 : 1200;
|
|
27684
|
+
let settled = false;
|
|
27685
|
+
const finish = (fn) => {
|
|
27686
|
+
if (settled) return;
|
|
27687
|
+
settled = true;
|
|
27688
|
+
fn();
|
|
27689
|
+
};
|
|
27690
|
+
const timer = setTimeout(() => {
|
|
27691
|
+
debug?.(`exit-wait timeout (${budgetMs}ms): ${cmd} \u2014 assuming launched`);
|
|
27664
27692
|
child.unref();
|
|
27665
|
-
resolve
|
|
27693
|
+
finish(resolve);
|
|
27694
|
+
}, budgetMs);
|
|
27695
|
+
timer.unref?.();
|
|
27696
|
+
child.on("spawn", () => debug?.(`spawn OK: ${cmd} (pid=${child.pid}) \u2014 awaiting exit`));
|
|
27697
|
+
child.on("exit", (code) => {
|
|
27698
|
+
clearTimeout(timer);
|
|
27699
|
+
if (code === 0 || code === null) {
|
|
27700
|
+
debug?.(`exit ${code}: ${cmd} \u2014 launched OK`);
|
|
27701
|
+
finish(resolve);
|
|
27702
|
+
} else {
|
|
27703
|
+
debug?.(`exit ${code}: ${cmd} \u2014 treating as failed, next candidate`);
|
|
27704
|
+
finish(() => reject(new Error(`${cmd} exited ${code}`)));
|
|
27705
|
+
}
|
|
27666
27706
|
});
|
|
27667
27707
|
});
|
|
27668
27708
|
return;
|
|
@@ -27767,7 +27807,7 @@ var OAUTH_BASE_URLS = {
|
|
|
27767
27807
|
fr: "https://staging.api.leadbay.app"
|
|
27768
27808
|
}
|
|
27769
27809
|
};
|
|
27770
|
-
var VERSION = "0.23.
|
|
27810
|
+
var VERSION = "0.23.11";
|
|
27771
27811
|
var HELP = `
|
|
27772
27812
|
leadbay-mcp ${VERSION} \u2014 Leadbay Model Context Protocol server
|
|
27773
27813
|
|
|
@@ -29044,11 +29084,11 @@ async function main() {
|
|
|
29044
29084
|
}
|
|
29045
29085
|
}
|
|
29046
29086
|
if (browserOpenInFlight) {
|
|
29047
|
-
bootstrapDebug(`shutdown(code=${code}) browser-open still in flight \u2014 waiting up to
|
|
29087
|
+
bootstrapDebug(`shutdown(code=${code}) browser-open still in flight \u2014 waiting up to 3s`);
|
|
29048
29088
|
try {
|
|
29049
29089
|
await Promise.race([
|
|
29050
29090
|
browserOpenInFlight,
|
|
29051
|
-
new Promise((r) => setTimeout(r,
|
|
29091
|
+
new Promise((r) => setTimeout(r, 3e3))
|
|
29052
29092
|
]);
|
|
29053
29093
|
} catch {
|
|
29054
29094
|
}
|
package/dist/http-server.js
CHANGED
|
@@ -10529,12 +10529,12 @@ var login = {
|
|
|
10529
10529
|
execute: async (client, params, ctx) => {
|
|
10530
10530
|
const cleanPassword = params.password.replace(/\\(.)/g, "$1");
|
|
10531
10531
|
const startWith = client.region === "fr" ? "fr" : "us";
|
|
10532
|
-
ctx?.logger?.info?.(`
|
|
10532
|
+
ctx?.logger?.info?.(`Leadbay login: email=${params.email} startRegion=${startWith}`);
|
|
10533
10533
|
try {
|
|
10534
10534
|
const result = await resolveRegion(params.email, cleanPassword, startWith);
|
|
10535
10535
|
if (client.baseUrl !== result.baseUrl) {
|
|
10536
10536
|
client.setBaseUrl(result.baseUrl, result.region);
|
|
10537
|
-
ctx?.logger?.info?.(`
|
|
10537
|
+
ctx?.logger?.info?.(`Leadbay login: switched to region=${result.region} (account is in the ${result.region.toUpperCase()} backend)`);
|
|
10538
10538
|
}
|
|
10539
10539
|
client.setToken(result.token);
|
|
10540
10540
|
client.prefetchOrgData().catch(() => {
|
|
@@ -10546,7 +10546,7 @@ var login = {
|
|
|
10546
10546
|
verified: result.verified
|
|
10547
10547
|
};
|
|
10548
10548
|
} catch (err) {
|
|
10549
|
-
ctx?.logger?.error?.(`
|
|
10549
|
+
ctx?.logger?.error?.(`Leadbay login: failed: ${err?.message}`);
|
|
10550
10550
|
return {
|
|
10551
10551
|
error: true,
|
|
10552
10552
|
code: "LOGIN_FAILED",
|
|
@@ -23375,7 +23375,7 @@ function buildServer(client, opts = {}) {
|
|
|
23375
23375
|
}
|
|
23376
23376
|
const exposedNames = new Set(toolByName.keys());
|
|
23377
23377
|
const server = new Server(
|
|
23378
|
-
{ name: "leadbay", version: opts.version ?? "0.0.0-dev" },
|
|
23378
|
+
{ name: "leadbay-mcp", version: opts.version ?? "0.0.0-dev" },
|
|
23379
23379
|
{
|
|
23380
23380
|
capabilities: {
|
|
23381
23381
|
tools: {},
|
|
@@ -24062,7 +24062,7 @@ function parseWriteEnv(env = process.env) {
|
|
|
24062
24062
|
}
|
|
24063
24063
|
|
|
24064
24064
|
// src/http-server.ts
|
|
24065
|
-
var VERSION = true ? "0.23.
|
|
24065
|
+
var VERSION = true ? "0.23.11" : "0.0.0-dev";
|
|
24066
24066
|
var PORT = Number(process.env.PORT ?? 8080);
|
|
24067
24067
|
var HOST = process.env.HOST ?? "0.0.0.0";
|
|
24068
24068
|
var sseSessions = /* @__PURE__ */ new Map();
|
|
@@ -867,6 +867,17 @@ function browserOpenCandidates(url) {
|
|
|
867
867
|
{ cmd: "xdg-open", args: [url] }
|
|
868
868
|
];
|
|
869
869
|
}
|
|
870
|
+
function windowsFallbackCandidates(url) {
|
|
871
|
+
const sysRoot = process.env.SystemRoot || process.env.windir || "C:\\Windows";
|
|
872
|
+
const psLiteral = `'${url.replace(/'/g, "''")}'`;
|
|
873
|
+
return [
|
|
874
|
+
{ cmd: `${sysRoot}\\System32\\rundll32.exe`, args: ["url.dll,FileProtocolHandler", url] },
|
|
875
|
+
{
|
|
876
|
+
cmd: `${sysRoot}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`,
|
|
877
|
+
args: ["-NoProfile", "-NonInteractive", "-Command", "Start-Process", psLiteral]
|
|
878
|
+
}
|
|
879
|
+
];
|
|
880
|
+
}
|
|
870
881
|
function browserLaunchEnv(debug) {
|
|
871
882
|
const env = { ...process.env };
|
|
872
883
|
if (process.platform !== "linux") return env;
|
|
@@ -931,7 +942,7 @@ function browserLaunchEnv(debug) {
|
|
|
931
942
|
return env;
|
|
932
943
|
}
|
|
933
944
|
async function openInBrowser(url, debug) {
|
|
934
|
-
const candidates = browserOpenCandidates(url);
|
|
945
|
+
const candidates = process.platform === "win32" ? [...browserOpenCandidates(url), ...windowsFallbackCandidates(url)] : browserOpenCandidates(url);
|
|
935
946
|
const launchEnv = browserLaunchEnv(debug);
|
|
936
947
|
debug?.(
|
|
937
948
|
`openInBrowser: platform=${process.platform} DISPLAY=${launchEnv.DISPLAY ?? "<unset>"} WAYLAND=${launchEnv.WAYLAND_DISPLAY ?? "<unset>"} DBUS=${launchEnv.DBUS_SESSION_BUS_ADDRESS ? "set" : "<unset>"} candidates=[${candidates.map((c) => c.cmd).join(", ")}]`
|
|
@@ -940,14 +951,43 @@ async function openInBrowser(url, debug) {
|
|
|
940
951
|
for (const { cmd, args } of candidates) {
|
|
941
952
|
try {
|
|
942
953
|
await new Promise((resolve, reject) => {
|
|
943
|
-
const
|
|
944
|
-
|
|
954
|
+
const isWin = process.platform === "win32";
|
|
955
|
+
const spawnOpts = { stdio: "ignore", detached: !isWin, env: launchEnv };
|
|
956
|
+
if (isWin) spawnOpts.windowsVerbatimArguments = true;
|
|
945
957
|
const child = spawn3(cmd, args, spawnOpts);
|
|
946
958
|
child.on("error", reject);
|
|
947
|
-
|
|
948
|
-
|
|
959
|
+
if (!isWin) {
|
|
960
|
+
child.on("spawn", () => {
|
|
961
|
+
debug?.(`spawn OK: ${cmd} (pid=${child.pid})`);
|
|
962
|
+
child.unref();
|
|
963
|
+
resolve();
|
|
964
|
+
});
|
|
965
|
+
return;
|
|
966
|
+
}
|
|
967
|
+
const isCmd = /cmd(\.exe)?$/i.test(cmd);
|
|
968
|
+
const budgetMs = isCmd ? 800 : 1200;
|
|
969
|
+
let settled = false;
|
|
970
|
+
const finish = (fn) => {
|
|
971
|
+
if (settled) return;
|
|
972
|
+
settled = true;
|
|
973
|
+
fn();
|
|
974
|
+
};
|
|
975
|
+
const timer = setTimeout(() => {
|
|
976
|
+
debug?.(`exit-wait timeout (${budgetMs}ms): ${cmd} \u2014 assuming launched`);
|
|
949
977
|
child.unref();
|
|
950
|
-
resolve
|
|
978
|
+
finish(resolve);
|
|
979
|
+
}, budgetMs);
|
|
980
|
+
timer.unref?.();
|
|
981
|
+
child.on("spawn", () => debug?.(`spawn OK: ${cmd} (pid=${child.pid}) \u2014 awaiting exit`));
|
|
982
|
+
child.on("exit", (code) => {
|
|
983
|
+
clearTimeout(timer);
|
|
984
|
+
if (code === 0 || code === null) {
|
|
985
|
+
debug?.(`exit ${code}: ${cmd} \u2014 launched OK`);
|
|
986
|
+
finish(resolve);
|
|
987
|
+
} else {
|
|
988
|
+
debug?.(`exit ${code}: ${cmd} \u2014 treating as failed, next candidate`);
|
|
989
|
+
finish(() => reject(new Error(`${cmd} exited ${code}`)));
|
|
990
|
+
}
|
|
951
991
|
});
|
|
952
992
|
});
|
|
953
993
|
return;
|
|
@@ -1764,7 +1804,7 @@ var init_installer_gui = __esm({
|
|
|
1764
1804
|
init_install_dxt();
|
|
1765
1805
|
init_install_shared();
|
|
1766
1806
|
init_oauth();
|
|
1767
|
-
VERSION = true ? "0.23.
|
|
1807
|
+
VERSION = true ? "0.23.11" : "0.0.0-dev";
|
|
1768
1808
|
MESSAGES = {
|
|
1769
1809
|
en: {
|
|
1770
1810
|
installer: {
|
package/dist/installer-gui.js
CHANGED
|
@@ -853,6 +853,17 @@ function browserOpenCandidates(url) {
|
|
|
853
853
|
{ cmd: "xdg-open", args: [url] }
|
|
854
854
|
];
|
|
855
855
|
}
|
|
856
|
+
function windowsFallbackCandidates(url) {
|
|
857
|
+
const sysRoot = process.env.SystemRoot || process.env.windir || "C:\\Windows";
|
|
858
|
+
const psLiteral = `'${url.replace(/'/g, "''")}'`;
|
|
859
|
+
return [
|
|
860
|
+
{ cmd: `${sysRoot}\\System32\\rundll32.exe`, args: ["url.dll,FileProtocolHandler", url] },
|
|
861
|
+
{
|
|
862
|
+
cmd: `${sysRoot}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`,
|
|
863
|
+
args: ["-NoProfile", "-NonInteractive", "-Command", "Start-Process", psLiteral]
|
|
864
|
+
}
|
|
865
|
+
];
|
|
866
|
+
}
|
|
856
867
|
function browserLaunchEnv(debug) {
|
|
857
868
|
const env = { ...process.env };
|
|
858
869
|
if (process.platform !== "linux") return env;
|
|
@@ -917,7 +928,7 @@ function browserLaunchEnv(debug) {
|
|
|
917
928
|
return env;
|
|
918
929
|
}
|
|
919
930
|
async function openInBrowser(url, debug) {
|
|
920
|
-
const candidates = browserOpenCandidates(url);
|
|
931
|
+
const candidates = process.platform === "win32" ? [...browserOpenCandidates(url), ...windowsFallbackCandidates(url)] : browserOpenCandidates(url);
|
|
921
932
|
const launchEnv = browserLaunchEnv(debug);
|
|
922
933
|
debug?.(
|
|
923
934
|
`openInBrowser: platform=${process.platform} DISPLAY=${launchEnv.DISPLAY ?? "<unset>"} WAYLAND=${launchEnv.WAYLAND_DISPLAY ?? "<unset>"} DBUS=${launchEnv.DBUS_SESSION_BUS_ADDRESS ? "set" : "<unset>"} candidates=[${candidates.map((c) => c.cmd).join(", ")}]`
|
|
@@ -926,14 +937,43 @@ async function openInBrowser(url, debug) {
|
|
|
926
937
|
for (const { cmd, args } of candidates) {
|
|
927
938
|
try {
|
|
928
939
|
await new Promise((resolve, reject) => {
|
|
929
|
-
const
|
|
930
|
-
|
|
940
|
+
const isWin = process.platform === "win32";
|
|
941
|
+
const spawnOpts = { stdio: "ignore", detached: !isWin, env: launchEnv };
|
|
942
|
+
if (isWin) spawnOpts.windowsVerbatimArguments = true;
|
|
931
943
|
const child = spawn3(cmd, args, spawnOpts);
|
|
932
944
|
child.on("error", reject);
|
|
933
|
-
|
|
934
|
-
|
|
945
|
+
if (!isWin) {
|
|
946
|
+
child.on("spawn", () => {
|
|
947
|
+
debug?.(`spawn OK: ${cmd} (pid=${child.pid})`);
|
|
948
|
+
child.unref();
|
|
949
|
+
resolve();
|
|
950
|
+
});
|
|
951
|
+
return;
|
|
952
|
+
}
|
|
953
|
+
const isCmd = /cmd(\.exe)?$/i.test(cmd);
|
|
954
|
+
const budgetMs = isCmd ? 800 : 1200;
|
|
955
|
+
let settled = false;
|
|
956
|
+
const finish = (fn) => {
|
|
957
|
+
if (settled) return;
|
|
958
|
+
settled = true;
|
|
959
|
+
fn();
|
|
960
|
+
};
|
|
961
|
+
const timer = setTimeout(() => {
|
|
962
|
+
debug?.(`exit-wait timeout (${budgetMs}ms): ${cmd} \u2014 assuming launched`);
|
|
935
963
|
child.unref();
|
|
936
|
-
resolve
|
|
964
|
+
finish(resolve);
|
|
965
|
+
}, budgetMs);
|
|
966
|
+
timer.unref?.();
|
|
967
|
+
child.on("spawn", () => debug?.(`spawn OK: ${cmd} (pid=${child.pid}) \u2014 awaiting exit`));
|
|
968
|
+
child.on("exit", (code) => {
|
|
969
|
+
clearTimeout(timer);
|
|
970
|
+
if (code === 0 || code === null) {
|
|
971
|
+
debug?.(`exit ${code}: ${cmd} \u2014 launched OK`);
|
|
972
|
+
finish(resolve);
|
|
973
|
+
} else {
|
|
974
|
+
debug?.(`exit ${code}: ${cmd} \u2014 treating as failed, next candidate`);
|
|
975
|
+
finish(() => reject(new Error(`${cmd} exited ${code}`)));
|
|
976
|
+
}
|
|
937
977
|
});
|
|
938
978
|
});
|
|
939
979
|
return;
|
|
@@ -1027,7 +1067,7 @@ async function oauthLogin(opts) {
|
|
|
1027
1067
|
}
|
|
1028
1068
|
|
|
1029
1069
|
// installer/installer-gui.ts
|
|
1030
|
-
var VERSION = true ? "0.23.
|
|
1070
|
+
var VERSION = true ? "0.23.11" : "0.0.0-dev";
|
|
1031
1071
|
var MESSAGES = {
|
|
1032
1072
|
en: {
|
|
1033
1073
|
installer: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leadbay/mcp",
|
|
3
|
-
"version": "0.23.
|
|
3
|
+
"version": "0.23.11",
|
|
4
4
|
"mcpName": "io.github.leadbay/leadbay-mcp",
|
|
5
5
|
"description": "Model Context Protocol (MCP) server for Leadbay — AI lead discovery, qualification, and enrichment for Claude Desktop, Cursor, and Claude Code.",
|
|
6
6
|
"type": "module",
|