mcp-google-map 0.5.0 → 0.6.0

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/cli.js CHANGED
@@ -19,6 +19,46 @@ var AUTO_UPDATE_DISABLED_ENV = "MCP_AUTO_UPDATE_DISABLED";
19
19
  var DEFAULT_PACKAGE_NAME = "mcp-google-map";
20
20
  var DEFAULT_REGISTRY_BASE_URL = "https://registry.npmjs.org";
21
21
  var DEFAULT_UPDATE_CHECK_TIMEOUT_MS = 2e3;
22
+ async function probeLatestVersion(deps = {}) {
23
+ const env = deps.env ?? process.env;
24
+ if (isAutoUpdateDisabled(env)) {
25
+ return { status: "disabled" };
26
+ }
27
+ const currentVersion = deps.currentVersion;
28
+ if (!currentVersion) {
29
+ return { status: "unknown-version" };
30
+ }
31
+ const packageName = deps.packageName ?? DEFAULT_PACKAGE_NAME;
32
+ const registryBaseUrl = deps.registryBaseUrl ?? DEFAULT_REGISTRY_BASE_URL;
33
+ const timeoutMs = deps.timeoutMs ?? DEFAULT_UPDATE_CHECK_TIMEOUT_MS;
34
+ const fetchImpl = deps.fetchImpl ?? fetch;
35
+ try {
36
+ const response = await fetchImpl(`${registryBaseUrl}/${packageName}/latest`, {
37
+ headers: { accept: "application/json" },
38
+ signal: AbortSignal.timeout(timeoutMs)
39
+ });
40
+ if (!response.ok) {
41
+ return {
42
+ status: "error",
43
+ message: `registry responded with HTTP ${response.status}.`
44
+ };
45
+ }
46
+ const payload = await response.json();
47
+ if (typeof payload?.version !== "string") {
48
+ return {
49
+ status: "error",
50
+ message: "registry response has no version field."
51
+ };
52
+ }
53
+ if (!isNewerVersion(payload.version, currentVersion)) {
54
+ return { status: "current", currentVersion };
55
+ }
56
+ return { status: "newer", currentVersion, latestVersion: payload.version };
57
+ } catch (error) {
58
+ const message = error instanceof Error ? error.message : String(error);
59
+ return { status: "error", message };
60
+ }
61
+ }
22
62
  function isAutoUpdateDisabled(env = process.env) {
23
63
  const raw = env[AUTO_UPDATE_DISABLED_ENV];
24
64
  return typeof raw === "string" && /^(1|true|yes)$/i.test(raw.trim());
@@ -40,54 +80,6 @@ function isNewerVersion(candidate, current) {
40
80
  }
41
81
  return false;
42
82
  }
43
- async function checkForUpdates(deps = {}) {
44
- const logger = deps.logger ?? Logger;
45
- const env = deps.env ?? process.env;
46
- try {
47
- if (isAutoUpdateDisabled(env)) {
48
- return null;
49
- }
50
- const currentVersion = deps.currentVersion;
51
- if (!currentVersion) {
52
- logger.error(
53
- `\u26A0\uFE0F [${DEFAULT_PACKAGE_NAME}] Automatic update check skipped: running package version is unknown.`
54
- );
55
- return null;
56
- }
57
- const packageName = deps.packageName ?? DEFAULT_PACKAGE_NAME;
58
- const registryBaseUrl = deps.registryBaseUrl ?? DEFAULT_REGISTRY_BASE_URL;
59
- const timeoutMs = deps.timeoutMs ?? DEFAULT_UPDATE_CHECK_TIMEOUT_MS;
60
- const fetchImpl = deps.fetchImpl ?? fetch;
61
- const response = await fetchImpl(`${registryBaseUrl}/${packageName}/latest`, {
62
- headers: { accept: "application/vnd.npm.install-v1+json" },
63
- signal: AbortSignal.timeout(timeoutMs)
64
- });
65
- if (!response.ok) {
66
- logger.error(
67
- `\u26A0\uFE0F [${DEFAULT_PACKAGE_NAME}] Automatic update check failed: registry responded with HTTP ${response.status}.`
68
- );
69
- return null;
70
- }
71
- const payload = await response.json();
72
- if (typeof payload?.version !== "string") {
73
- logger.error(
74
- `\u26A0\uFE0F [${DEFAULT_PACKAGE_NAME}] Automatic update check failed: registry response has no version field.`
75
- );
76
- return null;
77
- }
78
- if (!isNewerVersion(payload.version, currentVersion)) {
79
- return null;
80
- }
81
- logger.log(
82
- `\u26A0\uFE0F Update available: ${packageName} ${currentVersion} \u2192 ${payload.version}. Upgrade with: npm install -g ${packageName}@latest (or run npx -y ${packageName}@latest).`
83
- );
84
- return { currentVersion, latestVersion: payload.version };
85
- } catch (error) {
86
- const message = error instanceof Error ? error.message : String(error);
87
- logger.error(`\u26A0\uFE0F [${DEFAULT_PACKAGE_NAME}] Automatic update check failed: ${message}`);
88
- return null;
89
- }
90
- }
91
83
 
92
84
  // src/utils/configResolver.ts
93
85
  var NODE_ENGINE_FLOOR = 22;
@@ -1451,10 +1443,256 @@ var BaseMcpServer = class {
1451
1443
 
1452
1444
  // src/cli.ts
1453
1445
  import { fileURLToPath } from "url";
1454
- import { dirname } from "path";
1455
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync4 } from "fs";
1446
+ import { dirname as dirname2 } from "path";
1447
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, existsSync as existsSync4 } from "fs";
1456
1448
  import { createInterface } from "readline";
1457
1449
 
