mcp-google-map 0.8.0 → 0.10.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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # mcp-google-map (0.8.0)
1
+ # mcp-google-map (0.10.0)
2
2
 
3
3
  <p align="center">
4
4
  <img src="https://img.shields.io/badge/node-%3E%3D22-339933?style=flat-square&logo=nodedotjs&logoColor=white" alt="Node.js >= 22">
@@ -164,6 +164,7 @@ mcp-google-map doctor --live --probes geocoding,routes # probe only the selecte
164
164
  mcp-google-map exec geocode '{"address":"Tokyo Tower"}' # one tool call from the terminal
165
165
  mcp-google-map batch-geocode -i addresses.txt -o results.json
166
166
  mcp-google-map enable pi claude # enable MCP registration + skills for specific CLIs
167
+ mcp-google-map api-key "AIza..." # save the API key in the user settings and refresh every enabled CLI registration
167
168
  mcp-google-map install # register the stdio server and install skills in every enabled CLI
168
169
  mcp-google-map uninstall # reciprocal removal of install in every enabled CLI
169
170
  mcp-google-map show # CLI Configuration and Installation Status tables
@@ -178,9 +179,10 @@ mcp-google-map snippet --client cursor # print an MCP client re
178
179
  - `snippet` prints a valid `mcpServers` JSON registration to stdout (guidance notes on stderr) and never writes or edits configuration files; by default it embeds a literal placeholder, and `--env-key NAME` emits a `${NAME}` reference whose expansion is client-specific.
179
180
  - `--env-file <path>` loads exactly the given environment file for any command and exits 1 with a JSON error when the file is missing (no implicit `.env` fallback).
180
181
  - `enable <cli>` / `disable <cli>` manage the persisted enabled-CLI set at `~/.config/mcp-google-map/config.json`; accepted names (case-insensitive): `pi`, `openclaw`, `codex`, `antigravity`, `claude`; unsupported names exit 2 listing the supported ones.
181
- - `install` registers for every enabled CLI the stdio server entry `mcp-google-map` (`npx -y mcp-google-map start --stdio`, embedding the resolved `GOOGLE_MAPS_API_KEY` when set) and installs every bundled skill; `uninstall` is the reciprocal removal. Per-CLI targets: pi `~/.pi/agent/mcp.json` + `~/.pi/agent/skills`, openclaw `~/.openclaw/openclaw.json` + `~/.openclaw/workspace/skills`, codex `~/.codex/config.toml` (`mcp_servers` table) + `~/.codex/skills`, antigravity `~/.gemini/settings.json` + `~/.gemini/config/skills`, claude `~/.claude.json` + `~/.claude/skills`. Existing unrelated configuration entries are always preserved.
182
+ - `api-key <key>` validates the key (20-50 characters of letters, digits, hyphens, underscores), saves it as `apiKey` in the persisted settings at `~/.config/mcp-google-map/config.json` (masked in the JSON output), and immediately re-runs `install` for every enabled CLI; invalid keys fail with a JSON error and persist nothing.
183
+ - `install` registers for every enabled CLI the stdio server entry `mcp-google-map` (`npx -y mcp-google-map start --stdio`) and installs every bundled skill; the embedded `GOOGLE_MAPS_API_KEY` is resolved with priority `--apikey`, the persisted `api-key` settings, then the `GOOGLE_MAPS_API_KEY` environment — when none resolves, a literal placeholder that names the `api-key` command is embedded instead; `uninstall` is the reciprocal removal. Per-CLI targets: pi `~/.pi/agent/mcp.json` + `~/.pi/agent/skills`, openclaw `~/.openclaw/openclaw.json` + `~/.openclaw/workspace/skills`, codex `~/.codex/config.toml` (`mcp_servers` table) + `~/.codex/skills`, antigravity `~/.gemini/settings.json` + `~/.gemini/config/skills`, claude `~/.claude.json` + `~/.claude/skills`. Existing unrelated configuration entries are always preserved.
182
184
  - `show` prints two human-readable tables: CLI Configuration (CLI, Enabled, MCP Config Path, Skills Config Path for all five CLIs) and Installation Status (Type, Name, CLI, Enabled, Installed with OK/MISSING/STALE per enabled CLI).
