ornold-mcp 1.0.1 → 1.0.3

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.
Files changed (2) hide show
  1. package/dist/cli.js +926 -159
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -463,6 +463,8 @@ __export(multi_browser_exports, {
463
463
  MultiBrowserExecutor: () => MultiBrowserExecutor
464
464
  });
465
465
  import * as playwright from "patchright";
466
+ import { readFile, readdir, stat } from "node:fs/promises";
467
+ import { join as join2, extname } from "node:path";
466
468
  var MultiBrowserExecutor;
467
469
  var init_multi_browser = __esm({
468
470
  "src/executor/multi-browser.ts"() {
@@ -484,6 +486,8 @@ var init_multi_browser = __esm({
484
486
  lastMousePosition = /* @__PURE__ */ new Map();
485
487
  // Per-browser human profiles for varied timing
486
488
  profiles = /* @__PURE__ */ new Map();
489
+ // Snapshot refs map back to selectors for flow-agent style browser tools
490
+ snapshotRefs = /* @__PURE__ */ new Map();
487
491
  // Console messages collected per browser (since connect time)
488
492
  consoleMessages = /* @__PURE__ */ new Map();
489
493
  // Network requests collected per browser (since connect time)
@@ -644,6 +648,7 @@ var init_multi_browser = __esm({
644
648
  };
645
649
  this.browsers.set(endpoint.id, connected);
646
650
  console.error(`[Executor] Successfully stored ${endpoint.id} in browsers map. Total browsers: ${this.browsers.size}`);
651
+ this.snapshotRefs.set(endpoint.id, /* @__PURE__ */ new Map());
647
652
  const consoleLog = [];
648
653
  this.consoleMessages.set(endpoint.id, consoleLog);
649
654
  page.on("console", (msg) => {
@@ -668,6 +673,7 @@ var init_multi_browser = __esm({
668
673
  this.browsers.delete(endpoint.id);
669
674
  this.consoleMessages.delete(endpoint.id);
670
675
  this.networkRequests.delete(endpoint.id);
676
+ this.snapshotRefs.delete(endpoint.id);
671
677
  setTimeout(async () => {
672
678
  if (!this.browsers.has(endpoint.id)) {
673
679
  console.error(`[Executor] Attempting auto-reconnect for ${endpoint.id}...`);
@@ -701,6 +707,7 @@ var init_multi_browser = __esm({
701
707
  this.browsers.delete(browserId);
702
708
  this.consoleMessages.delete(browserId);
703
709
  this.networkRequests.delete(browserId);
710
+ this.snapshotRefs.delete(browserId);
704
711
  }
705
712
  async disconnectAll() {
706
713
  const ids = Array.from(this.browsers.keys());
@@ -940,6 +947,60 @@ var init_multi_browser = __esm({
940
947
  if (!browser) throw new Error(`Browser ${browserId} not found`);
941
948
  return browser.page;
942
949
  }
950
+ resolveSelector(target, browserId) {
951
+ if (typeof target === "string") return target;
952
+ if (target.selector) return target.selector;
953
+ if (target.ref) {
954
+ const selector = this.snapshotRefs.get(browserId)?.get(String(target.ref));
955
+ if (selector) return selector;
956
+ throw new Error(`Unknown ref "${target.ref}" for browser ${browserId}. Call browser_parallel_snapshot first.`);
957
+ }
958
+ throw new Error("Either selector or ref is required");
959
+ }
960
+ isTruthyFieldValue(value) {
961
+ return ["true", "1", "yes", "on", "checked"].includes(value.trim().toLowerCase());
962
+ }
963
+ async waitForDomStable(page, stableMs, timeoutMs) {
964
+ const startedAt = Date.now();
965
+ let lastSignature = "";
966
+ let stableSince = 0;
967
+ const pollInterval = Math.min(250, Math.max(75, Math.floor(stableMs / 3) || 100));
968
+ while (Date.now() - startedAt <= timeoutMs) {
969
+ const signature = await page.evaluate(() => JSON.stringify({
970
+ readyState: document.readyState,
971
+ nodeCount: document.querySelectorAll("*").length,
972
+ textLength: document.body?.innerText.length ?? 0,
973
+ scrollHeight: document.documentElement?.scrollHeight ?? 0,
974
+ scrollWidth: document.documentElement?.scrollWidth ?? 0
975
+ }));
976
+ if (signature === lastSignature) {
977
+ if (!stableSince) stableSince = Date.now();
978
+ if (Date.now() - stableSince >= stableMs) return;
979
+ } else {
980
+ lastSignature = signature;
981
+ stableSince = 0;
982
+ }
983
+ await page.waitForTimeout(pollInterval);
984
+ }
985
+ throw new Error(`DOM did not become stable within ${timeoutMs}ms`);
986
+ }
987
+ getMimeType(fileName) {
988
+ const ext = extname(fileName).toLowerCase();
989
+ const types = {
990
+ ".txt": "text/plain",
991
+ ".json": "application/json",
992
+ ".csv": "text/csv",
993
+ ".pdf": "application/pdf",
994
+ ".png": "image/png",
995
+ ".jpg": "image/jpeg",
996
+ ".jpeg": "image/jpeg",
997
+ ".gif": "image/gif",
998
+ ".webp": "image/webp",
999
+ ".svg": "image/svg+xml",
1000
+ ".zip": "application/zip"
1001
+ };
1002
+ return types[ext] || "application/octet-stream";
1003
+ }
943
1004
  // ==================== PARALLEL EXECUTION ====================
944
1005
  /**
945
1006
  * Get the appropriate limiter based on operation type
@@ -1249,11 +1310,20 @@ var init_multi_browser = __esm({
1249
1310
  }
1250
1311
  return results;
1251
1312
  }, !!options.compact);
1252
- let snapshot = this.formatSnapshot(elements, !!options.compact);
1313
+ const refMap = /* @__PURE__ */ new Map();
1314
+ let nextRef = 1;
1315
+ const elementsWithRefs = elements.map((element) => {
1316
+ if (!element.selector) return element;
1317
+ const ref = String(nextRef++);
1318
+ refMap.set(ref, element.selector);
1319
+ return { ...element, ref };
1320
+ });
1321
+ this.snapshotRefs.set(browserId, refMap);
1322
+ let snapshot = this.formatSnapshot(elementsWithRefs, !!options.compact);
1253
1323
  if (snapshot.length > MAX_SNAPSHOT_SIZE) {
1254
1324
  snapshot = snapshot.substring(0, MAX_SNAPSHOT_SIZE) + `
1255
1325
 
1256
- ... [TRUNCATED: ${elements.length} elements total, showing first ${MAX_SNAPSHOT_SIZE} chars]`;
1326
+ ... [TRUNCATED: ${elementsWithRefs.length} elements total, showing first ${MAX_SNAPSHOT_SIZE} chars]`;
1257
1327
  }
1258
1328
  return {
1259
1329
  browserId,
@@ -1285,6 +1355,7 @@ var init_multi_browser = __esm({
1285
1355
  let line = `- ${el.tag}`;
1286
1356
  if (el.type) line += `[type=${el.type}]`;
1287
1357
  if (el.disabled) line += " (disabled)";
1358
+ if (el.ref) line += ` [ref=${el.ref}]`;
1288
1359
  line += ` \u2192 ${el.selector}`;
1289
1360
  const details = [];
1290
1361
  if (el.placeholder) details.push(`placeholder="${el.placeholder}"`);
@@ -1341,30 +1412,32 @@ var init_multi_browser = __esm({
1341
1412
  this.lastMousePosition.set(browserId, pos);
1342
1413
  }
1343
1414
  // ==================== REF-BASED INTERACTION (human-like) ====================
1344
- async parallelClick(selector, browserIds) {
1415
+ async parallelClick(target, browserIds) {
1345
1416
  return this.executeParallel(browserIds, async (page, browserId) => {
1346
1417
  const profile = this.getProfile(browserId);
1418
+ const selector = this.resolveSelector(target, browserId);
1347
1419
  const locator = page.locator(selector);
1348
1420
  await locator.waitFor({ state: "visible", timeout: 5e3 });
1349
1421
  await ensureCursor(page);
1350
1422
  await preActionDelay(profile);
1351
- const { target } = await getClickTarget(page, locator);
1423
+ const { target: clickTarget } = await getClickTarget(page, locator);
1352
1424
  const fromPos = this.getMousePos(browserId);
1353
- await humanClick(page, target, fromPos, profile);
1354
- this.setMousePos(browserId, target);
1425
+ await humanClick(page, clickTarget, fromPos, profile);
1426
+ this.setMousePos(browserId, clickTarget);
1355
1427
  });
1356
1428
  }
1357
- async parallelFill(selector, text, browserIds) {
1429
+ async parallelFill(target, text, browserIds) {
1358
1430
  return this.executeParallel(browserIds, async (page, browserId) => {
1359
1431
  const profile = this.getProfile(browserId);
1432
+ const selector = this.resolveSelector(target, browserId);
1360
1433
  const locator = page.locator(selector);
1361
1434
  await locator.waitFor({ state: "visible", timeout: 5e3 });
1362
1435
  await ensureCursor(page);
1363
1436
  await preActionDelay(profile);
1364
- const { target } = await getClickTarget(page, locator);
1437
+ const { target: clickTarget } = await getClickTarget(page, locator);
1365
1438
  const fromPos = this.getMousePos(browserId);
1366
- await humanClick(page, target, fromPos, profile);
1367
- this.setMousePos(browserId, target);
1439
+ await humanClick(page, clickTarget, fromPos, profile);
1440
+ this.setMousePos(browserId, clickTarget);
1368
1441
  await humanDelay(80, 200);
1369
1442
  await page.keyboard.press("Meta+a");
1370
1443
  await humanDelay(30, 80);
@@ -1374,20 +1447,21 @@ var init_multi_browser = __esm({
1374
1447
  return `filled "${text}"`;
1375
1448
  });
1376
1449
  }
1377
- async parallelFillMulti(selector, texts) {
1450
+ async parallelFillMulti(target, texts) {
1378
1451
  const browserIds = Object.keys(texts);
1379
1452
  return this.executeParallel(browserIds, async (page, browserId) => {
1380
1453
  const text = texts[browserId];
1381
1454
  if (!text) throw new Error(`No text provided for browser ${browserId}`);
1382
1455
  const profile = this.getProfile(browserId);
1456
+ const selector = this.resolveSelector(target, browserId);
1383
1457
  const locator = page.locator(selector);
1384
1458
  await locator.waitFor({ state: "visible", timeout: 5e3 });
1385
1459
  await ensureCursor(page);
1386
1460
  await preActionDelay(profile);
1387
- const { target } = await getClickTarget(page, locator);
1461
+ const { target: clickTarget } = await getClickTarget(page, locator);
1388
1462
  const fromPos = this.getMousePos(browserId);
1389
- await humanClick(page, target, fromPos, profile);
1390
- this.setMousePos(browserId, target);
1463
+ await humanClick(page, clickTarget, fromPos, profile);
1464
+ this.setMousePos(browserId, clickTarget);
1391
1465
  await humanDelay(80, 200);
1392
1466
  await page.keyboard.press("Meta+a");
1393
1467
  await humanDelay(30, 80);
@@ -1396,44 +1470,47 @@ var init_multi_browser = __esm({
1396
1470
  await humanTypeText(page, text, profile);
1397
1471
  });
1398
1472
  }
1399
- async parallelType(selector, text, browserIds) {
1473
+ async parallelType(target, text, browserIds) {
1400
1474
  return this.executeParallel(browserIds, async (page, browserId) => {
1401
1475
  const profile = this.getProfile(browserId);
1476
+ const selector = this.resolveSelector(target, browserId);
1402
1477
  const locator = page.locator(selector);
1403
1478
  await locator.waitFor({ state: "visible", timeout: 5e3 });
1404
1479
  await ensureCursor(page);
1405
- const { target } = await getClickTarget(page, locator);
1480
+ const { target: clickTarget } = await getClickTarget(page, locator);
1406
1481
  const fromPos = this.getMousePos(browserId);
1407
- await humanClick(page, target, fromPos, profile);
1408
- this.setMousePos(browserId, target);
1482
+ await humanClick(page, clickTarget, fromPos, profile);
1483
+ this.setMousePos(browserId, clickTarget);
1409
1484
  await humanDelay(50, 150);
1410
1485
  await humanTypeText(page, text, profile);
1411
1486
  });
1412
1487
  }
1413
- async parallelHover(selector, browserIds) {
1488
+ async parallelHover(target, browserIds) {
1414
1489
  return this.executeParallel(browserIds, async (page, browserId) => {
1415
1490
  const profile = this.getProfile(browserId);
1491
+ const selector = this.resolveSelector(target, browserId);
1416
1492
  const locator = page.locator(selector);
1417
1493
  await locator.waitFor({ state: "visible", timeout: 5e3 });
1418
1494
  await ensureCursor(page);
1419
1495
  await preActionDelay(profile);
1420
- const { target } = await getClickTarget(page, locator);
1496
+ const { target: hoverTarget } = await getClickTarget(page, locator);
1421
1497
  const fromPos = this.getMousePos(browserId);
1422
- await humanMouseMove(page, fromPos, target, profile);
1423
- this.setMousePos(browserId, target);
1498
+ await humanMouseMove(page, fromPos, hoverTarget, profile);
1499
+ this.setMousePos(browserId, hoverTarget);
1424
1500
  });
1425
1501
  }
1426
- async parallelSelectOption(selector, values, browserIds) {
1502
+ async parallelSelectOption(target, values, browserIds) {
1427
1503
  return this.executeParallel(browserIds, async (page, browserId) => {
1428
1504
  const profile = this.getProfile(browserId);
1505
+ const selector = this.resolveSelector(target, browserId);
1429
1506
  const locator = page.locator(selector);
1430
1507
  await locator.waitFor({ state: "visible", timeout: 5e3 });
1431
1508
  await ensureCursor(page);
1432
1509
  await preActionDelay(profile);
1433
- const { target } = await getClickTarget(page, locator);
1510
+ const { target: clickTarget } = await getClickTarget(page, locator);
1434
1511
  const fromPos = this.getMousePos(browserId);
1435
- await humanClick(page, target, fromPos, profile);
1436
- this.setMousePos(browserId, target);
1512
+ await humanClick(page, clickTarget, fromPos, profile);
1513
+ this.setMousePos(browserId, clickTarget);
1437
1514
  await humanDelay(200, 500);
1438
1515
  return await locator.selectOption(values);
1439
1516
  });
@@ -1571,8 +1648,9 @@ var init_multi_browser = __esm({
1571
1648
  // ==================== WAITING ====================
1572
1649
  async parallelWaitFor(options, browserIds) {
1573
1650
  const waitTimeMs = options.time ? options.time * 1e3 : 0;
1574
- const textTimeout = 3e4;
1575
- const timeout = waitTimeMs + textTimeout + 5e3;
1651
+ const textTimeout = options.timeoutMs ?? 3e4;
1652
+ const domStableTimeout = options.timeoutMs ?? Math.max(options.domStableMs ?? 0, 5e3);
1653
+ const timeout = waitTimeMs + Math.max(textTimeout, domStableTimeout) + 5e3;
1576
1654
  return this.executeParallel(browserIds, async (page) => {
1577
1655
  if (options.time) {
1578
1656
  await page.waitForTimeout(options.time * 1e3);
@@ -1583,6 +1661,9 @@ var init_multi_browser = __esm({
1583
1661
  if (options.textGone) {
1584
1662
  await page.getByText(options.textGone).waitFor({ state: "hidden", timeout: textTimeout });
1585
1663
  }
1664
+ if (options.domStableMs) {
1665
+ await this.waitForDomStable(page, options.domStableMs, domStableTimeout);
1666
+ }
1586
1667
  }, { timeout });
1587
1668
  }
1588
1669
  // ==================== FILE OPERATIONS (downloads, uploads, drag&drop) ====================
@@ -1636,62 +1717,39 @@ var init_multi_browser = __esm({
1636
1717
  async listProjectFiles() {
1637
1718
  const dir = await this.getProjectFilesDir();
1638
1719
  if (!dir) return [];
1639
- const ids = this.getBrowserIds();
1640
- if (ids.length === 0) return [];
1641
- const browser = this.browsers.get(ids[0]);
1642
- if (!browser) return [];
1643
1720
  try {
1644
- const cdp = await browser.page.context().newCDPSession(browser.page);
1645
- try {
1646
- const result = await cdp.send("Runtime.evaluate", {
1647
- expression: `
1648
- (() => {
1649
- try {
1650
- const fs = require('fs');
1651
- const path = require('path');
1652
- const dir = ${JSON.stringify(dir)};
1653
- if (!fs.existsSync(dir)) return JSON.stringify([]);
1654
- const files = fs.readdirSync(dir).filter(f => !f.startsWith('.'));
1655
- return JSON.stringify(files.map(f => {
1656
- const stat = fs.statSync(path.join(dir, f));
1657
- return { name: f, size: stat.size, modified: stat.mtimeMs };
1658
- }));
1659
- } catch(e) { return JSON.stringify({ error: e.message }); }
1660
- })()
1661
- `,
1662
- returnByValue: true
1663
- });
1664
- const value = result.result?.value;
1665
- if (typeof value === "string") {
1666
- return JSON.parse(value);
1667
- }
1668
- } finally {
1669
- await cdp.detach().catch(() => {
1670
- });
1671
- }
1721
+ const files = await readdir(dir);
1722
+ const items = await Promise.all(
1723
+ files.filter((file) => !file.startsWith(".")).map(async (file) => {
1724
+ const fileStat = await stat(join2(dir, file));
1725
+ return { name: file, size: fileStat.size, modified: fileStat.mtimeMs };
1726
+ })
1727
+ );
1728
+ return items;
1672
1729
  } catch {
1673
1730
  }
1674
1731
  return [];
1675
1732
  }
1676
1733
  /** Upload a file from project directory via filechooser (selector-based) */
1677
- async parallelUploadFile(selector, fileName, browserIds) {
1734
+ async parallelUploadFile(target, fileName, browserIds) {
1678
1735
  const dir = await this.getProjectFilesDir();
1679
1736
  if (!dir) {
1680
1737
  throw new Error("Project files directory not available");
1681
1738
  }
1682
1739
  return this.executeParallel(browserIds, async (page, browserId) => {
1683
1740
  const profile = this.getProfile(browserId);
1741
+ const selector = this.resolveSelector(target, browserId);
1684
1742
  const locator = page.locator(selector);
1685
1743
  await locator.waitFor({ state: "visible", timeout: 5e3 });
1686
1744
  await ensureCursor(page);
1687
1745
  await preActionDelay(profile);
1688
1746
  const fileChooserPromise = page.waitForEvent("filechooser", { timeout: 1e4 });
1689
- const { target } = await getClickTarget(page, locator);
1747
+ const { target: clickTarget } = await getClickTarget(page, locator);
1690
1748
  const fromPos = this.getMousePos(browserId);
1691
- await humanClick(page, target, fromPos, profile);
1692
- this.setMousePos(browserId, target);
1749
+ await humanClick(page, clickTarget, fromPos, profile);
1750
+ this.setMousePos(browserId, clickTarget);
1693
1751
  const fileChooser = await fileChooserPromise;
1694
- const filePath = `${dir}/${fileName}`;
1752
+ const filePath = join2(dir, fileName);
1695
1753
  await fileChooser.setFiles(filePath);
1696
1754
  return `Uploaded "${fileName}" from ${dir}`;
1697
1755
  }, { timeout: 15e3 });
@@ -1702,29 +1760,56 @@ var init_multi_browser = __esm({
1702
1760
  const profile = this.getProfile(browserId);
1703
1761
  const filled = [];
1704
1762
  for (const field of fields) {
1705
- const locator = page.locator(field.selector);
1763
+ const selector = this.resolveSelector(field, browserId);
1764
+ const locator = page.locator(selector);
1706
1765
  await locator.waitFor({ state: "visible", timeout: 5e3 });
1707
1766
  await ensureCursor(page);
1708
1767
  await preActionDelay(profile);
1709
- const { target } = await getClickTarget(page, locator);
1768
+ if (field.type === "checkbox") {
1769
+ if (this.isTruthyFieldValue(field.value)) {
1770
+ await locator.check();
1771
+ } else {
1772
+ await locator.uncheck();
1773
+ }
1774
+ filled.push(`${selector}=${field.value}`);
1775
+ continue;
1776
+ }
1777
+ if (field.type === "radio") {
1778
+ await locator.check();
1779
+ filled.push(`${selector}=${field.value}`);
1780
+ continue;
1781
+ }
1782
+ if (field.type === "combobox") {
1783
+ const { target: clickTarget2 } = await getClickTarget(page, locator);
1784
+ const fromPos2 = this.getMousePos(browserId);
1785
+ await humanClick(page, clickTarget2, fromPos2, profile);
1786
+ this.setMousePos(browserId, clickTarget2);
1787
+ await humanDelay(120, 240);
1788
+ await locator.selectOption(field.value);
1789
+ filled.push(`${selector}="${field.value}"`);
1790
+ continue;
1791
+ }
1792
+ const { target: clickTarget } = await getClickTarget(page, locator);
1710
1793
  const fromPos = this.getMousePos(browserId);
1711
- await humanClick(page, target, fromPos, profile);
1712
- this.setMousePos(browserId, target);
1794
+ await humanClick(page, clickTarget, fromPos, profile);
1795
+ this.setMousePos(browserId, clickTarget);
1713
1796
  await humanDelay(80, 200);
1714
1797
  await page.keyboard.press("Meta+a");
1715
1798
  await humanDelay(30, 80);
1716
1799
  await page.keyboard.press("Backspace");
1717
1800
  await humanDelay(50, 150);
1718
1801
  await humanTypeText(page, field.value, profile);
1719
- filled.push(`${field.selector}="${field.value}"`);
1802
+ filled.push(`${selector}="${field.value}"`);
1720
1803
  }
1721
1804
  return `Filled ${filled.length} fields: ${filled.join(", ")}`;
1722
1805
  }, { timeout: fields.length * 5e3 + 5e3 });
1723
1806
  }
1724
1807
  // ==================== ELEMENT DRAG & DROP ====================
1725
- async parallelDrag(startSelector, endSelector, browserIds) {
1808
+ async parallelDrag(startTarget, endTarget, browserIds) {
1726
1809
  return this.executeParallel(browserIds, async (page, browserId) => {
1727
1810
  const profile = this.getProfile(browserId);
1811
+ const startSelector = this.resolveSelector(startTarget, browserId);
1812
+ const endSelector = this.resolveSelector(endTarget, browserId);
1728
1813
  const startLocator = page.locator(startSelector);
1729
1814
  const endLocator = page.locator(endSelector);
1730
1815
  await startLocator.waitFor({ state: "visible", timeout: 5e3 });
@@ -1890,35 +1975,37 @@ var init_multi_browser = __esm({
1890
1975
  };
1891
1976
  }
1892
1977
  /** Drag and drop a file onto a dropzone (selector-based) */
1893
- async parallelDragDropFile(selector, fileName, browserIds) {
1978
+ async parallelDragDropFile(target, fileName, browserIds) {
1894
1979
  const dir = await this.getProjectFilesDir();
1895
1980
  if (!dir) {
1896
1981
  throw new Error("Project files directory not available");
1897
1982
  }
1898
1983
  return this.executeParallel(browserIds, async (page, browserId) => {
1899
1984
  const profile = this.getProfile(browserId);
1985
+ const selector = this.resolveSelector(target, browserId);
1900
1986
  const locator = page.locator(selector);
1901
1987
  await locator.waitFor({ state: "visible", timeout: 5e3 });
1902
1988
  await ensureCursor(page);
1903
1989
  await preActionDelay(profile);
1904
- const { target } = await getClickTarget(page, locator);
1990
+ const { target: dropTarget } = await getClickTarget(page, locator);
1905
1991
  const fromPos = this.getMousePos(browserId);
1906
- await humanMouseMove(page, fromPos, target, profile);
1907
- this.setMousePos(browserId, target);
1908
- const filePath = `${dir}/${fileName}`;
1909
- await page.evaluate(async ({ x, y, fileName: fileName2, filePath: filePath2 }) => {
1992
+ await humanMouseMove(page, fromPos, dropTarget, profile);
1993
+ this.setMousePos(browserId, dropTarget);
1994
+ const filePath = join2(dir, fileName);
1995
+ const fileBytes = Array.from(await readFile(filePath));
1996
+ const mimeType = this.getMimeType(fileName);
1997
+ await page.evaluate(async ({
1998
+ x,
1999
+ y,
2000
+ fileName: fileName2,
2001
+ mimeType: mimeType2,
2002
+ fileBytes: fileBytes2
2003
+ }) => {
1910
2004
  const dropzone = document.elementFromPoint(x, y);
1911
2005
  if (!dropzone) throw new Error("No element at drop coordinates");
1912
2006
  const dataTransfer = new DataTransfer();
1913
- try {
1914
- const resp = await fetch(`file://${filePath2}`);
1915
- const blob = await resp.blob();
1916
- const file = new File([blob], fileName2, { type: blob.type });
1917
- dataTransfer.items.add(file);
1918
- } catch {
1919
- const file = new File([""], fileName2);
1920
- dataTransfer.items.add(file);
1921
- }
2007
+ const file = new File([new Uint8Array(fileBytes2)], fileName2, { type: mimeType2 });
2008
+ dataTransfer.items.add(file);
1922
2009
  const events = ["dragenter", "dragover", "drop"];
1923
2010
  for (const eventType of events) {
1924
2011
  const event = new DragEvent(eventType, {
@@ -1929,7 +2016,7 @@ var init_multi_browser = __esm({
1929
2016
  dropzone.dispatchEvent(event);
1930
2017
  await new Promise((r) => setTimeout(r, 50));
1931
2018
  }
1932
- }, { x: target.x, y: target.y, fileName, filePath });
2019
+ }, { x: dropTarget.x, y: dropTarget.y, fileName, mimeType, fileBytes });
1933
2020
  return `Dropped "${fileName}" onto element`;
1934
2021
  }, { timeout: 15e3 });
1935
2022
  }
@@ -1948,10 +2035,39 @@ var getArg = (name) => {
1948
2035
  const i = args.indexOf(`--${name}`);
1949
2036
  return i >= 0 ? args[i + 1] : void 0;
1950
2037
  };
2038
+ var getArgAny = (...names) => names.map((name) => getArg(name)).find((value) => value !== void 0);
2039
+ var getEnvAny = (...names) => names.map((name) => process.env[name]).find((value) => value !== void 0 && value !== "");
2040
+ function getOptionalPort(argNames, envNames) {
2041
+ const raw = getArgAny(...Array.isArray(argNames) ? argNames : [argNames]) ?? getEnvAny(...Array.isArray(envNames) ? envNames : [envNames]);
2042
+ if (raw === void 0 || raw === "") return void 0;
2043
+ const port = Number.parseInt(raw, 10);
2044
+ if (!Number.isFinite(port) || port <= 0) {
2045
+ const flagName = Array.isArray(argNames) ? argNames[0] : argNames;
2046
+ console.error(`[ornold] Invalid --${flagName}: ${raw}`);
2047
+ process.exit(1);
2048
+ }
2049
+ return port;
2050
+ }
2051
+ function getOptionalString(argNames, envNames) {
2052
+ const raw = getArgAny(...Array.isArray(argNames) ? argNames : [argNames]) ?? getEnvAny(...Array.isArray(envNames) ? envNames : [envNames]);
2053
+ if (raw === void 0) return void 0;
2054
+ const value = raw.trim();
2055
+ return value === "" ? void 0 : value;
2056
+ }
1951
2057
  var TOKEN = getArg("token") || process.env.ORNOLD_TOKEN || "";
1952
2058
  var SERVER_URL = getArg("server") || process.env.ORNOLD_SERVER || "wss://ornold-mcp.fly.dev/bridge";
1953
- var LINKEN_PORT = parseInt(getArg("linken-port") || process.env.LINKEN_PORT || "8080");
1954
- var DOLPHIN_PORT = parseInt(getArg("dolphin-port") || process.env.DOLPHIN_PORT || "3001");
2059
+ var LINKEN_PORT = getOptionalPort("linken-port", "LINKEN_PORT");
2060
+ var WADEX_PORT = getOptionalPort("wadex-port", "WADEX_PORT");
2061
+ var DOLPHIN_PORT = getOptionalPort("dolphin-port", "DOLPHIN_PORT");
2062
+ var DOLPHIN_API_TOKEN = getOptionalString("dolphin-token", "DOLPHIN_API_TOKEN");
2063
+ var VISION_PORT = getOptionalPort(["vision-port", "vision-local-port"], ["VISION_PORT", "VISION_LOCAL_PORT"]);
2064
+ var VISION_TOKEN = getOptionalString(["vision-token", "vision-x-token"], ["VISION_TOKEN", "VISION_X_TOKEN"]);
2065
+ var ENABLED_VENDORS = [
2066
+ ...LINKEN_PORT !== void 0 ? ["linken"] : [],
2067
+ ...WADEX_PORT !== void 0 ? ["wadex"] : [],
2068
+ ...DOLPHIN_PORT !== void 0 || DOLPHIN_API_TOKEN !== void 0 ? ["dolphin"] : [],
2069
+ ...VISION_TOKEN !== void 0 ? ["vision"] : []
2070
+ ];
1955
2071
  function getPackageVersion() {
1956
2072
  try {
1957
2073
  const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
@@ -2050,46 +2166,190 @@ async function getExecutor() {
2050
2166
  }
2051
2167
  return executor;
2052
2168
  }
2169
+ function getSelectorTarget(params) {
2170
+ const selector = typeof params.selector === "string" ? params.selector : void 0;
2171
+ const ref = typeof params.ref === "string" || typeof params.ref === "number" ? String(params.ref) : void 0;
2172
+ if (!selector && !ref) {
2173
+ throw new Error("Either selector or ref is required");
2174
+ }
2175
+ return selector ? { selector } : { ref };
2176
+ }
2177
+ function appendQueryValue(params, key, value) {
2178
+ if (value === void 0 || value === null) return;
2179
+ if (Array.isArray(value)) {
2180
+ for (const item of value) appendQueryValue(params, key, item);
2181
+ return;
2182
+ }
2183
+ if (typeof value === "object") {
2184
+ params.append(key, JSON.stringify(value));
2185
+ return;
2186
+ }
2187
+ params.append(key, String(value));
2188
+ }
2189
+ function withQuery(path2, query) {
2190
+ if (!query) return path2;
2191
+ const params = new URLSearchParams();
2192
+ for (const [key, value] of Object.entries(query)) {
2193
+ appendQueryValue(params, key, value);
2194
+ }
2195
+ const search = params.toString();
2196
+ return search ? `${path2}?${search}` : path2;
2197
+ }
2198
+ async function runVendorRequest(vendor, params) {
2199
+ const target = params.target === "local" ? "local" : "cloud";
2200
+ const path2 = typeof params.path === "string" ? params.path : "/";
2201
+ const method = typeof params.method === "string" ? params.method : "GET";
2202
+ const query = params.query && typeof params.query === "object" ? params.query : void 0;
2203
+ let url;
2204
+ const headers = {};
2205
+ if (vendor === "dolphin") {
2206
+ if (target === "cloud") {
2207
+ if (!DOLPHIN_API_TOKEN) {
2208
+ return { content: "DOLPHIN_API_TOKEN is not configured on this machine.", isError: true };
2209
+ }
2210
+ url = `https://dolphin-anty-api.com${withQuery(path2, query)}`;
2211
+ headers.Authorization = `Bearer ${DOLPHIN_API_TOKEN}`;
2212
+ } else {
2213
+ if (DOLPHIN_PORT === void 0) {
2214
+ return { content: "Dolphin local port is not configured on this machine.", isError: true };
2215
+ }
2216
+ url = `http://127.0.0.1:${DOLPHIN_PORT}${withQuery(path2, query)}`;
2217
+ }
2218
+ } else {
2219
+ if (!VISION_TOKEN) {
2220
+ return { content: "VISION_TOKEN is not configured on this machine.", isError: true };
2221
+ }
2222
+ headers["X-Token"] = VISION_TOKEN;
2223
+ if (target === "cloud") {
2224
+ url = `https://v1.empr.cloud/api/v1${withQuery(path2, query)}`;
2225
+ } else {
2226
+ if (VISION_PORT === void 0) {
2227
+ return { content: "Vision local port is not configured on this machine.", isError: true };
2228
+ }
2229
+ url = `http://127.0.0.1:${VISION_PORT}${withQuery(path2, query)}`;
2230
+ }
2231
+ }
2232
+ if (params.body !== void 0) {
2233
+ headers["Content-Type"] = "application/json";
2234
+ }
2235
+ const resp = await fetch(url, {
2236
+ method,
2237
+ headers,
2238
+ body: params.body !== void 0 ? JSON.stringify(params.body) : void 0,
2239
+ signal: AbortSignal.timeout(3e4)
2240
+ });
2241
+ const data = await resp.text();
2242
+ try {
2243
+ return { content: JSON.stringify(JSON.parse(data)), isError: !resp.ok };
2244
+ } catch {
2245
+ return { content: data, isError: !resp.ok };
2246
+ }
2247
+ }
2053
2248
  async function handleExecuteCommand(msg) {
2054
2249
  const { command, params } = msg;
2055
2250
  try {
2056
2251
  switch (command) {
2057
2252
  // CDP commands — executed via local Patchright
2253
+ case "cdp_status": {
2254
+ const exec = await getExecutor();
2255
+ await exec.ensureBrowsersLoaded();
2256
+ const status = await exec.getDetailedStatus({ checkContent: !!params.checkContent });
2257
+ return { content: JSON.stringify(status), isError: false };
2258
+ }
2259
+ case "cdp_tabs": {
2260
+ const exec = await getExecutor();
2261
+ const r = await exec.parallelTabs(params.action, { index: params.index, url: params.url }, params.browserIds);
2262
+ return { content: formatResult(r), isError: false };
2263
+ }
2058
2264
  case "cdp_navigate": {
2059
2265
  const exec = await getExecutor();
2060
2266
  const r = await exec.parallelNavigate(params.url, params.browserIds);
2061
2267
  return { content: formatResult(r), isError: false };
2062
2268
  }
2269
+ case "cdp_navigate_multi": {
2270
+ const exec = await getExecutor();
2271
+ const r = await exec.parallelNavigateMulti(params.targets);
2272
+ return { content: formatResult(r), isError: false };
2273
+ }
2063
2274
  case "cdp_click": {
2064
2275
  const exec = await getExecutor();
2065
- const r = await exec.parallelClick(params.selector, params.browserIds);
2276
+ const r = await exec.parallelClick(getSelectorTarget(params), params.browserIds);
2066
2277
  return { content: formatResult(r), isError: false };
2067
2278
  }
2068
2279
  case "cdp_type": {
2069
2280
  const exec = await getExecutor();
2070
- const r = await exec.parallelType(params.selector, params.text, params.browserIds);
2281
+ const r = await exec.parallelType(getSelectorTarget(params), params.text, params.browserIds);
2071
2282
  return { content: formatResult(r), isError: false };
2072
2283
  }
2073
2284
  case "cdp_fill": {
2074
2285
  const exec = await getExecutor();
2075
- const r = await exec.parallelFill(params.selector, params.text, params.browserIds);
2286
+ const target = getSelectorTarget(params);
2287
+ const r = params.texts ? await exec.parallelFillMulti(target, params.texts) : await exec.parallelFill(target, params.text, params.browserIds);
2288
+ return { content: formatResult(r), isError: false };
2289
+ }
2290
+ case "cdp_fill_multi": {
2291
+ const exec = await getExecutor();
2292
+ const r = await exec.parallelFillMulti(getSelectorTarget(params), params.texts);
2293
+ return { content: formatResult(r), isError: false };
2294
+ }
2295
+ case "cdp_fill_form": {
2296
+ const exec = await getExecutor();
2297
+ const r = await exec.parallelFillForm(params.fields, params.browserIds);
2298
+ return { content: formatResult(r), isError: false };
2299
+ }
2300
+ case "cdp_drag": {
2301
+ const exec = await getExecutor();
2302
+ const r = await exec.parallelDrag(
2303
+ {
2304
+ selector: typeof params.startSelector === "string" ? params.startSelector : void 0,
2305
+ ref: typeof params.startRef === "string" || typeof params.startRef === "number" ? String(params.startRef) : void 0
2306
+ },
2307
+ {
2308
+ selector: typeof params.endSelector === "string" ? params.endSelector : void 0,
2309
+ ref: typeof params.endRef === "string" || typeof params.endRef === "number" ? String(params.endRef) : void 0
2310
+ },
2311
+ params.browserIds
2312
+ );
2076
2313
  return { content: formatResult(r), isError: false };
2077
2314
  }
2078
2315
  case "cdp_snapshot": {
2079
2316
  const exec = await getExecutor();
2080
2317
  const r = await exec.parallelSnapshot(params.browserIds, { compact: params.compact });
2081
- return { content: formatResult(r), isError: false };
2318
+ const parts = (r.results || []).map((item) => {
2319
+ if (!item.success) return `[${item.browserId}] ERROR: ${item.error || "unknown"}`;
2320
+ const result = item.result || {};
2321
+ return `### ${item.browserId}
2322
+ URL: ${result.url || ""}
2323
+ Title: ${result.title || ""}
2324
+ ${result.snapshot || ""}`;
2325
+ });
2326
+ return { content: parts.join("\n\n") || "OK", isError: false };
2082
2327
  }
2083
2328
  case "cdp_screenshot": {
2084
2329
  const exec = await getExecutor();
2085
- const r = await exec.parallelScreenshot(params.browserIds);
2086
- return { content: formatResult(r), isError: false };
2330
+ const r = await exec.parallelScreenshot(params.browserIds, { fullPage: params.fullPage });
2331
+ const lines = (r.results || []).map((item) => {
2332
+ if (!item.success) return `[${item.browserId}] ERROR: ${item.error || "unknown"}`;
2333
+ const image = Buffer.isBuffer(item.result) ? item.result.toString("base64") : Buffer.from(item.result || []).toString("base64");
2334
+ return `[${item.browserId}] ${image}`;
2335
+ });
2336
+ return { content: lines.join("\n") || "OK", isError: false };
2087
2337
  }
2088
2338
  case "cdp_evaluate": {
2089
2339
  const exec = await getExecutor();
2090
2340
  const r = await exec.parallelEvaluate(params.script, params.browserIds);
2091
2341
  return { content: formatResult(r), isError: false };
2092
2342
  }
2343
+ case "cdp_run_code": {
2344
+ const exec = await getExecutor();
2345
+ const r = await exec.parallelRunCode(params.code, params.browserIds);
2346
+ return { content: formatResult(r), isError: false };
2347
+ }
2348
+ case "cdp_run_code_with_vars": {
2349
+ const exec = await getExecutor();
2350
+ const r = await exec.parallelRunCodeWithVariables(params.codeTemplate, params.variables);
2351
+ return { content: formatResult(r), isError: false };
2352
+ }
2093
2353
  case "cdp_press_key": {
2094
2354
  const exec = await getExecutor();
2095
2355
  const r = await exec.parallelPressKey(params.key, params.browserIds);
@@ -2097,12 +2357,12 @@ async function handleExecuteCommand(msg) {
2097
2357
  }
2098
2358
  case "cdp_select_option": {
2099
2359
  const exec = await getExecutor();
2100
- const r = await exec.parallelSelectOption(params.selector, params.values, params.browserIds);
2360
+ const r = await exec.parallelSelectOption(getSelectorTarget(params), params.values, params.browserIds);
2101
2361
  return { content: formatResult(r), isError: false };
2102
2362
  }
2103
2363
  case "cdp_hover": {
2104
2364
  const exec = await getExecutor();
2105
- const r = await exec.parallelHover(params.selector, params.browserIds);
2365
+ const r = await exec.parallelHover(getSelectorTarget(params), params.browserIds);
2106
2366
  return { content: formatResult(r), isError: false };
2107
2367
  }
2108
2368
  case "cdp_go_back": {
@@ -2110,6 +2370,11 @@ async function handleExecuteCommand(msg) {
2110
2370
  const r = await exec.parallelGoBack(params.browserIds);
2111
2371
  return { content: formatResult(r), isError: false };
2112
2372
  }
2373
+ case "cdp_go_forward": {
2374
+ const exec = await getExecutor();
2375
+ const r = await exec.parallelGoForward(params.browserIds);
2376
+ return { content: formatResult(r), isError: false };
2377
+ }
2113
2378
  case "cdp_reload": {
2114
2379
  const exec = await getExecutor();
2115
2380
  const r = await exec.parallelReload(params.browserIds);
@@ -2120,11 +2385,75 @@ async function handleExecuteCommand(msg) {
2120
2385
  const opts = {};
2121
2386
  if (params.time) opts.time = params.time;
2122
2387
  if (params.text) opts.text = params.text;
2388
+ if (params.textGone) opts.textGone = params.textGone;
2389
+ if (params.domStableMs) opts.domStableMs = params.domStableMs;
2390
+ if (params.timeoutMs) opts.timeoutMs = params.timeoutMs;
2123
2391
  const r = await exec.parallelWaitFor(opts, params.browserIds);
2124
2392
  return { content: formatResult(r), isError: false };
2125
2393
  }
2394
+ case "cdp_handle_dialog": {
2395
+ const exec = await getExecutor();
2396
+ const r = await exec.parallelHandleDialog(!!params.accept, params.promptText, params.browserIds);
2397
+ return { content: formatResult(r), isError: false };
2398
+ }
2399
+ case "cdp_console_messages": {
2400
+ const exec = await getExecutor();
2401
+ const r = await exec.parallelConsoleMessages(!!params.onlyErrors, params.browserIds);
2402
+ return { content: formatResult(r), isError: false };
2403
+ }
2404
+ case "cdp_network_requests": {
2405
+ const exec = await getExecutor();
2406
+ const r = await exec.parallelNetworkRequests(params.browserIds);
2407
+ return { content: formatResult(r), isError: false };
2408
+ }
2409
+ case "cdp_click_normalized_box": {
2410
+ const exec = await getExecutor();
2411
+ const r = await exec.parallelClickNormalizedBox(params.box, params.browserIds);
2412
+ return { content: formatResult(r), isError: false };
2413
+ }
2414
+ case "cdp_setup_downloads": {
2415
+ const exec = await getExecutor();
2416
+ const r = await exec.setupDownloads(params.browserIds);
2417
+ return { content: formatResult(r), isError: false };
2418
+ }
2419
+ case "cdp_list_downloads": {
2420
+ const exec = await getExecutor();
2421
+ const files = await exec.listProjectFiles();
2422
+ return { content: JSON.stringify(files), isError: false };
2423
+ }
2424
+ case "cdp_upload_file": {
2425
+ const exec = await getExecutor();
2426
+ const r = await exec.parallelUploadFile(getSelectorTarget(params), params.fileName, params.browserIds);
2427
+ return { content: formatResult(r), isError: false };
2428
+ }
2429
+ case "cdp_drag_drop_file": {
2430
+ const exec = await getExecutor();
2431
+ const r = await exec.parallelDragDropFile(getSelectorTarget(params), params.fileName, params.browserIds);
2432
+ return { content: formatResult(r), isError: false };
2433
+ }
2434
+ case "cdp_vision_capture": {
2435
+ const exec = await getExecutor();
2436
+ await exec.ensureBrowsersLoaded();
2437
+ const statuses = await exec.listBrowsers();
2438
+ const statusMap = new Map(statuses.map((browser) => [browser.id, browser]));
2439
+ const screenshotResult = await exec.parallelScreenshot(params.browserIds, {
2440
+ format: "jpeg",
2441
+ quality: 70
2442
+ });
2443
+ const captures = (screenshotResult.results || []).filter((item) => item.success && item.result !== void 0).map((item) => ({
2444
+ browserId: item.browserId,
2445
+ url: statusMap.get(item.browserId)?.url || "",
2446
+ screenshot: Buffer.isBuffer(item.result) ? item.result.toString("base64") : Buffer.from(item.result || []).toString("base64")
2447
+ }));
2448
+ const errors = (screenshotResult.results || []).filter((item) => !item.success).map((item) => ({
2449
+ browserId: item.browserId,
2450
+ error: item.error || "unknown"
2451
+ }));
2452
+ return { content: JSON.stringify({ captures, errors }), isError: captures.length === 0 };
2453
+ }
2126
2454
  case "cdp_list_browsers": {
2127
2455
  const exec = await getExecutor();
2456
+ await exec.ensureBrowsersLoaded();
2128
2457
  const browsers = await exec.listBrowsers();
2129
2458
  return { content: browsers.length === 0 ? "No browsers connected" : browsers.map((b) => `${b.id} ${b.connected ? "OK" : "DISCONNECTED"} ${b.url || ""}`).join("\n"), isError: false };
2130
2459
  }
@@ -2174,6 +2503,10 @@ async function handleExecuteCommand(msg) {
2174
2503
  return { content: data, isError: !resp.ok };
2175
2504
  }
2176
2505
  }
2506
+ case "dolphin_request":
2507
+ return await runVendorRequest("dolphin", params);
2508
+ case "vision_request":
2509
+ return await runVendorRequest("vision", params);
2177
2510
  default:
2178
2511
  return { content: `Unknown command: ${command}`, isError: true };
2179
2512
  }
@@ -2200,121 +2533,555 @@ async function toolHandler(tool, args2) {
2200
2533
  const result = await callServer(tool, args2);
2201
2534
  return textResult(result.content, result.isError);
2202
2535
  }
2536
+ var sphereStatusArg = z.enum(["stopped", "running", "imported", "warmup", "automationRunning"]).optional();
2537
+ var sphereProxyTypeArg = z.enum(["notSet", "socks5", "http", "ssh", "liveSocks5", "liveHttp", "direct", "tor", "localhost", "freeProxy"]);
2538
+ var visionFolderIconArg = z.enum([
2539
+ "Cloud",
2540
+ "Google",
2541
+ "Facebook",
2542
+ "TikTok",
2543
+ "Amazon",
2544
+ "Bitcoin",
2545
+ "Meta",
2546
+ "PayPal",
2547
+ "Discord",
2548
+ "Twitter",
2549
+ "Vkontakte",
2550
+ "Youtube",
2551
+ "Tinder",
2552
+ "Onlyfans",
2553
+ "Threads"
2554
+ ]);
2555
+ var visionFolderColorArg = z.enum([
2556
+ "#FFC1073D",
2557
+ "#C8E4FFCD",
2558
+ "#3366FF3D",
2559
+ "#54D62C3D",
2560
+ "#FF48423D",
2561
+ "#919EAB3D"
2562
+ ]);
2563
+ var visionPlatformArg = z.enum(["macos", "windows", "linux"]);
2564
+ var visionProfilePlatformArg = z.enum(["Windows", "MacOS", "Linux", "windows", "macos", "linux"]);
2565
+ var visionBrowserArg = z.enum(["Chrome", "chrome"]);
2566
+ var visionProxyTypeArg = z.enum(["HTTP", "SOCKS4", "SOCKS5", "SSH", "http", "socks4", "socks5", "ssh"]);
2567
+ function registerSphereTools(server, prefix, label) {
2568
+ server.tool(`${prefix}_get_instances`, `Get list of ${label} sessions`, {
2569
+ status: sphereStatusArg,
2570
+ proxy_info: z.boolean().optional()
2571
+ }, (args2) => toolHandler(`${prefix}_get_instances`, args2));
2572
+ server.tool(`${prefix}_create_quick_sessions`, `Create ${label} sessions`, {
2573
+ count: z.number().optional()
2574
+ }, (args2) => toolHandler(`${prefix}_create_quick_sessions`, args2));
2575
+ server.tool(`${prefix}_start_instances`, `Start ${label} browser sessions`, {
2576
+ uuids: z.array(z.string()),
2577
+ headless: z.boolean().optional(),
2578
+ debug_port: z.number().optional(),
2579
+ _scope: z.string().optional()
2580
+ }, (args2) => toolHandler(`${prefix}_start_instances`, args2));
2581
+ server.tool(`${prefix}_stop_instances`, `Stop ${label} sessions`, {
2582
+ uuids: z.array(z.string())
2583
+ }, (args2) => toolHandler(`${prefix}_stop_instances`, args2));
2584
+ server.tool(`${prefix}_session_info`, `Get ${label} session details`, {
2585
+ uuid: z.string()
2586
+ }, (args2) => toolHandler(`${prefix}_session_info`, args2));
2587
+ server.tool(`${prefix}_force_stop`, `Force stop ${label} session`, {
2588
+ uuid: z.string()
2589
+ }, (args2) => toolHandler(`${prefix}_force_stop`, args2));
2590
+ server.tool(`${prefix}_delete_sessions`, `Delete ${label} sessions`, {
2591
+ uuid: z.string().optional(),
2592
+ uuids: z.array(z.string()).optional()
2593
+ }, (args2) => toolHandler(`${prefix}_delete_sessions`, args2));
2594
+ server.tool(`${prefix}_unlock_stopped_sessions`, `Unlock stopped ${label} sessions`, {}, () => toolHandler(`${prefix}_unlock_stopped_sessions`, {}));
2595
+ server.tool(`${prefix}_set_session_name`, `Rename ${label} session`, {
2596
+ uuid: z.string(),
2597
+ name: z.string()
2598
+ }, (args2) => toolHandler(`${prefix}_set_session_name`, args2));
2599
+ server.tool(`${prefix}_set_connection`, `Set proxy for ${label} session`, {
2600
+ uuid: z.string(),
2601
+ type: sphereProxyTypeArg,
2602
+ ip: z.string().optional(),
2603
+ port: z.number().optional(),
2604
+ login: z.string().optional(),
2605
+ password: z.string().optional()
2606
+ }, (args2) => toolHandler(`${prefix}_set_connection`, args2));
2607
+ server.tool(`${prefix}_check_connection`, `Check proxy for ${label} session`, {
2608
+ uuid: z.string()
2609
+ }, (args2) => toolHandler(`${prefix}_check_connection`, args2));
2610
+ server.tool(`${prefix}_set_geo`, `Set ${label} geolocation`, {
2611
+ uuid: z.string(),
2612
+ timezone: z.string().optional(),
2613
+ language: z.string().optional(),
2614
+ latitude: z.number().optional(),
2615
+ longitude: z.number().optional()
2616
+ }, (args2) => toolHandler(`${prefix}_set_geo`, args2));
2617
+ server.tool(`${prefix}_set_useragent`, `Set ${label} user agent`, {
2618
+ uuid: z.string(),
2619
+ useragent: z.string()
2620
+ }, (args2) => toolHandler(`${prefix}_set_useragent`, args2));
2621
+ server.tool(`${prefix}_import_cookies`, `Import cookies into ${label} session`, {
2622
+ uuid: z.string(),
2623
+ file_path: z.string().optional(),
2624
+ json: z.string().optional()
2625
+ }, (args2) => toolHandler(`${prefix}_import_cookies`, args2));
2626
+ server.tool(`${prefix}_export_cookies`, `Export cookies from ${label} sessions`, {
2627
+ uuids: z.array(z.string()),
2628
+ folder_path: z.string()
2629
+ }, (args2) => toolHandler(`${prefix}_export_cookies`, args2));
2630
+ server.tool(`${prefix}_start_warmup`, `Start ${label} session warmup`, {
2631
+ uuid: z.string(),
2632
+ url_count: z.number().optional(),
2633
+ time_per_url: z.number().optional(),
2634
+ view_depth: z.number().optional(),
2635
+ urls: z.array(z.string()).optional()
2636
+ }, (args2) => toolHandler(`${prefix}_start_warmup`, args2));
2637
+ server.tool(`${prefix}_get_providers`, `List ${label} providers`, {}, () => toolHandler(`${prefix}_get_providers`, {}));
2638
+ server.tool(`${prefix}_set_active_provider`, `Set active ${label} provider`, {
2639
+ uuid: z.string()
2640
+ }, (args2) => toolHandler(`${prefix}_set_active_provider`, args2));
2641
+ server.tool(`${prefix}_delete_provider`, `Delete ${label} provider`, {
2642
+ uuid: z.string()
2643
+ }, (args2) => toolHandler(`${prefix}_delete_provider`, args2));
2644
+ server.tool(`${prefix}_get_desktops`, `List ${label} desktops`, {}, () => toolHandler(`${prefix}_get_desktops`, {}));
2645
+ server.tool(`${prefix}_create_desktop`, `Create ${label} desktop`, {
2646
+ name: z.string(),
2647
+ team_uuid: z.string().optional()
2648
+ }, (args2) => toolHandler(`${prefix}_create_desktop`, args2));
2649
+ server.tool(`${prefix}_set_active_desktop`, `Set active ${label} desktop`, {
2650
+ uuid: z.string()
2651
+ }, (args2) => toolHandler(`${prefix}_set_active_desktop`, args2));
2652
+ server.tool(`${prefix}_delete_desktop`, `Delete ${label} desktop`, {
2653
+ uuid: z.string()
2654
+ }, (args2) => toolHandler(`${prefix}_delete_desktop`, args2));
2655
+ server.tool(`${prefix}_optimize_storage`, `Optimize ${label} storage`, {}, () => toolHandler(`${prefix}_optimize_storage`, {}));
2656
+ }
2657
+ function registerDolphinTools(server) {
2658
+ if (DOLPHIN_API_TOKEN !== void 0) {
2659
+ server.tool("dolphin_get_profiles", "Get list of Dolphin Anty browser profiles", {
2660
+ limit: z.number().optional(),
2661
+ page: z.number().optional(),
2662
+ query: z.string().optional(),
2663
+ tags: z.array(z.string()).optional(),
2664
+ statuses: z.array(z.number()).optional(),
2665
+ mainWebsites: z.array(z.string()).optional()
2666
+ }, (args2) => toolHandler("dolphin_get_profiles", args2));
2667
+ }
2668
+ if (DOLPHIN_PORT !== void 0) {
2669
+ server.tool("dolphin_start_profile", "Start a Dolphin Anty browser profile", {
2670
+ profile_id: z.number(),
2671
+ headless: z.boolean().optional(),
2672
+ _scope: z.string().optional()
2673
+ }, (args2) => toolHandler("dolphin_start_profile", args2));
2674
+ server.tool("dolphin_stop_profile", "Stop a running Dolphin Anty browser profile", {
2675
+ profile_id: z.number()
2676
+ }, (args2) => toolHandler("dolphin_stop_profile", args2));
2677
+ }
2678
+ }
2679
+ function registerVisionTools(server) {
2680
+ if (VISION_TOKEN === void 0) {
2681
+ return;
2682
+ }
2683
+ server.tool("vision_get_folders", "Get Vision Browser folders via Cloud API", {}, () => toolHandler("vision_get_folders", {}));
2684
+ server.tool("vision_create_folder", "Create a Vision Browser folder via Cloud API", {
2685
+ folder_name: z.string(),
2686
+ folder_icon: visionFolderIconArg,
2687
+ folder_color: visionFolderColorArg
2688
+ }, (args2) => toolHandler("vision_create_folder", args2));
2689
+ server.tool("vision_update_folder", "Update a Vision Browser folder via Cloud API", {
2690
+ folder_id: z.string(),
2691
+ folder_name: z.string().optional(),
2692
+ folder_icon: visionFolderIconArg.optional(),
2693
+ folder_color: visionFolderColorArg.optional()
2694
+ }, (args2) => toolHandler("vision_update_folder", args2));
2695
+ server.tool("vision_delete_folder", "Delete a Vision Browser folder via Cloud API", {
2696
+ folder_id: z.string()
2697
+ }, (args2) => toolHandler("vision_delete_folder", args2));
2698
+ server.tool("vision_get_profiles", "Get Vision Browser profiles from a specific folder via Cloud API", {
2699
+ folder_id: z.string(),
2700
+ name: z.string().optional(),
2701
+ pn: z.number().optional(),
2702
+ ps: z.number().optional()
2703
+ }, (args2) => toolHandler("vision_get_profiles", args2));
2704
+ server.tool("vision_get_profile", "Get a specific Vision Browser profile via Cloud API", {
2705
+ folder_id: z.string(),
2706
+ profile_id: z.string()
2707
+ }, (args2) => toolHandler("vision_get_profile", args2));
2708
+ server.tool("vision_get_fingerprint", "Get a Vision Browser fingerprint via Cloud API", {
2709
+ platform: visionPlatformArg,
2710
+ version: z.number().optional()
2711
+ }, (args2) => toolHandler("vision_get_fingerprint", args2));
2712
+ server.tool("vision_import_cookies", "Import cookies into a Vision Browser profile via Cloud API", {
2713
+ folder_id: z.string(),
2714
+ profile_id: z.string(),
2715
+ cookies: z.array(z.object({
2716
+ name: z.string(),
2717
+ value: z.string(),
2718
+ path: z.string(),
2719
+ domain: z.string(),
2720
+ expires: z.number().optional()
2721
+ }).passthrough())
2722
+ }, (args2) => toolHandler("vision_import_cookies", args2));
2723
+ server.tool("vision_get_cookies", "Get cookies from a Vision Browser profile via Cloud API", {
2724
+ folder_id: z.string(),
2725
+ profile_id: z.string()
2726
+ }, (args2) => toolHandler("vision_get_cookies", args2));
2727
+ server.tool("vision_create_profile", "Create a Vision Browser profile via Cloud API", {
2728
+ folder_id: z.string(),
2729
+ profile_name: z.string(),
2730
+ profile_notes: z.string().nullable().optional(),
2731
+ profile_tags: z.array(z.string()).optional(),
2732
+ new_profile_tags: z.array(z.string()).optional(),
2733
+ proxy_id: z.string().nullable().optional(),
2734
+ profile_status: z.array(z.string()).nullable().optional(),
2735
+ platform: visionProfilePlatformArg,
2736
+ browser: visionBrowserArg,
2737
+ fingerprint: z.object({
2738
+ webrtc_pref: z.unknown(),
2739
+ webgl_pref: z.unknown(),
2740
+ canvas_pref: z.unknown(),
2741
+ ports_protection: z.array(z.number())
2742
+ }).passthrough()
2743
+ }, (args2) => toolHandler("vision_create_profile", args2));
2744
+ server.tool("vision_update_profile", "Update a Vision Browser profile via Cloud API", {
2745
+ folder_id: z.string(),
2746
+ profile_id: z.string(),
2747
+ profile_name: z.string().optional(),
2748
+ profile_notes: z.string().optional(),
2749
+ profile_tags: z.array(z.string()).optional(),
2750
+ new_profile_tags: z.array(z.string()).optional(),
2751
+ profile_status: z.string().nullable().optional(),
2752
+ pinned: z.boolean().optional(),
2753
+ proxy_id: z.union([z.string(), z.object({ id: z.string() })]).optional()
2754
+ }, (args2) => toolHandler("vision_update_profile", args2));
2755
+ server.tool("vision_delete_profile", "Delete a Vision Browser profile via Cloud API", {
2756
+ folder_id: z.string(),
2757
+ profile_id: z.string()
2758
+ }, (args2) => toolHandler("vision_delete_profile", args2));
2759
+ server.tool("vision_get_proxies", "Get Vision Browser proxies from a specific folder via Cloud API", {
2760
+ folder_id: z.string()
2761
+ }, (args2) => toolHandler("vision_get_proxies", args2));
2762
+ server.tool("vision_create_proxies", "Create Vision Browser proxies inside a folder via Cloud API", {
2763
+ folder_id: z.string(),
2764
+ proxies: z.array(z.object({
2765
+ proxy_name: z.string(),
2766
+ proxy_type: visionProxyTypeArg,
2767
+ proxy_ip: z.string(),
2768
+ proxy_port: z.number(),
2769
+ proxy_username: z.string().optional(),
2770
+ proxy_password: z.string().optional(),
2771
+ update_url: z.string().optional(),
2772
+ proxy_geo: z.record(z.unknown()).optional()
2773
+ }).passthrough())
2774
+ }, (args2) => toolHandler("vision_create_proxies", args2));
2775
+ server.tool("vision_update_proxy", "Update a Vision Browser proxy via Cloud API", {
2776
+ folder_id: z.string(),
2777
+ proxy_id: z.string(),
2778
+ proxy_name: z.string(),
2779
+ proxy_type: visionProxyTypeArg,
2780
+ proxy_ip: z.string(),
2781
+ proxy_port: z.number(),
2782
+ proxy_username: z.string().optional(),
2783
+ proxy_password: z.string().optional(),
2784
+ update_url: z.string().optional(),
2785
+ proxy_geo: z.record(z.unknown()).optional()
2786
+ }, (args2) => toolHandler("vision_update_proxy", args2));
2787
+ server.tool("vision_delete_proxies", "Delete Vision Browser proxies inside a folder via Cloud API", {
2788
+ folder_id: z.string(),
2789
+ proxy_ids: z.array(z.string())
2790
+ }, (args2) => toolHandler("vision_delete_proxies", args2));
2791
+ server.tool("vision_get_statuses", "Get Vision Browser statuses from a specific folder via Cloud API", {
2792
+ folder_id: z.string()
2793
+ }, (args2) => toolHandler("vision_get_statuses", args2));
2794
+ server.tool("vision_get_tags", "Get Vision Browser tags from a specific folder via Cloud API", {
2795
+ folder_id: z.string()
2796
+ }, (args2) => toolHandler("vision_get_tags", args2));
2797
+ server.tool("vision_create_tags", "Create Vision Browser tags inside a folder via Cloud API", {
2798
+ folder_id: z.string(),
2799
+ tags: z.array(z.string())
2800
+ }, (args2) => toolHandler("vision_create_tags", args2));
2801
+ server.tool("vision_update_tag", "Update a Vision Browser tag via Cloud API", {
2802
+ folder_id: z.string(),
2803
+ tag_id: z.string(),
2804
+ name: z.string()
2805
+ }, (args2) => toolHandler("vision_update_tag", args2));
2806
+ server.tool("vision_delete_tags", "Delete Vision Browser tags via Cloud API", {
2807
+ folder_id: z.string(),
2808
+ tag_ids: z.array(z.string())
2809
+ }, (args2) => toolHandler("vision_delete_tags", args2));
2810
+ server.tool("vision_create_statuses", "Create Vision Browser statuses via Cloud API", {
2811
+ folder_id: z.string(),
2812
+ statuses: z.array(z.tuple([z.string(), z.string()]))
2813
+ }, (args2) => toolHandler("vision_create_statuses", args2));
2814
+ server.tool("vision_update_status", "Update a Vision Browser status via Cloud API", {
2815
+ folder_id: z.string(),
2816
+ status_id: z.string(),
2817
+ name: z.string(),
2818
+ color: z.string()
2819
+ }, (args2) => toolHandler("vision_update_status", args2));
2820
+ server.tool("vision_delete_statuses", "Delete Vision Browser statuses via Cloud API", {
2821
+ folder_id: z.string(),
2822
+ status_ids: z.array(z.string())
2823
+ }, (args2) => toolHandler("vision_delete_statuses", args2));
2824
+ if (VISION_PORT !== void 0) {
2825
+ server.tool("vision_get_languages", "Get available Vision Browser languages from the local API", {}, () => toolHandler("vision_get_languages", {}));
2826
+ server.tool("vision_get_timezones", "Get available Vision Browser timezones from the local API", {}, () => toolHandler("vision_get_timezones", {}));
2827
+ server.tool("vision_get_renderers", "Get available Vision Browser renderers from the local API", {
2828
+ os: visionPlatformArg,
2829
+ version: z.number().optional()
2830
+ }, (args2) => toolHandler("vision_get_renderers", args2));
2831
+ }
2832
+ }
2833
+ var browserIdsArg = z.array(z.string()).optional();
2834
+ var browserScopeArg = z.string().optional();
2835
+ var browserRefArg = z.union([z.string(), z.number()]).optional();
2836
+ var browserTargetArgs = {
2837
+ element: z.string().optional(),
2838
+ ref: browserRefArg,
2839
+ selector: z.string().optional(),
2840
+ browserIds: browserIdsArg,
2841
+ _scope: browserScopeArg
2842
+ };
2203
2843
  function createServer() {
2204
2844
  const server = new McpServer({ name: "ornold-browser", version: CLIENT_VERSION });
2205
2845
  server.tool("browser_list", "List connected browsers", {}, () => toolHandler("browser_list", {}));
2846
+ server.tool("browser_status", "Check browser sync and responsiveness", {
2847
+ checkContent: z.boolean().optional(),
2848
+ _scope: browserScopeArg
2849
+ }, (args2) => toolHandler("browser_status", args2));
2850
+ server.tool("browser_parallel_tabs", "Manage browser tabs in parallel", {
2851
+ action: z.enum(["list", "new", "close", "select"]),
2852
+ index: z.number().optional(),
2853
+ url: z.string().optional(),
2854
+ browserIds: browserIdsArg,
2855
+ _scope: browserScopeArg
2856
+ }, (args2) => toolHandler("browser_parallel_tabs", args2));
2206
2857
  server.tool("browser_parallel_snapshot", "Get page snapshot with [ref=N] markers", {
2207
2858
  compact: z.boolean().optional(),
2208
- browserIds: z.array(z.string()).optional()
2859
+ browserIds: browserIdsArg,
2860
+ _scope: browserScopeArg
2209
2861
  }, (args2) => toolHandler("browser_parallel_snapshot", args2));
2210
2862
  server.tool("browser_parallel_navigate", "Navigate to URL", {
2211
2863
  url: z.string(),
2212
- browserIds: z.array(z.string()).optional()
2864
+ browserIds: browserIdsArg,
2865
+ _scope: browserScopeArg
2213
2866
  }, (args2) => toolHandler("browser_parallel_navigate", args2));
2867
+ server.tool("browser_parallel_navigate_multi", "Navigate each browser to a different URL", {
2868
+ targets: z.array(z.object({
2869
+ browserId: z.string(),
2870
+ url: z.string()
2871
+ })),
2872
+ _scope: browserScopeArg
2873
+ }, (args2) => toolHandler("browser_parallel_navigate_multi", args2));
2214
2874
  server.tool("browser_parallel_click", "Click element", {
2215
- selector: z.string(),
2216
- browserIds: z.array(z.string()).optional()
2875
+ ...browserTargetArgs
2217
2876
  }, (args2) => toolHandler("browser_parallel_click", args2));
2218
2877
  server.tool("browser_parallel_type", "Type text into element", {
2219
- selector: z.string(),
2220
- text: z.string(),
2221
- browserIds: z.array(z.string()).optional()
2878
+ ...browserTargetArgs,
2879
+ text: z.string()
2222
2880
  }, (args2) => toolHandler("browser_parallel_type", args2));
2223
2881
  server.tool("browser_parallel_fill", "Fill input (clear + type)", {
2224
- selector: z.string(),
2225
- text: z.string(),
2226
- browserIds: z.array(z.string()).optional()
2882
+ ...browserTargetArgs,
2883
+ text: z.string().optional(),
2884
+ texts: z.record(z.string()).optional()
2227
2885
  }, (args2) => toolHandler("browser_parallel_fill", args2));
2886
+ server.tool("browser_parallel_fill_multi", "Fill input with per-browser values", {
2887
+ ...browserTargetArgs,
2888
+ texts: z.record(z.string())
2889
+ }, (args2) => toolHandler("browser_parallel_fill_multi", args2));
2890
+ server.tool("browser_parallel_fill_form", "Fill multiple form fields sequentially", {
2891
+ fields: z.array(z.object({
2892
+ element: z.string().optional(),
2893
+ ref: browserRefArg,
2894
+ selector: z.string().optional(),
2895
+ value: z.string(),
2896
+ type: z.enum(["textbox", "checkbox", "radio", "combobox"]).optional()
2897
+ })),
2898
+ browserIds: browserIdsArg,
2899
+ _scope: browserScopeArg
2900
+ }, (args2) => toolHandler("browser_parallel_fill_form", args2));
2901
+ server.tool("browser_parallel_drag", "Drag from one element to another", {
2902
+ startElement: z.string().optional(),
2903
+ startRef: browserRefArg,
2904
+ startSelector: z.string().optional(),
2905
+ endElement: z.string().optional(),
2906
+ endRef: browserRefArg,
2907
+ endSelector: z.string().optional(),
2908
+ browserIds: browserIdsArg,
2909
+ _scope: browserScopeArg
2910
+ }, (args2) => toolHandler("browser_parallel_drag", args2));
2228
2911
  server.tool("browser_parallel_press_key", "Press keyboard key", {
2229
2912
  key: z.string(),
2230
- browserIds: z.array(z.string()).optional()
2913
+ browserIds: browserIdsArg,
2914
+ _scope: browserScopeArg
2231
2915
  }, (args2) => toolHandler("browser_parallel_press_key", args2));
2232
2916
  server.tool("browser_parallel_select_option", "Select dropdown option", {
2233
- selector: z.string(),
2234
- values: z.array(z.string()),
2235
- browserIds: z.array(z.string()).optional()
2917
+ ...browserTargetArgs,
2918
+ values: z.array(z.string())
2236
2919
  }, (args2) => toolHandler("browser_parallel_select_option", args2));
2237
2920
  server.tool("browser_parallel_wait_for", "Wait for condition", {
2238
2921
  time: z.number().optional(),
2239
2922
  text: z.string().optional(),
2240
- browserIds: z.array(z.string()).optional()
2923
+ textGone: z.string().optional(),
2924
+ domStableMs: z.number().optional(),
2925
+ timeoutMs: z.number().optional(),
2926
+ browserIds: browserIdsArg,
2927
+ _scope: browserScopeArg
2241
2928
  }, (args2) => toolHandler("browser_parallel_wait_for", args2));
2242
2929
  server.tool("browser_parallel_screenshot", "Take screenshot", {
2243
- browserIds: z.array(z.string()).optional()
2930
+ fullPage: z.boolean().optional(),
2931
+ browserIds: browserIdsArg,
2932
+ _scope: browserScopeArg
2244
2933
  }, (args2) => toolHandler("browser_parallel_screenshot", args2));
2245
2934
  server.tool("browser_parallel_evaluate", "Run JavaScript in page", {
2246
2935
  script: z.string(),
2247
- browserIds: z.array(z.string()).optional()
2936
+ browserIds: browserIdsArg,
2937
+ _scope: browserScopeArg
2248
2938
  }, (args2) => toolHandler("browser_parallel_evaluate", args2));
2939
+ server.tool("browser_parallel_run_code", "Run JavaScript code in page context", {
2940
+ code: z.string(),
2941
+ browserIds: browserIdsArg,
2942
+ _scope: browserScopeArg
2943
+ }, (args2) => toolHandler("browser_parallel_run_code", args2));
2944
+ server.tool("browser_parallel_run_code_with_vars", "Run templated JavaScript code with per-browser variables", {
2945
+ codeTemplate: z.string(),
2946
+ variables: z.record(z.record(z.string())),
2947
+ _scope: browserScopeArg
2948
+ }, (args2) => toolHandler("browser_parallel_run_code_with_vars", args2));
2249
2949
  server.tool("browser_parallel_hover", "Hover over element", {
2250
- selector: z.string(),
2251
- browserIds: z.array(z.string()).optional()
2950
+ ...browserTargetArgs
2252
2951
  }, (args2) => toolHandler("browser_parallel_hover", args2));
2253
2952
  server.tool("browser_parallel_go_back", "Go back", {
2254
- browserIds: z.array(z.string()).optional()
2953
+ browserIds: browserIdsArg,
2954
+ _scope: browserScopeArg
2255
2955
  }, (args2) => toolHandler("browser_parallel_go_back", args2));
2956
+ server.tool("browser_parallel_go_forward", "Go forward", {
2957
+ browserIds: browserIdsArg,
2958
+ _scope: browserScopeArg
2959
+ }, (args2) => toolHandler("browser_parallel_go_forward", args2));
2256
2960
  server.tool("browser_parallel_reload", "Reload page", {
2257
- browserIds: z.array(z.string()).optional()
2961
+ browserIds: browserIdsArg,
2962
+ _scope: browserScopeArg
2258
2963
  }, (args2) => toolHandler("browser_parallel_reload", args2));
2259
- server.tool("linken_create_quick_sessions", "Create Linken Sphere sessions", {
2260
- count: z.number().optional()
2261
- }, (args2) => toolHandler("linken_create_quick_sessions", args2));
2262
- server.tool("linken_start_instances", "Start Linken browser sessions", {
2263
- uuids: z.array(z.string()),
2264
- headless: z.boolean().optional()
2265
- }, (args2) => toolHandler("linken_start_instances", args2));
2266
- server.tool("linken_stop_instances", "Stop Linken sessions", {
2267
- uuids: z.array(z.string())
2268
- }, (args2) => toolHandler("linken_stop_instances", args2));
2269
- server.tool("linken_session_info", "Get session details", {
2270
- uuid: z.string()
2271
- }, (args2) => toolHandler("linken_session_info", args2));
2272
- server.tool("linken_set_connection", "Set proxy for session", {
2273
- uuid: z.string(),
2274
- type: z.string(),
2275
- ip: z.string(),
2276
- port: z.number(),
2277
- login: z.string().optional(),
2278
- password: z.string().optional()
2279
- }, (args2) => toolHandler("linken_set_connection", args2));
2280
- server.tool("linken_import_cookies", "Import cookies", {
2281
- uuid: z.string(),
2282
- json: z.string()
2283
- }, (args2) => toolHandler("linken_import_cookies", args2));
2284
- server.tool("linken_export_cookies", "Export cookies", {
2285
- uuids: z.array(z.string())
2286
- }, (args2) => toolHandler("linken_export_cookies", args2));
2287
- server.tool("dolphin_get_profiles", "List Dolphin profiles", {}, () => toolHandler("dolphin_get_profiles", {}));
2288
- server.tool("dolphin_start_profile", "Start Dolphin profile", {
2289
- profileId: z.string()
2290
- }, (args2) => toolHandler("dolphin_start_profile", args2));
2291
- server.tool("dolphin_stop_profile", "Stop Dolphin profile", {
2292
- profileId: z.string()
2293
- }, (args2) => toolHandler("dolphin_stop_profile", args2));
2964
+ server.tool("browser_parallel_handle_dialog", "Handle JavaScript dialogs", {
2965
+ accept: z.boolean(),
2966
+ promptText: z.string().optional(),
2967
+ browserIds: browserIdsArg,
2968
+ _scope: browserScopeArg
2969
+ }, (args2) => toolHandler("browser_parallel_handle_dialog", args2));
2970
+ server.tool("browser_parallel_console_messages", "Get console messages", {
2971
+ onlyErrors: z.boolean().optional(),
2972
+ browserIds: browserIdsArg,
2973
+ _scope: browserScopeArg
2974
+ }, (args2) => toolHandler("browser_parallel_console_messages", args2));
2975
+ server.tool("browser_parallel_network_requests", "Get network requests", {
2976
+ browserIds: browserIdsArg,
2977
+ _scope: browserScopeArg
2978
+ }, (args2) => toolHandler("browser_parallel_network_requests", args2));
2979
+ server.tool("browser_parallel_vision_analyze_grouped", "Analyze grouped browser screenshots with OmniParser via Ornold server", {
2980
+ similarityThreshold: z.number().optional(),
2981
+ browserIds: browserIdsArg,
2982
+ _scope: browserScopeArg
2983
+ }, (args2) => toolHandler("browser_parallel_vision_analyze_grouped", args2));
2984
+ server.tool("browser_parallel_click_normalized_box", "Click normalized viewport box center", {
2985
+ box: z.tuple([z.number(), z.number(), z.number(), z.number()]),
2986
+ browserIds: browserIdsArg,
2987
+ _scope: browserScopeArg
2988
+ }, (args2) => toolHandler("browser_parallel_click_normalized_box", args2));
2989
+ server.tool("browser_setup_downloads", "Enable browser downloads to project files directory", {
2990
+ browserIds: browserIdsArg,
2991
+ _scope: browserScopeArg
2992
+ }, (args2) => toolHandler("browser_setup_downloads", args2));
2993
+ server.tool("browser_list_downloads", "List files in project files directory", {}, () => toolHandler("browser_list_downloads", {}));
2994
+ server.tool("browser_parallel_upload_file", "Upload a file to an input element", {
2995
+ ...browserTargetArgs,
2996
+ fileName: z.string()
2997
+ }, (args2) => toolHandler("browser_parallel_upload_file", args2));
2998
+ server.tool("browser_parallel_drag_drop_file", "Drag and drop a file onto an element", {
2999
+ ...browserTargetArgs,
3000
+ fileName: z.string()
3001
+ }, (args2) => toolHandler("browser_parallel_drag_drop_file", args2));
3002
+ server.tool("browser_search_macros", "Search saved browser macros", {
3003
+ name: z.string(),
3004
+ _scope: browserScopeArg
3005
+ }, (args2) => toolHandler("browser_search_macros", args2));
3006
+ server.tool("browser_run_recorded_flow", "Run saved browser macro by ID", {
3007
+ macroId: z.string(),
3008
+ browserIds: browserIdsArg,
3009
+ _scope: browserScopeArg
3010
+ }, (args2) => toolHandler("browser_run_recorded_flow", args2));
3011
+ if (LINKEN_PORT !== void 0) registerSphereTools(server, "linken", "Linken Sphere");
3012
+ if (WADEX_PORT !== void 0) registerSphereTools(server, "wadex", "Wade X");
3013
+ if (DOLPHIN_PORT !== void 0 || DOLPHIN_API_TOKEN !== void 0) registerDolphinTools(server);
3014
+ if (VISION_TOKEN !== void 0) registerVisionTools(server);
3015
+ server.tool("browser_detect_captcha", "Detect captcha on page", {
3016
+ browserIds: browserIdsArg,
3017
+ _scope: browserScopeArg
3018
+ }, (args2) => toolHandler("browser_detect_captcha", args2));
3019
+ server.tool("browser_solve_press_hold", "Solve press-and-hold captcha", {
3020
+ browserIds: browserIdsArg,
3021
+ maxAttempts: z.number().optional(),
3022
+ holdMs: z.number().optional(),
3023
+ _scope: browserScopeArg
3024
+ }, (args2) => toolHandler("browser_solve_press_hold", args2));
3025
+ server.tool("browser_detect_press_hold", "Detect press-and-hold captcha", {
3026
+ browserIds: browserIdsArg,
3027
+ _scope: browserScopeArg
3028
+ }, (args2) => toolHandler("browser_detect_press_hold", args2));
3029
+ server.tool("browser_solve_captcha", "Solve captcha (reCAPTCHA/hCaptcha)", {
3030
+ browserIds: browserIdsArg,
3031
+ timeout: z.number().optional(),
3032
+ autoSubmit: z.boolean().optional(),
3033
+ _scope: browserScopeArg
3034
+ }, (args2) => toolHandler("browser_solve_captcha", args2));
3035
+ server.tool("browser_captcha_balance", "Check 2captcha balance", {}, () => toolHandler("browser_captcha_balance", {}));
2294
3036
  server.tool("captcha_detect", "Detect captcha on page", {
2295
- browserIds: z.array(z.string()).optional()
3037
+ browserIds: browserIdsArg
2296
3038
  }, (args2) => toolHandler("captcha_detect", args2));
2297
3039
  server.tool("captcha_solve_press_hold", "Solve press-and-hold captcha", {
2298
- browserIds: z.array(z.string()).optional()
3040
+ browserIds: browserIdsArg
2299
3041
  }, (args2) => toolHandler("captcha_solve_press_hold", args2));
2300
3042
  server.tool("captcha_solve", "Solve captcha (reCAPTCHA/hCaptcha)", {
2301
- browserIds: z.array(z.string()).optional()
3043
+ browserIds: browserIdsArg
2302
3044
  }, (args2) => toolHandler("captcha_solve", args2));
2303
3045
  return server;
2304
3046
  }
2305
3047
  async function main() {
2306
3048
  await connectServer();
2307
- for (const [name, port] of [["linken", LINKEN_PORT], ["dolphin", DOLPHIN_PORT]]) {
3049
+ if (ENABLED_VENDORS.length === 0) {
3050
+ console.error("[ornold] No antidetect vendors configured. Only browser_* and captcha_* tools will be available.");
3051
+ }
3052
+ for (const [name, port, path2, headers] of [
3053
+ ["linken", LINKEN_PORT, "/sessions", void 0],
3054
+ ["wadex", WADEX_PORT, "/sessions", void 0],
3055
+ ["dolphin", DOLPHIN_PORT, "/v1.0/browser_profiles", void 0],
3056
+ ["vision", VISION_PORT, "/variations/language", VISION_TOKEN ? { "X-Token": VISION_TOKEN } : void 0]
3057
+ ]) {
3058
+ if (port === void 0) continue;
2308
3059
  try {
2309
- const resp = await fetch(`http://127.0.0.1:${port}/sessions`, { signal: AbortSignal.timeout(2e3) });
3060
+ const resp = await fetch(`http://127.0.0.1:${port}${path2}`, { headers, signal: AbortSignal.timeout(2e3) });
2310
3061
  if (resp.ok) console.error(`[ornold] ${name}: detected on port ${port}`);
2311
3062
  } catch {
2312
3063
  }
2313
3064
  }
3065
+ if (DOLPHIN_API_TOKEN !== void 0) {
3066
+ console.error("[ornold] dolphin: cloud token configured");
3067
+ }
3068
+ if (VISION_TOKEN !== void 0) {
3069
+ console.error(`[ornold] vision: cloud token configured${VISION_PORT !== void 0 ? `, local port ${VISION_PORT}` : ""}`);
3070
+ }
2314
3071
  ws?.send(JSON.stringify({
2315
3072
  type: "bridge_hello",
2316
3073
  hostname: (await import("os")).hostname(),
2317
- config: { linkenPort: LINKEN_PORT, dolphinPort: DOLPHIN_PORT }
3074
+ config: {
3075
+ enabledVendors: ENABLED_VENDORS,
3076
+ ...LINKEN_PORT !== void 0 ? { linkenPort: LINKEN_PORT } : {},
3077
+ ...WADEX_PORT !== void 0 ? { wadexPort: WADEX_PORT } : {},
3078
+ ...DOLPHIN_PORT !== void 0 ? { dolphinPort: DOLPHIN_PORT } : {},
3079
+ ...VISION_PORT !== void 0 ? { visionPort: VISION_PORT } : {},
3080
+ dolphinCloud: DOLPHIN_API_TOKEN !== void 0,
3081
+ dolphinLocal: DOLPHIN_PORT !== void 0,
3082
+ visionCloud: VISION_TOKEN !== void 0,
3083
+ visionLocal: VISION_TOKEN !== void 0 && VISION_PORT !== void 0
3084
+ }
2318
3085
  }));
2319
3086
  const server = createServer();
2320
3087
  const transport = new StdioServerTransport();