1450
+ // src/utils/upgradeManager.ts
1451
+ import { spawnSync } from "child_process";
1452
+ import { mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
1453
+ import { homedir } from "os";
1454
+ import { dirname, join as join2 } from "path";
1455
+
1456
+ // src/utils/cliSettings.ts
1457
+ import { mkdirSync, readFileSync, renameSync, writeFileSync } from "fs";
1458
+ import { join, resolve } from "path";
1459
+ var SETTINGS_PROGRAM_NAME = "mcp-google-map";
1460
+ var CLI_SETTINGS_RELATIVE = [".config", SETTINGS_PROGRAM_NAME, "config.json"];
1461
+ var MCP_SERVER_NAME = "mcp-google-map";
1462
+ function resolveCliSettingsPath(home) {
1463
+ const root = home ?? (process.env.HOME ?? process.cwd());
1464
+ return resolve(root, ...CLI_SETTINGS_RELATIVE);
1465
+ }
1466
+ function uniqueStrings(value) {
1467
+ if (!Array.isArray(value)) return [];
1468
+ const result = [];
1469
+ for (const item of value) {
1470
+ if (typeof item === "string" && item.length > 0 && !result.includes(item)) {
1471
+ result.push(item);
1472
+ }
1473
+ }
1474
+ return result;
1475
+ }
1476
+ function loadCliSettings(home) {
1477
+ try {
1478
+ const raw = JSON.parse(readFileSync(resolveCliSettingsPath(home), "utf-8"));
1479
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
1480
+ return { enabled: [] };
1481
+ }
1482
+ return { enabled: uniqueStrings(raw.enabled) };
1483
+ } catch {
1484
+ return { enabled: [] };
1485
+ }
1486
+ }
1487
+ function saveCliSettings(settings, home) {
1488
+ const path = resolveCliSettingsPath(home);
1489
+ const temporary = `${path}.tmp`;
1490
+ try {
1491
+ mkdirSync(join(path, ".."), { recursive: true });
1492
+ writeFileSync(temporary, JSON.stringify({ enabled: uniqueStrings(settings.enabled) }, null, 2) + "\n", "utf-8");
1493
+ renameSync(temporary, path);
1494
+ } catch (error) {
1495
+ throw new Error(`settings write failed: ${error instanceof Error ? error.message : String(error)}`);
1496
+ }
1497
+ return path;
1498
+ }
1499
+
1500
+ // src/utils/upgradeManager.ts
1501
+ var ANSI_GREEN = "\x1B[92m";
1502
+ var ANSI_RED = "\x1B[91m";
1503
+ var ANSI_RESET = "\x1B[0m";
1504
+ var green = (text) => `${ANSI_GREEN}${text}${ANSI_RESET}`;
1505
+ var red = (text) => `${ANSI_RED}${text}${ANSI_RESET}`;
1506
+ var IDLE_CACHE_DIR_NAME = "mcp-google-map";
1507
+ var IDLE_CACHE_FILE_NAME = "check_version_idle-time.json";
1508
+ var IDLE_WINDOW_NEWER_MS = 60 * 60 * 1e3;
1509
+ var IDLE_WINDOW_DEFAULT_MS = 24 * 60 * 60 * 1e3;
1510
+ var PACKAGE_UPGRADE_COMMAND = [
1511
+ "npm",
1512
+ "install",
1513
+ "-g",
1514
+ `${DEFAULT_PACKAGE_NAME}@latest`
1515
+ ];
1516
+ var PACKAGE_UNINSTALL_COMMAND = [
1517
+ "npm",
1518
+ "uninstall",
1519
+ "-g",
1520
+ DEFAULT_PACKAGE_NAME
1521
+ ];
1522
+ var POST_UPGRADE_INSTALL_COMMAND = [
1523
+ "npx",
1524
+ "-y",
1525
+ DEFAULT_PACKAGE_NAME,
1526
+ "install"
1527
+ ];
1528
+ function resolveIdleCachePath(home) {
1529
+ return join2(home ?? homedir(), ".cache", IDLE_CACHE_DIR_NAME, IDLE_CACHE_FILE_NAME);
1530
+ }
1531
+ function loadIdleCache(cachePath, fs = {}) {
1532
+ try {
1533
+ const readFile = fs.readFile ?? ((path) => readFileSync2(path, "utf-8"));
1534
+ const raw = readFile(cachePath);
1535
+ const parsed = JSON.parse(raw);
1536
+ if (typeof parsed !== "object" || parsed === null) {
1537
+ return {};
1538
+ }
1539
+ const record = parsed;
1540
+ const isFiniteNumber = (value) => typeof value === "number" && Number.isFinite(value);
1541
+ return {
1542
+ last_success_epoch: isFiniteNumber(record.last_success_epoch) ? record.last_success_epoch : void 0,
1543
+ last_success_human: typeof record.last_success_human === "string" ? record.last_success_human : void 0,
1544
+ idle_time_epoch: isFiniteNumber(record.idle_time_epoch) ? record.idle_time_epoch : void 0,
1545
+ idle_time_human: typeof record.idle_time_human === "string" ? record.idle_time_human : void 0
1546
+ };
1547
+ } catch {
1548
+ return {};
1549
+ }
1550
+ }
1551
+ function persistIdleCache(cachePath, lastSuccess, idleUntil, fs = {}, logger = Logger) {
1552
+ const toIso = (epoch) => epoch === void 0 ? null : new Date(epoch).toISOString();
1553
+ const data = {
1554
+ last_success_epoch: lastSuccess ?? null,
1555
+ last_success_human: toIso(lastSuccess),
1556
+ idle_time_epoch: idleUntil,
1557
+ idle_time_human: toIso(idleUntil)
1558
+ };
1559
+ try {
1560
+ const mkdir = fs.mkdir ?? ((path) => mkdirSync2(path, { recursive: true }));
1561
+ const writeFile = fs.writeFile ?? ((path, data2) => writeFileSync2(path, data2));
1562
+ mkdir(dirname(cachePath));
1563
+ writeFile(cachePath, JSON.stringify(data, null, 2) + "\n");
1564
+ } catch (error) {
1565
+ const message = error instanceof Error ? error.message : String(error);
1566
+ logger.error(red(`Version cache error: ${message}`));
1567
+ }
1568
+ }
1569
+ async function checkVersionIdle(deps = {}) {
1570
+ const logger = deps.logger ?? Logger;
1571
+ const now = deps.now ?? (() => Date.now());
1572
+ const cachePath = deps.cachePath ?? resolveIdleCachePath();
1573
+ const cache = loadIdleCache(cachePath, deps.fs);
1574
+ if (deps.force !== true) {
1575
+ const idle = cache.idle_time_epoch;
1576
+ if (typeof idle === "number" && idle > now()) {
1577
+ return { checked: false, status: "idle" };
1578
+ }
1579
+ }
1580
+ const probe = await probeLatestVersion(deps);
1581
+ if (probe.status === "disabled") {
1582
+ return { checked: false, status: "disabled" };
1583
+ }
1584
+ let delayMs = IDLE_WINDOW_DEFAULT_MS;
1585
+ let lastSuccess = typeof cache.last_success_epoch === "number" ? cache.last_success_epoch : void 0;
1586
+ const result = { checked: true, status: probe.status };
1587
+ switch (probe.status) {
1588
+ case "unknown-version":
1589
+ logger.error(red("Version check error: running package version is unknown."));
1590
+ break;
1591
+ case "error":
1592
+ logger.error(red(`Version check error: ${probe.message}`));
1593
+ break;
1594
+ case "current":
1595
+ lastSuccess = now();
1596
+ result.currentVersion = probe.currentVersion;
1597
+ logger.error(red("Version check: no newer version available."));
1598
+ break;
1599
+ case "newer": {
1600
+ lastSuccess = now();
1601
+ delayMs = IDLE_WINDOW_NEWER_MS;
1602
+ result.currentVersion = probe.currentVersion;
1603
+ result.latestVersion = probe.latestVersion;
1604
+ logger.log(
1605
+ green(
1606
+ `Available Version: ${probe.latestVersion} | Installed Version: ${probe.currentVersion}`
1607
+ )
1608
+ );
1609
+ logger.log(
1610
+ green(
1611
+ `Upgrade with: npm install -g ${DEFAULT_PACKAGE_NAME}@latest (or run: ${DEFAULT_PACKAGE_NAME} --upgrade)`
1612
+ )
1613
+ );
1614
+ break;
1615
+ }
1616
+ }
1617
+ const finishedAt = now();
1618
+ const idleUntil = finishedAt + delayMs;
1619
+ persistIdleCache(cachePath, lastSuccess, idleUntil, deps.fs, logger);
1620
+ result.idleUntilEpoch = idleUntil;
1621
+ result.lastSuccessEpoch = lastSuccess;
1622
+ return result;
1623
+ }
1624
+ function parseManagementCommand(args) {
1625
+ if (args.length !== 1) {
1626
+ return void 0;
1627
+ }
1628
+ const arg = args[0];
1629
+ if (arg === "--ver" || arg === "--version" || arg === "--upgrade" || arg === "--uninstall") {
1630
+ return arg;
1631
+ }
1632
+ return void 0;
1633
+ }
1634
+ function runPackageManagerCommand(command, deps = {}) {
1635
+ const logger = deps.logger ?? Logger;
1636
+ const spawnImpl = deps.spawn ?? spawnSync;
1637
+ const reportSpawnFailure = (message) => {
1638
+ logger.error(`Error executing ${command[0]}: ${message}`);
1639
+ logger.log(`Warning: run this command manually: ${command.join(" ")}`);
1640
+ return 1;
1641
+ };
1642
+ try {
1643
+ const result = spawnImpl(command[0], [...command.slice(1)], {
1644
+ stdio: "inherit",
1645
+ shell: process.platform === "win32"
1646
+ });
1647
+ if (result.error) {
1648
+ return reportSpawnFailure(result.error.message);
1649
+ }
1650
+ return result.status ?? 1;
1651
+ } catch (error) {
1652
+ const message = error instanceof Error ? error.message : String(error);
1653
+ return reportSpawnFailure(message);
1654
+ }
1655
+ }
1656
+ function runPostUpgradeSkillInstall(options, deps = {}) {
1657
+ const enabled = loadCliSettings(options.home).enabled;
1658
+ if (enabled.length === 0) {
1659
+ return 0;
1660
+ }
1661
+ return runPackageManagerCommand(POST_UPGRADE_INSTALL_COMMAND, deps);
1662
+ }
1663
+ async function runVersionCommand(options, deps = {}) {
1664
+ await checkVersionIdle({
1665
+ ...deps.idleCheck,
1666
+ force: true,
1667
+ currentVersion: options.currentVersion
1668
+ });
1669
+ const stdout = deps.stdout ?? process.stdout;
1670
+ stdout.write(`${options.currentVersion}
1671
+ `);
1672
+ return 0;
1673
+ }
1674
+ function runUpgradeCommand(options, deps = {}) {
1675
+ const upgraded = runPackageManagerCommand(PACKAGE_UPGRADE_COMMAND, deps);
1676
+ if (upgraded !== 0) {
1677
+ return upgraded;
1678
+ }
1679
+ return runPostUpgradeSkillInstall(options, deps);
1680
+ }
1681
+ function runUninstallCommand(deps = {}) {
1682
+ return runPackageManagerCommand(PACKAGE_UNINSTALL_COMMAND, deps);
1683
+ }
1684
+ async function runManagementCommand(command, options, deps = {}) {
1685
+ switch (command) {
1686
+ case "--ver":
1687
+ case "--version":
1688
+ return runVersionCommand(options, deps);
1689
+ case "--upgrade":
1690
+ return runUpgradeCommand(options, deps);
1691
+ case "--uninstall":
1692
+ return runUninstallCommand(deps);
1693
+ }
1694
+ }
1695
+
1458
1696
  // src/utils/toolProfiles.ts