183
- - HTTP mode starts even without an API key and logs a warning; stdio mode and the CLI commands require a key (`--apikey` or `GOOGLE_MAPS_API_KEY`). When no HTTP instance can start (invalid or taken port), the process exits non-zero.
185
+ - HTTP mode starts even without an API key and logs a warning (per-request header keys remain supported); stdio mode resolves the effective key with priority `--apikey`, `GOOGLE_MAPS_API_KEY`, then the persisted `api-key` settings, and exits 1 with a JSON error on stderr inviting `mcp-google-map api-key <key>` when no key resolves; the CLI commands require a key (`--apikey` or `GOOGLE_MAPS_API_KEY`). When no HTTP instance can start (invalid or taken port), the process exits non-zero.
184
186
 
185
187
  ## Registering in an MCP client
186
188
 
package/dist/cli.d.ts CHANGED
@@ -138,6 +138,11 @@ declare function runEnableDisableCliCommand(name: string, enable: boolean, optio
138
138
  home?: string;
139
139
  streams?: ExecStreams;
140
140
  }): number;
141
+ declare function runApiKeyCommand(key: string | undefined, options: {
142
+ home?: string;
143
+ resourcesRoot: string;
144
+ streams?: ExecStreams;
145
+ }): number;
141
146
  declare function runInstallUninstallCommand(operation: "install" | "uninstall", options: {
142
147
  home?: string;
143
148
  apiKey?: string;
@@ -150,4 +155,4 @@ declare function runShowCommand(options: {
150
155
  streams?: ExecStreams;
151
156
  }): number;
152
157
 
153
- export { DOCTOR_PROBES, type DoctorCheck, type DoctorLiveProbe, type DoctorOptions, type DoctorProbeId, type DoctorProbesParseResult, type DoctorReport, EXEC_TOOLS, type ServerStartupOutcome, type SetupCheck, type SetupDeps, type SetupFs, type SetupOptions, type SetupReport, type ShutdownExitHook, createShutdownHandler, execTool, extractEnvFileOption, installShutdownHandlers, parseDoctorProbes, runDoctor, runEnableDisableCliCommand, runExecCommand, runInstallUninstallCommand, runSetup, runShowCommand, runSnippetCommand, startServer };
158
+ export { DOCTOR_PROBES, type DoctorCheck, type DoctorLiveProbe, type DoctorOptions, type DoctorProbeId, type DoctorProbesParseResult, type DoctorReport, EXEC_TOOLS, type ServerStartupOutcome, type SetupCheck, type SetupDeps, type SetupFs, type SetupOptions, type SetupReport, type ShutdownExitHook, createShutdownHandler, execTool, extractEnvFileOption, installShutdownHandlers, parseDoctorProbes, runApiKeyCommand, runDoctor, runEnableDisableCliCommand, runExecCommand, runInstallUninstallCommand, runSetup, runShowCommand, runSnippetCommand, startServer };
package/dist/cli.js CHANGED
@@ -1459,6 +1459,7 @@ import { join, resolve } from "path";
1459
1459
  var SETTINGS_PROGRAM_NAME = "mcp-google-map";
1460
1460
  var CLI_SETTINGS_RELATIVE = [".config", SETTINGS_PROGRAM_NAME, "config.json"];
1461
1461
  var MCP_SERVER_NAME = "mcp-google-map";
1462
+ var INSTALL_API_KEY_PLACEHOLDER = "__RUN_mcp-google-map_api-key_TO_CONFIGURE_YOUR_API_KEY__";
1462
1463
  function resolveCliSettingsPath(home) {
1463
1464
  const root = home ?? (process.env.HOME ?? process.cwd());
1464
1465
  return resolve(root, ...CLI_SETTINGS_RELATIVE);
@@ -1473,23 +1474,39 @@ function uniqueStrings(value) {
1473
1474
  }
1474
1475
  return result;
1475
1476
  }
1477
+ function isUnsetApiKey(value) {
1478
+ return value === void 0 || value === null || value.trim().length === 0 || value === INSTALL_API_KEY_PLACEHOLDER;
1479
+ }
1476
1480
  function loadCliSettings(home) {
1477
1481
  try {
1478
1482
  const raw = JSON.parse(readFileSync(resolveCliSettingsPath(home), "utf-8"));
1479
1483
  if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
1480
1484
  return { enabled: [] };
1481
1485
  }
1482
- return { enabled: uniqueStrings(raw.enabled) };
1486
+ const record = raw;
1487
+ const settings = { enabled: uniqueStrings(record.enabled) };
1488
+ if (typeof record.apiKey === "string" && record.apiKey.length > 0) {
1489
+ settings.apiKey = record.apiKey;
1490
+ }
1491
+ return settings;
1483
1492
  } catch {
1484
1493
  return { enabled: [] };
1485
1494
  }
1486
1495
  }
1496
+ function loadConfiguredApiKey(home) {
1497
+ const apiKey = loadCliSettings(home).apiKey;
1498
+ return isUnsetApiKey(apiKey) ? void 0 : apiKey;
1499
+ }
1487
1500
  function saveCliSettings(settings, home) {
1488
1501
  const path = resolveCliSettingsPath(home);
1489
1502
  const temporary = `${path}.tmp`;
1503
+ const payload = { enabled: uniqueStrings(settings.enabled) };
1504
+ if (typeof settings.apiKey === "string" && settings.apiKey.length > 0) {
1505
+ payload.apiKey = settings.apiKey;
1506
+ }
1490
1507
  try {
1491
1508
  mkdirSync(join(path, ".."), { recursive: true });
1492
- writeFileSync(temporary, JSON.stringify({ enabled: uniqueStrings(settings.enabled) }, null, 2) + "\n", "utf-8");
1509
+ writeFileSync(temporary, JSON.stringify(payload, null, 2) + "\n", "utf-8");
1493
1510
  renameSync(temporary, path);
1494
1511
  } catch (error) {
1495
1512
  throw new Error(`settings write failed: ${error instanceof Error ? error.message : String(error)}`);
@@ -1520,8 +1537,6 @@ var PACKAGE_UNINSTALL_COMMAND = [
1520
1537
  DEFAULT_PACKAGE_NAME
1521
1538
  ];
1522
1539
  var POST_UPGRADE_INSTALL_COMMAND = [
1523
- "npx",
1524
- "-y",
1525
1540
  DEFAULT_PACKAGE_NAME,
1526
1541
  "install"
1527
1542
  ];
@@ -2171,12 +2186,21 @@ function applyServerRegistration(target, serverName, entry, home) {
2171
2186
  import { existsSync as existsSync3, readFileSync as readFileSync4 } from "fs";
2172
2187
  import { join as join4, resolve as resolve3 } from "path";
2173
2188
  function buildServerRegistration(apiKey) {
2174
- const env = {};
2175
- if (apiKey !== void 0 && apiKey.length > 0) {
2176
- env.GOOGLE_MAPS_API_KEY = apiKey;
2177
- }
2189
+ const env = {
2190
+ GOOGLE_MAPS_API_KEY: isUnsetApiKey(apiKey) ? INSTALL_API_KEY_PLACEHOLDER : apiKey
2191
+ };
2178
2192
  return { command: "npx", args: ["-y", MCP_SERVER_NAME, "start", "--stdio"], env };
2179
2193
  }
2194
+ function resolveInstallApiKey(options) {
2195
+ if (!isUnsetApiKey(options.flagKey)) {
2196
+ return options.flagKey;
2197
+ }
2198
+ const persisted = loadConfiguredApiKey(options.home);
2199
+ if (persisted !== void 0) {
2200
+ return persisted;
2201
+ }
2202
+ return isUnsetApiKey(options.envKey) ? void 0 : options.envKey;
2203
+ }
2180
2204
  function resolveSkillsResourcesRoot(packageRoot) {
2181
2205
  const candidate = resolve3(packageRoot, "src", "resources", "skills");
2182
2206
  if (!existsSync3(candidate)) {
@@ -2876,6 +2900,68 @@ function runEnableDisableCliCommand(name, enable, options = {}) {
2876
2900
  );
2877
2901
  return 0;
2878
2902
  }
2903
+ function runApiKeyCommand(key, options) {
2904
+ const streams = options.streams ?? { stdout: process.stdout, stderr: process.stderr };
2905
+ const trimmed = (key ?? "").trim();
2906
+ if (!ApiKeyManager.getInstance().isValidApiKeyFormat(trimmed)) {
2907
+ streams.stderr.write(
2908
+ JSON.stringify(
2909
+ {
2910
+ success: false,
2911
+ error: "Invalid Google Maps API key. Expected 20-50 characters of letters, digits, hyphens, or underscores. Usage: mcp-google-map api-key <your-api-key>"
2912
+ },
2913
+ null,
2914
+ 2
2915
+ ) + "\n"
2916
+ );
2917
+ return 1;
2918
+ }
2919
+ let settingsPath;
2920
+ try {
2921
+ const settings = loadCliSettings(options.home);
2922
+ settings.apiKey = trimmed;
2923
+ settingsPath = saveCliSettings(settings, options.home);
2924
+ } catch (error) {
2925
+ streams.stderr.write(
2926
+ JSON.stringify({ success: false, error: error instanceof Error ? error.message : String(error) }, null, 2) + "\n"
2927
+ );
2928
+ return 1;
2929
+ }
2930
+ let install;
2931
+ try {
2932
+ install = installEnabledCliResources({ home: options.home, apiKey: trimmed, resourcesRoot: options.resourcesRoot });
2933
+ } catch (error) {
2934
+ streams.stderr.write(
2935
+ JSON.stringify(
2936
+ {
2937
+ success: false,
2938
+ apiKey: maskSecret(trimmed),
2939
+ settingsPath,
2940
+ error: error instanceof Error ? error.message : String(error)
2941
+ },
2942
+ null,
2943
+ 2
2944
+ ) + "\n"
2945
+ );
2946
+ return 1;
2947
+ }
2948
+ const zeroEnabled = install.summaries.length === 0 && install.errors.length === 0;
2949
+ streams.stdout.write(
2950
+ JSON.stringify(
2951
+ {
2952
+ success: install.errors.length === 0,
2953
+ command: "api-key",
2954
+ apiKey: maskSecret(trimmed),
2955
+ settingsPath,
2956
+ ...zeroEnabled ? { message: "API key saved. No CLI enabled. Use 'mcp-google-map enable <cli name>' first." } : {},
2957
+ install: { operation: "install", summaries: install.summaries, errors: install.errors }
2958
+ },
2959
+ null,
2960
+ 2
2961
+ ) + "\n"
2962
+ );
2963
+ return install.errors.length > 0 ? 1 : 0;
2964
+ }
2879
2965
  function runInstallUninstallCommand(operation, options) {
2880
2966
  const streams = options.streams ?? { stdout: process.stdout, stderr: process.stderr };
2881
2967
  if (loadCliSettings(options.home).enabled.length === 0) {
@@ -2970,21 +3056,42 @@ if (isRunDirectly || isMainModule) {
2970
3056
  if (argv.apikey) {
2971
3057
  process.env.GOOGLE_MAPS_API_KEY = argv.apikey;
2972
3058
  }
3059
+ let effectiveApiKey = isUnsetApiKey(process.env.GOOGLE_MAPS_API_KEY) ? void 0 : process.env.GOOGLE_MAPS_API_KEY;
3060
+ if (effectiveApiKey === void 0) {
3061
+ const persistedApiKey = loadConfiguredApiKey();
3062
+ if (persistedApiKey !== void 0) {
3063
+ process.env.GOOGLE_MAPS_API_KEY = persistedApiKey;
3064
+ effectiveApiKey = persistedApiKey;
3065
+ }
3066
+ }
2973
3067
  void checkVersionIdle({ currentVersion: packageVersion }).catch(() => void 0);
2974
3068
  const tools = filterTools(config_default[0].tools);
2975
3069
  if (argv.stdio) {
3070
+ if (effectiveApiKey === void 0) {
3071
+ process.stderr.write(
3072
+ JSON.stringify(
3073
+ {
3074
+ error: "Google Maps API key is not configured. Run 'mcp-google-map api-key <your-api-key>' to configure it, or pass --apikey / set GOOGLE_MAPS_API_KEY."
3075
+ },
3076
+ null,
3077
+ 2
3078
+ ) + "\n"
3079
+ );
3080
+ process.exitCode = 1;
3081
+ return;
3082
+ }
2976
3083
  const server = new BaseMcpServer(config_default[0].name, tools);
2977
3084
  await server.startStdio();
2978
3085
  } else {
2979
3086
  Logger.log("\u{1F5FA}\uFE0F Google Maps MCP Server");
2980
3087
  Logger.log(" A Model Context Protocol server for Google Maps services");
2981
3088
  Logger.log("");
2982
- if (!argv.apikey) {
3089
+ if (effectiveApiKey === void 0) {
2983
3090
  Logger.log("\u26A0\uFE0F Google Maps API Key not found!");
2984
- Logger.log(" Please provide --apikey parameter or set GOOGLE_MAPS_API_KEY in your .env file");
3091
+ Logger.log(" Run 'mcp-google-map api-key <your-api-key>' to configure it, or set GOOGLE_MAPS_API_KEY / pass --apikey");
2985
3092
  Logger.log("");
2986
3093
  }
2987
- startServer(argv.port, argv.apikey, argv.host).then((outcome) => {
3094
+ startServer(argv.port, effectiveApiKey, argv.host).then((outcome) => {
2988
3095
  if (outcome.started === 0) {
2989
3096
  process.exit(1);
2990
3097
  }
@@ -3140,6 +3247,22 @@ Usage: mcp-google-map <command> [options]
3140
3247
  home: argv.home
3141
3248
  });
3142
3249
  }
3250
+ ).command(
3251
+ "api-key <key>",
3252
+ "Save the Google Maps API key in the user settings and refresh every enabled CLI registration",
3253
+ (yargs2) => yargs2.positional("key", {
3254
+ type: "string",
3255
+ describe: "Google Maps API key (20-50 characters: letters, digits, hyphens, underscores)"
3256
+ }).option("home", {
3257
+ type: "string",
3258
+ description: "Home-directory override for CLI configuration paths (default: user home)"
3259
+ }).example([["$0 api-key AIzaSy...", "Save the key and reinstall every enabled CLI"]]),
3260
+ (argv) => {
3261
+ process.exitCode = runApiKeyCommand(argv.key, {
3262
+ home: argv.home,
3263
+ resourcesRoot: resolveSkillsResourcesRoot(resolve5(__dirname, ".."))
3264
+ });
3265
+ }
3143
3266
  ).command(
3144
3267
  "install",
3145
3268
  "Register the mcp-google-map stdio server and install packaged skills for every enabled CLI",
@@ -3149,13 +3272,17 @@ Usage: mcp-google-map <command> [options]
3149
3272
  }).option("apikey", {
3150
3273
  alias: "k",
3151
3274
  type: "string",
3152
- description: "Google Maps API key embedded in the registered entry (prefer GOOGLE_MAPS_API_KEY)",
3153
- default: resolveRuntimeConfig(process.env, { envFile: extractEnvFileOption(process.argv) }).apiKey
3275
+ description: "Google Maps API key embedded in the registered entry (priority: this flag, persisted api-key settings, GOOGLE_MAPS_API_KEY)"
3154
3276
  }).example([["$0 install", "Register the server and skills in every enabled CLI"]]),
3155
3277
  (argv) => {
3278
+ const config = resolveRuntimeConfig(process.env, { envFile: extractEnvFileOption(process.argv) });
3156
3279
  process.exitCode = runInstallUninstallCommand("install", {
3157
3280
  home: argv.home,
3158
- apiKey: argv.apikey,
3281
+ apiKey: resolveInstallApiKey({
3282
+ flagKey: argv.apikey,
3283
+ envKey: config.apiKey,
3284
+ home: argv.home
3285
+ }),
3159
3286
  resourcesRoot: resolveSkillsResourcesRoot(resolve5(__dirname, ".."))
3160
3287
  });
3161
3288
  }
@@ -3367,6 +3494,7 @@ export {
3367
3494
  extractEnvFileOption,
3368
3495
  installShutdownHandlers,
3369
3496
  parseDoctorProbes,
3497
+ runApiKeyCommand,
3370
3498
  runDoctor,
3371
3499
  runEnableDisableCliCommand,
3372
3500
  runExecCommand,