@attson/atwebpilot-mcp 0.0.78 → 0.0.79
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 +94 -16
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2543,7 +2543,7 @@ var SKILL_TOOL = {
|
|
|
2543
2543
|
// package.json
|
|
2544
2544
|
var package_default = {
|
|
2545
2545
|
name: "@attson/atwebpilot-mcp",
|
|
2546
|
-
version: "0.0.
|
|
2546
|
+
version: "0.0.79",
|
|
2547
2547
|
license: "Apache-2.0",
|
|
2548
2548
|
description: "MCP server for the atwebpilot browser extension - let Codex or Claude Code drive your browser.",
|
|
2549
2549
|
homepage: "https://github.com/attson/atwebpilot#readme",
|
|
@@ -2595,39 +2595,58 @@ var MCP_VERSION = package_default.version;
|
|
|
2595
2595
|
|
|
2596
2596
|
// src/pairing-presenter.ts
|
|
2597
2597
|
import { randomUUID } from "crypto";
|
|
2598
|
+
function isCodexClient(server) {
|
|
2599
|
+
return server.getClientVersion?.()?.name.toLowerCase().includes("codex") ?? false;
|
|
2600
|
+
}
|
|
2598
2601
|
function createPairingPresenter(server, fallbackOpenUrl) {
|
|
2599
2602
|
let presentedUrl = null;
|
|
2600
2603
|
const runFallback = async (url) => {
|
|
2601
|
-
if (!fallbackOpenUrl) return;
|
|
2604
|
+
if (!fallbackOpenUrl) return false;
|
|
2602
2605
|
try {
|
|
2603
2606
|
await fallbackOpenUrl(url);
|
|
2607
|
+
return true;
|
|
2604
2608
|
} catch (error) {
|
|
2605
|
-
presentedUrl = null;
|
|
2606
2609
|
console.error(
|
|
2607
2610
|
`[atwebpilot-mcp] failed to open pairing page ${url}:`,
|
|
2608
2611
|
error instanceof Error ? error.message : String(error)
|
|
2609
2612
|
);
|
|
2613
|
+
return false;
|
|
2610
2614
|
}
|
|
2611
2615
|
};
|
|
2612
|
-
|
|
2613
|
-
if (presentedUrl === url) return;
|
|
2614
|
-
presentedUrl = url;
|
|
2615
|
-
if (!server.getClientCapabilities()?.elicitation?.url) {
|
|
2616
|
-
void runFallback(url);
|
|
2617
|
-
return;
|
|
2618
|
-
}
|
|
2616
|
+
const requestHostPresentation = (url, fallbackOnFailure) => {
|
|
2619
2617
|
void server.elicitInput({
|
|
2620
2618
|
mode: "url",
|
|
2621
2619
|
message: "Open AtWebPilot in the browser to approve this pairing request.",
|
|
2622
2620
|
url,
|
|
2623
2621
|
elicitationId: `atwebpilot-pairing-${randomUUID()}`
|
|
2624
|
-
}).catch((error) => {
|
|
2622
|
+
}).catch(async (error) => {
|
|
2625
2623
|
if (!server.transport) return;
|
|
2626
2624
|
console.error(
|
|
2627
|
-
"[atwebpilot-mcp] URL elicitation failed; falling back to the system browser:",
|
|
2625
|
+
fallbackOnFailure ? "[atwebpilot-mcp] URL elicitation failed; falling back to the system browser:" : "[atwebpilot-mcp] URL elicitation failed:",
|
|
2628
2626
|
error instanceof Error ? error.message : String(error)
|
|
2629
2627
|
);
|
|
2630
|
-
|
|
2628
|
+
if (fallbackOnFailure && await runFallback(url)) return;
|
|
2629
|
+
presentedUrl = null;
|
|
2630
|
+
});
|
|
2631
|
+
};
|
|
2632
|
+
return (url) => {
|
|
2633
|
+
if (presentedUrl === url) return;
|
|
2634
|
+
presentedUrl = url;
|
|
2635
|
+
const supportsUrlElicitation = Boolean(server.getClientCapabilities()?.elicitation?.url);
|
|
2636
|
+
if (isCodexClient(server)) {
|
|
2637
|
+
void runFallback(url).then((opened) => {
|
|
2638
|
+
if (opened || !server.transport) return;
|
|
2639
|
+
if (supportsUrlElicitation) requestHostPresentation(url, false);
|
|
2640
|
+
else presentedUrl = null;
|
|
2641
|
+
});
|
|
2642
|
+
return;
|
|
2643
|
+
}
|
|
2644
|
+
if (supportsUrlElicitation) {
|
|
2645
|
+
requestHostPresentation(url, true);
|
|
2646
|
+
return;
|
|
2647
|
+
}
|
|
2648
|
+
void runFallback(url).then((opened) => {
|
|
2649
|
+
if (!opened) presentedUrl = null;
|
|
2631
2650
|
});
|
|
2632
2651
|
};
|
|
2633
2652
|
}
|
|
@@ -2800,6 +2819,9 @@ function createMcpServer(deps, state = DEFAULT_STATE, options = {}) {
|
|
|
2800
2819
|
return server;
|
|
2801
2820
|
}
|
|
2802
2821
|
|
|
2822
|
+
// src/ensure-hub.ts
|
|
2823
|
+
import { readFile } from "fs/promises";
|
|
2824
|
+
|
|
2803
2825
|
// src/loopback-ws-hub.ts
|
|
2804
2826
|
import { WebSocketServer, WebSocket } from "ws";
|
|
2805
2827
|
import {
|
|
@@ -3444,6 +3466,57 @@ function createHubEnsurer(d) {
|
|
|
3444
3466
|
bound: () => bundle != null
|
|
3445
3467
|
};
|
|
3446
3468
|
}
|
|
3469
|
+
var DESKTOP_ENV_KEYS = [
|
|
3470
|
+
"DISPLAY",
|
|
3471
|
+
"WAYLAND_DISPLAY",
|
|
3472
|
+
"XDG_RUNTIME_DIR",
|
|
3473
|
+
"DBUS_SESSION_BUS_ADDRESS",
|
|
3474
|
+
"XAUTHORITY"
|
|
3475
|
+
];
|
|
3476
|
+
function processId(field, status) {
|
|
3477
|
+
const match = new RegExp(`^${field}:\\s+(\\d+)`, "m").exec(status);
|
|
3478
|
+
if (!match) return null;
|
|
3479
|
+
const value = Number(match[1]);
|
|
3480
|
+
return Number.isSafeInteger(value) ? value : null;
|
|
3481
|
+
}
|
|
3482
|
+
function copyDesktopVariables(target, serialized) {
|
|
3483
|
+
for (const entry of serialized.split("\0")) {
|
|
3484
|
+
const separator = entry.indexOf("=");
|
|
3485
|
+
if (separator <= 0) continue;
|
|
3486
|
+
const key = entry.slice(0, separator);
|
|
3487
|
+
if (!DESKTOP_ENV_KEYS.includes(key) || target[key]) continue;
|
|
3488
|
+
const value = entry.slice(separator + 1);
|
|
3489
|
+
if (value) target[key] = value;
|
|
3490
|
+
}
|
|
3491
|
+
}
|
|
3492
|
+
async function resolveDesktopOpenEnvironment(options = {}) {
|
|
3493
|
+
const environment = { ...options.baseEnv ?? process.env };
|
|
3494
|
+
if ((options.platform ?? process.platform) !== "linux") return environment;
|
|
3495
|
+
const expectedUid = options.uid ?? process.getuid?.();
|
|
3496
|
+
const readTextFile = options.readTextFile ?? ((path) => readFile(path, "utf8"));
|
|
3497
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3498
|
+
let pid = options.parentPid ?? process.ppid;
|
|
3499
|
+
const maxDepth = options.maxDepth ?? 12;
|
|
3500
|
+
for (let depth = 0; depth < maxDepth && pid > 1 && !seen.has(pid); depth += 1) {
|
|
3501
|
+
seen.add(pid);
|
|
3502
|
+
let status;
|
|
3503
|
+
try {
|
|
3504
|
+
status = await readTextFile(`/proc/${pid}/status`);
|
|
3505
|
+
} catch {
|
|
3506
|
+
break;
|
|
3507
|
+
}
|
|
3508
|
+
const ownerUid = processId("Uid", status);
|
|
3509
|
+
if (expectedUid !== void 0 && ownerUid !== expectedUid) break;
|
|
3510
|
+
try {
|
|
3511
|
+
copyDesktopVariables(environment, await readTextFile(`/proc/${pid}/environ`));
|
|
3512
|
+
} catch {
|
|
3513
|
+
}
|
|
3514
|
+
const parentPid = processId("PPid", status);
|
|
3515
|
+
if (parentPid === null || parentPid === pid) break;
|
|
3516
|
+
pid = parentPid;
|
|
3517
|
+
}
|
|
3518
|
+
return environment;
|
|
3519
|
+
}
|
|
3447
3520
|
function openCommands(url) {
|
|
3448
3521
|
if (process.platform === "darwin") return [{ command: "open", args: [url] }];
|
|
3449
3522
|
if (process.platform === "win32") {
|
|
@@ -3457,10 +3530,14 @@ function openCommands(url) {
|
|
|
3457
3530
|
{ command: "gio", args: ["open", url] }
|
|
3458
3531
|
];
|
|
3459
3532
|
}
|
|
3460
|
-
async function runOpenCommand({ command, args }) {
|
|
3533
|
+
async function runOpenCommand({ command, args }, environment) {
|
|
3461
3534
|
const { spawn } = await import("child_process");
|
|
3462
3535
|
await new Promise((resolve, reject) => {
|
|
3463
|
-
const child = spawn(command, args, {
|
|
3536
|
+
const child = spawn(command, args, {
|
|
3537
|
+
stdio: "ignore",
|
|
3538
|
+
detached: true,
|
|
3539
|
+
env: environment
|
|
3540
|
+
});
|
|
3464
3541
|
let settled = false;
|
|
3465
3542
|
const finish = (error) => {
|
|
3466
3543
|
if (settled) return;
|
|
@@ -3483,9 +3560,10 @@ async function runOpenCommand({ command, args }) {
|
|
|
3483
3560
|
}
|
|
3484
3561
|
async function defaultOpenUrl(url) {
|
|
3485
3562
|
const errors = [];
|
|
3563
|
+
const environment = await resolveDesktopOpenEnvironment();
|
|
3486
3564
|
for (const candidate of openCommands(url)) {
|
|
3487
3565
|
try {
|
|
3488
|
-
await runOpenCommand(candidate);
|
|
3566
|
+
await runOpenCommand(candidate, environment);
|
|
3489
3567
|
return;
|
|
3490
3568
|
} catch (error) {
|
|
3491
3569
|
errors.push(error instanceof Error ? error.message : String(error));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@attson/atwebpilot-mcp",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.79",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "MCP server for the atwebpilot browser extension - let Codex or Claude Code drive your browser.",
|
|
6
6
|
"homepage": "https://github.com/attson/atwebpilot#readme",
|