1459
1697
  var TOOL_API_PROFILES = {
1460
1698
  maps_geocode: { tool: "maps_geocode", apis: ["geocoding"], dependsOnTools: [] },
@@ -1575,95 +1813,51 @@ function renderClientSnippet(options = {}) {
1575
1813
  return { json, notes };
1576
1814
  }
1577
1815
 
1578
- // src/utils/cliSettings.ts
1579
- import { mkdirSync, readFileSync, renameSync, writeFileSync } from "fs";
1580
- import { join, resolve } from "path";
1581
- var SETTINGS_PROGRAM_NAME = "mcp-google-map";
1582
- var CLI_SETTINGS_RELATIVE = [".config", SETTINGS_PROGRAM_NAME, "config.json"];
1583
- var MCP_SERVER_NAME = "mcp-google-map";
1584
- function resolveCliSettingsPath(home) {
1585
- const root = home ?? (process.env.HOME ?? process.cwd());
1586
- return resolve(root, ...CLI_SETTINGS_RELATIVE);
1587
- }
1588
- function uniqueStrings(value) {
1589
- if (!Array.isArray(value)) return [];
1590
- const result = [];
1591
- for (const item of value) {
1592
- if (typeof item === "string" && item.length > 0 && !result.includes(item)) {
1593
- result.push(item);
1594
- }
1595
- }
1596
- return result;
1597
- }
1598
- function loadCliSettings(home) {
1599
- try {
1600
- const raw = JSON.parse(readFileSync(resolveCliSettingsPath(home), "utf-8"));
1601
- if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
1602
- return { enabled: [] };
1603
- }
1604
- return { enabled: uniqueStrings(raw.enabled) };
1605
- } catch {
1606
- return { enabled: [] };
1607
- }
1608
- }
1609
- function saveCliSettings(settings, home) {
1610
- const path = resolveCliSettingsPath(home);
1611
- const temporary = `${path}.tmp`;
1612
- try {
1613
- mkdirSync(join(path, ".."), { recursive: true });
1614
- writeFileSync(temporary, JSON.stringify({ enabled: uniqueStrings(settings.enabled) }, null, 2) + "\n", "utf-8");
1615
- renameSync(temporary, path);
1616
- } catch (error) {
1617
- throw new Error(`settings write failed: ${error instanceof Error ? error.message : String(error)}`);
1618
- }
1619
- return path;
1620
- }
1621
-
1622
1816
  // src/utils/cliTargets.ts
1623
1817
  import {
1624
1818
  cpSync,
1625
1819
  existsSync as existsSync2,
1626
- mkdirSync as mkdirSync2,
1627
- readFileSync as readFileSync2,
1820
+ mkdirSync as mkdirSync3,
1821
+ readFileSync as readFileSync3,
1628
1822
  readdirSync,
1629
1823
  renameSync as renameSync2,
1630
1824
  rmSync,
1631
1825
  statSync,
1632
- writeFileSync as writeFileSync2
1826
+ writeFileSync as writeFileSync3
1633
1827
  } from "fs";
1634
- import { join as join2, relative } from "path";
1828
+ import { join as join3, relative } from "path";
1635
1829
  function homeRoot(home) {
1636
1830
  return home ?? (process.env.HOME ?? process.cwd());
1637
1831
  }
1638
1832
  var PI_TARGET = {
1639
1833
  id: "pi",
1640
1834
  configFormat: "json",
1641
- mcpConfigPath: (home) => join2(homeRoot(home), ".pi", "agent", "mcp.json"),
1642
- skillsDir: (home) => join2(homeRoot(home), ".pi", "agent", "skills")
1835
+ mcpConfigPath: (home) => join3(homeRoot(home), ".pi", "agent", "mcp.json"),
1836
+ skillsDir: (home) => join3(homeRoot(home), ".pi", "agent", "skills")
1643
1837
  };
1644
1838
  var OPENCLAW_TARGET = {
1645
1839
  id: "openclaw",
1646
1840
  configFormat: "json",
1647
- mcpConfigPath: (home) => join2(homeRoot(home), ".openclaw", "openclaw.json"),
1648
- skillsDir: (home) => join2(homeRoot(home), ".openclaw", "workspace", "skills")
1841
+ mcpConfigPath: (home) => join3(homeRoot(home), ".openclaw", "openclaw.json"),
1842
+ skillsDir: (home) => join3(homeRoot(home), ".openclaw", "workspace", "skills")
1649
1843
  };
1650
1844
  var CODEX_TARGET = {
1651
1845
  id: "codex",
1652
1846
  configFormat: "toml",
1653
- mcpConfigPath: (home) => join2(homeRoot(home), ".codex", "config.toml"),
1654
- skillsDir: (home) => join2(homeRoot(home), ".codex", "skills")
1847
+ mcpConfigPath: (home) => join3(homeRoot(home), ".codex", "config.toml"),
1848
+ skillsDir: (home) => join3(homeRoot(home), ".codex", "skills")
1655
1849
  };
1656
1850
  var ANTIGRAVITY_TARGET = {
1657
1851
  id: "antigravity",
1658
1852
  configFormat: "json",
1659
- mcpConfigPath: (home) => join2(homeRoot(home), ".gemini", "settings.json"),
1660
- skillsDir: (home) => join2(homeRoot(home), ".gemini", "config", "skills")
1853
+ mcpConfigPath: (home) => join3(homeRoot(home), ".gemini", "settings.json"),
1854
+ skillsDir: (home) => join3(homeRoot(home), ".gemini", "config", "skills")
1661
1855
  };
1662
1856
  var CLAUDE_TARGET = {
1663
1857
  id: "claude",
1664
1858
  configFormat: "json",
1665
- mcpConfigPath: (home) => join2(homeRoot(home), ".claude.json"),
1666
- skillsDir: (home) => join2(homeRoot(home), ".claude", "skills")
1859
+ mcpConfigPath: (home) => join3(homeRoot(home), ".claude.json"),
1860
+ skillsDir: (home) => join3(homeRoot(home), ".claude", "skills")
1667
1861
  };
