mcp-google-api 0.21.0 → 0.22.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
@@ -2,22 +2,117 @@
2
2
  import {
3
3
  Logger,
4
4
  PlacesSearcher
5
- } from "./chunk-VCFXCLJF.js";
5
+ } from "./chunk-GRSJKPXN.js";
6
6
 
7
7
  // src/cli.ts
8
- import { config as dotenvConfig2 } from "dotenv";
9
- import { resolve as resolve5 } from "path";
10
8
  import yargs from "yargs";
11
9
  import { hideBin } from "yargs/helpers";
12
10
 
11
+ // src/utils/cliSettings.ts
12
+ import { mkdirSync, readFileSync, renameSync, writeFileSync } from "fs";
13
+ import { join, resolve } from "path";
14
+ var DEFAULT_SETTINGS_HOST = "127.0.0.1";
15
+ var DEFAULT_SETTINGS_PORT = 3e3;
16
+ var DEFAULT_SETTINGS_ENABLED_TOOLS = "*";
17
+ var SETTINGS_PROGRAM_NAME = "mcp-google-api";
18
+ var CLI_SETTINGS_RELATIVE = [".config", SETTINGS_PROGRAM_NAME, "config.json"];
19
+ var MCP_SERVER_NAME = "mcp-google-api";
20
+ var INSTALL_API_KEY_PLACEHOLDER = "__RUN_mcp-google-api_api-key_TO_CONFIGURE_YOUR_API_KEY__";
21
+ function resolveCliSettingsPath(home) {
22
+ const root = home ?? (process.env.HOME ?? process.cwd());
23
+ return resolve(root, ...CLI_SETTINGS_RELATIVE);
24
+ }
25
+ function normalizeEnabledTools(value) {
26
+ if (typeof value !== "string") {
27
+ return DEFAULT_SETTINGS_ENABLED_TOOLS;
28
+ }
29
+ const trimmed = value.trim();
30
+ return trimmed.length > 0 ? trimmed : DEFAULT_SETTINGS_ENABLED_TOOLS;
31
+ }
32
+ function normalizeHost(value) {
33
+ if (typeof value !== "string") {
34
+ return DEFAULT_SETTINGS_HOST;
35
+ }
36
+ const trimmed = value.trim();
37
+ return trimmed.length > 0 ? trimmed : DEFAULT_SETTINGS_HOST;
38
+ }
39
+ function normalizePort(value) {
40
+ if (typeof value !== "number" || !Number.isInteger(value) || value < 1 || value > 65535) {
41
+ return DEFAULT_SETTINGS_PORT;
42
+ }
43
+ return value;
44
+ }
45
+ function defaultSettings() {
46
+ return {
47
+ enabled: [],
48
+ apiKey: "",
49
+ autoUpdate: true,
50
+ enabledTools: DEFAULT_SETTINGS_ENABLED_TOOLS,
51
+ host: DEFAULT_SETTINGS_HOST,
52
+ port: DEFAULT_SETTINGS_PORT
53
+ };
54
+ }
55
+ function isUnsetApiKey(value) {
56
+ return value === void 0 || value === null || value.trim().length === 0 || value === INSTALL_API_KEY_PLACEHOLDER;
57
+ }
58
+ function uniqueStrings(value) {
59
+ if (!Array.isArray(value)) return [];
60
+ const result = [];
61
+ for (const item of value) {
62
+ if (typeof item === "string" && item.length > 0 && !result.includes(item)) {
63
+ result.push(item);
64
+ }
65
+ }
66
+ return result;
67
+ }
68
+ function loadCliSettings(home) {
69
+ try {
70
+ const raw = JSON.parse(readFileSync(resolveCliSettingsPath(home), "utf-8"));
71
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
72
+ return defaultSettings();
73
+ }
74
+ const record = raw;
75
+ return {
76
+ enabled: uniqueStrings(record.enabled),
77
+ apiKey: typeof record.apiKey === "string" ? record.apiKey : "",
78
+ autoUpdate: typeof record.autoUpdate === "boolean" ? record.autoUpdate : true,
79
+ enabledTools: normalizeEnabledTools(record.enabledTools),
80
+ host: normalizeHost(record.host),
81
+ port: normalizePort(record.port)
82
+ };
83
+ } catch {
84
+ return defaultSettings();
85
+ }
86
+ }
87
+ function loadConfiguredApiKey(home) {
88
+ const apiKey = loadCliSettings(home).apiKey;
89
+ return isUnsetApiKey(apiKey) ? void 0 : apiKey;
90
+ }
91
+ function saveCliSettings(settings, home) {
92
+ const path = resolveCliSettingsPath(home);
93
+ const temporary = `${path}.tmp`;
94
+ const payload = {
95
+ enabled: uniqueStrings(settings.enabled),
96
+ apiKey: typeof settings.apiKey === "string" ? settings.apiKey : "",
97
+ autoUpdate: settings.autoUpdate === true,
98
+ enabledTools: normalizeEnabledTools(settings.enabledTools),
99
+ host: normalizeHost(settings.host),
100
+ port: normalizePort(settings.port)
101
+ };
102
+ try {
103
+ mkdirSync(join(path, ".."), { recursive: true });
104
+ writeFileSync(temporary, JSON.stringify(payload, null, 2) + "\n", "utf-8");
105
+ renameSync(temporary, path);
106
+ } catch (error) {
107
+ throw new Error(`settings write failed: ${error instanceof Error ? error.message : String(error)}`);
108
+ }
109
+ return path;
110
+ }
111
+
13
112
  // src/utils/configResolver.ts
14
- import { config as dotenvConfig } from "dotenv";
15
- import { existsSync } from "fs";
16
113
  var NODE_ENGINE_FLOOR = 24;