1668
1862
  var CLI_TARGETS = {
1669
1863
  pi: PI_TARGET,
@@ -1680,7 +1874,7 @@ function supportedCliNames() {
1680
1874
  }
1681
1875
  function readJsonConfig(configPath) {
1682
1876
  if (!existsSync2(configPath)) return {};
1683
- const parsed = JSON.parse(readFileSync2(configPath, "utf-8"));
1877
+ const parsed = JSON.parse(readFileSync3(configPath, "utf-8"));
1684
1878
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
1685
1879
  throw new Error(`configuration is not a JSON object: ${configPath}`);
1686
1880
  }
@@ -1688,8 +1882,8 @@ function readJsonConfig(configPath) {
1688
1882
  }
1689
1883
  function writeJsonConfig(configPath, value) {
1690
1884
  const temporary = `${configPath}.tmp`;
1691
- mkdirSync2(join2(configPath, ".."), { recursive: true });
1692
- writeFileSync2(temporary, JSON.stringify(value, null, 2) + "\n", "utf-8");
1885
+ mkdirSync3(join3(configPath, ".."), { recursive: true });
1886
+ writeFileSync3(temporary, JSON.stringify(value, null, 2) + "\n", "utf-8");
1693
1887
  renameSync2(temporary, configPath);
1694
1888
  }
1695
1889
  function writeJsonMcpServerEntry(configPath, serverName, entry) {
@@ -1776,35 +1970,35 @@ function registrationToTomlLines(entry) {
1776
1970
  return lines;
1777
1971
  }
1778
1972
  function writeTomlMcpServerSection(configPath, serverName, entry) {
1779
- const previous = existsSync2(configPath) ? readFileSync2(configPath, "utf-8") : "";
1973
+ const previous = existsSync2(configPath) ? readFileSync3(configPath, "utf-8") : "";
1780
1974
  const base = removeTomlSection(previous, serverName);
1781
1975
  const table = [tomlSectionHeader(serverName), ...registrationToTomlLines(entry), ""].join("\n");
1782
1976
  const content = base.length > 0 ? base.replace(/\n*$/, "\n") + table : table;
1783
1977
  const temporary = `${configPath}.tmp`;
1784
- mkdirSync2(join2(configPath, ".."), { recursive: true });
1785
- writeFileSync2(temporary, content, "utf-8");
1978
+ mkdirSync3(join3(configPath, ".."), { recursive: true });
1979
+ writeFileSync3(temporary, content, "utf-8");
1786
1980
  renameSync2(temporary, configPath);
1787
1981
  }
1788
1982
  function removeTomlMcpServerSection(configPath, serverName) {
1789
1983
  if (!existsSync2(configPath)) return false;
1790
- const previous = readFileSync2(configPath, "utf-8");
1984
+ const previous = readFileSync3(configPath, "utf-8");
1791
1985
  if (!hasTomlSection(previous, serverName)) return false;
1792
1986
  const content = removeTomlSection(previous, serverName);
1793
1987
  const temporary = `${configPath}.tmp`;
1794
- writeFileSync2(temporary, content, "utf-8");
1988
+ writeFileSync3(temporary, content, "utf-8");
1795
1989
  renameSync2(temporary, configPath);
1796
1990
  return true;
1797
1991
  }
1798
1992
  function hasTomlMcpServerSection(configPath, serverName) {
1799
1993
  if (!existsSync2(configPath)) return false;
1800
- return hasTomlSection(readFileSync2(configPath, "utf-8"), serverName);
1994
+ return hasTomlSection(readFileSync3(configPath, "utf-8"), serverName);
1801
1995
  }
1802
1996
  function listFilesRecursive(root) {
1803
1997
  if (!existsSync2(root)) return [];
1804
1998
  const files = [];
1805
1999
  const walk = (dir) => {
1806
2000
  for (const entry of readdirSync(dir)) {
1807
- const full = join2(dir, entry);
2001
+ const full = join3(dir, entry);
1808
2002
  if (statSync(full).isDirectory()) {
1809
2003
  walk(full);
1810
2004
  } else {
@@ -1816,14 +2010,14 @@ function listFilesRecursive(root) {
1816
2010
  return files;
1817
2011
  }
1818
2012
  function syncSkillTree(source, destination) {
1819
- mkdirSync2(destination, { recursive: true });
2013
+ mkdirSync3(destination, { recursive: true });
1820
2014
  cpSync(source, destination, { recursive: true, force: true });
1821
2015
  const expected = new Set(listFilesRecursive(source));
1822
2016
  const existing = listFilesRecursive(destination);
1823
2017
  existing.sort((a, b) => b.length - a.length);
1824
2018
  for (const rel of existing) {
1825
2019
  if (expected.has(rel)) continue;
1826
- rmSync(join2(destination, rel), { recursive: true, force: true });
2020
+ rmSync(join3(destination, rel), { recursive: true, force: true });
1827
2021
  }
1828
2022
  }
1829
2023
  function removeSkillDir(skillDir) {
@@ -1834,9 +2028,9 @@ function compareSkillTree(source, destination) {
1834
2028
  if (packaged.length === 0) return "MISSING";
1835
2029
  if (!existsSync2(destination)) return "MISSING";
1836
2030
  for (const rel of packaged) {
1837
- const target = join2(destination, ...rel.split("/"));
2031
+ const target = join3(destination, ...rel.split("/"));
1838
2032
  if (!existsSync2(target)) return "MISSING";
1839
- if (readFileSync2(target).toString("utf-8") !== readFileSync2(join2(source, ...rel.split("/"))).toString("utf-8")) {
2033
+ if (readFileSync3(target).toString("utf-8") !== readFileSync3(join3(source, ...rel.split("/"))).toString("utf-8")) {
1840
2034
  return "STALE";
1841
2035
  }
1842
2036
  }
@@ -1867,8 +2061,8 @@ function applyServerRegistration(target, serverName, entry, home) {
1867
2061
  }
1868
2062
 
1869
2063
  // src/utils/cliInstaller.ts
1870
- import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
1871
- import { join as join3, resolve as resolve3 } from "path";
2064
+ import { existsSync as existsSync3, readFileSync as readFileSync4 } from "fs";
2065
+ import { join as join4, resolve as resolve3 } from "path";
1872
2066
  function buildServerRegistration(apiKey) {
1873
2067
  const env = {};
1874
2068
  if (apiKey !== void 0 && apiKey.length > 0) {
@@ -1884,13 +2078,13 @@ function resolveSkillsResourcesRoot(packageRoot) {
1884
2078
  return candidate;
1885
2079
  }
1886
2080
  function loadSkillsManifest(resourcesRoot) {
1887
- const manifestPath = join3(resourcesRoot, "manifest.json");
2081
+ const manifestPath = join4(resourcesRoot, "manifest.json");
1888
2082
  if (!existsSync3(manifestPath)) {
1889
2083
  throw new Error(`skills manifest not found: ${manifestPath}`);
1890
2084
  }
1891
2085
  let parsed;
1892
2086
  try {
1893
- parsed = JSON.parse(readFileSync3(manifestPath, "utf-8"));
2087
+ parsed = JSON.parse(readFileSync4(manifestPath, "utf-8"));
1894
2088
  } catch (error) {
1895
2089
  throw new Error(`skills manifest is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
1896
2090
  }
@@ -1903,8 +2097,8 @@ function loadSkillsManifest(resourcesRoot) {
1903
2097
  if (typeof skill.id !== "string" || typeof skill.path !== "string") {
1904
2098
  throw new Error(`skills manifest entry is missing id or path: ${manifestPath}`);
1905
2099
  }
1906
- if (!existsSync3(join3(resourcesRoot, skill.path))) {
1907
- throw new Error(`manifest skill file not found: ${join3(resourcesRoot, skill.path)}`);
2100
+ if (!existsSync3(join4(resourcesRoot, skill.path))) {
2101
+ throw new Error(`manifest skill file not found: ${join4(resourcesRoot, skill.path)}`);
1908
2102
  }
1909
2103
  return {
1910
2104
  id: skill.id,
@@ -1929,7 +2123,7 @@ function installEnabledCliResources(options) {
1929
2123
  applyServerRegistration(target, MCP_SERVER_NAME, entry, options.home);
1930
2124
  let skills = 0;
1931
2125
  for (const skill of manifest) {
1932
- syncSkillTree(join3(options.resourcesRoot, skill.id), join3(target.skillsDir(options.home), skill.id));
2126
+ syncSkillTree(join4(options.resourcesRoot, skill.id), join4(target.skillsDir(options.home), skill.id));
1933
2127
  skills += 1;
1934
2128
  }
1935
2129
  result.summaries.push({ cli: target.id, server: 1, skills });
@@ -1952,7 +2146,7 @@ function uninstallEnabledCliResources(options) {
1952
2146
  applyServerRegistration(target, MCP_SERVER_NAME, void 0, options.home);
1953
2147
  let skills = 0;
1954
2148
  for (const skill of manifest) {
1955
- removeSkillDir(join3(target.skillsDir(options.home), skill.id));
2149
+ removeSkillDir(join4(target.skillsDir(options.home), skill.id));
1956
2150
  skills += 1;
1957
2151
  }
1958
2152
  result.summaries.push({ cli: target.id, server: 0, skills });
@@ -1964,7 +2158,7 @@ function uninstallEnabledCliResources(options) {
1964
2158
  }
1965
2159
 
1966
2160
  // src/utils/cliShow.ts
1967
- import { join as join4 } from "path";
2161
+ import { join as join5 } from "path";
1968
2162
  import { relative as relative2, resolve as resolve4 } from "path";
1969
2163
  var MAX_CELL_WIDTH = 48;
1970
2164
  var STATUS_OK = "OK";
@@ -2051,7 +2245,7 @@ function buildInstallRows(home, resourcesRoot) {
2051
2245
  skill.id,
2052
2246
  target.id,
2053
2247
  "yes",
2054
- compareSkillTree(join4(resourcesRoot, skill.id), join4(target.skillsDir(home), skill.id))
2248
+ compareSkillTree(join5(resourcesRoot, skill.id), join5(target.skillsDir(home), skill.id))
2055
2249
  ]);
2056
2250
  }
2057
2251
  }
@@ -2069,7 +2263,7 @@ function buildCliShowReport(options) {
2069
2263
 
2070
2264
  // src/cli.ts
2071
2265
  var __filename = fileURLToPath(import.meta.url);
2072
- var __dirname = dirname(__filename);
2266
+ var __dirname = dirname2(__filename);
2073
2267
  function extractEnvFileOption(argv) {
2074
2268
  for (let i = 0; i < argv.length; i++) {
2075
2269
  const arg = argv[i];
@@ -2466,8 +2660,8 @@ async function runDoctor(packageVersion, apiKey, live = false, runner = execTool
2466
2660
  async function runSetup(options, deps = {}) {
2467
2661
  const fsImpl = deps.fs ?? {
2468
2662
  existsSync: (path) => existsSync4(path),
2469
- readFileSync: (path, encoding) => readFileSync4(path, encoding),
2470
- writeFileSync: (path, data, encoding) => writeFileSync3(path, data, encoding)
2663
+ readFileSync: (path, encoding) => readFileSync5(path, encoding),
2664
+ writeFileSync: (path, data, encoding) => writeFileSync4(path, data, encoding)
2471
2665
  };
2472
2666
  const nodeVersion = deps.nodeVersion ?? process.versions.node;
2473
2667
  const nodeMajor = Number.parseInt(nodeVersion.split(".")[0] ?? "0", 10);
@@ -2625,402 +2819,413 @@ if (isRunDirectly || isMainModule) {
2625
2819
  let packageVersion = "0.0.0";
2626
2820
  try {
2627
2821
  const packageJsonPath = resolve5(__dirname, "../package.json");
2628
- const packageJson = JSON.parse(readFileSync4(packageJsonPath, "utf-8"));
2822
+ const packageJson = JSON.parse(readFileSync5(packageJsonPath, "utf-8"));
2629
2823
  packageVersion = packageJson.version;
2630
2824
  } catch (e) {
2631
2825
  packageVersion = "0.0.0";
2632
2826
  }
2633
- yargs(hideBin(process.argv)).command(
2634
- "doctor",
2635
- "Check standalone CLI readiness without starting an MCP server",
2636
- (yargs2) => yargs2.option("live", {
2637
- type: "boolean",
2638
- default: false,
2639
- description: "Make billable test requests to Geocoding, Places (New), and Routes APIs"
2640
- }).option("probes", {
2641
- type: "string",
2642
- description: "Comma-separated subset of live probes: geocoding, places-new, routes (default: all three)"
2643
- }).option("apikey", {
2644
- alias: "k",
2645
- type: "string",
2646
- description: "Google Maps API key (prefer GOOGLE_MAPS_API_KEY to avoid shell history exposure)",
2647
- default: process.env.GOOGLE_MAPS_API_KEY
2648
- }).example([
2649
- ["$0 doctor", "Check local runtime and API key configuration without network calls"],
2650
- ["$0 doctor --live", "Also verify three Google Maps APIs with billable requests"],
2651
- ["$0 doctor --live --probes geocoding,routes", "Probe only the selected APIs"]
2652
- ]),
2653
- async (argv) => {
2654
- const parsedProbes = parseDoctorProbes(argv.probes);
2655
- if (parsedProbes.error) {
2656
- process.stderr.write(JSON.stringify({ error: parsedProbes.error }, null, 2) + "\n");
2657
- process.exitCode = 1;
2658
- return;
2659
- }
2660
- const report = await runDoctor(packageVersion, argv.apikey, argv.live, void 0, {
2661
- probes: parsedProbes.probes,
2662
- config: resolveRuntimeConfig(process.env, { envFile: extractEnvFileOption(process.argv) })
2663
- });
2664
- process.stdout.write(JSON.stringify(report, null, 2) + "\n");
2665
- process.exitCode = report.success ? 0 : 1;
2666
- }
2667
- ).command(
2668
- "setup",
2669
- "Non-interactive onboarding: verify local readiness, optionally scaffold .env",
2670
- (yargs2) => yargs2.option("write-env", {
2671
- type: "boolean",
2672
- default: false,
2673
- description: "Create .env from .env.example in --env-dir when it does not exist (never overwrites)"
2674
- }).option("env-dir", {
2675
- type: "string",
2676
- default: process.cwd(),
2677
- description: "Directory where .env is looked up / created"
2678
- }).example([
2679
- ["$0 setup", "Check readiness without writing anything"],
2680
- ["$0 setup --write-env", "Also scaffold .env from the package template"]
2681
- ]),
2682
- async (argv) => {
2683
- const report = await runSetup({
2684
- packageDir: resolve5(__dirname, ".."),
2685
- targetDir: argv.envDir,
2686
- writeEnv: argv.writeEnv
2687
- });
2688
- process.stdout.write(JSON.stringify(report, null, 2) + "\n");
2689
- process.exitCode = report.success ? 0 : 1;
2690
- }
2691
- ).command(
2692
- "snippet",
2693
- "Print an MCP client registration snippet (JSON on stdout; never writes files)",
2694
- (yargs2) => yargs2.option("client", {
2695
- type: "string",
2696
- choices: ["generic", "claude", "cursor", "pi"],
2697
- default: "generic",
2698
- description: "Target client (selects the documented target file)"
2699
- }).option("transport", {
2700
- type: "string",
2701
- choices: ["stdio", "http"],
2702
- default: "stdio",
2703
- description: "MCP transport of the snippet"
2704
- }).option("launcher", {
2705
- type: "string",
2706
- choices: ["npx", "node", "bin"],
2707
- default: "npx",
2708
- description: "stdio launcher command"
2709
- }).option("command", {
2710
- type: "string",
2711
- description: "Absolute path to dist/cli.js (required for --launcher node)"
2712
- }).option("host", {
2713
- type: "string",
2714
- default: "127.0.0.1",
2715
- description: "Host used in the URL (transport http)"
2716
- }).option("port", {
2717
- type: "number",
2718
- default: 3e3,
2719
- description: "Port used in the URL (transport http)"
2720
- }).option("env-key", {
2721
- type: "string",
2722
- description: "Emit a ${NAME} variable reference instead of a literal placeholder (expansion is client-specific)"
2723
- }).option("name", {
2724
- type: "string",
2725
- default: "mcp-google-map",
2726
- description: "Server name inside mcpServers"
2727
- }).example([
2728
- ["$0 snippet --client claude", "stdio snippet using the npx launcher"],
2729
- ["$0 snippet --client pi --launcher node --command /abs/path/dist/cli.js", "stdio snippet with an explicit artifact"],
2730
- ["$0 snippet --transport http --port 3100", "HTTP URL snippet"]
2731
- ]),
2732
- (argv) => {
2733
- process.exitCode = runSnippetCommand({
2734
- client: argv.client,
2735
- transport: argv.transport,
2736
- launcher: argv.launcher,
2737
- commandPath: argv.command,
2738
- host: argv.host,
2739
- port: argv.port,
2740
- envKey: argv.envKey,
2741
- serverName: argv.name
2742
- });
2743
- }
2744
- ).command(
2745
- "enable <cli>",
2746
- "Enable MCP-server and skill installation for a supported CLI",
2747
- (yargs2) => yargs2.positional("cli", {
2748
- type: "string",
2749
- describe: `CLI name: ${supportedCliNames()}`
2750
- }).option("home", {
2751
- type: "string",
2752
- description: "Home-directory override for the settings file (default: user home)"
2753
- }).example([["$0 enable pi", "Enable pi for install/uninstall/show"]]),
2754
- (argv) => {
2755
- process.exitCode = runEnableDisableCliCommand(argv.cli, true, {
2756
- home: argv.home
2757
- });
2758
- }
2759
- ).command(
2760
- "disable <cli>",
2761
- "Disable MCP-server and skill installation for a supported CLI",
2762
- (yargs2) => yargs2.positional("cli", {
2763
- type: "string",
2764
- describe: `CLI name: ${supportedCliNames()}`
2765
- }).option("home", {
2766
- type: "string",
2767
- description: "Home-directory override for the settings file (default: user home)"
2768
- }).example([["$0 disable claude", "Disable claude for install/uninstall/show"]]),
2769
- (argv) => {
2770
- process.exitCode = runEnableDisableCliCommand(argv.cli, false, {
2771
- home: argv.home
2772
- });
2773
- }
2774
- ).command(
2775
- "install",
2776
- "Register the mcp-google-map stdio server and install packaged skills for every enabled CLI",
2777
- (yargs2) => yargs2.option("home", {
2778
- type: "string",
2779
- description: "Home-directory override for CLI configuration paths (default: user home)"
2780
- }).option("apikey", {
2781
- alias: "k",
2782
- type: "string",
2783
- description: "Google Maps API key embedded in the registered entry (prefer GOOGLE_MAPS_API_KEY)",
2784
- default: resolveRuntimeConfig(process.env, { envFile: extractEnvFileOption(process.argv) }).apiKey
2785
- }).example([["$0 install", "Register the server and skills in every enabled CLI"]]),
2786
- (argv) => {
2787
- process.exitCode = runInstallUninstallCommand("install", {
2788
- home: argv.home,
2789
- apiKey: argv.apikey,
2790
- resourcesRoot: resolveSkillsResourcesRoot(resolve5(__dirname, ".."))
2791
- });
2792
- }
2793
- ).command(
2794
- "uninstall",
2795
- "Remove the mcp-google-map server entry and managed skills from every enabled CLI",
2796
- (yargs2) => yargs2.option("home", {
2797
- type: "string",
2798
- description: "Home-directory override for CLI configuration paths (default: user home)"
2799
- }).example([["$0 uninstall", "Reciprocal removal of install for every enabled CLI"]]),
2800
- (argv) => {
2801
- process.exitCode = runInstallUninstallCommand("uninstall", {
2802
- home: argv.home,
2803
- resourcesRoot: resolveSkillsResourcesRoot(resolve5(__dirname, ".."))
2804
- });
2805
- }
2806
- ).command(
2807
- "show",
2808
- "Show CLI configuration and installation status tables (human-readable)",
2809
- (yargs2) => yargs2.option("home", {
2810
- type: "string",
2811
- description: "Home-directory override for CLI configuration paths (default: user home)"
2812
- }).example([["$0 show", "Print CLI Configuration and Installation Status tables"]]),
2813
- (argv) => {
2814
- process.exitCode = runShowCommand({
2815
- home: argv.home,
2816
- resourcesRoot: resolveSkillsResourcesRoot(resolve5(__dirname, ".."))
2817
- });
2818
- }
2819
- ).command(
2820
- "exec <tool> [params]",
2821
- "Execute a tool directly and output JSON",
2822
- (yargs2) => {
2823
- return yargs2.positional("tool", {
2824
- type: "string",
2825
- describe: `Tool name: ${EXEC_TOOLS.join(", ")}`
2826
- }).positional("params", {
2827
+ const managementCommand = parseManagementCommand(hideBin(process.argv));
2828
+ if (managementCommand !== void 0) {
2829
+ void runManagementCommand(managementCommand, { currentVersion: packageVersion }).then((code) => {
2830
+ process.exitCode = code;
2831
+ }).catch((error) => {
2832
+ const message = error instanceof Error ? error.message : String(error);
2833
+ process.stderr.write(JSON.stringify({ error: message }, null, 2) + "\n");
2834
+ process.exitCode = 1;
2835
+ });
2836
+ } else {
2837
+ yargs(hideBin(process.argv)).command(
2838
+ "doctor",
2839
+ "Check standalone CLI readiness without starting an MCP server",
2840
+ (yargs2) => yargs2.option("live", {
2841
+ type: "boolean",
2842
+ default: false,
2843
+ description: "Make billable test requests to Geocoding, Places (New), and Routes APIs"
2844
+ }).option("probes", {
2827
2845
  type: "string",
2828
- describe: "JSON parameters string"
2846
+ description: "Comma-separated subset of live probes: geocoding, places-new, routes (default: all three)"
2829
2847
  }).option("apikey", {
2830
2848
  alias: "k",
2831
2849
  type: "string",
2832
- description: "Google Maps API key",
2850
+ description: "Google Maps API key (prefer GOOGLE_MAPS_API_KEY to avoid shell history exposure)",
2833
2851
  default: process.env.GOOGLE_MAPS_API_KEY
2834
2852
  }).example([
2835
- [`$0 exec geocode '{"address":"Tokyo Tower"}'`, "Geocode an address"],
2836
- [
2837
- `$0 exec search-nearby '{"center":{"value":"35.68,139.74","isCoordinates":true},"keyword":"restaurant"}'`,
2838
- "Search nearby"
2839
- ],
2840
- [`$0 exec search-places '{"query":"ramen in Tokyo"}'`, "Text search"]
2841
- ]);
2842
- },
2843
- async (argv) => {
2844
- if (!argv.apikey) {
2845
- process.stderr.write(
2846
- JSON.stringify(
2847
- {
2848
- error: "GOOGLE_MAPS_API_KEY not set. Use --apikey or set GOOGLE_MAPS_API_KEY environment variable."
2849
- },
2850
- null,
2851
- 2
2852
- ) + "\n"
2853
- );
2854
- process.exitCode = 1;
2855
- return;
2853
+ ["$0 doctor", "Check local runtime and API key configuration without network calls"],
2854
+ ["$0 doctor --live", "Also verify three Google Maps APIs with billable requests"],
2855
+ ["$0 doctor --live --probes geocoding,routes", "Probe only the selected APIs"]
2856
+ ]),
2857
+ async (argv) => {
2858
+ const parsedProbes = parseDoctorProbes(argv.probes);
2859
+ if (parsedProbes.error) {
2860
+ process.stderr.write(JSON.stringify({ error: parsedProbes.error }, null, 2) + "\n");
2861
+ process.exitCode = 1;
2862
+ return;
2863
+ }
2864
+ const report = await runDoctor(packageVersion, argv.apikey, argv.live, void 0, {
2865
+ probes: parsedProbes.probes,
2866
+ config: resolveRuntimeConfig(process.env, { envFile: extractEnvFileOption(process.argv) })
2867
+ });
2868
+ process.stdout.write(JSON.stringify(report, null, 2) + "\n");
2869
+ process.exitCode = report.success ? 0 : 1;
2856
2870
  }
2857
- try {
2858
- const params = argv.params ? JSON.parse(argv.params) : {};
2859
- process.exitCode = await runExecCommand(argv.tool, params, argv.apikey);
2860
- } catch (error) {
2861
- process.stderr.write(JSON.stringify({ error: error.message }, null, 2) + "\n");
2862
- process.exitCode = 1;
2871
+ ).command(
2872
+ "setup",
2873
+ "Non-interactive onboarding: verify local readiness, optionally scaffold .env",
2874
+ (yargs2) => yargs2.option("write-env", {
2875
+ type: "boolean",
2876
+ default: false,
2877
+ description: "Create .env from .env.example in --env-dir when it does not exist (never overwrites)"
2878
+ }).option("env-dir", {
2879
+ type: "string",
2880
+ default: process.cwd(),
2881
+ description: "Directory where .env is looked up / created"
2882
+ }).example([
2883
+ ["$0 setup", "Check readiness without writing anything"],
2884
+ ["$0 setup --write-env", "Also scaffold .env from the package template"]
2885
+ ]),
2886
+ async (argv) => {
2887
+ const report = await runSetup({
2888
+ packageDir: resolve5(__dirname, ".."),
2889
+ targetDir: argv.envDir,
2890
+ writeEnv: argv.writeEnv
2891
+ });
2892
+ process.stdout.write(JSON.stringify(report, null, 2) + "\n");
2893
+ process.exitCode = report.success ? 0 : 1;
2863
2894
  }
2864
- }
2865
- ).command(
2866
- "batch-geocode",
2867
- "Geocode multiple addresses from a file (one address per line)",
2868
- (yargs2) => {
2869
- return yargs2.option("input", {
2870
- alias: "i",
2895
+ ).command(
2896
+ "snippet",
2897
+ "Print an MCP client registration snippet (JSON on stdout; never writes files)",
2898
+ (yargs2) => yargs2.option("client", {
2899
+ type: "string",
2900
+ choices: ["generic", "claude", "cursor", "pi"],
2901
+ default: "generic",
2902
+ description: "Target client (selects the documented target file)"
2903
+ }).option("transport", {
2904
+ type: "string",
2905
+ choices: ["stdio", "http"],
2906
+ default: "stdio",
2907
+ description: "MCP transport of the snippet"
2908
+ }).option("launcher", {
2909
+ type: "string",
2910
+ choices: ["npx", "node", "bin"],
2911
+ default: "npx",
2912
+ description: "stdio launcher command"
2913
+ }).option("command", {
2871
2914
  type: "string",
2872
- describe: "Input file path (one address per line). Use - for stdin.",
2873
- demandOption: true
2874
- }).option("output", {
2875
- alias: "o",
2915
+ description: "Absolute path to dist/cli.js (required for --launcher node)"
2916
+ }).option("host", {
2876
2917
  type: "string",
2877
- describe: "Output file path (JSON). Defaults to stdout."
2878
- }).option("concurrency", {
2879
- alias: "c",
2918
+ default: "127.0.0.1",
2919
+ description: "Host used in the URL (transport http)"
2920
+ }).option("port", {
2880
2921
  type: "number",
2881
- describe: "Max parallel requests",
2882
- default: 20
2922
+ default: 3e3,
2923
+ description: "Port used in the URL (transport http)"
2924
+ }).option("env-key", {
2925
+ type: "string",
2926
+ description: "Emit a ${NAME} variable reference instead of a literal placeholder (expansion is client-specific)"
2927
+ }).option("name", {
2928
+ type: "string",
2929
+ default: "mcp-google-map",
2930
+ description: "Server name inside mcpServers"
2931
+ }).example([
2932
+ ["$0 snippet --client claude", "stdio snippet using the npx launcher"],
2933
+ ["$0 snippet --client pi --launcher node --command /abs/path/dist/cli.js", "stdio snippet with an explicit artifact"],
2934
+ ["$0 snippet --transport http --port 3100", "HTTP URL snippet"]
2935
+ ]),
2936
+ (argv) => {
2937
+ process.exitCode = runSnippetCommand({
2938
+ client: argv.client,
2939
+ transport: argv.transport,
2940
+ launcher: argv.launcher,
2941
+ commandPath: argv.command,
2942
+ host: argv.host,
2943
+ port: argv.port,
2944
+ envKey: argv.envKey,
2945
+ serverName: argv.name
2946
+ });
2947
+ }
2948
+ ).command(
2949
+ "enable <cli>",
2950
+ "Enable MCP-server and skill installation for a supported CLI",
2951
+ (yargs2) => yargs2.positional("cli", {
2952
+ type: "string",
2953
+ describe: `CLI name: ${supportedCliNames()}`
2954
+ }).option("home", {
2955
+ type: "string",
2956
+ description: "Home-directory override for the settings file (default: user home)"
2957
+ }).example([["$0 enable pi", "Enable pi for install/uninstall/show"]]),
2958
+ (argv) => {
2959
+ process.exitCode = runEnableDisableCliCommand(argv.cli, true, {
2960
+ home: argv.home
2961
+ });
2962
+ }
2963
+ ).command(
2964
+ "disable <cli>",
2965
+ "Disable MCP-server and skill installation for a supported CLI",
2966
+ (yargs2) => yargs2.positional("cli", {
2967
+ type: "string",
2968
+ describe: `CLI name: ${supportedCliNames()}`
2969
+ }).option("home", {
2970
+ type: "string",
2971
+ description: "Home-directory override for the settings file (default: user home)"
2972
+ }).example([["$0 disable claude", "Disable claude for install/uninstall/show"]]),
2973
+ (argv) => {
2974
+ process.exitCode = runEnableDisableCliCommand(argv.cli, false, {
2975
+ home: argv.home
2976
+ });
2977
+ }
2978
+ ).command(
2979
+ "install",
2980
+ "Register the mcp-google-map stdio server and install packaged skills for every enabled CLI",
2981
+ (yargs2) => yargs2.option("home", {
2982
+ type: "string",
2983
+ description: "Home-directory override for CLI configuration paths (default: user home)"
2883
2984
  }).option("apikey", {
2884
2985
  alias: "k",
2885
2986
  type: "string",
2886
- description: "Google Maps API key",
2887
- default: process.env.GOOGLE_MAPS_API_KEY
2888
- }).example([
2889
- ["$0 batch-geocode -i addresses.txt", "Geocode to stdout"],
2890
- ["$0 batch-geocode -i addresses.txt -o results.json", "Geocode to file"],
2891
- ["cat addresses.txt | $0 batch-geocode -i -", "Geocode from stdin"]
2892
- ]);
2893
- },
2894
- async (argv) => {
2895
- if (!argv.apikey) {
2896
- console.error("Error: GOOGLE_MAPS_API_KEY not set. Use --apikey or set env var.");
2897
- process.exit(1);
2987
+ description: "Google Maps API key embedded in the registered entry (prefer GOOGLE_MAPS_API_KEY)",
2988
+ default: resolveRuntimeConfig(process.env, { envFile: extractEnvFileOption(process.argv) }).apiKey
2989
+ }).example([["$0 install", "Register the server and skills in every enabled CLI"]]),
2990
+ (argv) => {
2991
+ process.exitCode = runInstallUninstallCommand("install", {
2992
+ home: argv.home,
2993
+ apiKey: argv.apikey,
2994
+ resourcesRoot: resolveSkillsResourcesRoot(resolve5(__dirname, ".."))
2995
+ });
2898
2996
  }
2899
- let lines;
2900
- if (argv.input === "-") {
2901
- const rl = createInterface({ input: process.stdin });
2902
- lines = [];
2903
- for await (const line of rl) {
2904
- const trimmed = line.trim();
2905
- if (trimmed) lines.push(trimmed);
2906
- }
2907
- } else {
2908
- if (!existsSync4(argv.input)) {
2909
- console.error(`Error: File not found: ${argv.input}`);
2910
- process.exit(1);
2911
- }
2912
- lines = readFileSync4(argv.input, "utf-8").split("\n").map((l) => l.trim()).filter((l) => l.length > 0);
2997
+ ).command(
2998
+ "uninstall",
2999
+ "Remove the mcp-google-map server entry and managed skills from every enabled CLI",
3000
+ (yargs2) => yargs2.option("home", {
3001
+ type: "string",
3002
+ description: "Home-directory override for CLI configuration paths (default: user home)"
3003
+ }).example([["$0 uninstall", "Reciprocal removal of install for every enabled CLI"]]),
3004
+ (argv) => {
3005
+ process.exitCode = runInstallUninstallCommand("uninstall", {
3006
+ home: argv.home,
3007
+ resourcesRoot: resolveSkillsResourcesRoot(resolve5(__dirname, ".."))
3008
+ });
2913
3009
  }
2914
- if (lines.length === 0) {
2915
- console.error("Error: No addresses found in input.");
2916
- process.exit(1);
3010
+ ).command(
3011
+ "show",
3012
+ "Show CLI configuration and installation status tables (human-readable)",
3013
+ (yargs2) => yargs2.option("home", {
3014
+ type: "string",
3015
+ description: "Home-directory override for CLI configuration paths (default: user home)"
3016
+ }).example([["$0 show", "Print CLI Configuration and Installation Status tables"]]),
3017
+ (argv) => {
3018
+ process.exitCode = runShowCommand({
3019
+ home: argv.home,
3020
+ resourcesRoot: resolveSkillsResourcesRoot(resolve5(__dirname, ".."))
3021
+ });
2917
3022
  }
2918
- const searcher = new PlacesSearcher(argv.apikey);
2919
- const concurrency = Math.min(Math.max(argv.concurrency, 1), 50);
2920
- const results = [];
2921
- let completed = 0;
2922
- const semaphore = async (tasks2, limit) => {
2923
- const executing = [];
2924
- for (const task of tasks2) {
2925
- const p = task().then(() => {
2926
- executing.splice(executing.indexOf(p), 1);
2927
- });
2928
- executing.push(p);
2929
- if (executing.length >= limit) {
2930
- await Promise.race(executing);
2931
- }
3023
+ ).command(
3024
+ "exec <tool> [params]",
3025
+ "Execute a tool directly and output JSON",
3026
+ (yargs2) => {
3027
+ return yargs2.positional("tool", {
3028
+ type: "string",
3029
+ describe: `Tool name: ${EXEC_TOOLS.join(", ")}`
3030
+ }).positional("params", {
3031
+ type: "string",
3032
+ describe: "JSON parameters string"
3033
+ }).option("apikey", {
3034
+ alias: "k",
3035
+ type: "string",
3036
+ description: "Google Maps API key",
3037
+ default: process.env.GOOGLE_MAPS_API_KEY
3038
+ }).example([
3039
+ [`$0 exec geocode '{"address":"Tokyo Tower"}'`, "Geocode an address"],
3040
+ [
3041
+ `$0 exec search-nearby '{"center":{"value":"35.68,139.74","isCoordinates":true},"keyword":"restaurant"}'`,
3042
+ "Search nearby"
3043
+ ],
3044
+ [`$0 exec search-places '{"query":"ramen in Tokyo"}'`, "Text search"]
3045
+ ]);
3046
+ },
3047
+ async (argv) => {
3048
+ if (!argv.apikey) {
3049
+ process.stderr.write(
3050
+ JSON.stringify(
3051
+ {
3052
+ error: "GOOGLE_MAPS_API_KEY not set. Use --apikey or set GOOGLE_MAPS_API_KEY environment variable."
3053
+ },
3054
+ null,
3055
+ 2
3056
+ ) + "\n"
3057
+ );
3058
+ process.exitCode = 1;
3059
+ return;
2932
3060
  }
2933
- await Promise.all(executing);
2934
- };
2935
- const tasks = lines.map((address, index) => async () => {
2936
3061
  try {
2937
- const result = await searcher.geocode(address);
2938
- results[index] = { address, ...result };
3062
+ const params = argv.params ? JSON.parse(argv.params) : {};
3063
+ process.exitCode = await runExecCommand(argv.tool, params, argv.apikey);
2939
3064
  } catch (error) {
2940
- results[index] = { address, success: false, error: error.message };
3065
+ process.stderr.write(JSON.stringify({ error: error.message }, null, 2) + "\n");
3066
+ process.exitCode = 1;
2941
3067
  }
2942
- completed++;
2943
- if (!argv.output) return;
2944
- process.stderr.write(`\r ${completed}/${lines.length} geocoded`);
2945
- });
2946
- await semaphore(tasks, concurrency);
2947
- if (argv.output) {
2948
- process.stderr.write("\n");
2949
- }
2950
- const succeeded = results.filter((r) => r.success).length;
2951
- const failed = results.filter((r) => !r.success).length;
2952
- const summary = { total: lines.length, succeeded, failed, results };
2953
- const json = JSON.stringify(summary, null, 2);
2954
- if (argv.output) {
2955
- writeFileSync3(argv.output, json, "utf-8");
2956
- console.error(`Done: ${succeeded}/${lines.length} succeeded. Output: ${argv.output}`);
2957
- } else {
2958
- console.log(json);
2959
- }
2960
- process.exit(failed > 0 ? 1 : 0);
2961
- }
2962
- ).command(
2963
- "$0",
2964
- "Start the MCP server (HTTP by default, --stdio for stdio mode)",
2965
- (yargs2) => {
2966
- return yargs2.option("port", {
2967
- alias: "p",
2968
- type: "number",
2969
- description: "Port to run the MCP server on",
2970
- default: process.env.MCP_SERVER_PORT ? parseInt(process.env.MCP_SERVER_PORT) : 3e3
2971
- }).option("host", {
2972
- type: "string",
2973
- description: "Hostname to bind the server to (default 127.0.0.1 loopback; 0.0.0.0 for all interfaces)",
2974
- default: process.env.MCP_SERVER_HOST || "127.0.0.1"
2975
- }).option("apikey", {
2976
- alias: "k",
2977
- type: "string",
2978
- description: "Google Maps API key",
2979
- default: process.env.GOOGLE_MAPS_API_KEY
2980
- }).option("stdio", {
2981
- type: "boolean",
2982
- description: "Use stdio transport instead of HTTP",
2983
- default: false
2984
- }).example([
2985
- ["$0", "Start HTTP server with default settings"],
2986
- ['$0 --port 3000 --apikey "your_api_key"', "Start HTTP with custom port and API key"],
2987
- ["$0 --host 0.0.0.0 --port 3000", "Start HTTP accessible from all interfaces"],
2988
- ["$0 --stdio", "Start in stdio mode (for Claude Desktop, Cursor, etc.)"]
2989
- ]);
2990
- },
2991
- async (argv) => {
2992
- if (argv.apikey) {
2993
- process.env.GOOGLE_MAPS_API_KEY = argv.apikey;
2994
3068
  }
2995
- void checkForUpdates({ currentVersion: packageVersion }).catch(() => void 0);
2996
- const tools = filterTools(config_default[0].tools);
2997
- if (argv.stdio) {
2998
- const server = new BaseMcpServer(config_default[0].name, tools);
2999
- await server.startStdio();
3000
- } else {
3001
- Logger.log("\u{1F5FA}\uFE0F Google Maps MCP Server");
3002
- Logger.log(" A Model Context Protocol server for Google Maps services");
3003
- Logger.log("");
3069
+ ).command(
3070
+ "batch-geocode",
3071
+ "Geocode multiple addresses from a file (one address per line)",
3072
+ (yargs2) => {
3073
+ return yargs2.option("input", {
3074
+ alias: "i",
3075
+ type: "string",
3076
+ describe: "Input file path (one address per line). Use - for stdin.",
3077
+ demandOption: true
3078
+ }).option("output", {
3079
+ alias: "o",
3080
+ type: "string",
3081
+ describe: "Output file path (JSON). Defaults to stdout."
3082
+ }).option("concurrency", {
3083
+ alias: "c",
3084
+ type: "number",
3085
+ describe: "Max parallel requests",
3086
+ default: 20
3087
+ }).option("apikey", {
3088
+ alias: "k",
3089
+ type: "string",
3090
+ description: "Google Maps API key",
3091
+ default: process.env.GOOGLE_MAPS_API_KEY
3092
+ }).example([
3093
+ ["$0 batch-geocode -i addresses.txt", "Geocode to stdout"],
3094
+ ["$0 batch-geocode -i addresses.txt -o results.json", "Geocode to file"],
3095
+ ["cat addresses.txt | $0 batch-geocode -i -", "Geocode from stdin"]
3096
+ ]);
3097
+ },
3098
+ async (argv) => {
3004
3099
  if (!argv.apikey) {
3005
- Logger.log("\u26A0\uFE0F Google Maps API Key not found!");
3006
- Logger.log(" Please provide --apikey parameter or set GOOGLE_MAPS_API_KEY in your .env file");
3007
- Logger.log("");
3100
+ console.error("Error: GOOGLE_MAPS_API_KEY not set. Use --apikey or set env var.");
3101
+ process.exit(1);
3008
3102
  }
3009
- startServer(argv.port, argv.apikey, argv.host).then((outcome) => {
3010
- if (outcome.started === 0) {
3103
+ let lines;
3104
+ if (argv.input === "-") {
3105
+ const rl = createInterface({ input: process.stdin });
3106
+ lines = [];
3107
+ for await (const line of rl) {
3108
+ const trimmed = line.trim();
3109
+ if (trimmed) lines.push(trimmed);
3110
+ }
3111
+ } else {
3112
+ if (!existsSync4(argv.input)) {
3113
+ console.error(`Error: File not found: ${argv.input}`);
3011
3114
  process.exit(1);
3012
3115
  }
3013
- }).catch((error) => {
3014
- Logger.error("\u274C Failed to start server:", error);
3116
+ lines = readFileSync5(argv.input, "utf-8").split("\n").map((l) => l.trim()).filter((l) => l.length > 0);
3117
+ }
3118
+ if (lines.length === 0) {
3119
+ console.error("Error: No addresses found in input.");
3015
3120
  process.exit(1);
3121
+ }
3122
+ const searcher = new PlacesSearcher(argv.apikey);
3123
+ const concurrency = Math.min(Math.max(argv.concurrency, 1), 50);
3124
+ const results = [];
3125
+ let completed = 0;
3126
+ const semaphore = async (tasks2, limit) => {
3127
+ const executing = [];
3128
+ for (const task of tasks2) {
3129
+ const p = task().then(() => {
3130
+ executing.splice(executing.indexOf(p), 1);
3131
+ });
3132
+ executing.push(p);
3133
+ if (executing.length >= limit) {
3134
+ await Promise.race(executing);
3135
+ }
3136
+ }
3137
+ await Promise.all(executing);
3138
+ };
3139
+ const tasks = lines.map((address, index) => async () => {
3140
+ try {
3141
+ const result = await searcher.geocode(address);
3142
+ results[index] = { address, ...result };
3143
+ } catch (error) {
3144
+ results[index] = { address, success: false, error: error.message };
3145
+ }
3146
+ completed++;
3147
+ if (!argv.output) return;
3148
+ process.stderr.write(`\r ${completed}/${lines.length} geocoded`);
3016
3149
  });
3150
+ await semaphore(tasks, concurrency);
3151
+ if (argv.output) {
3152
+ process.stderr.write("\n");
3153
+ }
3154
+ const succeeded = results.filter((r) => r.success).length;
3155
+ const failed = results.filter((r) => !r.success).length;
3156
+ const summary = { total: lines.length, succeeded, failed, results };
3157
+ const json = JSON.stringify(summary, null, 2);
3158
+ if (argv.output) {
3159
+ writeFileSync4(argv.output, json, "utf-8");
3160
+ console.error(`Done: ${succeeded}/${lines.length} succeeded. Output: ${argv.output}`);
3161
+ } else {
3162
+ console.log(json);
3163
+ }
3164
+ process.exit(failed > 0 ? 1 : 0);
3017
3165
  }
3018
- }
3019
- ).version(packageVersion).alias("version", "v").option("env-file", {
3020
- type: "string",
3021
- global: true,
3022
- description: "Load environment variables from this exact file (error if missing; no implicit .env fallback)"
3023
- }).help().parse();
3166
+ ).command(
3167
+ "$0",
3168
+ "Start the MCP server (HTTP by default, --stdio for stdio mode)",
3169
+ (yargs2) => {
3170
+ return yargs2.option("port", {
3171
+ alias: "p",
3172
+ type: "number",
3173
+ description: "Port to run the MCP server on",
3174
+ default: process.env.MCP_SERVER_PORT ? parseInt(process.env.MCP_SERVER_PORT) : 3e3
3175
+ }).option("host", {
3176
+ type: "string",
3177
+ description: "Hostname to bind the server to (default 127.0.0.1 loopback; 0.0.0.0 for all interfaces)",
3178
+ default: process.env.MCP_SERVER_HOST || "127.0.0.1"
3179
+ }).option("apikey", {
3180
+ alias: "k",
3181
+ type: "string",
3182
+ description: "Google Maps API key",
3183
+ default: process.env.GOOGLE_MAPS_API_KEY
3184
+ }).option("stdio", {
3185
+ type: "boolean",
3186
+ description: "Use stdio transport instead of HTTP",
3187
+ default: false
3188
+ }).example([
3189
+ ["$0", "Start HTTP server with default settings"],
3190
+ ['$0 --port 3000 --apikey "your_api_key"', "Start HTTP with custom port and API key"],
3191
+ ["$0 --host 0.0.0.0 --port 3000", "Start HTTP accessible from all interfaces"],
3192
+ ["$0 --stdio", "Start in stdio mode (for Claude Desktop, Cursor, etc.)"]
3193
+ ]);
3194
+ },
3195
+ async (argv) => {
3196
+ if (argv.apikey) {
3197
+ process.env.GOOGLE_MAPS_API_KEY = argv.apikey;
3198
+ }
3199
+ void checkVersionIdle({ currentVersion: packageVersion }).catch(() => void 0);
3200
+ const tools = filterTools(config_default[0].tools);
3201
+ if (argv.stdio) {
3202
+ const server = new BaseMcpServer(config_default[0].name, tools);
3203
+ await server.startStdio();
3204
+ } else {
3205
+ Logger.log("\u{1F5FA}\uFE0F Google Maps MCP Server");
3206
+ Logger.log(" A Model Context Protocol server for Google Maps services");
3207
+ Logger.log("");
3208
+ if (!argv.apikey) {
3209
+ Logger.log("\u26A0\uFE0F Google Maps API Key not found!");
3210
+ Logger.log(" Please provide --apikey parameter or set GOOGLE_MAPS_API_KEY in your .env file");
3211
+ Logger.log("");
3212
+ }
3213
+ startServer(argv.port, argv.apikey, argv.host).then((outcome) => {
3214
+ if (outcome.started === 0) {
3215
+ process.exit(1);
3216
+ }
3217
+ }).catch((error) => {
3218
+ Logger.error("\u274C Failed to start server:", error);
3219
+ process.exit(1);
3220
+ });
3221
+ }
3222
+ }
3223
+ ).version(packageVersion).alias("version", "v").option("env-file", {
3224
+ type: "string",
3225
+ global: true,
3226
+ description: "Load environment variables from this exact file (error if missing; no implicit .env fallback)"
3227
+ }).help().parse();
3228
+ }
3024
3229
  }
3025
3230
  export {
3026
3231
  DOCTOR_PROBES,