17
- var DEFAULT_HTTP_HOST = "127.0.0.1";
18
- var DEFAULT_HTTP_PORT = 3e3;
19
- function resolveRuntimeConfig(env = process.env, overrides = {}) {
20
- const envPort = env.MCP_SERVER_PORT?.trim() || void 0;
114
+ function resolveRuntimeConfig(settings, overrides = {}) {
115
+ const settingsPort = Number.isInteger(settings.port) && settings.port >= 1 && settings.port <= 65535 ? settings.port : void 0;
21
116
  let port;
22
117
  let portRaw;
23
118
  let portSource;
@@ -25,30 +120,30 @@ function resolveRuntimeConfig(env = process.env, overrides = {}) {
25
120
  port = overrides.port;
26
121
  portRaw = String(overrides.port);
27
122
  portSource = "flag";
28
- } else if (envPort !== void 0) {
29
- const parsed = Number(envPort);
30
- port = Number.isFinite(parsed) ? parsed : void 0;
31
- portRaw = envPort;
32
- portSource = "environment";
123
+ } else if (settingsPort !== void 0) {
124
+ port = settingsPort;
125
+ portRaw = String(settingsPort);
126
+ portSource = "settings";
33
127
  } else {
34
- port = DEFAULT_HTTP_PORT;
35
- portRaw = void 0;
36
- portSource = "default";
37
- }
38
- const apiKey = overrides.apiKey ?? env.GOOGLE_MAPS_API_KEY;
39
- const enabledToolsRaw = env.GOOGLE_MAPS_ENABLED_TOOLS?.trim() || void 0;
128
+ port = void 0;
129
+ portRaw = String(settings.port);
130
+ portSource = "settings";
131
+ }
132
+ const flagApiKey = overrides.apiKey !== void 0 ? overrides.apiKey.trim() : void 0;
133
+ const settingsApiKey = isUnsetApiKey(settings.apiKey) ? void 0 : settings.apiKey;
134
+ const apiKey = flagApiKey !== void 0 && flagApiKey.length > 0 ? flagApiKey : settingsApiKey;
135
+ const apiKeySource = flagApiKey !== void 0 && flagApiKey.length > 0 ? "flag" : settingsApiKey !== void 0 ? "settings" : "none";
40
136
  return {
41
137
  apiKey,
42
- apiKeySource: overrides.apiKey !== void 0 ? "flag" : apiKey ? "environment" : "none",
43
- host: overrides.host ?? env.MCP_SERVER_HOST ?? DEFAULT_HTTP_HOST,
44
- hostSource: overrides.host !== void 0 ? "flag" : env.MCP_SERVER_HOST ? "environment" : "default",
138
+ apiKeySource,
139
+ host: overrides.host ?? settings.host,
140
+ hostSource: overrides.host !== void 0 ? "flag" : "settings",
45
141
  port,
46
142
  portRaw,
47
143
  portSource,
48
- enabledToolsRaw,
49
- enabledToolsSource: enabledToolsRaw ? "environment" : "default",
50
- autoUpdateDisabled: overrides.autoUpdateDisabled === true,
51
- envFile: overrides.envFile
144
+ enabledToolsRaw: settings.enabledTools,
145
+ enabledToolsSource: "settings",
146
+ autoUpdateDisabled: settings.autoUpdate !== true
52
147
  };
53
148
  }
54
149
  function maskSecret(value) {
@@ -69,9 +164,8 @@ function describeRuntimeConfig(config) {
69
164
  raw: config.portRaw ?? null,
70
165
  source: config.portSource
71
166
  },
72
- enabledTools: { value: config.enabledToolsRaw ?? "*", source: config.enabledToolsSource },
73
- autoUpdateCheck: { enabled: !config.autoUpdateDisabled },
74
- envFile: { value: config.envFile ?? null }
167
+ enabledTools: { value: config.enabledToolsRaw, source: config.enabledToolsSource },
168
+ autoUpdateCheck: { enabled: !config.autoUpdateDisabled }
75
169
  };
76
170
  }
77
171
  function formatConfigDiagnostics(diagnostics) {
@@ -83,13 +177,6 @@ function formatConfigDiagnostics(diagnostics) {
83
177
  `updateCheck=${diagnostics.autoUpdateCheck.enabled ? "enabled" : "disabled"}`
84
178
  ].join("; ");
85
179
  }
86
- function applyExplicitEnvFile(path) {
87
- if (!existsSync(path)) {
88
- return { ok: false, error: `env file not found: ${path}` };
89
- }
90
- dotenvConfig({ path });
91
- return { ok: true };
92
- }
93
180
  function resolveEnabledToolNames(allToolNames, raw) {
94
181
  const trimmed = raw?.trim();
95
182
  if (!trimmed || trimmed === "*") {
@@ -1067,7 +1154,6 @@ var MAPS_TOOL_ANNOTATIONS = {
1067
1154
  var serverConfigs = [
1068
1155
  {
1069
1156
  name: "MCP-Server",
1070
- portEnvVar: "MCP_SERVER_PORT",
1071
1157
  tools: [
1072
1158
  {
1073
1159
  name: SearchNearby.NAME,
@@ -1198,17 +1284,17 @@ var serverConfigs = [
1198
1284
  ]
1199
1285
  }
1200
1286
  ];
1201
- function filterTools(tools) {
1287
+ function filterTools(tools, raw = loadCliSettings().enabledTools) {
1202
1288
  const resolution = resolveEnabledToolNames(
1203
1289
  tools.map((tool) => tool.name),
1204
- process.env.GOOGLE_MAPS_ENABLED_TOOLS
1290
+ raw
1205
1291
  );
1206
1292
  if (resolution.fallback) {
1207
- Logger.error(`GOOGLE_MAPS_ENABLED_TOOLS matched 0 tools. Available: ${tools.map((t) => t.name).join(", ")}`);
1293
+ Logger.error(`enabledTools matched 0 tools. Available: ${tools.map((t) => t.name).join(", ")}`);
1208
1294
  return tools;
1209
1295
  }
1210
1296
  if (resolution.matched !== tools.length) {
1211
- Logger.log(`GOOGLE_MAPS_ENABLED_TOOLS: ${resolution.matched}/${tools.length} tools active`);
1297
+ Logger.log(`enabledTools: ${resolution.matched}/${tools.length} tools active`);
1212
1298
  }
1213
1299
  const enabled = new Set(resolution.names);
1214
1300
  return tools.filter((tool) => enabled.has(tool.name));
@@ -1400,8 +1486,8 @@ var BaseMcpServer = class {
1400
1486
 
1401
1487
  // src/cli.ts
1402
1488
  import { fileURLToPath } from "url";
1403
- import { dirname as dirname3 } from "path";
1404
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, existsSync as existsSync4 } from "fs";
1489
+ import { dirname as dirname3, resolve as resolve5 } from "path";
1490
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, existsSync as existsSync3, realpathSync } from "fs";
1405
1491
  import { createInterface } from "readline";
1406
1492
 
1407
1493
  // src/utils/upgradeManager.ts
@@ -1516,68 +1602,6 @@ async function probeLatestGitHubVersion(deps = {}) {
1516
1602
  }
1517
1603
  }
1518
1604
 
1519
- // src/utils/cliSettings.ts
1520
- import { mkdirSync, readFileSync, renameSync, writeFileSync } from "fs";
1521
- import { join, resolve } from "path";
1522
- var SETTINGS_PROGRAM_NAME = "mcp-google-api";
1523
- var CLI_SETTINGS_RELATIVE = [".config", SETTINGS_PROGRAM_NAME, "config.json"];
1524
- var MCP_SERVER_NAME = "mcp-google-api";
1525
- var INSTALL_API_KEY_PLACEHOLDER = "__RUN_mcp-google-api_api-key_TO_CONFIGURE_YOUR_API_KEY__";
1526
- function resolveCliSettingsPath(home) {
1527
- const root = home ?? (process.env.HOME ?? process.cwd());
1528
- return resolve(root, ...CLI_SETTINGS_RELATIVE);
1529
- }
1530
- function uniqueStrings(value) {
1531
- if (!Array.isArray(value)) return [];
1532
- const result = [];
1533
- for (const item of value) {
1534
- if (typeof item === "string" && item.length > 0 && !result.includes(item)) {
1535
- result.push(item);
1536
- }
1537
- }
1538
- return result;
1539
- }
1540
- function isUnsetApiKey(value) {
1541
- return value === void 0 || value === null || value.trim().length === 0 || value === INSTALL_API_KEY_PLACEHOLDER;
1542
- }
1543
- function loadCliSettings(home) {
1544
- try {
1545
- const raw = JSON.parse(readFileSync(resolveCliSettingsPath(home), "utf-8"));
1546
- if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
1547
- return { enabled: [], apiKey: "", autoUpdate: true };
1548
- }
1549
- const record = raw;
1550
- return {
1551
- enabled: uniqueStrings(record.enabled),
1552
- apiKey: typeof record.apiKey === "string" ? record.apiKey : "",
1553
- autoUpdate: typeof record.autoUpdate === "boolean" ? record.autoUpdate : true
1554
- };
1555
- } catch {
1556
- return { enabled: [], apiKey: "", autoUpdate: true };
1557
- }
1558
- }
1559
- function loadConfiguredApiKey(home) {
1560
- const apiKey = loadCliSettings(home).apiKey;
1561
- return isUnsetApiKey(apiKey) ? void 0 : apiKey;
1562
- }
1563
- function saveCliSettings(settings, home) {
1564
- const path = resolveCliSettingsPath(home);
1565
- const temporary = `${path}.tmp`;
1566
- const payload = {
1567
- enabled: uniqueStrings(settings.enabled),
1568
- apiKey: typeof settings.apiKey === "string" ? settings.apiKey : "",
1569
- autoUpdate: settings.autoUpdate === true
1570
- };
1571
- try {
1572
- mkdirSync(join(path, ".."), { recursive: true });
1573
- writeFileSync(temporary, JSON.stringify(payload, null, 2) + "\n", "utf-8");
1574
- renameSync(temporary, path);
1575
- } catch (error) {
1576
- throw new Error(`settings write failed: ${error instanceof Error ? error.message : String(error)}`);
1577
- }
1578
- return path;
1579
- }
1580
-
1581
1605
  // src/utils/upgradeManager.ts
1582
1606
  var ANSI_GREEN = "\x1B[92m";
1583
1607
  var ANSI_RED = "\x1B[91m";
@@ -1732,46 +1756,28 @@ function runPackageManagerCommand(command, deps = {}) {
1732
1756
  }
1733
1757
  }
1734
1758
  function parsePostUpgradeCliOutcomes(raw) {
1735
- if (raw === void 0) {
1736
- return void 0;
1737
- }
1738
- const start = raw.indexOf("{");
1739
- if (start < 0) {
1740
- return void 0;
1741
- }
1742
- let parsed;
1743
- try {
1744
- parsed = JSON.parse(raw.slice(start));
1745
- } catch {
1759
+ if (raw === void 0 || !raw.includes("install report:")) {
1746
1760
  return void 0;
1747
1761
  }
1748
- if (typeof parsed !== "object" || parsed === null) {
1749
- return void 0;
1762
+ const lines = raw.split(/\r?\n/);
1763
+ const cliLine = /^\s{2,}([a-z][a-z0-9-]*):\s+/;
1764
+ const outcomes = [];
1765
+ for (const line of lines) {
1766
+ const match = cliLine.exec(line);
1767
+ if (match) {
1768
+ outcomes.push({ cli: match[1], ok: true });
1769
+ }
1750
1770
  }
1751
- const summaries = parsed.summaries;
1752
- const errors = parsed.errors;
1753
- if (!Array.isArray(summaries)) {
1771
+ if (outcomes.length === 0) {
1754
1772
  return void 0;
1755
1773
  }
1756
- const errorTexts = Array.isArray(errors) ? errors.filter((item) => typeof item === "string") : [];
1757
- const outcomes = [];
1758
- for (const entry of summaries) {
1759
- if (typeof entry !== "object" || entry === null) {
1760
- continue;
1774
+ const errorBlockIndex = lines.findIndex((line) => line.trim() === "Errors:");
1775
+ const errorTexts = errorBlockIndex >= 0 ? lines.slice(errorBlockIndex + 1).filter((line) => line.trim().length > 0) : [];
1776
+ for (const outcome of outcomes) {
1777
+ const lowered = outcome.cli.toLowerCase();
1778
+ if (errorTexts.some((text) => text.toLowerCase().includes(lowered))) {
1779
+ outcome.ok = false;
1761
1780
  }
1762
- const record = entry;
1763
- const cli = record.cli;
1764
- if (typeof cli !== "string" || cli.length === 0) {
1765
- continue;
1766
- }
1767
- const lowered = cli.toLowerCase();
1768
- const failed = errorTexts.some((text) => text.toLowerCase().includes(lowered));
1769
- outcomes.push({
1770
- cli,
1771
- ok: !failed,
1772
- server: typeof record.server === "number" ? record.server : void 0,
1773
- skills: typeof record.skills === "number" ? record.skills : void 0
1774
- });
1775
1781
  }
1776
1782
  return outcomes;
1777
1783
  }
@@ -1976,7 +1982,6 @@ function describeToolsProfile(toolNames) {
1976
1982
  }
1977
1983
 
1978
1984
  // src/utils/clientSnippets.ts
1979
- var API_KEY_PLACEHOLDER = "<your-google-maps-api-key>";
1980
1985
  var SNIPPET_DEFAULT_HOST = "127.0.0.1";
1981
1986
  var SNIPPET_DEFAULT_PORT = 3e3;
1982
1987
  var SNIPPET_CLIENT_TARGETS = {
@@ -2007,15 +2012,8 @@ function renderClientSnippet(options = {}) {
2007
2012
  if (launcher === "npx") {
2008
2013
  notes.push("The npx launcher runs the published package; npm must be available on PATH.");
2009
2014
  }
2010
- const apiKeyValue = options.envKey ? `\${${options.envKey}}` : API_KEY_PLACEHOLDER;
2011
- entry = { command, args, env: { GOOGLE_MAPS_API_KEY: apiKeyValue } };
2012
- if (options.envKey) {
2013
- notes.push(
2014
- `Variable references (\${${options.envKey}}) are client-specific: confirm your client expands environment variables before relying on them.`
2015
- );
2016
- } else {
2017
- notes.push(`Replace ${API_KEY_PLACEHOLDER} with your Google Maps API key.`);
2018
- }
2015
+ entry = { command, args };
2016
+ notes.push("The registration carries no API key: configure it once with 'mcp-google-api api-key <key>'.");
2019
2017
  }
2020
2018
  const json = JSON.stringify({ mcpServers: { [serverName]: entry } }, null, 2);
2021
2019
  return { json, notes };
@@ -2025,7 +2023,7 @@ function renderClientSnippet(options = {}) {
2025
2023
  import {
2026
2024
  appendFileSync,
2027
2025
  cpSync,
2028
- existsSync as existsSync2,
2026
+ existsSync,
2029
2027
  mkdirSync as mkdirSync3,
2030
2028
  readFileSync as readFileSync3,
2031
2029
  readdirSync,
@@ -2082,7 +2080,7 @@ function supportedCliNames() {
2082
2080
  return Object.keys(CLI_TARGETS).join(", ");
2083
2081
  }
2084
2082
  function readJsonConfig(configPath) {
2085
- if (!existsSync2(configPath)) return {};
2083
+ if (!existsSync(configPath)) return {};
2086
2084
  const parsed = JSON.parse(readFileSync3(configPath, "utf-8"));
2087
2085
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
2088
2086
  throw new Error(`configuration is not a JSON object: ${configPath}`);
@@ -2106,7 +2104,7 @@ function writeJsonMcpServerEntry(configPath, serverName, entry) {
2106
2104
  writeJsonConfig(configPath, config);
2107
2105
  }
2108
2106
  function removeJsonMcpServerEntry(configPath, serverName) {
2109
- if (!existsSync2(configPath)) return false;
2107
+ if (!existsSync(configPath)) return false;
2110
2108
  const config = readJsonConfig(configPath);
2111
2109
  const mcpServers = config.mcpServers;
2112
2110
  if (mcpServers === void 0) return false;
@@ -2179,7 +2177,7 @@ function registrationToTomlLines(entry) {
2179
2177
  return lines;
2180
2178
  }
2181
2179
  function writeTomlMcpServerSection(configPath, serverName, entry) {
2182
- const previous = existsSync2(configPath) ? readFileSync3(configPath, "utf-8") : "";
2180
+ const previous = existsSync(configPath) ? readFileSync3(configPath, "utf-8") : "";
2183
2181
  const base = removeTomlSection(previous, serverName);
2184
2182
  const table = [tomlSectionHeader(serverName), ...registrationToTomlLines(entry), ""].join("\n");
2185
2183
  const content = base.length > 0 ? base.replace(/\n*$/, "\n") + table : table;
@@ -2189,7 +2187,7 @@ function writeTomlMcpServerSection(configPath, serverName, entry) {
2189
2187
  renameSync2(temporary, configPath);
2190
2188
  }
2191
2189
  function removeTomlMcpServerSection(configPath, serverName) {
2192
- if (!existsSync2(configPath)) return false;
2190
+ if (!existsSync(configPath)) return false;
2193
2191
  const previous = readFileSync3(configPath, "utf-8");
2194
2192
  if (!hasTomlSection(previous, serverName)) return false;
2195
2193
  const content = removeTomlSection(previous, serverName);
@@ -2199,11 +2197,11 @@ function removeTomlMcpServerSection(configPath, serverName) {
2199
2197
  return true;
2200
2198
  }
2201
2199
  function hasTomlMcpServerSection(configPath, serverName) {
2202
- if (!existsSync2(configPath)) return false;
2200
+ if (!existsSync(configPath)) return false;
2203
2201
  return hasTomlSection(readFileSync3(configPath, "utf-8"), serverName);
2204
2202
  }
2205
2203
  function listFilesRecursive(root) {
2206
- if (!existsSync2(root)) return [];
2204
+ if (!existsSync(root)) return [];
2207
2205
  const files = [];
2208
2206
  const walk = (dir) => {
2209
2207
  for (const entry of readdirSync(dir)) {
@@ -2246,10 +2244,10 @@ function removeSkillDir(skillDir) {
2246
2244
  function compareSkillTree(source, destination, layout = {}) {
2247
2245
  const packaged = listFilesRecursive(source).filter((rel) => rel !== layout.debugPath);
2248
2246
  if (packaged.length === 0) return "MISSING";
2249
- if (!existsSync2(destination)) return "MISSING";
2247
+ if (!existsSync(destination)) return "MISSING";
2250
2248
  for (const rel of packaged) {
2251
2249
  const target = join3(destination, ...rel.split("/"));
2252
- if (!existsSync2(target)) return "MISSING";
2250
+ if (!existsSync(target)) return "MISSING";
2253
2251
  const packagedText = readFileSync3(join3(source, ...rel.split("/"))).toString("utf-8");
2254
2252
  const installedText = readFileSync3(target).toString("utf-8");
2255
2253
  if (installedText === packagedText) continue;
@@ -2286,21 +2284,21 @@ function applyServerRegistration(target, serverName, entry, home) {
2286
2284
  }
2287
2285
 
2288
2286
  // src/utils/cliInstaller.ts
2289
- import { existsSync as existsSync3, readFileSync as readFileSync4 } from "fs";
2287
+ import { existsSync as existsSync2, readFileSync as readFileSync4 } from "fs";
2290
2288
  import { dirname as dirname2, join as join4, resolve as resolve3 } from "path";
2291
2289
  function buildServerRegistration() {
2292
2290
  return { command: "npx", args: ["-y", MCP_SERVER_NAME, "start", "--stdio"] };
2293
2291
  }
2294
2292
  function resolveSkillsResourcesRoot(packageRoot) {
2295
2293
  const candidate = resolve3(packageRoot, "src", "resources", "skills");
2296
- if (!existsSync3(candidate)) {
2294
+ if (!existsSync2(candidate)) {
2297
2295
  throw new Error(`skills resources root not found: ${candidate}`);
2298
2296
  }
2299
2297
  return candidate;
2300
2298
  }
2301
2299
  function loadSkillsManifest(resourcesRoot) {
2302
2300
  const manifestPath = join4(resourcesRoot, "manifest.json");
2303
- if (!existsSync3(manifestPath)) {
2301
+ if (!existsSync2(manifestPath)) {
2304
2302
  throw new Error(`skills manifest not found: ${manifestPath}`);
2305
2303
  }
2306
2304
  let parsed;
@@ -2319,14 +2317,14 @@ function loadSkillsManifest(resourcesRoot) {
2319
2317
  throw new Error(`skills manifest entry is missing id or path: ${manifestPath}`);
2320
2318
  }
2321
2319
  const skillFile = join4(resourcesRoot, skill.path);
2322
- if (!existsSync3(skillFile)) {
2320
+ if (!existsSync2(skillFile)) {
2323
2321
  throw new Error(`manifest skill file not found: ${skillFile}`);
2324
2322
  }
2325
2323
  if (skill.debug !== void 0 && (typeof skill.debug !== "string" || skill.debug.trim() === "")) {
2326
2324
  throw new Error(`manifest skill debug path is invalid: ${manifestPath}`);
2327
2325
  }
2328
2326
  const debugPath = typeof skill.debug === "string" ? skill.debug : void 0;
2329
- if (debugPath !== void 0 && !existsSync3(join4(dirname2(resolve3(skillFile)), debugPath))) {
2327
+ if (debugPath !== void 0 && !existsSync2(join4(dirname2(resolve3(skillFile)), debugPath))) {
2330
2328
  throw new Error(`manifest skill debug file not found: ${join4(dirname2(resolve3(skillFile)), debugPath)}`);
2331
2329
  }
2332
2330
  return {
@@ -2506,40 +2504,9 @@ function buildCliShowReport(options) {
2506
2504
  // src/cli.ts
2507
2505
  var __filename = fileURLToPath(import.meta.url);
2508
2506
  var __dirname = dirname3(__filename);
2509
- function extractEnvFileOption(argv) {
2510
- for (let i = 0; i < argv.length; i++) {
2511
- const arg = argv[i];
2512
- if (arg === "--env-file" && i + 1 < argv.length) {
2513
- return argv[i + 1];
2514
- }
2515
- if (arg.startsWith("--env-file=")) {
2516
- return arg.slice("--env-file=".length);
2517
- }
2518
- }
2519
- return void 0;
2520
- }
2521
- function loadEnvironment(envFile) {
2522
- if (envFile !== void 0) {
2523
- const result = applyExplicitEnvFile(envFile);
2524
- if (!result.ok) {
2525
- process.stderr.write(JSON.stringify({ error: result.error }, null, 2) + "\n");
2526
- process.exit(1);
2527
- }
2528
- return;
2529
- }
2530
- dotenvConfig2({ path: resolve5(process.cwd(), ".env") });
2531
- dotenvConfig2({ path: resolve5(__dirname, "../.env") });
2532
- }
2533
- async function startServer(port, apiKey, host) {
2534
- if (port) {
2535
- process.env.MCP_SERVER_PORT = port.toString();
2536
- }
2507
+ async function startServer(port, apiKey, host = "127.0.0.1") {
2537
2508
  ApiKeyManager.getInstance().setDefaultApiKey(apiKey);
2538
- if (host) {
2539
- process.env.MCP_SERVER_HOST = host;
2540
- }
2541
- Logger.log("\u{1F680} Starting Google Maps MCP Server...");
2542
- Logger.log("\u{1F4CD} 18 tools registered (set GOOGLE_MAPS_ENABLED_TOOLS to limit)");
2509
+ Logger.log("\u{1F680} Starting MCP Google API server...");
2543
2510
  Logger.log(
2544
2511
  "\u2139\uFE0F Reminder: enable Places API (New) in https://console.cloud.google.com before using the new Place features."
2545
2512
  );
@@ -2549,26 +2516,20 @@ async function startServer(port, apiKey, host) {
2549
2516
  let failed = 0;
2550
2517
  await Promise.all(
2551
2518
  config_default.map(async (config) => {
2552
- const portString = process.env[config.portEnvVar];
2553
- if (!portString) {
2554
- Logger.error(`\u26A0\uFE0F [${config.name}] Port environment variable ${config.portEnvVar} not set.`);
2555
- Logger.log(`\u{1F4A1} Please set ${config.portEnvVar} in your .env file or use --port parameter.`);
2556
- Logger.log(` Example: ${config.portEnvVar}=3000 or --port 3000`);
2557
- failed++;
2558
- return;
2559
- }
2560
- const serverPort = Number(portString);
2519
+ const serverPort = port;
2561
2520
  if (!Number.isInteger(serverPort) || serverPort < 1 || serverPort > 65535) {
2562
2521
  Logger.error(
2563
- `\u274C [${config.name}] Invalid port number "${portString}" defined in ${config.portEnvVar} (expected integer 1-65535).`
2522
+ `\u274C [${config.name}] Invalid port number "${serverPort}" (expected integer 1-65535).`
2564
2523
  );
2524
+ Logger.log("\u{1F4A1} Fix the persisted port with 'mcp-google-api port <number>' or pass --port.");
2565
2525
  failed++;
2566
2526
  return;
2567
2527
  }
2568
2528
  try {
2569
2529
  const activeTools = filterTools(config.tools);
2530
+ Logger.log(`\u{1F4CD} ${activeTools.length} tools registered (configure with 'mcp-google-api tools')`);
2570
2531
  const server = new BaseMcpServer(config.name, activeTools);
2571
- const serverHost = process.env.MCP_SERVER_HOST || "127.0.0.1";
2532
+ const serverHost = host;
2572
2533
  Logger.log(`\u{1F527} [${config.name}] Initializing MCP Server in HTTP mode on ${serverHost}:${serverPort}...`);
2573
2534
  await server.startHttpServer(serverPort, serverHost);
2574
2535
  servers.push(server);
@@ -2814,7 +2775,7 @@ function parseDoctorProbes(raw) {
2814
2775
  async function runDoctor(packageVersion, apiKey, live = false, runner = execTool, options = {}) {
2815
2776
  const nodeVersion = options.nodeVersion ?? process.versions.node;
2816
2777
  const nodeMajor = Number.parseInt(nodeVersion.split(".")[0] ?? "0", 10);
2817
- const config = options.config ?? resolveRuntimeConfig(process.env);
2778
+ const config = options.config ?? resolveRuntimeConfig(loadCliSettings());
2818
2779
  const allToolNames = options.allToolNames ?? config_default[0].tools.map((tool) => tool.name);
2819
2780
  const toolsResolution = resolveEnabledToolNames(allToolNames, config.enabledToolsRaw);
2820
2781
  const diagnostics = describeRuntimeConfig(config);
@@ -2833,17 +2794,12 @@ async function runDoctor(packageVersion, apiKey, live = false, runner = execTool
2833
2794
  {
2834
2795
  name: "api-key",
2835
2796
  status: apiKey ? "pass" : "fail",
2836
- detail: apiKey ? "GOOGLE_MAPS_API_KEY is configured (value hidden)." : "GOOGLE_MAPS_API_KEY is not configured. Set it in the environment before making API calls."
2797
+ detail: apiKey ? "Google Maps API key is configured via 'mcp-google-api api-key' (value hidden)." : "Google Maps API key is not configured. Run 'mcp-google-api api-key <your-api-key>' to configure it."
2837
2798
  },
2838
2799
  {
2839
2800
  name: "config",
2840
2801
  status: toolsResolution.fallback ? "fail" : "pass",
2841
- detail: toolsResolution.fallback ? `GOOGLE_MAPS_ENABLED_TOOLS matched 0 tools; the server falls back to all ${allToolNames.length} tools. Effective configuration: ${formatConfigDiagnostics(diagnostics)}` : `Effective configuration: ${formatConfigDiagnostics(diagnostics)}`
2842
- },
2843
- {
2844
- name: "env-file",
2845
- status: "pass",
2846
- detail: config.envFile ? `Explicit environment file loaded: ${config.envFile}` : "No explicit --env-file requested; implicit .env discovery (current directory, then package directory) applies."
2802
+ detail: toolsResolution.fallback ? `enabledTools matched 0 tools; the server falls back to all ${allToolNames.length} tools. Effective configuration: ${formatConfigDiagnostics(diagnostics)}` : `Effective configuration: ${formatConfigDiagnostics(diagnostics)}`
2847
2803
  },
2848
2804
  {
2849
2805
  name: "tools",
@@ -2861,7 +2817,7 @@ async function runDoctor(packageVersion, apiKey, live = false, runner = execTool
2861
2817
  checks.push({
2862
2818
  name: "live-api",
2863
2819
  status: "skip",
2864
- detail: "Live API checks require GOOGLE_MAPS_API_KEY."
2820
+ detail: "Live API checks require a configured Google Maps API key."
2865
2821
  });
2866
2822
  } else {
2867
2823
  const selected = options.probes ? DOCTOR_PROBES.filter((probe) => options.probes.includes(probe.id)) : DOCTOR_PROBES;
@@ -2897,78 +2853,6 @@ async function runDoctor(packageVersion, apiKey, live = false, runner = execTool
2897
2853
  checks
2898
2854
  };
2899
2855
  }
2900
- async function runSetup(options, deps = {}) {
2901
- const fsImpl = deps.fs ?? {
2902
- existsSync: (path) => existsSync4(path),
2903
- readFileSync: (path, encoding) => readFileSync5(path, encoding),
2904
- writeFileSync: (path, data, encoding) => writeFileSync4(path, data, encoding)
2905
- };
2906
- const nodeVersion = deps.nodeVersion ?? process.versions.node;
2907
- const nodeMajor = Number.parseInt(nodeVersion.split(".")[0] ?? "0", 10);
2908
- const config = deps.config ?? resolveRuntimeConfig(process.env);
2909
- const examplePath = resolve5(options.packageDir, ".env.example");
2910
- const envPath = resolve5(options.targetDir, ".env");
2911
- const checks = [
2912
- {
2913
- name: "node",
2914
- status: nodeMajor >= NODE_ENGINE_FLOOR ? "pass" : "fail",
2915
- detail: `Node.js ${nodeVersion} detected; version ${NODE_ENGINE_FLOOR} or newer is required (package.json engines).`
2916
- },
2917
- {
2918
- name: "env-template",
2919
- status: fsImpl.existsSync(examplePath) ? "pass" : "fail",
2920
- detail: fsImpl.existsSync(examplePath) ? `Template found: ${examplePath}` : `Template missing: ${examplePath} (expected next to the installed package).`
2921
- }
2922
- ];
2923
- let created = false;
2924
- if (options.writeEnv) {
2925
- if (fsImpl.existsSync(envPath)) {
2926
- checks.push({
2927
- name: "env-file",
2928
- status: "pass",
2929
- detail: `${envPath} already exists; left untouched (no overwrite).`
2930
- });
2931
- } else if (!fsImpl.existsSync(examplePath)) {
2932
- checks.push({
2933
- name: "env-file",
2934
- status: "fail",
2935
- detail: `Cannot create ${envPath}: template ${examplePath} is missing.`
2936
- });
2937
- } else {
2938
- try {
2939
- fsImpl.writeFileSync(envPath, fsImpl.readFileSync(examplePath, "utf-8"), "utf-8");
2940
- created = true;
2941
- checks.push({
2942
- name: "env-file",
2943
- status: "pass",
2944
- detail: `Created ${envPath} from template; edit it and set GOOGLE_MAPS_API_KEY.`
2945
- });
2946
- } catch (error) {
2947
- checks.push({
2948
- name: "env-file",
2949
- status: "fail",
2950
- detail: `Failed to create ${envPath}: ${error instanceof Error ? error.message : String(error)}`
2951
- });
2952
- }
2953
- }
2954
- } else {
2955
- checks.push({
2956
- name: "env-file",
2957
- status: fsImpl.existsSync(envPath) ? "pass" : "skip",
2958
- detail: fsImpl.existsSync(envPath) ? `${envPath} found.` : `${envPath} not found; rerun with --write-env to create it from the template.`
2959
- });
2960
- }
2961
- checks.push({
2962
- name: "api-key",
2963
- status: config.apiKey ? "pass" : "fail",
2964
- detail: config.apiKey ? `GOOGLE_MAPS_API_KEY is configured (source: ${config.apiKeySource}, value hidden).` : "GOOGLE_MAPS_API_KEY is not configured. Set it in the environment or in .env after scaffolding."
2965
- });
2966
- return {
2967
- success: checks.every((check) => check.status !== "fail"),
2968
- created,
2969
- checks
2970
- };
2971
- }
2972
2856
  function runSnippetCommand(options, streams = { stdout: process.stdout, stderr: process.stderr }) {
2973
2857
  try {
2974
2858
  const snippet = renderClientSnippet(options);
@@ -3083,21 +2967,95 @@ function runAutoUpdateCommand(rawState, options = {}) {
3083
2967
  streams.stdout.write(enabled ? "Auto-update check enabled.\n" : "Auto-update check disabled.\n");
3084
2968
  return 0;
3085
2969
  }
2970
+ function runToolsCommand(raw, options = {}) {
2971
+ const streams = options.streams ?? { stdout: process.stdout, stderr: process.stderr };
2972
+ const allToolNames = config_default[0].tools.map((tool) => tool.name);
2973
+ const trimmed = (raw ?? "").trim();
2974
+ if (trimmed.length === 0) {
2975
+ streams.stderr.write(
2976
+ `tools: missing or empty tool list. Use '*' for all tools or a comma-separated subset of: ${allToolNames.join(", ")}.
2977
+ `
2978
+ );
2979
+ return 1;
2980
+ }
2981
+ let value;
2982
+ if (trimmed === "*") {
2983
+ value = "*";
2984
+ } else {
2985
+ const requested = trimmed.split(",").map((item) => item.trim()).filter(Boolean);
2986
+ const unknown = requested.filter((item) => !allToolNames.includes(item));
2987
+ if (requested.length === 0 || unknown.length > 0) {
2988
+ streams.stderr.write(
2989
+ `tools: unknown tool name(s): ${unknown.join(", ") || "(none)"}. Accepted: ${allToolNames.join(", ")} (or '*').
2990
+ `
2991
+ );
2992
+ return 1;
2993
+ }
2994
+ value = requested.join(",");
2995
+ }
2996
+ try {
2997
+ const settings = loadCliSettings(options.home);
2998
+ settings.enabledTools = value;
2999
+ saveCliSettings(settings, options.home);
3000
+ } catch (error) {
3001
+ const message = error instanceof Error ? error.message : String(error);
3002
+ streams.stderr.write(`tools: failed to persist the setting: ${message}
3003
+ `);
3004
+ return 1;
3005
+ }
3006
+ const count = value === "*" ? allToolNames.length : value.split(",").length;
3007
+ streams.stdout.write(`Enabled tools set to ${value === "*" ? `* (all ${count})` : value}.
3008
+ `);
3009
+ return 0;
3010
+ }
3011
+ function runHostCommand(raw, options = {}) {
3012
+ const streams = options.streams ?? { stdout: process.stdout, stderr: process.stderr };
3013
+ const trimmed = (raw ?? "").trim();
3014
+ if (trimmed.length === 0) {
3015
+ streams.stderr.write("host: missing or empty hostname. Example: mcp-google-api host 127.0.0.1\n");
3016
+ return 1;
3017
+ }
3018
+ try {
3019
+ const settings = loadCliSettings(options.home);
3020
+ settings.host = trimmed;
3021
+ saveCliSettings(settings, options.home);
3022
+ } catch (error) {
3023
+ const message = error instanceof Error ? error.message : String(error);
3024
+ streams.stderr.write(`host: failed to persist the setting: ${message}
3025
+ `);
3026
+ return 1;
3027
+ }
3028
+ streams.stdout.write(`HTTP bind host set to ${trimmed}.
3029
+ `);
3030
+ return 0;
3031
+ }
3032
+ function runPortCommand(raw, options = {}) {
3033
+ const streams = options.streams ?? { stdout: process.stdout, stderr: process.stderr };
3034
+ const trimmed = (raw ?? "").trim();
3035
+ const parsed = Number(trimmed);
3036
+ if (trimmed.length === 0 || !Number.isInteger(parsed) || parsed < 1 || parsed > 65535) {
3037
+ streams.stderr.write(`port: invalid port "${trimmed || "(none)"}" (expected integer 1-65535).
3038
+ `);
3039
+ return 1;
3040
+ }
3041
+ try {
3042
+ const settings = loadCliSettings(options.home);
3043
+ settings.port = parsed;
3044
+ saveCliSettings(settings, options.home);
3045
+ } catch (error) {
3046
+ const message = error instanceof Error ? error.message : String(error);
3047
+ streams.stderr.write(`port: failed to persist the setting: ${message}
3048
+ `);
3049
+ return 1;
3050
+ }
3051
+ streams.stdout.write(`HTTP port set to ${parsed}.
3052
+ `);
3053
+ return 0;
3054
+ }
3086
3055
  function runInstallUninstallCommand(operation, options) {
3087
3056
  const streams = options.streams ?? { stdout: process.stdout, stderr: process.stderr };
3088
3057
  if (loadCliSettings(options.home).enabled.length === 0) {
3089
- streams.stdout.write(
3090
- JSON.stringify(
3091
- {
3092
- success: true,
3093
- message: "No CLI enabled. Use 'mcp-google-api enable <cli name>' first.",
3094
- summaries: [],
3095
- errors: []
3096
- },
3097
- null,
3098
- 2
3099
- ) + "\n"
3100
- );
3058
+ streams.stdout.write("No CLI agent enabled. Run 'mcp-google-api enable <cli name>' first.\n");
3101
3059
  return 0;
3102
3060
  }
3103
3061
  let result;
@@ -3109,13 +3067,26 @@ function runInstallUninstallCommand(operation, options) {
3109
3067
  }) : uninstallEnabledCliResources({ home: options.home, resourcesRoot: options.resourcesRoot });
3110
3068
  } catch (error) {
3111
3069
  streams.stderr.write(
3112
- JSON.stringify({ success: false, errors: [error instanceof Error ? error.message : String(error)] }, null, 2) + "\n"
3070
+ `${operation} failed: ${error instanceof Error ? error.message : String(error)}
3071
+ `
3113
3072
  );
3114
3073
  return 1;
3115
3074
  }
3116
- streams.stdout.write(
3117
- JSON.stringify({ success: result.errors.length === 0, operation, summaries: result.summaries, errors: result.errors }, null, 2) + "\n"
3118
- );
3075
+ streams.stdout.write(`mcp-google-api ${operation} report:
3076
+ `);
3077
+ for (const summary of result.summaries) {
3078
+ streams.stdout.write(
3079
+ ` ${summary.cli}: MCP server ${operation === "install" ? "registered" : "removed"}, ${summary.skills} skill(s) ${operation === "install" ? "installed" : "removed"}
3080
+ `
3081
+ );
3082
+ }
3083
+ if (result.errors.length > 0) {
3084
+ streams.stdout.write("Errors:\n");
3085
+ for (const error of result.errors) {
3086
+ streams.stdout.write(` ${error}
3087
+ `);
3088
+ }
3089
+ }
3119
3090
  return result.errors.length > 0 ? 1 : 0;
3120
3091
  }
3121
3092
  function runShowCommand(options) {
@@ -3130,10 +3101,20 @@ function runShowCommand(options) {
3130
3101
  return 1;
3131
3102
  }
3132
3103
  }
3104
+ function isEntryMainModule() {
3105
+ const entryPath = process.argv[1];
3106
+ if (entryPath === void 0 || entryPath === "") {
3107
+ return false;
3108
+ }
3109
+ try {
3110
+ return realpathSync(entryPath) === realpathSync(fileURLToPath(import.meta.url));
3111
+ } catch {
3112
+ return false;
3113
+ }
3114
+ }
3133
3115
  var isRunDirectly = process.argv[1] && (process.argv[1].endsWith("cli.ts") || process.argv[1].endsWith("cli.js") || process.argv[1].endsWith("mcp-google-api") || process.argv[1].includes("mcp-google-api"));
3134
- var isMainModule = import.meta.url === `file://${process.argv[1]}`;
3116
+ var isMainModule = isEntryMainModule();
3135
3117
  if (isRunDirectly || isMainModule) {
3136
- loadEnvironment(extractEnvFileOption(process.argv));
3137
3118
  let packageVersion = "0.0.0";
3138
3119
  try {
3139
3120
  const packageJsonPath = resolve5(__dirname, "../package.json");
@@ -3152,25 +3133,28 @@ if (isRunDirectly || isMainModule) {
3152
3133
  process.exitCode = 1;
3153
3134
  });
3154
3135
  } else {
3155
- const buildServerCommandOptions = (yargs2) => yargs2.option("port", {
3156
- alias: "p",
3157
- type: "number",
3158
- description: "Port to run the MCP server on",
3159
- default: process.env.MCP_SERVER_PORT ? parseInt(process.env.MCP_SERVER_PORT) : 3e3
3160
- }).option("host", {
3161
- type: "string",
3162
- description: "Hostname to bind the server to (default 127.0.0.1 loopback; 0.0.0.0 for all interfaces)",
3163
- default: process.env.MCP_SERVER_HOST || "127.0.0.1"
3164
- }).option("stdio", {
3165
- type: "boolean",
3166
- description: "Use stdio transport instead of HTTP",
3167
- default: false
3168
- }).example([
3169
- ["$0 start", "Start HTTP server with default settings"],
3170
- ["$0 start --host 0.0.0.0 --port 3000", "Start HTTP accessible from all interfaces"],
3171
- ["$0 start --stdio", "Start in stdio mode (for MCP clients)"],
3172
- ["$0 run --stdio", "Alias: run the server in stdio mode"]
3173
- ]);
3136
+ const buildServerCommandOptions = (yargs2) => {
3137
+ const settings = loadCliSettings();
3138
+ return yargs2.option("port", {
3139
+ alias: "p",
3140
+ type: "number",
3141
+ description: "Port to run the MCP server on (default: persisted 'port' setting)",
3142
+ default: settings.port
3143
+ }).option("host", {
3144
+ type: "string",
3145
+ description: "Hostname to bind the server to (default: persisted 'host' setting; 0.0.0.0 for all interfaces)",
3146
+ default: settings.host
3147
+ }).option("stdio", {
3148
+ type: "boolean",
3149
+ description: "Use stdio transport instead of HTTP",
3150
+ default: false
3151
+ }).example([
3152
+ ["$0 start", "Start HTTP server with default settings"],
3153
+ ["$0 start --host 0.0.0.0 --port 3000", "Start HTTP accessible from all interfaces"],
3154
+ ["$0 start --stdio", "Start in stdio mode (for MCP clients)"],
3155
+ ["$0 run --stdio", "Alias: run the server in stdio mode"]
3156
+ ]);
3157
+ };
3174
3158
  const runServerCommand = async (argv) => {
3175
3159
  const effectiveApiKey = loadConfiguredApiKey();
3176
3160
  ApiKeyManager.getInstance().setDefaultApiKey(effectiveApiKey);
@@ -3195,8 +3179,8 @@ if (isRunDirectly || isMainModule) {
3195
3179
  const server = new BaseMcpServer(config_default[0].name, tools);
3196
3180
  await server.startStdio();
3197
3181
  } else {
3198
- Logger.log("\u{1F5FA}\uFE0F Google Maps MCP Server");
3199
- Logger.log(" A Model Context Protocol server for Google Maps services");
3182
+ Logger.log("\u{1F5FA}\uFE0F MCP Google API server");
3183
+ Logger.log(" Google APIs for AI agents over the Model Context Protocol");
3200
3184
  Logger.log("");
3201
3185
  if (effectiveApiKey === void 0) {
3202
3186
  Logger.log("\u26A0\uFE0F Google Maps API Key not found!");
@@ -3231,8 +3215,7 @@ Usage: mcp-google-api <command> [options]
3231
3215
  }).option("apikey", {
3232
3216
  alias: "k",
3233
3217
  type: "string",
3234
- description: "Google Maps API key (prefer GOOGLE_MAPS_API_KEY to avoid shell history exposure)",
3235
- default: process.env.GOOGLE_MAPS_API_KEY
3218
+ description: "Google Maps API key override for live probes (default: persisted api-key setting)"
3236
3219
  }).example([
3237
3220
  ["$0 doctor", "Check local runtime and API key configuration without network calls"],
3238
3221
  ["$0 doctor --live", "Also verify three Google Maps APIs with billable requests"],
@@ -3245,33 +3228,10 @@ Usage: mcp-google-api <command> [options]
3245
3228
  process.exitCode = 1;
3246
3229
  return;
3247
3230
  }
3248
- const report = await runDoctor(packageVersion, argv.apikey, argv.live, void 0, {
3231
+ const effectiveKey = (argv.apikey ?? "").trim() || loadConfiguredApiKey();
3232
+ const report = await runDoctor(packageVersion, effectiveKey, argv.live, void 0, {
3249
3233
  probes: parsedProbes.probes,
3250
- config: resolveRuntimeConfig(process.env, { envFile: extractEnvFileOption(process.argv) })
3251
- });
3252
- process.stdout.write(JSON.stringify(report, null, 2) + "\n");
3253
- process.exitCode = report.success ? 0 : 1;
3254
- }
3255
- ).command(
3256
- "setup",
3257
- "Non-interactive onboarding: verify local readiness, optionally scaffold .env",
3258
- (yargs2) => yargs2.option("write-env", {
3259
- type: "boolean",
3260
- default: false,
3261
- description: "Create .env from .env.example in --env-dir when it does not exist (never overwrites)"
3262
- }).option("env-dir", {
3263
- type: "string",
3264
- default: process.cwd(),
3265
- description: "Directory where .env is looked up / created"
3266
- }).example([
3267
- ["$0 setup", "Check readiness without writing anything"],
3268
- ["$0 setup --write-env", "Also scaffold .env from the package template"]
3269
- ]),
3270
- async (argv) => {
3271
- const report = await runSetup({
3272
- packageDir: resolve5(__dirname, ".."),
3273
- targetDir: argv.envDir,
3274
- writeEnv: argv.writeEnv
3234
+ config: resolveRuntimeConfig(loadCliSettings())
3275
3235
  });
3276
3236
  process.stdout.write(JSON.stringify(report, null, 2) + "\n");
3277
3237
  process.exitCode = report.success ? 0 : 1;
@@ -3305,9 +3265,6 @@ Usage: mcp-google-api <command> [options]
3305
3265
  type: "number",
3306
3266
  default: 3e3,
3307
3267
  description: "Port used in the URL (transport http)"
3308
- }).option("env-key", {
3309
- type: "string",
3310
- description: "Emit a ${NAME} variable reference instead of a literal placeholder (expansion is client-specific)"
3311
3268
  }).option("name", {
3312
3269
  type: "string",
3313
3270
  default: "mcp-google-api",
@@ -3325,7 +3282,6 @@ Usage: mcp-google-api <command> [options]
3325
3282
  commandPath: argv.command,
3326
3283
  host: argv.host,
3327
3284
  port: argv.port,
3328
- envKey: argv.envKey,
3329
3285
  serverName: argv.name
3330
3286
  });
3331
3287
  }
@@ -3377,6 +3333,54 @@ Usage: mcp-google-api <command> [options]
3377
3333
  home: argv.home
3378
3334
  });
3379
3335
  }
3336
+ ).command(
3337
+ "tools <tools>",
3338
+ "Persist the enabled-tool allowlist in the configuration file ('*' = all 18 tools)",
3339
+ (yargs2) => yargs2.positional("tools", {
3340
+ type: "string",
3341
+ describe: "Comma-separated tool names (e.g. maps_geocode,maps_search_places) or '*' for all"
3342
+ }).option("home", {
3343
+ type: "string",
3344
+ description: "Home-directory override for the settings file (default: user home)"
3345
+ }).example([
3346
+ ["$0 tools '*'", "Expose every registered tool (default)"],
3347
+ ["$0 tools maps_geocode,maps_search_places", "Expose only the named tools"]
3348
+ ]),
3349
+ (argv) => {
3350
+ process.exitCode = runToolsCommand(argv.tools, {
3351
+ home: argv.home
3352
+ });
3353
+ }
3354
+ ).command(
3355
+ "host <host>",
3356
+ "Persist the HTTP bind host in the configuration file (default 127.0.0.1)",
3357
+ (yargs2) => yargs2.positional("host", {
3358
+ type: "string",
3359
+ describe: "Bind hostname (e.g. 127.0.0.1 loopback; 0.0.0.0 for all interfaces)"
3360
+ }).option("home", {
3361
+ type: "string",
3362
+ description: "Home-directory override for the settings file (default: user home)"
3363
+ }).example([["$0 host 0.0.0.0", "Bind the HTTP server on all interfaces"]]),
3364
+ (argv) => {
3365
+ process.exitCode = runHostCommand(argv.host, {
3366
+ home: argv.home
3367
+ });
3368
+ }
3369
+ ).command(
3370
+ "port <port>",
3371
+ "Persist the HTTP listen port in the configuration file (default 3000)",
3372
+ (yargs2) => yargs2.positional("port", {
3373
+ type: "number",
3374
+ describe: "Listen port (integer 1-65535)"
3375
+ }).option("home", {
3376
+ type: "string",
3377
+ description: "Home-directory override for the settings file (default: user home)"
3378
+ }).example([["$0 port 3100", "Serve Streamable HTTP on port 3100"]]),
3379
+ (argv) => {
3380
+ process.exitCode = runPortCommand(argv.port === void 0 ? void 0 : String(argv.port), {
3381
+ home: argv.home
3382
+ });
3383
+ }
3380
3384
  ).command(
3381
3385
  "api-key <key>",
3382
3386
  "Save the Google Maps API key in the user settings and refresh every enabled CLI registration",
@@ -3521,7 +3525,7 @@ Usage: mcp-google-api <command> [options]
3521
3525
  if (trimmed) lines.push(trimmed);
3522
3526
  }
3523
3527
  } else {
3524
- if (!existsSync4(argv.input)) {
3528
+ if (!existsSync3(argv.input)) {
3525
3529
  console.error(`Error: File not found: ${argv.input}`);
3526
3530
  process.exit(1);
3527
3531
  }
@@ -3592,11 +3596,7 @@ Usage: mcp-google-api <command> [options]
3592
3596
  () => {
3593
3597
  cli.showHelp("log");
3594
3598
  }
3595
- ).version(packageVersion).alias("version", "v").option("env-file", {
3596
- type: "string",
3597
- global: true,
3598
- description: "Load environment variables from this exact file (error if missing; no implicit .env fallback)"
3599
- }).epilog(
3599
+ ).version(packageVersion).alias("version", "v").epilog(
3600
3600
  `Management commands (single flags, dispatched before subcommands):
3601
3601
  --ver Print the installed version and force one update check
3602
3602
  --version Alias of --ver
@@ -3611,7 +3611,6 @@ export {
3611
3611
  EXEC_TOOLS,
3612
3612
  createShutdownHandler,
3613
3613
  execTool,
3614
- extractEnvFileOption,
3615
3614
  installShutdownHandlers,
3616
3615
  parseDoctorProbes,
3617
3616
  runApiKeyCommand,
@@ -3619,10 +3618,12 @@ export {
3619
3618
  runDoctor,
3620
3619
  runEnableDisableCliCommand,
3621
3620
  runExecCommand,
3621
+ runHostCommand,
3622
3622
  runInstallUninstallCommand,
3623
- runSetup,
3623
+ runPortCommand,
3624
3624
  runShowCommand,
3625
3625
  runSnippetCommand,
3626
+ runToolsCommand,
3626
3627
  startServer
3627
3628
  };
3628
3629
  //# sourceMappingURL=cli.js.map