mcp-google-map 0.3.0 → 0.4.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/.env.example CHANGED
@@ -11,3 +11,7 @@ MCP_SERVER_HOST=127.0.0.1
11
11
 
12
12
  # Optional: comma-separated allowlist of exposed tools (omit or "*" = all 18)
13
13
  # GOOGLE_MAPS_ENABLED_TOOLS=maps_search_places,maps_place_details,maps_geocode
14
+
15
+ # Automatic update check at server startup (enabled by default).
16
+ # Set to 1, true, or yes to skip the npm registry version check.
17
+ # MCP_AUTO_UPDATE_DISABLED=1
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # mcp-google-map (0.3.0)
1
+ # mcp-google-map (0.4.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">
@@ -9,21 +9,22 @@
9
9
 
10
10
  <p align="center">
11
11
  <strong>Google Maps Platform MCP server — 18 tools for AI agents (stdio + Streamable HTTP)</strong><br>
12
- Server [Model Context Protocol](https://modelcontextprotocol.io) per **Google Maps Platform**, con 18 tool per agenti AI: ricerca Places API (New) con **filtri server-side** (`priceLevels`, `minRating`, `strictTypeFiltering`), paginazione nativa, accesso al **payload raw** delle risposte API, geocoding, indicazioni, matrice delle distanze e altro.
12
+ A [Model Context Protocol](https://modelcontextprotocol.io) server for **Google Maps Platform** with 18 tools for AI agents: Places API (New) search with **server-side filters** (`priceLevels`, `minRating`, `strictTypeFiltering`), raw API payload access, geocoding, directions, distance matrix, and more.
13
13
 
14
- Trasporti supportati: **stdio** (client MCP locali) e **Streamable HTTP**.
14
+ Supported transports: **stdio** (local MCP clients) and **Streamable HTTP**.
15
15
 
16
- > Compatibile con il protocollo di ricerca **GeoScout 6.2** — vedi [docs/GEOSCOUT.md](docs/GEOSCOUT.md).
16
+ > Compatible with the **GeoScout 6.2** search protocol — see [docs/GEOSCOUT.md](docs/GEOSCOUT.md).
17
17
 
18
18
  </p>
19
19
 
20
20
  <p align="center">
21
21
  <a href="#feature-highlights">Feature Highlights</a> |
22
- <a href="#requisiti">Requirements</a> |
22
+ <a href="#requirements">Requirements</a> |
23
23
  <a href="#install">Install / Uninstall</a> |
24
- <a href="#avvio-rapido">Quick Start</a> |
25
- <a href="#registrazione-in-un-client-mcp">MCP Clients</a> |
26
- <a href="#documentazione">Docs</a>
24
+ <a href="#quick-start">Quick Start</a> |
25
+ <a href="#command-line-interface">CLI</a> |
26
+ <a href="#registering-in-an-mcp-client">MCP Clients</a> |
27
+ <a href="#documentation">Docs</a>
27
28
  </p>
28
29
  <p align="center">
29
30
  <br>
@@ -36,37 +37,38 @@ Trasporti supportati: **stdio** (client MCP locali) e **Streamable HTTP**.
36
37
  ## Feature Highlights
37
38
 
38
39
  - **18 Google Maps MCP tools** — geocoding, reverse geocoding, Places API (New) text/nearby search, place details, directions, distance matrix, elevation, timezone, weather, air quality, static maps, batch geocode, plus composite tools (explore-area, plan-route, compare-places, search-along-route, local-rank-tracker). Full catalog: [docs/TOOLS.md](docs/TOOLS.md).
39
- - **Server-side Places filters** — `priceLevels`, `minRating`, `openNow`, `strictTypeFiltering`, and location bias are forwarded to Places API (New), not emulated client-side.
40
+ - **Server-side Places filters** — `priceLevels`, `minRating`, `openNow`, `includedType`, `strictTypeFiltering`, and location bias are forwarded to Places API (New) as request fields by `maps_search_places`; in `maps_search_nearby`, `openNow` and `minRating` are applied after the query, so filters can return fewer than 20 results.
40
41
  - **Raw API payloads** — searches and details can return the untouched Google response (`includeRaw: true`) with explicit Field Masks.
41
42
  - **Two transports** — stdio for local MCP clients (pi, Claude Desktop, Cursor, ...) and Streamable HTTP at `/mcp` with per-session API keys.
42
43
  - **Per-request credentials** — key resolution from `X-Google-Maps-API-Key` or `Authorization: Bearer` headers, session key, or `GOOGLE_MAPS_API_KEY` environment.
43
44
  - **Standalone CLI** — `doctor` self-checks, `exec <tool>` one-shot calls, `batch-geocode` with bounded concurrency.
45
+ - **Automatic update check** — at server startup the server compares its version against the latest npm release and prints an upgrade notice on stderr; it never blocks startup and can be disabled with `MCP_AUTO_UPDATE_DISABLED=1` (see [Configuration prerequisites](#configuration-prerequisites)).
44
46
  - **GeoScout 6.2 compatible** — see [docs/GEOSCOUT.md](docs/GEOSCOUT.md).
45
47
 
46
- ## Requisiti
48
+ ## Requirements
47
49
 
48
50
  - Node.js **>= 22**
49
- - Una **Google Maps API key** (<https://console.cloud.google.com/apis/credentials>) con i servizi abilitati — vedi sotto
51
+ - A **Google Maps API key** (<https://console.cloud.google.com/apis/credentials>) with the services enabled — see below
50
52
 
51
- ## API Google Cloud richieste
53
+ ## Required Google Cloud APIs
52
54
 
53
- Mappatura verificata sui sorgenti: ogni endpoint usato dal server e il tool che lo richiede.
55
+ Mapping verified against the sources: every endpoint the server calls and the tools that call it.
54
56
 
55
- | # | API da abilitare | Endpoint usato dal server | Tool che la richiedono | Necessaria per | Priorità GeoScout |
57
+ | # | API to enable | Endpoint used by the server | Tools that require it | Needed for | GeoScout priority |
56
58
  |---|---|---|---|---|---|
57
- | 1 | **Places API (New)** | `places.googleapis.com` (`places:searchText`, `places:searchNearby`, `GET places/{id}`, photo media) via `@googlemaps/places` | `maps_search_places`, `maps_search_nearby`, `maps_place_details`, `maps_explore_area`, `maps_compare_places`, `maps_search_along_route`, `maps_local_rank_tracker` | Ricerca/dettaglio locali, filtri `priceLevels`/`minRating`, `priceRange`, orari | **Obbligatoria** |
58
- | 2 | **Geocoding API** | `maps.googleapis.com/maps/api/geocode/json` via `@googlemaps/google-maps-services-js` | `maps_geocode`, `maps_reverse_geocode`, `maps_batch_geocode` (+ fallback interno di risoluzione indirizzi) | Conversione indirizzo ↔ coordinate | Alta |
59
- | 3 | **Routes API** | `routes.googleapis.com` (`computeRoutes`, `computeRouteMatrix`) | `maps_directions`, `maps_distance_matrix`, `maps_plan_route` | Percorsi e matrice distanze | Media |
60
- | 4 | **Time Zone API** | `maps.googleapis.com/maps/api/timezone/json` | `maps_timezone` | Fuso orario / ora locale | Bassa |
61
- | 5 | **Maps Elevation API** *(in console: "Maps Elevation API", servizio `elevation-backend`)* | `maps.googleapis.com/maps/api/elevation/json` | `maps_elevation` | Quota del terreno | Bassa |
62
- | 6 | **Maps Static API** | `maps.googleapis.com/maps/api/staticmap` | `maps_static_map` | Immagine mappa PNG | Bassa |
63
- | 7 | **Weather API** | `weather.googleapis.com/v1` (current, forecast/days, forecast/hours) | `maps_weather` | Meteo corrente/previsioni | Bassa (disponibilità regionale) |
64
- | 8 | **Air Quality API** | `airquality.googleapis.com/v1/currentConditions:lookup` | `maps_air_quality` | Qualità dell'aria | Bassa (disponibilità regionale) |
59
+ | 1 | **Places API (New)** | `places.googleapis.com` (`places:searchText`, `places:searchNearby`, `GET places/{id}`, photo media) via `@googlemaps/places` | `maps_search_places`, `maps_search_nearby`, `maps_place_details`, `maps_explore_area`, `maps_compare_places`, `maps_search_along_route`, `maps_local_rank_tracker` | Place search/details, `priceLevels`/`minRating` filters, `priceRange`, opening hours | **Required** |
60
+ | 2 | **Geocoding API** | `maps.googleapis.com/maps/api/geocode/json` via `@googlemaps/google-maps-services-js` | `maps_geocode`, `maps_reverse_geocode`, `maps_batch_geocode` (+ internal address-resolution fallback) | Address ↔ coordinate conversion | High |
61
+ | 3 | **Routes API** | `routes.googleapis.com` (`computeRoutes`, `computeRouteMatrix`) | `maps_directions`, `maps_distance_matrix`, `maps_plan_route` | Routes and distance matrix | Medium |
62
+ | 4 | **Time Zone API** | `maps.googleapis.com/maps/api/timezone/json` | `maps_timezone` | Time zone / local time | Low |
63
+ | 5 | **Maps Elevation API** *(in the console: "Maps Elevation API", service `elevation-backend`)* | `maps.googleapis.com/maps/api/elevation/json` | `maps_elevation` | Ground elevation | Low |
64
+ | 6 | **Maps Static API** | `maps.googleapis.com/maps/api/staticmap` | `maps_static_map` | PNG map image | Low |
65
+ | 7 | **Weather API** | `weather.googleapis.com/v1` (current, forecast/days, forecast/hours) | `maps_weather` | Current weather / forecasts | Low (regional availability) |
66
+ | 8 | **Air Quality API** | `airquality.googleapis.com/v1/currentConditions:lookup` | `maps_air_quality` | Air quality | Low (regional availability) |
65
67
 
66
- Abilitazione rapida (progetto GCP corrente):
68
+ Quick enablement (current GCP project):
67
69
 
68
70
  ```bash
69
- PROJECT=iltuoprogetto
71
+ PROJECT=your-project
70
72
  gcloud services enable places-backend-new.googleapis.com \
71
73
  geocoding-backend.googleapis.com \
72
74
  routes.googleapis.com \
@@ -77,17 +79,17 @@ gcloud services enable places-backend-new.googleapis.com \
77
79
  airquality.googleapis.com --project=$PROJECT
78
80
  ```
79
81
 
80
- ### Note
82
+ ### Notes
81
83
 
82
- - Per l'uso minimo/GeoScout bastano **Places API (New)** + **Geocoding API**; le altre si abilitano solo se si usano i tool corrispondenti (in alternativa limitare l'esposizione con `GOOGLE_MAPS_ENABLED_TOOLS`).
83
- - **Maps Grounding Lite** e **Geolocation API** **non sono richieste** da questo server: la prima serve all'MCP hosted di Google (`mapstools.googleapis.com`), la seconda non è usata da nessun tool (non c'è `ip_geolocate` in questo fork).
84
- - La vecchia **Places API** (legacy) non è necessaria: il server usa esclusivamente Places API (New).
85
- - Weather API e Air Quality API hanno copertura regionale limitata: fuori copertura il tool restituisce errore dell'API.
84
+ - For minimal/GeoScout use, **Places API (New)** + **Geocoding API** suffice; enable the others only for the corresponding tools (or limit exposure with `GOOGLE_MAPS_ENABLED_TOOLS`).
85
+ - **Maps Grounding Lite** and **Geolocation API** are **not required** by this server: the former belongs to Google's hosted MCP (`mapstools.googleapis.com`), the latter is used by no tool (there is no `ip_geolocate` in this fork).
86
+ - The legacy **Places API** is not needed: the server uses Places API (New) exclusively.
87
+ - Weather API and Air Quality API have limited regional coverage: outside coverage, the tool returns an unsupported-location error message.
86
88
 
87
89
 
88
90
  ## Install
89
91
 
90
- **Prerequisites**: Node.js **>= 22** and a Google Maps API key (see [Requisiti](#requisiti)).
92
+ **Prerequisites**: Node.js **>= 22** and a Google Maps API key (see [Requirements](#requirements)).
91
93
 
92
94
  ### From npm
93
95
 
@@ -131,19 +133,37 @@ npm uninstall -g mcp-google-map # npm-based install
131
133
  rm -rf mcp-google-map # from-source clone; also remove any MCP client registration
132
134
  ```
133
135
 
134
- ## Avvio rapido
136
+ ## Quick Start
135
137
 
136
138
  ```bash
137
- scripts/setup.sh # installa le dipendenze e crea .env
138
- $EDITOR .env # inserisci GOOGLE_MAPS_API_KEY
139
- scripts/build.sh # compila in dist/
139
+ scripts/setup.sh # installs dependencies and creates .env
140
+ $EDITOR .env # enter GOOGLE_MAPS_API_KEY
141
+ scripts/build.sh # compiles to dist/
140
142
 
141
- scripts/start-mcp.sh # server MCP su stdio (per pi, Claude Desktop, Cursor, ...)
142
- scripts/start-http.sh # server MCP su http://127.0.0.1:3000/mcp
143
- scripts/test.sh # test unitari (nessuna API key richiesta)
143
+ scripts/start-mcp.sh # MCP server over stdio (for pi, Claude Desktop, Cursor, ...)
144
+ scripts/start-http.sh # MCP server at http://127.0.0.1:3000/mcp
145
+ scripts/test.sh # unit tests (no API key required)
144
146
  ```
145
147
 
146
- ## Registrazione in un client MCP
148
+ ## Command-line interface
149
+
150
+ All commands work through the `mcp-google-map` binary (npm install) or `node dist/cli.js` (from source).
151
+
152
+ ```bash
153
+ mcp-google-map --stdio # MCP server over stdio
154
+ mcp-google-map --host 127.0.0.1 --port 3000 # MCP server over Streamable HTTP at /mcp
155
+ mcp-google-map doctor # local self-check: Node version, package version, API key (no network)
156
+ mcp-google-map doctor --live --apikey "AIza..." # also probes Geocoding, Places (New), Routes (billable calls)
157
+ mcp-google-map exec geocode '{"address":"Tokyo Tower"}' # one tool call from the terminal
158
+ mcp-google-map batch-geocode -i addresses.txt -o results.json
159
+ ```
160
+
161
+ - `exec <tool> [params]` runs one tool and prints JSON; `params` is a JSON string. Tool names accept short (`geocode`), snake_case (`search_places`), and `maps_`-prefixed (`maps_geocode`) forms.
162
+ - `exec` writes results to stdout and errors to stderr; it exits 1 when no API key is configured, the tool reports a failure, the JSON is invalid, or the tool name is unknown.
163
+ - `batch-geocode` reads one address per line from `--input` (use `-` for stdin), geocodes with bounded concurrency (`--concurrency`, default 20, clamped to 1–50), writes a JSON summary `{ total, succeeded, failed, results }` to `--output` or stdout, and exits 1 if any address failed.
164
+ - 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`).
165
+
166
+ ## Registering in an MCP client
147
167
 
148
168
  **stdio:**
149
169
 
@@ -151,14 +171,14 @@ scripts/test.sh # test unitari (nessuna API key richiesta)
151
171
  {
152
172
  "mcpServers": {
153
173
  "mcp-google-map": {
154
- "command": "/percorso/assoluto/a/mcp-google-map/scripts/start-mcp.sh",
174
+ "command": "/absolute/path/to/mcp-google-map/scripts/start-mcp.sh",
155
175
  "env": { "GOOGLE_MAPS_API_KEY": "AIza..." }
156
176
  }
157
177
  }
158
178
  }
159
179
  ```
160
180
 
161
- **HTTP** (dopo `scripts/start-http.sh`):
181
+ **HTTP** (after `scripts/start-http.sh`):
162
182
 
163
183
  ```json
164
184
  {
@@ -172,74 +192,76 @@ scripts/test.sh # test unitari (nessuna API key richiesta)
172
192
 
173
193
  ### pi CLI
174
194
 
175
- pi legge i server MCP da `~/.pi/agent/mcp.json` (utente) o `.pi/mcp.json` (progetto, richiede trust). Voce stdio per questo server:
195
+ pi reads MCP servers from `~/.pi/agent/mcp.json` (user) or `.pi/mcp.json` (project, requires trust). stdio entry for this server:
176
196
 
177
197
  ```json
178
198
  {
179
199
  "mcpServers": {
180
200
  "maps": {
181
201
  "command": "node",
182
- "args": ["/percorso/assoluto/a/mcp-google-map/dist/cli.js", "--stdio"],
202
+ "args": ["/absolute/path/to/mcp-google-map/dist/cli.js", "--stdio"],
183
203
  "env": { "GOOGLE_MAPS_API_KEY": "${GOOGLE_MAPS_API_KEY}" }
184
204
  }
185
205
  }
186
206
  }
187
207
  ```
188
208
 
189
- - Da terminale: `pi mcp add maps -- node /percorso/assoluto/a/mcp-google-map/dist/cli.js --stdio` (aggiungere `--env GOOGLE_MAPS_API_KEY=...` per la chiave).
190
- - `${GOOGLE_MAPS_API_KEY}` espande la variabile d'ambiente al volo: la chiave non resta cablata nel file di configurazione.
191
- - Dopo una modifica di `mcp.json` esterna alla sessione, eseguire `/reload` in pi; `/mcp` ispeziona stato, tool ed errori di connessione.
192
- - I tool appaiono con il prefisso `mcp__<server>__`: `mcp__maps__maps_geocode`, `mcp__maps__maps_search_places`, ...
209
+ - From a terminal: `pi mcp add maps -- node /absolute/path/to/mcp-google-map/dist/cli.js --stdio` (add `--env GOOGLE_MAPS_API_KEY=...` to pass the key).
210
+ - `${GOOGLE_MAPS_API_KEY}` expands the environment variable on the fly: the key never stays hard-coded in the configuration file.
211
+ - After editing `mcp.json` outside the session, run `/reload` in pi; `/mcp` inspects status, tools, and connection errors.
212
+ - Tools appear with the `mcp__<server>__` prefix: `mcp__maps__maps_geocode`, `mcp__maps__maps_search_places`, ...
193
213
 
194
214
  ### OpenClaw
195
215
 
196
- OpenClaw gestisce i server MCP in `~/.openclaw/openclaw.json` tramite CLI (verificato su OpenClaw 2026.4.21):
216
+ OpenClaw manages MCP servers in `~/.openclaw/openclaw.json` through its CLI (verified on OpenClaw 2026.4.21):
197
217
 
198
218
  ```bash
199
- openclaw mcp set maps '{"command":"node","args":["/percorso/assoluto/a/mcp-google-map/dist/cli.js","--stdio"],"env":{"GOOGLE_MAPS_API_KEY":"AIza..."},"description":"Google Maps: Places API (New), geocoding, routes, weather"}'
219
+ openclaw mcp set maps '{"command":"node","args":["/absolute/path/to/mcp-google-map/dist/cli.js","--stdio"],"env":{"GOOGLE_MAPS_API_KEY":"AIza..."},"description":"Google Maps: Places API (New), geocoding, routes, weather"}'
200
220
  ```
201
221
 
202
- - Senza installazione locale: usare `"command":"npx","args":["-y","mcp-google-map","--stdio"]` (esegue il pacchetto npm pubblicato).
203
- - Dopo la modifica ricaricare il gateway o riavviare la sessione agente perché il nuovo server venga collegato.
204
- - Ispezione e rimozione: `openclaw mcp list`, `openclaw mcp show maps`, `openclaw mcp unset maps`.
205
- - L'agente OpenClaw può installare e configurare il server in autonomia (shell + `openclaw mcp set`); la creazione della API key su Google Cloud Console resta un'operazione umana.
222
+ - Without a local install: use `"command":"npx","args":["-y","mcp-google-map","--stdio"]` (runs the published npm package).
223
+ - After the change, reload the gateway or restart the agent session so the new server gets connected.
224
+ - Inspect and remove: `openclaw mcp list`, `openclaw mcp show maps`, `openclaw mcp unset maps`.
225
+ - The OpenClaw agent can install and configure the server on its own (shell + `openclaw mcp set`); creating the API key in Google Cloud Console remains a human task.
206
226
 
207
- ### Prerequisiti di configurazione
227
+ ### Configuration prerequisites
208
228
 
209
- 1. **Una sola API key**: crea `GOOGLE_MAPS_API_KEY` su <https://console.cloud.google.com/apis/credentials> e abilita i servizi elencati nella tabella [API Google Cloud richieste](#api-google-cloud-richieste).
210
- 2. **Minimo operativo**: Places API (New) + Geocoding API; abilitare gli altri servizi solo per i tool corrispondenti.
211
- 3. **Limitare l'esposizione**: `GOOGLE_MAPS_ENABLED_TOOLS=maps_geocode,maps_search_places,maps_place_details` riduce i tool registrati (e il contesto per l'LLM).
212
- 4. **Verifica post-installazione**: `mcp-google-map doctor` (nessuna chiamata di rete), poi `mcp-google-map doctor --live --apikey "AIza..."` (probe reali su Geocoding, Places, Routes).
229
+ 1. **A single API key**: create `GOOGLE_MAPS_API_KEY` at <https://console.cloud.google.com/apis/credentials> and enable the services listed in the [Required Google Cloud APIs](#required-google-cloud-apis) table.
230
+ 2. **Minimal operational subset**: Places API (New) + Geocoding API; enable the other services only for the tools you use.
231
+ 3. **Restrict exposure**: `GOOGLE_MAPS_ENABLED_TOOLS=maps_geocode,maps_search_places,maps_place_details` reduces the registered tools (and the LLM context).
232
+ 4. **Post-install verification**: `mcp-google-map doctor` (no network calls), then `mcp-google-map doctor --live --apikey "AIza..."` (real probes against Geocoding, Places, and Routes).
233
+ 5. **Automatic update check**: enabled by default at server startup; set `MCP_AUTO_UPDATE_DISABLED=1` (also `true`/`yes`) to skip the npm registry version check.
213
234
 
214
- ## Struttura del progetto
235
+ ## Project structure
215
236
 
216
237
  ```
217
238
  mcp-google-map/
218
- ├── src/ # sorgenti del server MCP
219
- │ ├── cli.ts # entry point (stdio/HTTP, comandi exec e doctor)
220
- │ ├── config.ts # registrazione dei tool esposti
239
+ ├── src/ # MCP server sources
240
+ │ ├── cli.ts # entry point (stdio/HTTP, exec and doctor commands)
241
+ │ ├── config.ts # registration of the exposed tools
221
242
  │ ├── core/ # BaseMcpServer: MCP SDK, stdio + Streamable HTTP
222
- │ ├── services/ # Places API (New), Geocoding, Routes, clima
223
- │ └── tools/ # definizione dei 18 tool MCP
224
- ├── scripts/ # script bash di supporto (setup/build/start/test)
225
- ├── docs/ # documentazione del progetto
226
- └── tests/ # test unitari (mock) + smoke/e2e (API key reale)
243
+ │ ├── services/ # Places API (New), Geocoding, Routes, environment
244
+ │ ├── tools/ # definition of the 18 MCP tools
245
+ │ └── utils/ # API key resolution, request context, update check
246
+ ├── scripts/ # helper bash scripts (setup/build/start/test)
247
+ ├── docs/ # project documentation
248
+ └── tests/ # unit tests (mocked) + smoke/e2e (real API key)
227
249
  ```
228
250
 
229
- ## Documentazione
251
+ ## Documentation
230
252
 
231
- - [docs/TOOLS.md](docs/TOOLS.md) — catalogo dei tool e parametri
232
- - [docs/CONFIGURATION.md](docs/CONFIGURATION.md) — variabili d'ambiente, trasporti, API key
233
- - [docs/GEOSCOUT.md](docs/GEOSCOUT.md) — compatibilità GeoScout 6.2 (filtri economici, FieldMask, payload raw)
253
+ - [docs/TOOLS.md](docs/TOOLS.md) — tool catalog and parameters
254
+ - [docs/CONFIGURATION.md](docs/CONFIGURATION.md) — environment variables, transports, API key
255
+ - [docs/GEOSCOUT.md](docs/GEOSCOUT.md) — GeoScout 6.2 compatibility (budget filters, FieldMask, raw payload)
234
256
 
235
- ## Sviluppo
257
+ ## Development
236
258
 
237
259
  ```bash
238
- npm run dev # build incrementale in watch
260
+ npm run dev # incremental watch build
239
261
  npm run typecheck # tsc --noEmit
240
- scripts/test.sh # unit test
262
+ npm test # unit tests
241
263
  ```
242
264
 
243
- ## Licenza
265
+ ## License
244
266
 
245
- GPL-3.0 — vedi [LICENSE](LICENSE).
267
+ GPL-3.0 — see [LICENSE](LICENSE).
package/dist/cli.js CHANGED
@@ -1258,6 +1258,83 @@ import { fileURLToPath } from "url";
1258
1258
  import { dirname } from "path";
1259
1259
  import { readFileSync, writeFileSync, existsSync } from "fs";
1260
1260
  import { createInterface } from "readline";
1261
+
1262
+ // src/utils/autoUpdate.ts
1263
+ var AUTO_UPDATE_DISABLED_ENV = "MCP_AUTO_UPDATE_DISABLED";
1264
+ var DEFAULT_PACKAGE_NAME = "mcp-google-map";
1265
+ var DEFAULT_REGISTRY_BASE_URL = "https://registry.npmjs.org";
1266
+ var DEFAULT_UPDATE_CHECK_TIMEOUT_MS = 2e3;
1267
+ function isAutoUpdateDisabled(env = process.env) {
1268
+ const raw = env[AUTO_UPDATE_DISABLED_ENV];
1269
+ return typeof raw === "string" && /^(1|true|yes)$/i.test(raw.trim());
1270
+ }
1271
+ function isNewerVersion(candidate, current) {
1272
+ const toSegments = (version) => version.trim().split(".").map((segment) => /^\d+$/.test(segment) ? Number(segment) : Number.NaN);
1273
+ const candidateSegments = toSegments(candidate);
1274
+ const currentSegments = toSegments(current);
1275
+ if (candidateSegments.some((segment) => !Number.isInteger(segment)) || currentSegments.some((segment) => !Number.isInteger(segment))) {
1276
+ return false;
1277
+ }
1278
+ const length = Math.max(candidateSegments.length, currentSegments.length);
1279
+ for (let index = 0; index < length; index += 1) {
1280
+ const candidatePart = candidateSegments[index] ?? 0;
1281
+ const currentPart = currentSegments[index] ?? 0;
1282
+ if (candidatePart !== currentPart) {
1283
+ return candidatePart > currentPart;
1284
+ }
1285
+ }
1286
+ return false;
1287
+ }
1288
+ async function checkForUpdates(deps = {}) {
1289
+ const logger = deps.logger ?? Logger;
1290
+ const env = deps.env ?? process.env;
1291
+ try {
1292
+ if (isAutoUpdateDisabled(env)) {
1293
+ return null;
1294
+ }
1295
+ const currentVersion = deps.currentVersion;
1296
+ if (!currentVersion) {
1297
+ logger.error(
1298
+ `\u26A0\uFE0F [${DEFAULT_PACKAGE_NAME}] Automatic update check skipped: running package version is unknown.`
1299
+ );
1300
+ return null;
1301
+ }
1302
+ const packageName = deps.packageName ?? DEFAULT_PACKAGE_NAME;
1303
+ const registryBaseUrl = deps.registryBaseUrl ?? DEFAULT_REGISTRY_BASE_URL;
1304
+ const timeoutMs = deps.timeoutMs ?? DEFAULT_UPDATE_CHECK_TIMEOUT_MS;
1305
+ const fetchImpl = deps.fetchImpl ?? fetch;
1306
+ const response = await fetchImpl(`${registryBaseUrl}/${packageName}/latest`, {
1307
+ headers: { accept: "application/vnd.npm.install-v1+json" },
1308
+ signal: AbortSignal.timeout(timeoutMs)
1309
+ });
1310
+ if (!response.ok) {
1311
+ logger.error(
1312
+ `\u26A0\uFE0F [${DEFAULT_PACKAGE_NAME}] Automatic update check failed: registry responded with HTTP ${response.status}.`
1313
+ );
1314
+ return null;
1315
+ }
1316
+ const payload = await response.json();
1317
+ if (typeof payload?.version !== "string") {
1318
+ logger.error(
1319
+ `\u26A0\uFE0F [${DEFAULT_PACKAGE_NAME}] Automatic update check failed: registry response has no version field.`
1320
+ );
1321
+ return null;
1322
+ }
1323
+ if (!isNewerVersion(payload.version, currentVersion)) {
1324
+ return null;
1325
+ }
1326
+ logger.log(
1327
+ `\u26A0\uFE0F Update available: ${packageName} ${currentVersion} \u2192 ${payload.version}. Upgrade with: npm install -g ${packageName}@latest (or run npx -y ${packageName}@latest).`
1328
+ );
1329
+ return { currentVersion, latestVersion: payload.version };
1330
+ } catch (error) {
1331
+ const message = error instanceof Error ? error.message : String(error);
1332
+ logger.error(`\u26A0\uFE0F [${DEFAULT_PACKAGE_NAME}] Automatic update check failed: ${message}`);
1333
+ return null;
1334
+ }
1335
+ }
1336
+
1337
+ // src/cli.ts
1261
1338
  var __filename = fileURLToPath(import.meta.url);
1262
1339
  var __dirname = dirname(__filename);
1263
1340
  dotenvConfig({ path: resolve(process.cwd(), ".env") });
@@ -1754,6 +1831,7 @@ if (isRunDirectly || isMainModule) {
1754
1831
  if (argv.apikey) {
1755
1832
  process.env.GOOGLE_MAPS_API_KEY = argv.apikey;
1756
1833
  }
1834
+ void checkForUpdates({ currentVersion: packageVersion }).catch(() => void 0);
1757
1835
  const tools = filterTools(config_default[0].tools);
1758
1836
  if (argv.stdio) {
1759
1837
  const server = new BaseMcpServer(config_default[0].name, tools);
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/tools/maps/searchNearby.ts","../src/utils/requestContext.ts","../src/tools/maps/placeDetails.ts","../src/tools/maps/geocode.ts","../src/tools/maps/reverseGeocode.ts","../src/tools/maps/distanceMatrix.ts","../src/tools/maps/directions.ts","../src/tools/maps/elevation.ts","../src/tools/maps/searchPlaces.ts","../src/tools/maps/timezone.ts","../src/tools/maps/weather.ts","../src/tools/maps/exploreArea.ts","../src/tools/maps/planRoute.ts","../src/tools/maps/comparePlaces.ts","../src/tools/maps/airQuality.ts","../src/tools/maps/staticMap.ts","../src/tools/maps/batchGeocode.ts","../src/tools/maps/searchAlongRoute.ts","../src/tools/maps/localRankTracker.ts","../src/config.ts","../src/core/BaseMcpServer.ts","../src/utils/apiKeyManager.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { config as dotenvConfig } from \"dotenv\";\nimport { resolve } from \"path\";\nimport yargs from \"yargs\";\nimport { hideBin } from \"yargs/helpers\";\nimport serverConfigs, { filterTools } from \"./config.js\";\nimport { BaseMcpServer } from \"./core/BaseMcpServer.js\";\nimport { Logger } from \"./index.js\";\nimport { PlacesSearcher } from \"./services/PlacesSearcher.js\";\nimport { fileURLToPath } from \"url\";\nimport { dirname } from \"path\";\nimport { readFileSync, writeFileSync, existsSync } from \"fs\";\nimport { createInterface } from \"readline\";\n\n// Get the directory of the current module\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// Try to load .env from current directory first, then from package directory\ndotenvConfig({ path: resolve(process.cwd(), \".env\") });\n// Also try to load from the package installation directory\ndotenvConfig({ path: resolve(__dirname, \"../.env\") });\n\nexport async function startServer(port?: number, apiKey?: string, host?: string): Promise<void> {\n // Override environment variables with CLI arguments if provided\n if (port) {\n process.env.MCP_SERVER_PORT = port.toString();\n }\n if (apiKey) {\n process.env.GOOGLE_MAPS_API_KEY = apiKey;\n }\n if (host) {\n process.env.MCP_SERVER_HOST = host;\n }\n\n Logger.log(\"🚀 Starting Google Maps MCP Server...\");\n Logger.log(\"📍 18 tools registered (set GOOGLE_MAPS_ENABLED_TOOLS to limit)\");\n Logger.log(\n \"ℹ️ Reminder: enable Places API (New) in https://console.cloud.google.com before using the new Place features.\"\n );\n Logger.log(\"\");\n\n const startPromises = serverConfigs.map(async (config) => {\n const portString = process.env[config.portEnvVar];\n if (!portString) {\n Logger.error(`⚠️ [${config.name}] Port environment variable ${config.portEnvVar} not set.`);\n Logger.log(`💡 Please set ${config.portEnvVar} in your .env file or use --port parameter.`);\n Logger.log(` Example: ${config.portEnvVar}=3000 or --port 3000`);\n return;\n }\n\n const serverPort = Number(portString);\n if (isNaN(serverPort) || serverPort <= 0) {\n Logger.error(`❌ [${config.name}] Invalid port number \"${portString}\" defined in ${config.portEnvVar}.`);\n return;\n }\n\n try {\n const server = new BaseMcpServer(config.name, filterTools(config.tools));\n const serverHost = process.env.MCP_SERVER_HOST || \"0.0.0.0\";\n Logger.log(`🔧 [${config.name}] Initializing MCP Server in HTTP mode on ${serverHost}:${serverPort}...`);\n await server.startHttpServer(serverPort, serverHost);\n const displayHost = serverHost === \"0.0.0.0\" ? \"localhost\" : serverHost;\n Logger.log(`✅ [${config.name}] MCP Server started successfully!`);\n Logger.log(` 🌐 Endpoint: http://${displayHost}:${serverPort}/mcp`);\n Logger.log(` 📚 Tools: ${config.tools.length} available`);\n } catch (error) {\n Logger.error(`❌ [${config.name}] Failed to start MCP Server on port ${serverPort}:`, error);\n }\n });\n\n await Promise.allSettled(startPromises);\n\n Logger.log(\"\");\n Logger.log(\"🎉 Server initialization completed!\");\n Logger.log(\"💡 Need help? Check the README.md for configuration details.\");\n}\n\n// --------------- Exec Mode ---------------\n\nexport const EXEC_TOOLS = [\n \"geocode\",\n \"reverse-geocode\",\n \"search-nearby\",\n \"search-places\",\n \"place-details\",\n \"directions\",\n \"distance-matrix\",\n \"elevation\",\n \"timezone\",\n \"weather\",\n \"explore-area\",\n \"plan-route\",\n \"compare-places\",\n \"air-quality\",\n \"static-map\",\n \"batch-geocode-tool\",\n \"search-along-route\",\n \"local-rank-tracker\",\n] as const;\n\ntype ExecFailureResponse = {\n success: false;\n error?: unknown;\n};\n\ninterface ExecOutput {\n write(chunk: string): unknown;\n}\n\ninterface ExecStreams {\n stdout: ExecOutput;\n stderr: ExecOutput;\n}\n\ntype ExecToolRunner = (toolName: string, params: any, apiKey: string) => Promise<unknown>;\n\nexport type DoctorCheck = {\n name: string;\n status: \"pass\" | \"fail\" | \"skip\";\n detail: string;\n};\n\nexport type DoctorReport = {\n success: boolean;\n version: string;\n live: boolean;\n checks: DoctorCheck[];\n};\n\ntype DoctorToolRunner = (toolName: string, params: any, apiKey: string) => Promise<unknown>;\n\nfunction isExecFailureResponse(result: unknown): result is ExecFailureResponse {\n return (\n typeof result === \"object\" &&\n result !== null &&\n \"success\" in result &&\n (result as { success?: unknown }).success === false\n );\n}\n\nfunction getExecFailureMessage(toolName: string, result: ExecFailureResponse): string {\n if (typeof result.error === \"string\" && result.error.trim().length > 0) {\n return result.error;\n }\n if (result.error !== undefined && result.error !== null) {\n return String(result.error);\n }\n return `Tool \"${toolName}\" returned a failure response`;\n}\n\nexport async function execTool(toolName: string, params: any, apiKey: string): Promise<any> {\n const searcher = new PlacesSearcher(apiKey);\n\n switch (toolName) {\n case \"geocode\":\n case \"maps_geocode\":\n return searcher.geocode(params.address);\n\n case \"reverse-geocode\":\n case \"maps_reverse_geocode\":\n return searcher.reverseGeocode(params.latitude, params.longitude);\n\n case \"search-nearby\":\n case \"search_nearby\":\n case \"maps_search_nearby\":\n return searcher.searchNearby(params);\n\n case \"search-places\":\n case \"maps_search_places\":\n return searcher.searchText({\n query: params.query,\n locationBias: params.locationBias,\n openNow: params.openNow,\n minRating: params.minRating,\n includedType: params.includedType,\n strictTypeFiltering: params.strictTypeFiltering,\n priceLevels: params.priceLevels,\n pageSize: params.pageSize,\n pageToken: params.pageToken,\n languageCode: params.languageCode,\n includeRaw: params.includeRaw,\n });\n\n case \"place-details\":\n case \"get_place_details\":\n case \"maps_place_details\":\n return searcher.getPlaceDetails(params.placeId, params.maxPhotos || 0, params.includeRaw || false);\n\n case \"directions\":\n case \"maps_directions\":\n return searcher.getDirections(\n params.origin,\n params.destination,\n params.mode,\n params.departure_time,\n params.arrival_time,\n params.avoid_tolls,\n params.avoid_highways\n );\n\n case \"distance-matrix\":\n case \"maps_distance_matrix\":\n return searcher.calculateDistanceMatrix(\n params.origins,\n params.destinations,\n params.mode,\n params.departure_time,\n params.avoid_tolls,\n params.avoid_highways\n );\n\n case \"elevation\":\n case \"maps_elevation\":\n return searcher.getElevation(params.locations);\n\n case \"timezone\":\n case \"maps_timezone\":\n return searcher.getTimezone(params.latitude, params.longitude, params.timestamp);\n\n case \"weather\":\n case \"maps_weather\":\n return searcher.getWeather(\n params.latitude,\n params.longitude,\n params.type,\n params.forecastDays,\n params.forecastHours\n );\n\n case \"explore-area\":\n case \"maps_explore_area\":\n return searcher.exploreArea(params);\n\n case \"plan-route\":\n case \"maps_plan_route\":\n return searcher.planRoute(params);\n\n case \"compare-places\":\n case \"maps_compare_places\":\n return searcher.comparePlaces(params);\n\n case \"air-quality\":\n case \"maps_air_quality\":\n return searcher.getAirQuality(\n params.latitude,\n params.longitude,\n params.includeHealthRecommendations,\n params.includePollutants\n );\n\n case \"static-map\":\n case \"maps_static_map\":\n return searcher.getStaticMap(params);\n\n case \"batch-geocode-tool\":\n case \"maps_batch_geocode\": {\n const results = await Promise.all(\n (params.addresses as string[]).map(async (address: string) => {\n try {\n const result = await searcher.geocode(address);\n return { address, ...result };\n } catch (error: any) {\n return { address, success: false, error: error.message };\n }\n })\n );\n const succeeded = results.filter((r) => r.success).length;\n return {\n success: true,\n data: { total: params.addresses.length, succeeded, failed: params.addresses.length - succeeded, results },\n };\n }\n\n case \"search-along-route\":\n case \"maps_search_along_route\":\n return searcher.searchAlongRoute(params);\n\n case \"local-rank-tracker\":\n case \"maps_local_rank_tracker\":\n return searcher.localRankTracker(params);\n\n default:\n throw new Error(`Unknown tool: ${toolName}. Available: ${EXEC_TOOLS.join(\", \")}`);\n }\n}\n\n/**\n * Run an exec-mode tool and route its result to the appropriate stream.\n *\n * Service methods report API failures as `{ success: false, error }` rather\n * than throwing. Treat those responses as command failures so scripts can\n * rely on the exit code while successful responses remain machine-readable\n * JSON on stdout.\n */\nexport async function runExecCommand(\n toolName: string,\n params: any,\n apiKey: string,\n runner: ExecToolRunner = execTool,\n streams: ExecStreams = { stdout: process.stdout, stderr: process.stderr }\n): Promise<number> {\n try {\n const result = await runner(toolName, params, apiKey);\n if (isExecFailureResponse(result)) {\n streams.stderr.write(JSON.stringify({ error: getExecFailureMessage(toolName, result) }, null, 2) + \"\\n\");\n return 1;\n }\n\n streams.stdout.write(JSON.stringify(result, null, 2) + \"\\n\");\n return 0;\n } catch (error: unknown) {\n streams.stderr.write(\n JSON.stringify({ error: error instanceof Error ? error.message : String(error) }, null, 2) + \"\\n\"\n );\n return 1;\n }\n}\n\n/**\n * Check whether the standalone CLI is ready for Skill-driven use. Local mode\n * performs no Google API requests. Live mode makes three small requests so it\n * can distinguish Geocoding, Places (New), and Routes API availability.\n */\nexport async function runDoctor(\n packageVersion: string,\n apiKey: string | undefined,\n live = false,\n runner: DoctorToolRunner = execTool\n): Promise<DoctorReport> {\n const nodeMajor = Number.parseInt(process.versions.node.split(\".\")[0] ?? \"0\", 10);\n const checks: DoctorCheck[] = [\n {\n name: \"node\",\n status: nodeMajor >= 18 ? \"pass\" : \"fail\",\n detail: `Node.js ${process.versions.node} detected; version 18 or newer is required.`,\n },\n {\n name: \"package\",\n status: packageVersion !== \"0.0.0\" ? \"pass\" : \"fail\",\n detail:\n packageVersion !== \"0.0.0\"\n ? `mcp-google-map ${packageVersion} is available.`\n : \"Could not read the installed package version.\",\n },\n {\n name: \"api-key\",\n status: apiKey ? \"pass\" : \"fail\",\n detail: apiKey\n ? \"GOOGLE_MAPS_API_KEY is configured (value hidden).\"\n : \"GOOGLE_MAPS_API_KEY is not configured. Set it in the environment before making API calls.\",\n },\n ];\n\n if (!live) {\n checks.push({\n name: \"live-api\",\n status: \"skip\",\n detail: \"Live API checks were not requested; no Google Maps API calls were made.\",\n });\n } else if (!apiKey) {\n checks.push({\n name: \"live-api\",\n status: \"skip\",\n detail: \"Live API checks require GOOGLE_MAPS_API_KEY.\",\n });\n } else {\n const liveChecks = [\n { name: \"geocoding-api\", tool: \"geocode\", params: { address: \"Tokyo Tower\" } },\n { name: \"places-api-new\", tool: \"search-places\", params: { query: \"Tokyo Tower\" } },\n {\n name: \"routes-api\",\n tool: \"directions\",\n params: { origin: \"Tokyo Tower\", destination: \"Tokyo Station\", mode: \"walking\" },\n },\n ];\n\n for (const check of liveChecks) {\n try {\n const result = await runner(check.tool, check.params, apiKey);\n if (isExecFailureResponse(result)) {\n checks.push({\n name: check.name,\n status: \"fail\",\n detail: getExecFailureMessage(check.tool, result),\n });\n } else {\n checks.push({\n name: check.name,\n status: \"pass\",\n detail: `${check.name} request succeeded.`,\n });\n }\n } catch (error: unknown) {\n checks.push({\n name: check.name,\n status: \"fail\",\n detail: error instanceof Error ? error.message : String(error),\n });\n }\n }\n }\n\n return {\n success: checks.every((check) => check.status !== \"fail\"),\n version: packageVersion,\n live,\n checks,\n };\n}\n\n// --------------- Entry Point ---------------\n\n// Check if this script is being run directly\nconst isRunDirectly =\n process.argv[1] &&\n (process.argv[1].endsWith(\"cli.ts\") ||\n process.argv[1].endsWith(\"cli.js\") ||\n process.argv[1].endsWith(\"mcp-google-map\") ||\n process.argv[1].includes(\"mcp-google-map\"));\n\nconst isMainModule = import.meta.url === `file://${process.argv[1]}`;\n\nif (isRunDirectly || isMainModule) {\n let packageVersion = \"0.0.0\";\n try {\n const packageJsonPath = resolve(__dirname, \"../package.json\");\n const packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\"));\n packageVersion = packageJson.version;\n } catch (e) {\n packageVersion = \"0.0.0\";\n }\n\n yargs(hideBin(process.argv))\n .command(\n \"doctor\",\n \"Check standalone CLI readiness without starting an MCP server\",\n (yargs) =>\n yargs\n .option(\"live\", {\n type: \"boolean\",\n default: false,\n description: \"Make billable test requests to Geocoding, Places (New), and Routes APIs\",\n })\n .option(\"apikey\", {\n alias: \"k\",\n type: \"string\",\n description: \"Google Maps API key (prefer GOOGLE_MAPS_API_KEY to avoid shell history exposure)\",\n default: process.env.GOOGLE_MAPS_API_KEY,\n })\n .example([\n [\"$0 doctor\", \"Check local runtime and API key configuration without network calls\"],\n [\"$0 doctor --live\", \"Also verify three Google Maps APIs with billable requests\"],\n ]),\n async (argv) => {\n const report = await runDoctor(packageVersion, argv.apikey as string | undefined, argv.live as boolean);\n process.stdout.write(JSON.stringify(report, null, 2) + \"\\n\");\n process.exitCode = report.success ? 0 : 1;\n }\n )\n .command(\n \"exec <tool> [params]\",\n \"Execute a tool directly and output JSON\",\n (yargs) => {\n return yargs\n .positional(\"tool\", {\n type: \"string\",\n describe: `Tool name: ${EXEC_TOOLS.join(\", \")}`,\n })\n .positional(\"params\", {\n type: \"string\",\n describe: \"JSON parameters string\",\n })\n .option(\"apikey\", {\n alias: \"k\",\n type: \"string\",\n description: \"Google Maps API key\",\n default: process.env.GOOGLE_MAPS_API_KEY,\n })\n .example([\n ['$0 exec geocode \\'{\"address\":\"Tokyo Tower\"}\\'', \"Geocode an address\"],\n [\n '$0 exec search-nearby \\'{\"center\":{\"value\":\"35.68,139.74\",\"isCoordinates\":true},\"keyword\":\"restaurant\"}\\'',\n \"Search nearby\",\n ],\n ['$0 exec search-places \\'{\"query\":\"ramen in Tokyo\"}\\'', \"Text search\"],\n ]);\n },\n async (argv) => {\n if (!argv.apikey) {\n process.stderr.write(\n JSON.stringify(\n {\n error: \"GOOGLE_MAPS_API_KEY not set. Use --apikey or set GOOGLE_MAPS_API_KEY environment variable.\",\n },\n null,\n 2\n ) + \"\\n\"\n );\n process.exitCode = 1;\n return;\n }\n try {\n const params = argv.params ? JSON.parse(argv.params as string) : {};\n process.exitCode = await runExecCommand(argv.tool as string, params, argv.apikey as string);\n } catch (error: any) {\n process.stderr.write(JSON.stringify({ error: error.message }, null, 2) + \"\\n\");\n process.exitCode = 1;\n }\n }\n )\n .command(\n \"batch-geocode\",\n \"Geocode multiple addresses from a file (one address per line)\",\n (yargs) => {\n return yargs\n .option(\"input\", {\n alias: \"i\",\n type: \"string\",\n describe: \"Input file path (one address per line). Use - for stdin.\",\n demandOption: true,\n })\n .option(\"output\", {\n alias: \"o\",\n type: \"string\",\n describe: \"Output file path (JSON). Defaults to stdout.\",\n })\n .option(\"concurrency\", {\n alias: \"c\",\n type: \"number\",\n describe: \"Max parallel requests\",\n default: 20,\n })\n .option(\"apikey\", {\n alias: \"k\",\n type: \"string\",\n description: \"Google Maps API key\",\n default: process.env.GOOGLE_MAPS_API_KEY,\n })\n .example([\n [\"$0 batch-geocode -i addresses.txt\", \"Geocode to stdout\"],\n [\"$0 batch-geocode -i addresses.txt -o results.json\", \"Geocode to file\"],\n [\"cat addresses.txt | $0 batch-geocode -i -\", \"Geocode from stdin\"],\n ]);\n },\n async (argv) => {\n if (!argv.apikey) {\n console.error(\"Error: GOOGLE_MAPS_API_KEY not set. Use --apikey or set env var.\");\n process.exit(1);\n }\n\n // Read addresses\n let lines: string[];\n if (argv.input === \"-\") {\n // Read from stdin\n const rl = createInterface({ input: process.stdin });\n lines = [];\n for await (const line of rl) {\n const trimmed = line.trim();\n if (trimmed) lines.push(trimmed);\n }\n } else {\n if (!existsSync(argv.input as string)) {\n console.error(`Error: File not found: ${argv.input}`);\n process.exit(1);\n }\n lines = readFileSync(argv.input as string, \"utf-8\")\n .split(\"\\n\")\n .map((l) => l.trim())\n .filter((l) => l.length > 0);\n }\n\n if (lines.length === 0) {\n console.error(\"Error: No addresses found in input.\");\n process.exit(1);\n }\n\n const searcher = new PlacesSearcher(argv.apikey as string);\n const concurrency = Math.min(Math.max(argv.concurrency as number, 1), 50);\n const results: any[] = [];\n let completed = 0;\n\n // Process with concurrency limit\n const semaphore = async (tasks: (() => Promise<void>)[], limit: number) => {\n const executing: Promise<void>[] = [];\n for (const task of tasks) {\n const p = task().then(() => {\n executing.splice(executing.indexOf(p), 1);\n });\n executing.push(p);\n if (executing.length >= limit) {\n await Promise.race(executing);\n }\n }\n await Promise.all(executing);\n };\n\n const tasks = lines.map((address, index) => async () => {\n try {\n const result = await searcher.geocode(address);\n results[index] = { address, ...result };\n } catch (error: any) {\n results[index] = { address, success: false, error: error.message };\n }\n completed++;\n if (!argv.output) return; // Don't log progress when outputting to stdout\n process.stderr.write(`\\r ${completed}/${lines.length} geocoded`);\n });\n\n await semaphore(tasks, concurrency);\n\n if (argv.output) {\n process.stderr.write(\"\\n\");\n }\n\n // Summary\n const succeeded = results.filter((r) => r.success).length;\n const failed = results.filter((r) => !r.success).length;\n const summary = { total: lines.length, succeeded, failed, results };\n\n const json = JSON.stringify(summary, null, 2);\n\n if (argv.output) {\n writeFileSync(argv.output as string, json, \"utf-8\");\n console.error(`Done: ${succeeded}/${lines.length} succeeded. Output: ${argv.output}`);\n } else {\n console.log(json);\n }\n\n process.exit(failed > 0 ? 1 : 0);\n }\n )\n .command(\n \"$0\",\n \"Start the MCP server (HTTP by default, --stdio for stdio mode)\",\n (yargs) => {\n return yargs\n .option(\"port\", {\n alias: \"p\",\n type: \"number\",\n description: \"Port to run the MCP server on\",\n default: process.env.MCP_SERVER_PORT ? parseInt(process.env.MCP_SERVER_PORT) : 3000,\n })\n .option(\"host\", {\n type: \"string\",\n description: \"Hostname to bind the server to (e.g. 0.0.0.0 for all interfaces)\",\n default: process.env.MCP_SERVER_HOST || \"0.0.0.0\",\n })\n .option(\"apikey\", {\n alias: \"k\",\n type: \"string\",\n description: \"Google Maps API key\",\n default: process.env.GOOGLE_MAPS_API_KEY,\n })\n .option(\"stdio\", {\n type: \"boolean\",\n description: \"Use stdio transport instead of HTTP\",\n default: false,\n })\n .example([\n [\"$0\", \"Start HTTP server with default settings\"],\n ['$0 --port 3000 --apikey \"your_api_key\"', \"Start HTTP with custom port and API key\"],\n [\"$0 --host 0.0.0.0 --port 3000\", \"Start HTTP accessible from all interfaces\"],\n [\"$0 --stdio\", \"Start in stdio mode (for Claude Desktop, Cursor, etc.)\"],\n ]);\n },\n async (argv) => {\n if (argv.apikey) {\n process.env.GOOGLE_MAPS_API_KEY = argv.apikey as string;\n }\n\n const tools = filterTools(serverConfigs[0].tools);\n\n if (argv.stdio) {\n // stdio mode — all logs go to stderr, stdout reserved for JSON-RPC\n const server = new BaseMcpServer(serverConfigs[0].name, tools);\n await server.startStdio();\n } else {\n // HTTP mode\n Logger.log(\"🗺️ Google Maps MCP Server\");\n Logger.log(\" A Model Context Protocol server for Google Maps services\");\n Logger.log(\"\");\n\n if (!argv.apikey) {\n Logger.log(\"⚠️ Google Maps API Key not found!\");\n Logger.log(\" Please provide --apikey parameter or set GOOGLE_MAPS_API_KEY in your .env file\");\n Logger.log(\"\");\n }\n\n startServer(argv.port as number, argv.apikey as string, argv.host as string).catch((error) => {\n Logger.error(\"❌ Failed to start server:\", error);\n process.exit(1);\n });\n }\n }\n )\n .version(packageVersion)\n .alias(\"version\", \"v\")\n .help()\n .parse();\n}\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_search_nearby\";\nconst DESCRIPTION =\n \"Find places near a specific location by type (e.g., restaurants, cafes, hotels). Use when the user wants to discover what's around a given address or coordinates, such as 'find coffee shops near Times Square' or 'what hotels are near the airport'. Supports filtering by place type, search radius, minimum rating, and whether currently open.\";\n\nconst SCHEMA = {\n center: z\n .object({\n value: z.string().describe(\"Address, landmark name, or coordinates (coordinate format: lat,lng)\"),\n isCoordinates: z.boolean().default(false).describe(\"Whether the value is coordinates\"),\n })\n .describe(\"Search center point (e.g. value: 49.3268778,-123.0585982, isCoordinates: true)\"),\n keyword: z\n .string()\n .optional()\n .describe(\"Place type to search for (e.g., restaurant, cafe, hotel, gas_station, hospital)\"),\n radius: z.number().default(1000).describe(\"Search radius in meters\"),\n openNow: z.boolean().default(false).describe(\"Only show places that are currently open\"),\n minRating: z.number().min(0).max(5).optional().describe(\"Minimum rating requirement (0-5)\"),\n};\n\nexport type SearchNearbyParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: SearchNearbyParams): Promise<{ content: any[]; isError?: boolean }> {\n try {\n // Create a new PlacesSearcher instance with the current request's API key\n const apiKey = getCurrentApiKey();\n const placesSearcher = new PlacesSearcher(apiKey);\n const result = await placesSearcher.searchNearby(params);\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Search failed\" }],\n isError: true,\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: `location: ${JSON.stringify(result.location, null, 2)}\\n` + JSON.stringify(result.data, null, 2),\n },\n ],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error searching nearby places: ${errorMessage}` }],\n };\n }\n}\n\nexport const SearchNearby = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { AsyncLocalStorage } from \"node:async_hooks\";\n\ninterface RequestContext {\n apiKey?: string;\n sessionId?: string;\n}\n\n// Create AsyncLocalStorage instance to track request context\nexport const requestContextStorage = new AsyncLocalStorage<RequestContext>();\n\n/**\n * Get the current request's API key\n */\nexport function getCurrentApiKey(): string | undefined {\n const context = requestContextStorage.getStore();\n return context?.apiKey || process.env.GOOGLE_MAPS_API_KEY;\n}\n\n/**\n * Run a function with a specific request context\n */\nexport function runWithContext<T>(context: RequestContext, fn: () => T | Promise<T>): T | Promise<T> {\n return requestContextStorage.run(context, fn);\n}\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_place_details\";\nconst DESCRIPTION =\n \"Get comprehensive details for a specific place using its Google Maps place_id. Use after search_nearby or maps_search_places to get reviews, phone, website, and hours. Includes priceRange (raw Money structure: startPrice/endPrice with currencyCode/units/nanos), businessStatus, types and both regular and current opening hours. Reviews, photos, and AI summaries include source/disclosure metadata that must accompany end-user display. Set maxPhotos (1-10) to include photo URLs; omit or set 0 for none. Set includeRaw to attach the original Places API payload (raw_place) for API-verified validation.\";\n\nconst SCHEMA = {\n placeId: z.string().describe(\"Google Maps place ID\"),\n maxPhotos: z\n .number()\n .int()\n .min(0)\n .max(10)\n .optional()\n .describe(\"Number of photo URLs to include (0 = none, max 10). Omit to skip photos and save tokens.\"),\n includeRaw: z\n .boolean()\n .optional()\n .describe(\n \"Include the original Places API payload (raw_place) alongside the interpreted fields, for API-verified validation\"\n ),\n};\n\nexport type PlaceDetailsParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n const apiKey = getCurrentApiKey();\n const placesSearcher = new PlacesSearcher(apiKey);\n const result = await placesSearcher.getPlaceDetails(params.placeId, params.maxPhotos || 0, params.includeRaw || false);\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Failed to get place details\" }],\n isError: true,\n };\n }\n\n const payload: Record<string, any> = { ...result.data };\n if (result.fieldMask) payload.field_mask = result.fieldMask;\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(payload, null, 2),\n },\n ],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error getting place details: ${errorMessage}` }],\n };\n }\n}\n\nexport const PlaceDetails = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_geocode\";\nconst DESCRIPTION =\n \"Convert an address, city name, or landmark into GPS coordinates (latitude/longitude). Use when you need coordinates for a location described in text — for example, to provide a center point for search_nearby or a starting point for maps_directions.\";\n\nconst SCHEMA = {\n address: z.string().describe(\"Address or place name to convert to coordinates\"),\n};\n\nexport type GeocodeParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n // Create a new PlacesSearcher instance with the current request's API key\n const apiKey = getCurrentApiKey();\n const placesSearcher = new PlacesSearcher(apiKey);\n const result = await placesSearcher.geocode(params.address);\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Failed to geocode address\" }],\n isError: true,\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(result.data, null, 2),\n },\n ],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error geocoding address: ${errorMessage}` }],\n };\n }\n}\n\nexport const Geocode = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_reverse_geocode\";\nconst DESCRIPTION =\n \"Convert GPS coordinates (latitude/longitude) into a human-readable street address. Use when you have coordinates from another tool's output or a user's shared location and need the actual address.\";\n\nconst SCHEMA = {\n latitude: z.number().describe(\"Latitude coordinate\"),\n longitude: z.number().describe(\"Longitude coordinate\"),\n};\n\nexport type ReverseGeocodeParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n // Create a new PlacesSearcher instance with the current request's API key\n const apiKey = getCurrentApiKey();\n const placesSearcher = new PlacesSearcher(apiKey);\n const result = await placesSearcher.reverseGeocode(params.latitude, params.longitude);\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Failed to reverse geocode coordinates\" }],\n isError: true,\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(result.data, null, 2),\n },\n ],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error reverse geocoding: ${errorMessage}` }],\n };\n }\n}\n\nexport const ReverseGeocode = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_distance_matrix\";\nconst DESCRIPTION =\n \"Calculate travel distances and durations between multiple origins and destinations in a single request. Use for comparing travel options — e.g., 'which hotel is closest to the office?' or batch distance calculations. Supports driving, walking, bicycling, and transit modes.\";\n\nconst SCHEMA = {\n origins: z.array(z.string()).describe(\"List of origin addresses or coordinates\"),\n destinations: z.array(z.string()).describe(\"List of destination addresses or coordinates\"),\n mode: z\n .enum([\"driving\", \"walking\", \"bicycling\", \"transit\"])\n .default(\"driving\")\n .describe(\"Travel mode for calculation\"),\n departure_time: z\n .string()\n .optional()\n .describe(\n \"Departure time in ISO 8601 format (e.g. 2026-03-21T09:00:00Z). Enables traffic-aware duration estimates.\"\n ),\n avoid_tolls: z\n .boolean()\n .optional()\n .describe('Avoid toll roads where reasonable. Only supported with mode \"driving\".'),\n avoid_highways: z\n .boolean()\n .optional()\n .describe('Avoid highways where reasonable. Only supported with mode \"driving\".'),\n};\n\nexport type DistanceMatrixParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n // Create a new PlacesSearcher instance with the current request's API key\n const apiKey = getCurrentApiKey();\n const placesSearcher = new PlacesSearcher(apiKey);\n const result = await placesSearcher.calculateDistanceMatrix(\n params.origins,\n params.destinations,\n params.mode,\n params.departure_time,\n params.avoid_tolls,\n params.avoid_highways\n );\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Failed to calculate distance matrix\" }],\n isError: true,\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(result.data, null, 2),\n },\n ],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error calculating distance matrix: ${errorMessage}` }],\n };\n }\n}\n\nexport const DistanceMatrix = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_directions\";\nconst DESCRIPTION =\n \"Get step-by-step navigation directions between two points with route details. Use when the user asks 'how do I get from A to B?' and needs the route summary, total distance, estimated travel time, or turn-by-turn instructions. Supports departure/arrival times and multiple travel modes.\";\n\nconst SCHEMA = {\n origin: z.string().describe(\"Starting point address or coordinates\"),\n destination: z.string().describe(\"Destination address or coordinates\"),\n mode: z\n .enum([\"driving\", \"walking\", \"bicycling\", \"transit\"])\n .default(\"driving\")\n .describe(\"Travel mode for directions\"),\n departure_time: z.string().optional().describe(\"Departure time (ISO string format)\"),\n arrival_time: z.string().optional().describe(\"Arrival time (ISO string format)\"),\n avoid_tolls: z\n .boolean()\n .optional()\n .describe('Avoid toll roads where reasonable. Only supported with mode \"driving\".'),\n avoid_highways: z\n .boolean()\n .optional()\n .describe('Avoid highways where reasonable. Only supported with mode \"driving\".'),\n};\n\nexport type DirectionsParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n // Create a new PlacesSearcher instance with the current request's API key\n const apiKey = getCurrentApiKey();\n const placesSearcher = new PlacesSearcher(apiKey);\n const result = await placesSearcher.getDirections(\n params.origin,\n params.destination,\n params.mode,\n params.departure_time,\n params.arrival_time,\n params.avoid_tolls,\n params.avoid_highways\n );\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Failed to get directions\" }],\n isError: true,\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(result.data, null, 2),\n },\n ],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error getting directions: ${errorMessage}` }],\n };\n }\n}\n\nexport const Directions = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_elevation\";\nconst DESCRIPTION =\n \"Get elevation (meters above sea level) for geographic coordinates. Use when the user asks 'how high is this place', 'is this area flood-prone', or needs altitude for hiking/cycling route profiles. Also useful for real estate risk assessment — low elevation near water suggests flood risk.\";\n\nconst SCHEMA = {\n locations: z\n .array(\n z.object({\n latitude: z.number().describe(\"Latitude coordinate\"),\n longitude: z.number().describe(\"Longitude coordinate\"),\n })\n )\n .describe(\"List of locations to get elevation data for\"),\n};\n\nexport type ElevationParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n // Create a new PlacesSearcher instance with the current request's API key\n const apiKey = getCurrentApiKey();\n const placesSearcher = new PlacesSearcher(apiKey);\n const result = await placesSearcher.getElevation(params.locations);\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Failed to get elevation data\" }],\n isError: true,\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(result.data, null, 2),\n },\n ],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error getting elevation data: ${errorMessage}` }],\n };\n }\n}\n\nexport const Elevation = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_search_places\";\nconst DESCRIPTION =\n \"Search for places using a free-text query like 'sushi restaurants in Tokyo' or 'best coffee shops near Central Park'. More flexible than search_nearby — supports natural language queries, optional location bias, server-side rating and cumulative price-level filters (Places API Text Search priceLevels enum), strict type filtering, and open-now filtering. Returns place details including priceRange (raw Money structure), types, businessStatus, rating, userRatingCount and opening hours. Supports pageSize/pageToken pagination (up to 20 per page) and an optional includeRaw mode that attaches the original Places API payload for API-verified validation.\";\n\nconst PRICE_LEVELS = [\n \"PRICE_LEVEL_FREE\",\n \"PRICE_LEVEL_INEXPENSIVE\",\n \"PRICE_LEVEL_MODERATE\",\n \"PRICE_LEVEL_EXPENSIVE\",\n \"PRICE_LEVEL_VERY_EXPENSIVE\",\n] as const;\n\nconst SCHEMA = {\n query: z.string().describe(\"Text search query (e.g., 'Italian restaurants in Manhattan', 'hotels near Taipei 101')\"),\n locationBias: z\n .object({\n latitude: z.number().describe(\"Latitude to bias results toward\"),\n longitude: z.number().describe(\"Longitude to bias results toward\"),\n radius: z.number().optional().describe(\"Bias radius in meters (default: 5000)\"),\n })\n .optional()\n .describe(\"Optional location to bias results toward\"),\n openNow: z.boolean().optional().describe(\"Only return places that are currently open (server-side filter)\"),\n minRating: z.number().optional().describe(\"Minimum rating filter (1.0 - 5.0), applied server-side by the API\"),\n includedType: z\n .string()\n .optional()\n .describe(\n \"Filter by a single place type (e.g., restaurant, cafe, bakery). Text Search supports exactly one includedType per call\"\n ),\n strictTypeFiltering: z\n .boolean()\n .optional()\n .describe(\n \"Strict type filtering: if true, only results of the same type as includedType are returned (default: loose interpretation)\"\n ),\n priceLevels: z\n .array(z.enum(PRICE_LEVELS))\n .optional()\n .describe(\n 'Server-side economic filter. Pass ALL allowed levels cumulatively up to the budget cap, e.g. budget 30 EUR -> [\"PRICE_LEVEL_INEXPENSIVE\", \"PRICE_LEVEL_MODERATE\"]. Do not include PRICE_LEVEL_FREE'\n ),\n pageSize: z\n .number()\n .int()\n .min(1)\n .max(20)\n .optional()\n .describe(\"Number of results per page (1-20). Use nextPageToken from the response to fetch further pages (up to 60 total)\"),\n pageToken: z\n .string()\n .optional()\n .describe(\"nextPageToken returned by a previous maps_search_places call, to retrieve the next page of results\"),\n languageCode: z.string().optional().describe(\"Language code for results (e.g., 'en', 'it', 'ja')\"),\n includeRaw: z\n .boolean()\n .optional()\n .describe(\n \"Include the original Places API payload: each result gets a raw_place field and the full raw_response is returned (for API-verified validation)\"\n ),\n};\n\nexport type SearchPlacesParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n const apiKey = getCurrentApiKey();\n const placesSearcher = new PlacesSearcher(apiKey);\n const result = await placesSearcher.searchText({\n query: params.query,\n locationBias: params.locationBias,\n openNow: params.openNow,\n minRating: params.minRating,\n includedType: params.includedType,\n strictTypeFiltering: params.strictTypeFiltering,\n priceLevels: params.priceLevels,\n pageSize: params.pageSize,\n pageToken: params.pageToken,\n languageCode: params.languageCode,\n includeRaw: params.includeRaw,\n });\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Failed to search places\" }],\n isError: true,\n };\n }\n\n const payload: Record<string, any> = {\n results: result.data,\n };\n if (result.nextPageToken) payload.nextPageToken = result.nextPageToken;\n if (result.fieldMask) payload.field_mask = result.fieldMask;\n if (params.includeRaw && result.raw_response) payload.raw_response = result.raw_response;\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(payload, null, 2),\n },\n ],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error searching places: ${errorMessage}` }],\n };\n }\n}\n\nexport const SearchPlaces = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_timezone\";\nconst DESCRIPTION =\n \"Get the timezone and current local time for a location. Use when the user asks 'what time is it in Tokyo', needs to coordinate a meeting across timezones, or is planning travel across timezone boundaries. Returns timezone ID, UTC/DST offsets, and computed local time.\";\n\nconst SCHEMA = {\n latitude: z.number().describe(\"Latitude coordinate\"),\n longitude: z.number().describe(\"Longitude coordinate\"),\n timestamp: z\n .number()\n .optional()\n .describe(\"Unix timestamp in ms to query timezone at a specific moment (defaults to now)\"),\n};\n\nexport type TimezoneParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n const apiKey = getCurrentApiKey();\n const placesSearcher = new PlacesSearcher(apiKey);\n const result = await placesSearcher.getTimezone(params.latitude, params.longitude, params.timestamp);\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Failed to get timezone data\" }],\n isError: true,\n };\n }\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(result.data, null, 2) }],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error getting timezone: ${errorMessage}` }],\n };\n }\n}\n\nexport const Timezone = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_weather\";\nconst DESCRIPTION =\n \"Get weather for a location — current conditions, daily forecast (10 days), or hourly forecast (240 hours). Use when the user asks 'what's the weather in Paris', is planning outdoor activities, or needs to pack for a trip. Coverage: most regions supported, but China, Japan, South Korea, Cuba, Iran, North Korea, Syria are unavailable.\";\n\nconst SCHEMA = {\n latitude: z.number().describe(\"Latitude coordinate\"),\n longitude: z.number().describe(\"Longitude coordinate\"),\n type: z\n .enum([\"current\", \"forecast_daily\", \"forecast_hourly\"])\n .optional()\n .describe(\"current = right now, forecast_daily = multi-day outlook, forecast_hourly = hour-by-hour\"),\n forecastDays: z.number().optional().describe(\"Number of forecast days (1-10, only for forecast_daily, default: 5)\"),\n forecastHours: z\n .number()\n .optional()\n .describe(\"Number of forecast hours (1-240, only for forecast_hourly, default: 24)\"),\n};\n\nexport type WeatherParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n const apiKey = getCurrentApiKey();\n const placesSearcher = new PlacesSearcher(apiKey);\n const result = await placesSearcher.getWeather(\n params.latitude,\n params.longitude,\n params.type || \"current\",\n params.forecastDays,\n params.forecastHours\n );\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Failed to get weather data\" }],\n isError: true,\n };\n }\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(result.data, null, 2) }],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error getting weather: ${errorMessage}` }],\n };\n }\n}\n\nexport const Weather = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_explore_area\";\nconst DESCRIPTION =\n \"Explore what's around a location in one call — searches multiple place types, gets details for the top results, and returns a categorized summary. Use when the user asks 'what's around here', 'explore the area near my hotel', or needs a quick overview of a neighborhood. Replaces the manual chain of geocode → search-nearby → place-details. For trip planning: use search_places first to get geographically spread anchor points, then call this tool around each anchor (e.g. 'Gion, Kyoto') — never pass just the city name, as it clusters all results in one area. After results, call static_map to visualize.\";\n\nconst SCHEMA = {\n location: z.string().describe(\"Address or landmark to explore around\"),\n types: z\n .array(z.string())\n .optional()\n .describe(\n \"Place types to search (default: restaurant, cafe, tourist_attraction). Must be Places API (New) type names. Examples: hotel, bar, park, museum\"\n ),\n radius: z.number().optional().describe(\"Search radius in meters (default: 1000)\"),\n topN: z.number().optional().describe(\"Number of top results per type to get details for (default: 3)\"),\n};\n\nexport type ExploreAreaParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n const apiKey = getCurrentApiKey();\n const searcher = new PlacesSearcher(apiKey);\n const result = await searcher.exploreArea(params);\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(result.data, null, 2) }],\n isError: false,\n };\n } catch (error: any) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error exploring area: ${error.message}` }],\n };\n }\n}\n\nexport const ExploreArea = { NAME, DESCRIPTION, SCHEMA, ACTION };\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_plan_route\";\nconst DESCRIPTION =\n \"Plan an optimized multi-stop route in one call — geocodes all stops, uses Routes API waypoint optimization (2 to 25 intermediate stops) to find the most efficient visit order, and returns directions for each leg. Use when the user says 'visit these 5 places efficiently', 'plan a route through A, B, C', or needs a multi-stop itinerary. Replaces the manual chain of geocode → distance-matrix → directions. Waypoint optimization requires at least 4 stops (2 intermediates); with 2 or 3 stops the route is returned in the original order. For multi-day trips: create one plan_route call per day with stops that follow a geographic arc (e.g. east→west) rather than mixing distant areas. After results, call static_map to visualize the route.\";\n\nconst SCHEMA = {\n stops: z.array(z.string()).min(2).describe(\"List of addresses or landmarks to visit (minimum 2)\"),\n mode: z.enum([\"driving\", \"walking\", \"bicycling\", \"transit\"]).optional().describe(\"Travel mode (default: driving)\"),\n optimize: z\n .boolean()\n .optional()\n .describe(\n \"Auto-optimize visit order via Routes API waypoint optimization (default: true). Requires at least 4 stops (2 intermediates) — ignored for 2-3 stops. Set false to keep original order. Not available for transit mode.\"\n ),\n departure_time: z\n .string()\n .optional()\n .describe(\"Departure time in ISO 8601 format (e.g. 2026-03-21T09:00:00Z). Enables traffic-aware routing.\"),\n avoid_tolls: z\n .boolean()\n .optional()\n .describe('Avoid toll roads where reasonable. Only supported with mode \"driving\".'),\n avoid_highways: z\n .boolean()\n .optional()\n .describe('Avoid highways where reasonable. Only supported with mode \"driving\".'),\n};\n\nexport type PlanRouteParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n const apiKey = getCurrentApiKey();\n const searcher = new PlacesSearcher(apiKey);\n const result = await searcher.planRoute(params);\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(result.data, null, 2) }],\n isError: false,\n };\n } catch (error: any) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error planning route: ${error.message}` }],\n };\n }\n}\n\nexport const PlanRoute = { NAME, DESCRIPTION, SCHEMA, ACTION };\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_compare_places\";\nconst DESCRIPTION =\n \"Compare multiple places side-by-side in one call — searches by query, gets details for each result, and optionally calculates distance from your location. Use when the user asks 'which restaurant should I pick', 'compare these hotels', or needs a decision table. Replaces the manual chain of search-places → place-details → distance-matrix.\";\n\nconst SCHEMA = {\n query: z.string().describe(\"Search query (e.g., 'ramen near Shibuya', 'hotels in Taipei')\"),\n userLocation: z\n .object({\n latitude: z.number().describe(\"Your latitude\"),\n longitude: z.number().describe(\"Your longitude\"),\n })\n .optional()\n .describe(\"Your current location — if provided, adds distance and drive time to each result\"),\n limit: z.number().optional().describe(\"Max places to compare (default: 5)\"),\n};\n\nexport type ComparePlacesParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n const apiKey = getCurrentApiKey();\n const searcher = new PlacesSearcher(apiKey);\n const result = await searcher.comparePlaces(params);\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(result.data, null, 2) }],\n isError: false,\n };\n } catch (error: any) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error comparing places: ${error.message}` }],\n };\n }\n}\n\nexport const ComparePlaces = { NAME, DESCRIPTION, SCHEMA, ACTION };\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_air_quality\";\nconst DESCRIPTION =\n \"Get air quality for a location — AQI index, pollutant concentrations, and health recommendations by demographic group (elderly, children, athletes, pregnant women, etc.). Use when the user asks 'is the air safe', 'should I wear a mask', 'good for outdoor exercise', or is planning travel for someone with respiratory/heart conditions. Coverage: global including Japan (unlike weather). Returns both universal AQI and local index (EPA for US, AEROS for Japan, etc.).\";\n\nconst SCHEMA = {\n latitude: z.number().describe(\"Latitude coordinate\"),\n longitude: z.number().describe(\"Longitude coordinate\"),\n includeHealthRecommendations: z\n .boolean()\n .optional()\n .describe(\"Include health advice per demographic group (default: true)\"),\n includePollutants: z\n .boolean()\n .optional()\n .describe(\"Include individual pollutant concentrations — PM2.5, PM10, NO2, O3, CO, SO2 (default: false)\"),\n};\n\nexport type AirQualityParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n const apiKey = getCurrentApiKey();\n const placesSearcher = new PlacesSearcher(apiKey);\n const result = await placesSearcher.getAirQuality(\n params.latitude,\n params.longitude,\n params.includeHealthRecommendations,\n params.includePollutants\n );\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Failed to get air quality data\" }],\n isError: true,\n };\n }\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(result.data, null, 2) }],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error getting air quality: ${errorMessage}` }],\n };\n }\n}\n\nexport const AirQuality = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_static_map\";\nconst DESCRIPTION =\n \"Generate a map image with markers, paths, or routes — returned as an inline image the user can see directly in chat. PROACTIVELY call this tool after explore_area, plan_route, search_nearby, or directions to visualize results on a map — don't wait for the user to ask. Use markers from search results and path from route data. Supports roadmap, satellite, terrain, and hybrid views. Max 640x640 pixels.\";\n\nconst SCHEMA = {\n center: z\n .string()\n .optional()\n .describe('Map center — \"lat,lng\" or address. Optional if markers or path are provided.'),\n zoom: z.number().optional().describe(\"Zoom level 0-21 (0 = world, 15 = streets, 21 = buildings). Default: auto-fit.\"),\n size: z.string().optional().describe('Image size \"WxH\" in pixels. Default: \"600x400\". Max: \"640x640\".'),\n maptype: z.enum([\"roadmap\", \"satellite\", \"terrain\", \"hybrid\"]).optional().describe(\"Map style. Default: roadmap.\"),\n markers: z\n .array(z.string())\n .optional()\n .describe(\n 'Marker descriptors. Each string: \"color:red|label:A|lat,lng\" or \"color:blue|address\". Multiple markers per string separated by |.'\n ),\n path: z\n .array(z.string())\n .optional()\n .describe(\n 'Path descriptors. Each string: \"color:0x0000ff|weight:3|lat1,lng1|lat2,lng2|...\" to draw lines/routes on the map.'\n ),\n};\n\nexport type StaticMapParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n const apiKey = getCurrentApiKey();\n const placesSearcher = new PlacesSearcher(apiKey);\n const result = await placesSearcher.getStaticMap(params);\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Failed to generate static map\" }],\n isError: true,\n };\n }\n\n return {\n content: [\n {\n type: \"image\",\n data: result.data!.base64,\n mimeType: \"image/png\",\n },\n {\n type: \"text\",\n text: `Map generated (${result.data!.size} bytes, ${result.data!.dimensions})`,\n },\n ],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error generating static map: ${errorMessage}` }],\n };\n }\n}\n\nexport const StaticMap = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_batch_geocode\";\nconst DESCRIPTION =\n \"Geocode multiple addresses in one call — up to 50 addresses, returns coordinates for each. Use when the user provides a list of addresses and needs all their coordinates, e.g. 'geocode these 10 offices' or 'get coordinates for all these restaurants'. For more than 50, use the CLI batch-geocode command instead.\";\n\nconst SCHEMA = {\n addresses: z.array(z.string()).min(1).max(50).describe(\"List of addresses or landmark names to geocode (max 50)\"),\n};\n\nexport type BatchGeocodeParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n const apiKey = getCurrentApiKey();\n const searcher = new PlacesSearcher(apiKey);\n const addresses: string[] = params.addresses;\n\n const results = await Promise.all(\n addresses.map(async (address: string) => {\n try {\n const result = await searcher.geocode(address);\n return { address, ...result };\n } catch (error: any) {\n return { address, success: false, error: error.message };\n }\n })\n );\n\n const succeeded = results.filter((r) => r.success).length;\n const failed = results.filter((r) => !r.success).length;\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ total: addresses.length, succeeded, failed, results }, null, 2),\n },\n ],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error batch geocoding: ${errorMessage}` }],\n };\n }\n}\n\nexport const BatchGeocode = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_search_along_route\";\nconst DESCRIPTION =\n \"Search for places along a route between two points — restaurants, cafes, gas stations, etc. ranked by minimal detour time. Use for trip planning to find meals, rest stops, or attractions between landmarks without backtracking. Internally computes the route, then searches along it. Essential for building itineraries where stops should feel 'on the way' rather than 'detour to'.\";\n\nconst SCHEMA = {\n textQuery: z.string().describe(\"What to search for along the route (e.g. 'restaurant', 'coffee shop', 'temple')\"),\n origin: z.string().describe(\"Route start point — address or landmark name\"),\n destination: z.string().describe(\"Route end point — address or landmark name\"),\n mode: z\n .enum([\"driving\", \"walking\", \"bicycling\", \"transit\"])\n .optional()\n .describe(\"Travel mode for the route (default: walking)\"),\n maxResults: z.number().optional().describe(\"Max results to return (default: 5, max: 20)\"),\n};\n\nexport type SearchAlongRouteParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n const apiKey = getCurrentApiKey();\n const searcher = new PlacesSearcher(apiKey);\n const result = await searcher.searchAlongRoute(params);\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Failed to search along route\" }],\n isError: true,\n };\n }\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(result.data, null, 2) }],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error searching along route: ${errorMessage}` }],\n };\n }\n}\n\nexport const SearchAlongRoute = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_local_rank_tracker\";\nconst DESCRIPTION =\n \"Track a business's local search ranking across a geographic grid (like LocalFalcon). Searches the same keyword(s) from multiple coordinates around a center point to see how rank varies by location. Supports up to 3 keywords for batch scanning. Returns rank at each grid point, top-3 competitors per point, and summary metrics (ARP, ATRP, SoLV). Useful for local SEO analysis.\";\n\nconst SCHEMA = {\n keyword: z\n .string()\n .optional()\n .describe(\"Single search keyword (e.g., 'dentist'). Use 'keywords' for multi-keyword scanning.\"),\n keywords: z\n .array(z.string())\n .min(1)\n .max(3)\n .optional()\n .describe(\n \"Array of 1-3 keywords to scan (e.g., ['dentist', 'dental clinic', 'teeth cleaning']). Overrides 'keyword'.\"\n ),\n placeId: z.string().describe(\"Google Maps place_id of the target business to track\"),\n center: z\n .object({\n latitude: z.number().describe(\"Center latitude of the grid\"),\n longitude: z.number().describe(\"Center longitude of the grid\"),\n })\n .describe(\"Center coordinate for the grid (typically the business location)\"),\n gridSize: z\n .number()\n .int()\n .min(3)\n .max(7)\n .optional()\n .describe(\"Grid dimension (3 = 3×3 = 9 points, 5 = 5×5 = 25 points, 7 = 7×7 = 49 points). Default: 3\"),\n gridSpacing: z\n .number()\n .min(100)\n .max(10000)\n .optional()\n .describe(\"Distance between grid points in meters (100-10000). Default: 1000\"),\n};\n\nexport type LocalRankTrackerParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n // Resolve keywords: keywords array takes priority, fallback to keyword string\n const resolvedKeywords: string[] = params.keywords || (params.keyword ? [params.keyword] : []);\n if (resolvedKeywords.length === 0) {\n return {\n content: [{ type: \"text\", text: \"Either 'keyword' or 'keywords' must be provided.\" }],\n isError: true,\n };\n }\n\n const apiKey = getCurrentApiKey();\n const placesSearcher = new PlacesSearcher(apiKey);\n const result = await placesSearcher.localRankTracker({ ...params, keywords: resolvedKeywords });\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Failed to track local rank\" }],\n isError: true,\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(result.data, null, 2),\n },\n ],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error tracking local rank: ${errorMessage}` }],\n };\n }\n}\n\nexport const LocalRankTracker = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { Logger } from \"./index.js\";\nimport { ToolConfig } from \"./core/BaseMcpServer.js\";\n\n// Import tool definitions\nimport { SearchNearby, SearchNearbyParams } from \"./tools/maps/searchNearby.js\";\nimport { PlaceDetails, PlaceDetailsParams } from \"./tools/maps/placeDetails.js\";\nimport { Geocode, GeocodeParams } from \"./tools/maps/geocode.js\";\nimport { ReverseGeocode, ReverseGeocodeParams } from \"./tools/maps/reverseGeocode.js\";\nimport { DistanceMatrix, DistanceMatrixParams } from \"./tools/maps/distanceMatrix.js\";\nimport { Directions, DirectionsParams } from \"./tools/maps/directions.js\";\nimport { Elevation, ElevationParams } from \"./tools/maps/elevation.js\";\nimport { SearchPlaces, SearchPlacesParams } from \"./tools/maps/searchPlaces.js\";\nimport { Timezone, TimezoneParams } from \"./tools/maps/timezone.js\";\nimport { Weather, WeatherParams } from \"./tools/maps/weather.js\";\nimport { ExploreArea, ExploreAreaParams } from \"./tools/maps/exploreArea.js\";\nimport { PlanRoute, PlanRouteParams } from \"./tools/maps/planRoute.js\";\nimport { ComparePlaces, ComparePlacesParams } from \"./tools/maps/comparePlaces.js\";\nimport { AirQuality, AirQualityParams } from \"./tools/maps/airQuality.js\";\nimport { StaticMap, StaticMapParams } from \"./tools/maps/staticMap.js\";\nimport { BatchGeocode, BatchGeocodeParams } from \"./tools/maps/batchGeocode.js\";\nimport { SearchAlongRoute, SearchAlongRouteParams } from \"./tools/maps/searchAlongRoute.js\";\nimport { LocalRankTracker, LocalRankTrackerParams } from \"./tools/maps/localRankTracker.js\";\n\n// All Google Maps tools are read-only API queries\nconst MAPS_TOOL_ANNOTATIONS = {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n} as const;\n\ninterface ServerInstanceConfig {\n name: string;\n portEnvVar: string;\n tools: ToolConfig[];\n}\n\nconst serverConfigs: ServerInstanceConfig[] = [\n {\n name: \"MCP-Server\",\n portEnvVar: \"MCP_SERVER_PORT\",\n tools: [\n {\n name: SearchNearby.NAME,\n description: SearchNearby.DESCRIPTION,\n schema: SearchNearby.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: SearchNearbyParams) => SearchNearby.ACTION(params),\n },\n {\n name: PlaceDetails.NAME,\n description: PlaceDetails.DESCRIPTION,\n schema: PlaceDetails.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: PlaceDetailsParams) => PlaceDetails.ACTION(params),\n },\n {\n name: Geocode.NAME,\n description: Geocode.DESCRIPTION,\n schema: Geocode.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: GeocodeParams) => Geocode.ACTION(params),\n },\n {\n name: ReverseGeocode.NAME,\n description: ReverseGeocode.DESCRIPTION,\n schema: ReverseGeocode.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: ReverseGeocodeParams) => ReverseGeocode.ACTION(params),\n },\n {\n name: DistanceMatrix.NAME,\n description: DistanceMatrix.DESCRIPTION,\n schema: DistanceMatrix.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: DistanceMatrixParams) => DistanceMatrix.ACTION(params),\n },\n {\n name: Directions.NAME,\n description: Directions.DESCRIPTION,\n schema: Directions.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: DirectionsParams) => Directions.ACTION(params),\n },\n {\n name: Elevation.NAME,\n description: Elevation.DESCRIPTION,\n schema: Elevation.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: ElevationParams) => Elevation.ACTION(params),\n },\n {\n name: SearchPlaces.NAME,\n description: SearchPlaces.DESCRIPTION,\n schema: SearchPlaces.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: SearchPlacesParams) => SearchPlaces.ACTION(params),\n },\n {\n name: Timezone.NAME,\n description: Timezone.DESCRIPTION,\n schema: Timezone.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: TimezoneParams) => Timezone.ACTION(params),\n },\n {\n name: Weather.NAME,\n description: Weather.DESCRIPTION,\n schema: Weather.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: WeatherParams) => Weather.ACTION(params),\n },\n {\n name: ExploreArea.NAME,\n description: ExploreArea.DESCRIPTION,\n schema: ExploreArea.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: ExploreAreaParams) => ExploreArea.ACTION(params),\n },\n {\n name: PlanRoute.NAME,\n description: PlanRoute.DESCRIPTION,\n schema: PlanRoute.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: PlanRouteParams) => PlanRoute.ACTION(params),\n },\n {\n name: ComparePlaces.NAME,\n description: ComparePlaces.DESCRIPTION,\n schema: ComparePlaces.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: ComparePlacesParams) => ComparePlaces.ACTION(params),\n },\n {\n name: AirQuality.NAME,\n description: AirQuality.DESCRIPTION,\n schema: AirQuality.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: AirQualityParams) => AirQuality.ACTION(params),\n },\n {\n name: StaticMap.NAME,\n description: StaticMap.DESCRIPTION,\n schema: StaticMap.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: StaticMapParams) => StaticMap.ACTION(params),\n },\n {\n name: BatchGeocode.NAME,\n description: BatchGeocode.DESCRIPTION,\n schema: BatchGeocode.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: BatchGeocodeParams) => BatchGeocode.ACTION(params),\n },\n {\n name: SearchAlongRoute.NAME,\n description: SearchAlongRoute.DESCRIPTION,\n schema: SearchAlongRoute.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: SearchAlongRouteParams) => SearchAlongRoute.ACTION(params),\n },\n {\n name: LocalRankTracker.NAME,\n description: LocalRankTracker.DESCRIPTION,\n schema: LocalRankTracker.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: LocalRankTrackerParams) => LocalRankTracker.ACTION(params),\n },\n ],\n },\n];\n\nexport function filterTools(tools: ToolConfig[]): ToolConfig[] {\n const raw = process.env.GOOGLE_MAPS_ENABLED_TOOLS?.trim();\n if (!raw || raw === \"*\") return tools;\n\n const enabled = new Set(\n raw\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean)\n );\n const filtered = tools.filter((t) => enabled.has(t.name));\n\n if (filtered.length === 0) {\n Logger.error(`GOOGLE_MAPS_ENABLED_TOOLS matched 0 tools. Available: ${tools.map((t) => t.name).join(\", \")}`);\n return tools;\n }\n\n Logger.log(`GOOGLE_MAPS_ENABLED_TOOLS: ${filtered.length}/${tools.length} tools active`);\n return filtered;\n}\n\nexport default serverConfigs;\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport { isInitializeRequest, ToolAnnotations } from \"@modelcontextprotocol/sdk/types.js\";\nimport express, { Request, Response } from \"express\";\nimport { Server } from \"http\";\nimport { randomUUID } from \"node:crypto\";\nimport { z } from \"zod\";\nimport { Logger } from \"../index.js\";\nimport { ApiKeyManager } from \"../utils/apiKeyManager.js\";\nimport { runWithContext } from \"../utils/requestContext.js\";\n\nconst VERSION = \"0.0.1\";\n\n// Define a structure for tool configurations\nexport interface ToolConfig {\n name: string;\n description: string;\n schema: Record<string, z.ZodTypeAny>;\n annotations?: ToolAnnotations;\n action: (params: any) => Promise<any>;\n}\n\nexport interface SessionContext {\n apiKey?: string;\n transport: StreamableHTTPServerTransport;\n}\n\nexport class BaseMcpServer {\n protected readonly server: McpServer;\n private sessions: { [sessionId: string]: SessionContext } = {};\n private httpServer: Server | null = null;\n private serverName: string;\n private tools: ToolConfig[];\n\n constructor(name: string, tools: ToolConfig[]) {\n this.serverName = name;\n this.tools = tools;\n this.server = this.createMcpServer();\n }\n\n private createMcpServer(): McpServer {\n const server = new McpServer(\n { name: this.serverName, version: VERSION },\n { capabilities: { logging: {}, tools: {} } }\n );\n this.tools.forEach((tool) => {\n server.registerTool(\n tool.name,\n {\n description: tool.description,\n inputSchema: z.object(tool.schema),\n annotations: tool.annotations,\n },\n async (params: any) => tool.action(params)\n );\n });\n return server;\n }\n\n async connect(transport: Transport): Promise<void> {\n await this.server.connect(transport);\n\n // Ensure stdout is only used for JSON messages\n const originalStdoutWrite = process.stdout.write.bind(process.stdout);\n process.stdout.write = (chunk: any, encoding?: any, callback?: any) => {\n if (typeof chunk === \"string\" && !chunk.startsWith(\"{\")) {\n return true; // Silently skip non-JSON messages\n }\n return originalStdoutWrite(chunk, encoding, callback);\n };\n\n Logger.log(`${this.serverName} connected and ready to process requests`);\n }\n\n async startHttpServer(port: number, host: string = \"0.0.0.0\"): Promise<void> {\n const app = express();\n app.use(express.json());\n\n // Handle POST requests for client-to-server communication\n app.post(\"/mcp\", async (req: Request, res: Response) => {\n const sessionId = req.headers[\"mcp-session-id\"] as string | undefined;\n let context: SessionContext;\n\n // Extract API key from headers if provided\n const apiKeyManager = ApiKeyManager.getInstance();\n const requestApiKey = apiKeyManager.getApiKey(req, sessionId ? this.sessions[sessionId]?.apiKey : undefined);\n\n Logger.log(`${this.serverName} API key received from request context`);\n\n if (sessionId && this.sessions[sessionId]) {\n // Reuse existing session\n context = this.sessions[sessionId];\n // Update API key if provided in this request\n if (requestApiKey) {\n context.apiKey = requestApiKey;\n }\n } else if (!sessionId && isInitializeRequest(req.body)) {\n // New initialization request\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: () => randomUUID(),\n onsessioninitialized: (sessionId) => {\n this.sessions[sessionId] = context;\n Logger.log(`[${this.serverName}] New session initialized: ${sessionId}`);\n },\n // DNS rebinding protection is disabled by default for backwards compatibility\n // For production use, enable this:\n // enableDnsRebindingProtection: true,\n // allowedHosts: ['127.0.0.1'],\n });\n\n // Create session context\n context = {\n transport,\n apiKey: requestApiKey,\n };\n\n // Clean up transport when closed\n transport.onclose = () => {\n if (transport.sessionId) {\n delete this.sessions[transport.sessionId];\n Logger.log(`[${this.serverName}] Session closed: ${transport.sessionId}`);\n }\n };\n\n const sessionServer = this.createMcpServer();\n await sessionServer.connect(transport);\n } else {\n // Invalid request\n res.status(400).json({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: \"Bad Request: No valid session ID provided\",\n },\n id: null,\n });\n return;\n }\n\n // Run the request handler with the API key in context\n await runWithContext({ apiKey: context.apiKey, sessionId }, async () => {\n await context.transport.handleRequest(req, res, req.body);\n });\n });\n\n // Reusable handler for GET and DELETE requests\n const handleSessionRequest = async (req: Request, res: Response) => {\n const sessionId = req.headers[\"mcp-session-id\"] as string | undefined;\n if (!sessionId || !this.sessions[sessionId]) {\n res.status(400).send(\"Invalid or missing session ID\");\n return;\n }\n\n const context = this.sessions[sessionId];\n\n // Check for updated API key in headers\n const apiKeyManager = ApiKeyManager.getInstance();\n const requestApiKey = apiKeyManager.getApiKey(req, context.apiKey);\n if (requestApiKey) {\n context.apiKey = requestApiKey;\n }\n\n // Run the request handler with the API key in context\n await runWithContext({ apiKey: context.apiKey, sessionId }, async () => {\n await context.transport.handleRequest(req, res);\n });\n };\n\n // Handle GET requests for server-to-client notifications via SSE\n app.get(\"/mcp\", handleSessionRequest);\n\n // Handle DELETE requests for session termination\n app.delete(\"/mcp\", handleSessionRequest);\n\n const displayHost = host === \"0.0.0.0\" ? \"localhost\" : host;\n this.httpServer = app.listen(port, host, () => {\n Logger.log(`[${this.serverName}] HTTP server listening on ${host}:${port}`);\n Logger.log(`[${this.serverName}] MCP endpoint available at http://${displayHost}:${port}/mcp`);\n });\n }\n\n async startStdio(): Promise<void> {\n const transport = new StdioServerTransport();\n await this.connect(transport);\n }\n\n async stopHttpServer(): Promise<void> {\n if (!this.httpServer) {\n // Changed to Logger.warn and return, as throwing an error might be too harsh if called multiple times.\n Logger.error(`[${this.serverName}] HTTP server is not running or already stopped.`);\n return;\n }\n\n return new Promise((resolve, reject) => {\n this.httpServer!.close((err: Error | undefined) => {\n if (err) {\n Logger.error(`[${this.serverName}] Error stopping HTTP server:`, err);\n reject(err);\n return;\n }\n Logger.log(`[${this.serverName}] HTTP server stopped.`);\n this.httpServer = null;\n const closingSessions = Object.values(this.sessions).map((context) => {\n // Clean up session\n if (context.transport.sessionId) {\n delete this.sessions[context.transport.sessionId];\n }\n return Promise.resolve();\n });\n Promise.all(closingSessions)\n .then(() => {\n Logger.log(`[${this.serverName}] All transports closed.`);\n resolve();\n })\n .catch((transportCloseErr) => {\n // This catch might be redundant if individual transport close errors are handled\n Logger.error(`[${this.serverName}] Error during bulk transport closing:`, transportCloseErr);\n reject(transportCloseErr);\n });\n });\n });\n }\n}\n","import { Request } from \"express\";\n\nexport class ApiKeyManager {\n private static instance: ApiKeyManager;\n private defaultApiKey: string | undefined;\n\n private constructor() {\n // Initialize with environment variable or command-line provided key\n this.defaultApiKey = process.env.GOOGLE_MAPS_API_KEY;\n }\n\n public static getInstance(): ApiKeyManager {\n if (!ApiKeyManager.instance) {\n ApiKeyManager.instance = new ApiKeyManager();\n }\n return ApiKeyManager.instance;\n }\n\n /**\n * Set the default API key (from command line or environment)\n */\n public setDefaultApiKey(key: string): void {\n this.defaultApiKey = key;\n process.env.GOOGLE_MAPS_API_KEY = key;\n }\n\n /**\n * Get API key with priority:\n * 1. HTTP Header (X-Google-Maps-API-Key or Authorization: Bearer)\n * 2. Session-specific API key\n * 3. Default API key (command line or environment)\n */\n public getApiKey(req?: Request, sessionApiKey?: string): string | undefined {\n if (req) {\n // Check for API key in headers\n const headerApiKey = req.headers[\"x-google-maps-api-key\"] as string;\n if (headerApiKey) {\n return headerApiKey;\n }\n\n // Check for Bearer token in Authorization header\n const authHeader = req.headers[\"authorization\"] as string;\n if (authHeader && authHeader.startsWith(\"Bearer \")) {\n return authHeader.substring(7);\n }\n }\n\n // Use session-specific API key if available\n if (sessionApiKey) {\n return sessionApiKey;\n }\n\n // Fall back to default API key\n return this.defaultApiKey;\n }\n\n /**\n * Check if any API key is available\n */\n public hasApiKey(req?: Request, sessionApiKey?: string): boolean {\n return !!this.getApiKey(req, sessionApiKey);\n }\n\n /**\n * Validate API key format (basic validation)\n */\n public isValidApiKeyFormat(key: string): boolean {\n // Google Maps API keys are typically 39 characters long\n // and contain alphanumeric characters, hyphens, and underscores\n return /^[A-Za-z0-9_-]{20,50}$/.test(key);\n }\n}\n"],"mappings":"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","names":["z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","z","sessionId","resolve","yargs","tasks"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/tools/maps/searchNearby.ts","../src/utils/requestContext.ts","../src/tools/maps/placeDetails.ts","../src/tools/maps/geocode.ts","../src/tools/maps/reverseGeocode.ts","../src/tools/maps/distanceMatrix.ts","../src/tools/maps/directions.ts","../src/tools/maps/elevation.ts","../src/tools/maps/searchPlaces.ts","../src/tools/maps/timezone.ts","../src/tools/maps/weather.ts","../src/tools/maps/exploreArea.ts","../src/tools/maps/planRoute.ts","../src/tools/maps/comparePlaces.ts","../src/tools/maps/airQuality.ts","../src/tools/maps/staticMap.ts","../src/tools/maps/batchGeocode.ts","../src/tools/maps/searchAlongRoute.ts","../src/tools/maps/localRankTracker.ts","../src/config.ts","../src/core/BaseMcpServer.ts","../src/utils/apiKeyManager.ts","../src/utils/autoUpdate.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { config as dotenvConfig } from \"dotenv\";\nimport { resolve } from \"path\";\nimport yargs from \"yargs\";\nimport { hideBin } from \"yargs/helpers\";\nimport serverConfigs, { filterTools } from \"./config.js\";\nimport { BaseMcpServer } from \"./core/BaseMcpServer.js\";\nimport { Logger } from \"./index.js\";\nimport { PlacesSearcher } from \"./services/PlacesSearcher.js\";\nimport { fileURLToPath } from \"url\";\nimport { dirname } from \"path\";\nimport { readFileSync, writeFileSync, existsSync } from \"fs\";\nimport { createInterface } from \"readline\";\nimport { checkForUpdates } from \"./utils/autoUpdate.js\";\n\n// Get the directory of the current module\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// Try to load .env from current directory first, then from package directory\ndotenvConfig({ path: resolve(process.cwd(), \".env\") });\n// Also try to load from the package installation directory\ndotenvConfig({ path: resolve(__dirname, \"../.env\") });\n\nexport async function startServer(port?: number, apiKey?: string, host?: string): Promise<void> {\n // Override environment variables with CLI arguments if provided\n if (port) {\n process.env.MCP_SERVER_PORT = port.toString();\n }\n if (apiKey) {\n process.env.GOOGLE_MAPS_API_KEY = apiKey;\n }\n if (host) {\n process.env.MCP_SERVER_HOST = host;\n }\n\n Logger.log(\"🚀 Starting Google Maps MCP Server...\");\n Logger.log(\"📍 18 tools registered (set GOOGLE_MAPS_ENABLED_TOOLS to limit)\");\n Logger.log(\n \"ℹ️ Reminder: enable Places API (New) in https://console.cloud.google.com before using the new Place features.\"\n );\n Logger.log(\"\");\n\n const startPromises = serverConfigs.map(async (config) => {\n const portString = process.env[config.portEnvVar];\n if (!portString) {\n Logger.error(`⚠️ [${config.name}] Port environment variable ${config.portEnvVar} not set.`);\n Logger.log(`💡 Please set ${config.portEnvVar} in your .env file or use --port parameter.`);\n Logger.log(` Example: ${config.portEnvVar}=3000 or --port 3000`);\n return;\n }\n\n const serverPort = Number(portString);\n if (isNaN(serverPort) || serverPort <= 0) {\n Logger.error(`❌ [${config.name}] Invalid port number \"${portString}\" defined in ${config.portEnvVar}.`);\n return;\n }\n\n try {\n const server = new BaseMcpServer(config.name, filterTools(config.tools));\n const serverHost = process.env.MCP_SERVER_HOST || \"0.0.0.0\";\n Logger.log(`🔧 [${config.name}] Initializing MCP Server in HTTP mode on ${serverHost}:${serverPort}...`);\n await server.startHttpServer(serverPort, serverHost);\n const displayHost = serverHost === \"0.0.0.0\" ? \"localhost\" : serverHost;\n Logger.log(`✅ [${config.name}] MCP Server started successfully!`);\n Logger.log(` 🌐 Endpoint: http://${displayHost}:${serverPort}/mcp`);\n Logger.log(` 📚 Tools: ${config.tools.length} available`);\n } catch (error) {\n Logger.error(`❌ [${config.name}] Failed to start MCP Server on port ${serverPort}:`, error);\n }\n });\n\n await Promise.allSettled(startPromises);\n\n Logger.log(\"\");\n Logger.log(\"🎉 Server initialization completed!\");\n Logger.log(\"💡 Need help? Check the README.md for configuration details.\");\n}\n\n// --------------- Exec Mode ---------------\n\nexport const EXEC_TOOLS = [\n \"geocode\",\n \"reverse-geocode\",\n \"search-nearby\",\n \"search-places\",\n \"place-details\",\n \"directions\",\n \"distance-matrix\",\n \"elevation\",\n \"timezone\",\n \"weather\",\n \"explore-area\",\n \"plan-route\",\n \"compare-places\",\n \"air-quality\",\n \"static-map\",\n \"batch-geocode-tool\",\n \"search-along-route\",\n \"local-rank-tracker\",\n] as const;\n\ntype ExecFailureResponse = {\n success: false;\n error?: unknown;\n};\n\ninterface ExecOutput {\n write(chunk: string): unknown;\n}\n\ninterface ExecStreams {\n stdout: ExecOutput;\n stderr: ExecOutput;\n}\n\ntype ExecToolRunner = (toolName: string, params: any, apiKey: string) => Promise<unknown>;\n\nexport type DoctorCheck = {\n name: string;\n status: \"pass\" | \"fail\" | \"skip\";\n detail: string;\n};\n\nexport type DoctorReport = {\n success: boolean;\n version: string;\n live: boolean;\n checks: DoctorCheck[];\n};\n\ntype DoctorToolRunner = (toolName: string, params: any, apiKey: string) => Promise<unknown>;\n\nfunction isExecFailureResponse(result: unknown): result is ExecFailureResponse {\n return (\n typeof result === \"object\" &&\n result !== null &&\n \"success\" in result &&\n (result as { success?: unknown }).success === false\n );\n}\n\nfunction getExecFailureMessage(toolName: string, result: ExecFailureResponse): string {\n if (typeof result.error === \"string\" && result.error.trim().length > 0) {\n return result.error;\n }\n if (result.error !== undefined && result.error !== null) {\n return String(result.error);\n }\n return `Tool \"${toolName}\" returned a failure response`;\n}\n\nexport async function execTool(toolName: string, params: any, apiKey: string): Promise<any> {\n const searcher = new PlacesSearcher(apiKey);\n\n switch (toolName) {\n case \"geocode\":\n case \"maps_geocode\":\n return searcher.geocode(params.address);\n\n case \"reverse-geocode\":\n case \"maps_reverse_geocode\":\n return searcher.reverseGeocode(params.latitude, params.longitude);\n\n case \"search-nearby\":\n case \"search_nearby\":\n case \"maps_search_nearby\":\n return searcher.searchNearby(params);\n\n case \"search-places\":\n case \"maps_search_places\":\n return searcher.searchText({\n query: params.query,\n locationBias: params.locationBias,\n openNow: params.openNow,\n minRating: params.minRating,\n includedType: params.includedType,\n strictTypeFiltering: params.strictTypeFiltering,\n priceLevels: params.priceLevels,\n pageSize: params.pageSize,\n pageToken: params.pageToken,\n languageCode: params.languageCode,\n includeRaw: params.includeRaw,\n });\n\n case \"place-details\":\n case \"get_place_details\":\n case \"maps_place_details\":\n return searcher.getPlaceDetails(params.placeId, params.maxPhotos || 0, params.includeRaw || false);\n\n case \"directions\":\n case \"maps_directions\":\n return searcher.getDirections(\n params.origin,\n params.destination,\n params.mode,\n params.departure_time,\n params.arrival_time,\n params.avoid_tolls,\n params.avoid_highways\n );\n\n case \"distance-matrix\":\n case \"maps_distance_matrix\":\n return searcher.calculateDistanceMatrix(\n params.origins,\n params.destinations,\n params.mode,\n params.departure_time,\n params.avoid_tolls,\n params.avoid_highways\n );\n\n case \"elevation\":\n case \"maps_elevation\":\n return searcher.getElevation(params.locations);\n\n case \"timezone\":\n case \"maps_timezone\":\n return searcher.getTimezone(params.latitude, params.longitude, params.timestamp);\n\n case \"weather\":\n case \"maps_weather\":\n return searcher.getWeather(\n params.latitude,\n params.longitude,\n params.type,\n params.forecastDays,\n params.forecastHours\n );\n\n case \"explore-area\":\n case \"maps_explore_area\":\n return searcher.exploreArea(params);\n\n case \"plan-route\":\n case \"maps_plan_route\":\n return searcher.planRoute(params);\n\n case \"compare-places\":\n case \"maps_compare_places\":\n return searcher.comparePlaces(params);\n\n case \"air-quality\":\n case \"maps_air_quality\":\n return searcher.getAirQuality(\n params.latitude,\n params.longitude,\n params.includeHealthRecommendations,\n params.includePollutants\n );\n\n case \"static-map\":\n case \"maps_static_map\":\n return searcher.getStaticMap(params);\n\n case \"batch-geocode-tool\":\n case \"maps_batch_geocode\": {\n const results = await Promise.all(\n (params.addresses as string[]).map(async (address: string) => {\n try {\n const result = await searcher.geocode(address);\n return { address, ...result };\n } catch (error: any) {\n return { address, success: false, error: error.message };\n }\n })\n );\n const succeeded = results.filter((r) => r.success).length;\n return {\n success: true,\n data: { total: params.addresses.length, succeeded, failed: params.addresses.length - succeeded, results },\n };\n }\n\n case \"search-along-route\":\n case \"maps_search_along_route\":\n return searcher.searchAlongRoute(params);\n\n case \"local-rank-tracker\":\n case \"maps_local_rank_tracker\":\n return searcher.localRankTracker(params);\n\n default:\n throw new Error(`Unknown tool: ${toolName}. Available: ${EXEC_TOOLS.join(\", \")}`);\n }\n}\n\n/**\n * Run an exec-mode tool and route its result to the appropriate stream.\n *\n * Service methods report API failures as `{ success: false, error }` rather\n * than throwing. Treat those responses as command failures so scripts can\n * rely on the exit code while successful responses remain machine-readable\n * JSON on stdout.\n */\nexport async function runExecCommand(\n toolName: string,\n params: any,\n apiKey: string,\n runner: ExecToolRunner = execTool,\n streams: ExecStreams = { stdout: process.stdout, stderr: process.stderr }\n): Promise<number> {\n try {\n const result = await runner(toolName, params, apiKey);\n if (isExecFailureResponse(result)) {\n streams.stderr.write(JSON.stringify({ error: getExecFailureMessage(toolName, result) }, null, 2) + \"\\n\");\n return 1;\n }\n\n streams.stdout.write(JSON.stringify(result, null, 2) + \"\\n\");\n return 0;\n } catch (error: unknown) {\n streams.stderr.write(\n JSON.stringify({ error: error instanceof Error ? error.message : String(error) }, null, 2) + \"\\n\"\n );\n return 1;\n }\n}\n\n/**\n * Check whether the standalone CLI is ready for Skill-driven use. Local mode\n * performs no Google API requests. Live mode makes three small requests so it\n * can distinguish Geocoding, Places (New), and Routes API availability.\n */\nexport async function runDoctor(\n packageVersion: string,\n apiKey: string | undefined,\n live = false,\n runner: DoctorToolRunner = execTool\n): Promise<DoctorReport> {\n const nodeMajor = Number.parseInt(process.versions.node.split(\".\")[0] ?? \"0\", 10);\n const checks: DoctorCheck[] = [\n {\n name: \"node\",\n status: nodeMajor >= 18 ? \"pass\" : \"fail\",\n detail: `Node.js ${process.versions.node} detected; version 18 or newer is required.`,\n },\n {\n name: \"package\",\n status: packageVersion !== \"0.0.0\" ? \"pass\" : \"fail\",\n detail:\n packageVersion !== \"0.0.0\"\n ? `mcp-google-map ${packageVersion} is available.`\n : \"Could not read the installed package version.\",\n },\n {\n name: \"api-key\",\n status: apiKey ? \"pass\" : \"fail\",\n detail: apiKey\n ? \"GOOGLE_MAPS_API_KEY is configured (value hidden).\"\n : \"GOOGLE_MAPS_API_KEY is not configured. Set it in the environment before making API calls.\",\n },\n ];\n\n if (!live) {\n checks.push({\n name: \"live-api\",\n status: \"skip\",\n detail: \"Live API checks were not requested; no Google Maps API calls were made.\",\n });\n } else if (!apiKey) {\n checks.push({\n name: \"live-api\",\n status: \"skip\",\n detail: \"Live API checks require GOOGLE_MAPS_API_KEY.\",\n });\n } else {\n const liveChecks = [\n { name: \"geocoding-api\", tool: \"geocode\", params: { address: \"Tokyo Tower\" } },\n { name: \"places-api-new\", tool: \"search-places\", params: { query: \"Tokyo Tower\" } },\n {\n name: \"routes-api\",\n tool: \"directions\",\n params: { origin: \"Tokyo Tower\", destination: \"Tokyo Station\", mode: \"walking\" },\n },\n ];\n\n for (const check of liveChecks) {\n try {\n const result = await runner(check.tool, check.params, apiKey);\n if (isExecFailureResponse(result)) {\n checks.push({\n name: check.name,\n status: \"fail\",\n detail: getExecFailureMessage(check.tool, result),\n });\n } else {\n checks.push({\n name: check.name,\n status: \"pass\",\n detail: `${check.name} request succeeded.`,\n });\n }\n } catch (error: unknown) {\n checks.push({\n name: check.name,\n status: \"fail\",\n detail: error instanceof Error ? error.message : String(error),\n });\n }\n }\n }\n\n return {\n success: checks.every((check) => check.status !== \"fail\"),\n version: packageVersion,\n live,\n checks,\n };\n}\n\n// --------------- Entry Point ---------------\n\n// Check if this script is being run directly\nconst isRunDirectly =\n process.argv[1] &&\n (process.argv[1].endsWith(\"cli.ts\") ||\n process.argv[1].endsWith(\"cli.js\") ||\n process.argv[1].endsWith(\"mcp-google-map\") ||\n process.argv[1].includes(\"mcp-google-map\"));\n\nconst isMainModule = import.meta.url === `file://${process.argv[1]}`;\n\nif (isRunDirectly || isMainModule) {\n let packageVersion = \"0.0.0\";\n try {\n const packageJsonPath = resolve(__dirname, \"../package.json\");\n const packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\"));\n packageVersion = packageJson.version;\n } catch (e) {\n packageVersion = \"0.0.0\";\n }\n\n yargs(hideBin(process.argv))\n .command(\n \"doctor\",\n \"Check standalone CLI readiness without starting an MCP server\",\n (yargs) =>\n yargs\n .option(\"live\", {\n type: \"boolean\",\n default: false,\n description: \"Make billable test requests to Geocoding, Places (New), and Routes APIs\",\n })\n .option(\"apikey\", {\n alias: \"k\",\n type: \"string\",\n description: \"Google Maps API key (prefer GOOGLE_MAPS_API_KEY to avoid shell history exposure)\",\n default: process.env.GOOGLE_MAPS_API_KEY,\n })\n .example([\n [\"$0 doctor\", \"Check local runtime and API key configuration without network calls\"],\n [\"$0 doctor --live\", \"Also verify three Google Maps APIs with billable requests\"],\n ]),\n async (argv) => {\n const report = await runDoctor(packageVersion, argv.apikey as string | undefined, argv.live as boolean);\n process.stdout.write(JSON.stringify(report, null, 2) + \"\\n\");\n process.exitCode = report.success ? 0 : 1;\n }\n )\n .command(\n \"exec <tool> [params]\",\n \"Execute a tool directly and output JSON\",\n (yargs) => {\n return yargs\n .positional(\"tool\", {\n type: \"string\",\n describe: `Tool name: ${EXEC_TOOLS.join(\", \")}`,\n })\n .positional(\"params\", {\n type: \"string\",\n describe: \"JSON parameters string\",\n })\n .option(\"apikey\", {\n alias: \"k\",\n type: \"string\",\n description: \"Google Maps API key\",\n default: process.env.GOOGLE_MAPS_API_KEY,\n })\n .example([\n ['$0 exec geocode \\'{\"address\":\"Tokyo Tower\"}\\'', \"Geocode an address\"],\n [\n '$0 exec search-nearby \\'{\"center\":{\"value\":\"35.68,139.74\",\"isCoordinates\":true},\"keyword\":\"restaurant\"}\\'',\n \"Search nearby\",\n ],\n ['$0 exec search-places \\'{\"query\":\"ramen in Tokyo\"}\\'', \"Text search\"],\n ]);\n },\n async (argv) => {\n if (!argv.apikey) {\n process.stderr.write(\n JSON.stringify(\n {\n error: \"GOOGLE_MAPS_API_KEY not set. Use --apikey or set GOOGLE_MAPS_API_KEY environment variable.\",\n },\n null,\n 2\n ) + \"\\n\"\n );\n process.exitCode = 1;\n return;\n }\n try {\n const params = argv.params ? JSON.parse(argv.params as string) : {};\n process.exitCode = await runExecCommand(argv.tool as string, params, argv.apikey as string);\n } catch (error: any) {\n process.stderr.write(JSON.stringify({ error: error.message }, null, 2) + \"\\n\");\n process.exitCode = 1;\n }\n }\n )\n .command(\n \"batch-geocode\",\n \"Geocode multiple addresses from a file (one address per line)\",\n (yargs) => {\n return yargs\n .option(\"input\", {\n alias: \"i\",\n type: \"string\",\n describe: \"Input file path (one address per line). Use - for stdin.\",\n demandOption: true,\n })\n .option(\"output\", {\n alias: \"o\",\n type: \"string\",\n describe: \"Output file path (JSON). Defaults to stdout.\",\n })\n .option(\"concurrency\", {\n alias: \"c\",\n type: \"number\",\n describe: \"Max parallel requests\",\n default: 20,\n })\n .option(\"apikey\", {\n alias: \"k\",\n type: \"string\",\n description: \"Google Maps API key\",\n default: process.env.GOOGLE_MAPS_API_KEY,\n })\n .example([\n [\"$0 batch-geocode -i addresses.txt\", \"Geocode to stdout\"],\n [\"$0 batch-geocode -i addresses.txt -o results.json\", \"Geocode to file\"],\n [\"cat addresses.txt | $0 batch-geocode -i -\", \"Geocode from stdin\"],\n ]);\n },\n async (argv) => {\n if (!argv.apikey) {\n console.error(\"Error: GOOGLE_MAPS_API_KEY not set. Use --apikey or set env var.\");\n process.exit(1);\n }\n\n // Read addresses\n let lines: string[];\n if (argv.input === \"-\") {\n // Read from stdin\n const rl = createInterface({ input: process.stdin });\n lines = [];\n for await (const line of rl) {\n const trimmed = line.trim();\n if (trimmed) lines.push(trimmed);\n }\n } else {\n if (!existsSync(argv.input as string)) {\n console.error(`Error: File not found: ${argv.input}`);\n process.exit(1);\n }\n lines = readFileSync(argv.input as string, \"utf-8\")\n .split(\"\\n\")\n .map((l) => l.trim())\n .filter((l) => l.length > 0);\n }\n\n if (lines.length === 0) {\n console.error(\"Error: No addresses found in input.\");\n process.exit(1);\n }\n\n const searcher = new PlacesSearcher(argv.apikey as string);\n const concurrency = Math.min(Math.max(argv.concurrency as number, 1), 50);\n const results: any[] = [];\n let completed = 0;\n\n // Process with concurrency limit\n const semaphore = async (tasks: (() => Promise<void>)[], limit: number) => {\n const executing: Promise<void>[] = [];\n for (const task of tasks) {\n const p = task().then(() => {\n executing.splice(executing.indexOf(p), 1);\n });\n executing.push(p);\n if (executing.length >= limit) {\n await Promise.race(executing);\n }\n }\n await Promise.all(executing);\n };\n\n const tasks = lines.map((address, index) => async () => {\n try {\n const result = await searcher.geocode(address);\n results[index] = { address, ...result };\n } catch (error: any) {\n results[index] = { address, success: false, error: error.message };\n }\n completed++;\n if (!argv.output) return; // Don't log progress when outputting to stdout\n process.stderr.write(`\\r ${completed}/${lines.length} geocoded`);\n });\n\n await semaphore(tasks, concurrency);\n\n if (argv.output) {\n process.stderr.write(\"\\n\");\n }\n\n // Summary\n const succeeded = results.filter((r) => r.success).length;\n const failed = results.filter((r) => !r.success).length;\n const summary = { total: lines.length, succeeded, failed, results };\n\n const json = JSON.stringify(summary, null, 2);\n\n if (argv.output) {\n writeFileSync(argv.output as string, json, \"utf-8\");\n console.error(`Done: ${succeeded}/${lines.length} succeeded. Output: ${argv.output}`);\n } else {\n console.log(json);\n }\n\n process.exit(failed > 0 ? 1 : 0);\n }\n )\n .command(\n \"$0\",\n \"Start the MCP server (HTTP by default, --stdio for stdio mode)\",\n (yargs) => {\n return yargs\n .option(\"port\", {\n alias: \"p\",\n type: \"number\",\n description: \"Port to run the MCP server on\",\n default: process.env.MCP_SERVER_PORT ? parseInt(process.env.MCP_SERVER_PORT) : 3000,\n })\n .option(\"host\", {\n type: \"string\",\n description: \"Hostname to bind the server to (e.g. 0.0.0.0 for all interfaces)\",\n default: process.env.MCP_SERVER_HOST || \"0.0.0.0\",\n })\n .option(\"apikey\", {\n alias: \"k\",\n type: \"string\",\n description: \"Google Maps API key\",\n default: process.env.GOOGLE_MAPS_API_KEY,\n })\n .option(\"stdio\", {\n type: \"boolean\",\n description: \"Use stdio transport instead of HTTP\",\n default: false,\n })\n .example([\n [\"$0\", \"Start HTTP server with default settings\"],\n ['$0 --port 3000 --apikey \"your_api_key\"', \"Start HTTP with custom port and API key\"],\n [\"$0 --host 0.0.0.0 --port 3000\", \"Start HTTP accessible from all interfaces\"],\n [\"$0 --stdio\", \"Start in stdio mode (for Claude Desktop, Cursor, etc.)\"],\n ]);\n },\n async (argv) => {\n if (argv.apikey) {\n process.env.GOOGLE_MAPS_API_KEY = argv.apikey as string;\n }\n\n // Automatic update check (enabled by default). Fire-and-forget so it\n // never blocks startup; failures are logged to stderr only.\n void checkForUpdates({ currentVersion: packageVersion }).catch(() => undefined);\n\n const tools = filterTools(serverConfigs[0].tools);\n\n if (argv.stdio) {\n // stdio mode — all logs go to stderr, stdout reserved for JSON-RPC\n const server = new BaseMcpServer(serverConfigs[0].name, tools);\n await server.startStdio();\n } else {\n // HTTP mode\n Logger.log(\"🗺️ Google Maps MCP Server\");\n Logger.log(\" A Model Context Protocol server for Google Maps services\");\n Logger.log(\"\");\n\n if (!argv.apikey) {\n Logger.log(\"⚠️ Google Maps API Key not found!\");\n Logger.log(\" Please provide --apikey parameter or set GOOGLE_MAPS_API_KEY in your .env file\");\n Logger.log(\"\");\n }\n\n startServer(argv.port as number, argv.apikey as string, argv.host as string).catch((error) => {\n Logger.error(\"❌ Failed to start server:\", error);\n process.exit(1);\n });\n }\n }\n )\n .version(packageVersion)\n .alias(\"version\", \"v\")\n .help()\n .parse();\n}\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_search_nearby\";\nconst DESCRIPTION =\n \"Find places near a specific location by type (e.g., restaurants, cafes, hotels). Use when the user wants to discover what's around a given address or coordinates, such as 'find coffee shops near Times Square' or 'what hotels are near the airport'. Supports filtering by place type, search radius, minimum rating, and whether currently open.\";\n\nconst SCHEMA = {\n center: z\n .object({\n value: z.string().describe(\"Address, landmark name, or coordinates (coordinate format: lat,lng)\"),\n isCoordinates: z.boolean().default(false).describe(\"Whether the value is coordinates\"),\n })\n .describe(\"Search center point (e.g. value: 49.3268778,-123.0585982, isCoordinates: true)\"),\n keyword: z\n .string()\n .optional()\n .describe(\"Place type to search for (e.g., restaurant, cafe, hotel, gas_station, hospital)\"),\n radius: z.number().default(1000).describe(\"Search radius in meters\"),\n openNow: z.boolean().default(false).describe(\"Only show places that are currently open\"),\n minRating: z.number().min(0).max(5).optional().describe(\"Minimum rating requirement (0-5)\"),\n};\n\nexport type SearchNearbyParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: SearchNearbyParams): Promise<{ content: any[]; isError?: boolean }> {\n try {\n // Create a new PlacesSearcher instance with the current request's API key\n const apiKey = getCurrentApiKey();\n const placesSearcher = new PlacesSearcher(apiKey);\n const result = await placesSearcher.searchNearby(params);\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Search failed\" }],\n isError: true,\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: `location: ${JSON.stringify(result.location, null, 2)}\\n` + JSON.stringify(result.data, null, 2),\n },\n ],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error searching nearby places: ${errorMessage}` }],\n };\n }\n}\n\nexport const SearchNearby = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { AsyncLocalStorage } from \"node:async_hooks\";\n\ninterface RequestContext {\n apiKey?: string;\n sessionId?: string;\n}\n\n// Create AsyncLocalStorage instance to track request context\nexport const requestContextStorage = new AsyncLocalStorage<RequestContext>();\n\n/**\n * Get the current request's API key\n */\nexport function getCurrentApiKey(): string | undefined {\n const context = requestContextStorage.getStore();\n return context?.apiKey || process.env.GOOGLE_MAPS_API_KEY;\n}\n\n/**\n * Run a function with a specific request context\n */\nexport function runWithContext<T>(context: RequestContext, fn: () => T | Promise<T>): T | Promise<T> {\n return requestContextStorage.run(context, fn);\n}\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_place_details\";\nconst DESCRIPTION =\n \"Get comprehensive details for a specific place using its Google Maps place_id. Use after search_nearby or maps_search_places to get reviews, phone, website, and hours. Includes priceRange (raw Money structure: startPrice/endPrice with currencyCode/units/nanos), businessStatus, types and both regular and current opening hours. Reviews, photos, and AI summaries include source/disclosure metadata that must accompany end-user display. Set maxPhotos (1-10) to include photo URLs; omit or set 0 for none. Set includeRaw to attach the original Places API payload (raw_place) for API-verified validation.\";\n\nconst SCHEMA = {\n placeId: z.string().describe(\"Google Maps place ID\"),\n maxPhotos: z\n .number()\n .int()\n .min(0)\n .max(10)\n .optional()\n .describe(\"Number of photo URLs to include (0 = none, max 10). Omit to skip photos and save tokens.\"),\n includeRaw: z\n .boolean()\n .optional()\n .describe(\n \"Include the original Places API payload (raw_place) alongside the interpreted fields, for API-verified validation\"\n ),\n};\n\nexport type PlaceDetailsParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n const apiKey = getCurrentApiKey();\n const placesSearcher = new PlacesSearcher(apiKey);\n const result = await placesSearcher.getPlaceDetails(params.placeId, params.maxPhotos || 0, params.includeRaw || false);\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Failed to get place details\" }],\n isError: true,\n };\n }\n\n const payload: Record<string, any> = { ...result.data };\n if (result.fieldMask) payload.field_mask = result.fieldMask;\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(payload, null, 2),\n },\n ],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error getting place details: ${errorMessage}` }],\n };\n }\n}\n\nexport const PlaceDetails = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_geocode\";\nconst DESCRIPTION =\n \"Convert an address, city name, or landmark into GPS coordinates (latitude/longitude). Use when you need coordinates for a location described in text — for example, to provide a center point for search_nearby or a starting point for maps_directions.\";\n\nconst SCHEMA = {\n address: z.string().describe(\"Address or place name to convert to coordinates\"),\n};\n\nexport type GeocodeParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n // Create a new PlacesSearcher instance with the current request's API key\n const apiKey = getCurrentApiKey();\n const placesSearcher = new PlacesSearcher(apiKey);\n const result = await placesSearcher.geocode(params.address);\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Failed to geocode address\" }],\n isError: true,\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(result.data, null, 2),\n },\n ],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error geocoding address: ${errorMessage}` }],\n };\n }\n}\n\nexport const Geocode = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_reverse_geocode\";\nconst DESCRIPTION =\n \"Convert GPS coordinates (latitude/longitude) into a human-readable street address. Use when you have coordinates from another tool's output or a user's shared location and need the actual address.\";\n\nconst SCHEMA = {\n latitude: z.number().describe(\"Latitude coordinate\"),\n longitude: z.number().describe(\"Longitude coordinate\"),\n};\n\nexport type ReverseGeocodeParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n // Create a new PlacesSearcher instance with the current request's API key\n const apiKey = getCurrentApiKey();\n const placesSearcher = new PlacesSearcher(apiKey);\n const result = await placesSearcher.reverseGeocode(params.latitude, params.longitude);\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Failed to reverse geocode coordinates\" }],\n isError: true,\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(result.data, null, 2),\n },\n ],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error reverse geocoding: ${errorMessage}` }],\n };\n }\n}\n\nexport const ReverseGeocode = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_distance_matrix\";\nconst DESCRIPTION =\n \"Calculate travel distances and durations between multiple origins and destinations in a single request. Use for comparing travel options — e.g., 'which hotel is closest to the office?' or batch distance calculations. Supports driving, walking, bicycling, and transit modes.\";\n\nconst SCHEMA = {\n origins: z.array(z.string()).describe(\"List of origin addresses or coordinates\"),\n destinations: z.array(z.string()).describe(\"List of destination addresses or coordinates\"),\n mode: z\n .enum([\"driving\", \"walking\", \"bicycling\", \"transit\"])\n .default(\"driving\")\n .describe(\"Travel mode for calculation\"),\n departure_time: z\n .string()\n .optional()\n .describe(\n \"Departure time in ISO 8601 format (e.g. 2026-03-21T09:00:00Z). Enables traffic-aware duration estimates.\"\n ),\n avoid_tolls: z\n .boolean()\n .optional()\n .describe('Avoid toll roads where reasonable. Only supported with mode \"driving\".'),\n avoid_highways: z\n .boolean()\n .optional()\n .describe('Avoid highways where reasonable. Only supported with mode \"driving\".'),\n};\n\nexport type DistanceMatrixParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n // Create a new PlacesSearcher instance with the current request's API key\n const apiKey = getCurrentApiKey();\n const placesSearcher = new PlacesSearcher(apiKey);\n const result = await placesSearcher.calculateDistanceMatrix(\n params.origins,\n params.destinations,\n params.mode,\n params.departure_time,\n params.avoid_tolls,\n params.avoid_highways\n );\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Failed to calculate distance matrix\" }],\n isError: true,\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(result.data, null, 2),\n },\n ],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error calculating distance matrix: ${errorMessage}` }],\n };\n }\n}\n\nexport const DistanceMatrix = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_directions\";\nconst DESCRIPTION =\n \"Get step-by-step navigation directions between two points with route details. Use when the user asks 'how do I get from A to B?' and needs the route summary, total distance, estimated travel time, or turn-by-turn instructions. Supports departure/arrival times and multiple travel modes.\";\n\nconst SCHEMA = {\n origin: z.string().describe(\"Starting point address or coordinates\"),\n destination: z.string().describe(\"Destination address or coordinates\"),\n mode: z\n .enum([\"driving\", \"walking\", \"bicycling\", \"transit\"])\n .default(\"driving\")\n .describe(\"Travel mode for directions\"),\n departure_time: z.string().optional().describe(\"Departure time (ISO string format)\"),\n arrival_time: z.string().optional().describe(\"Arrival time (ISO string format)\"),\n avoid_tolls: z\n .boolean()\n .optional()\n .describe('Avoid toll roads where reasonable. Only supported with mode \"driving\".'),\n avoid_highways: z\n .boolean()\n .optional()\n .describe('Avoid highways where reasonable. Only supported with mode \"driving\".'),\n};\n\nexport type DirectionsParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n // Create a new PlacesSearcher instance with the current request's API key\n const apiKey = getCurrentApiKey();\n const placesSearcher = new PlacesSearcher(apiKey);\n const result = await placesSearcher.getDirections(\n params.origin,\n params.destination,\n params.mode,\n params.departure_time,\n params.arrival_time,\n params.avoid_tolls,\n params.avoid_highways\n );\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Failed to get directions\" }],\n isError: true,\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(result.data, null, 2),\n },\n ],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error getting directions: ${errorMessage}` }],\n };\n }\n}\n\nexport const Directions = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_elevation\";\nconst DESCRIPTION =\n \"Get elevation (meters above sea level) for geographic coordinates. Use when the user asks 'how high is this place', 'is this area flood-prone', or needs altitude for hiking/cycling route profiles. Also useful for real estate risk assessment — low elevation near water suggests flood risk.\";\n\nconst SCHEMA = {\n locations: z\n .array(\n z.object({\n latitude: z.number().describe(\"Latitude coordinate\"),\n longitude: z.number().describe(\"Longitude coordinate\"),\n })\n )\n .describe(\"List of locations to get elevation data for\"),\n};\n\nexport type ElevationParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n // Create a new PlacesSearcher instance with the current request's API key\n const apiKey = getCurrentApiKey();\n const placesSearcher = new PlacesSearcher(apiKey);\n const result = await placesSearcher.getElevation(params.locations);\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Failed to get elevation data\" }],\n isError: true,\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(result.data, null, 2),\n },\n ],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error getting elevation data: ${errorMessage}` }],\n };\n }\n}\n\nexport const Elevation = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_search_places\";\nconst DESCRIPTION =\n \"Search for places using a free-text query like 'sushi restaurants in Tokyo' or 'best coffee shops near Central Park'. More flexible than search_nearby — supports natural language queries, optional location bias, server-side rating and cumulative price-level filters (Places API Text Search priceLevels enum), strict type filtering, and open-now filtering. Returns place details including priceRange (raw Money structure), types, businessStatus, rating, userRatingCount and opening hours. Supports pageSize/pageToken pagination (up to 20 per page) and an optional includeRaw mode that attaches the original Places API payload for API-verified validation.\";\n\nconst PRICE_LEVELS = [\n \"PRICE_LEVEL_FREE\",\n \"PRICE_LEVEL_INEXPENSIVE\",\n \"PRICE_LEVEL_MODERATE\",\n \"PRICE_LEVEL_EXPENSIVE\",\n \"PRICE_LEVEL_VERY_EXPENSIVE\",\n] as const;\n\nconst SCHEMA = {\n query: z.string().describe(\"Text search query (e.g., 'Italian restaurants in Manhattan', 'hotels near Taipei 101')\"),\n locationBias: z\n .object({\n latitude: z.number().describe(\"Latitude to bias results toward\"),\n longitude: z.number().describe(\"Longitude to bias results toward\"),\n radius: z.number().optional().describe(\"Bias radius in meters (default: 5000)\"),\n })\n .optional()\n .describe(\"Optional location to bias results toward\"),\n openNow: z.boolean().optional().describe(\"Only return places that are currently open (server-side filter)\"),\n minRating: z.number().optional().describe(\"Minimum rating filter (1.0 - 5.0), applied server-side by the API\"),\n includedType: z\n .string()\n .optional()\n .describe(\n \"Filter by a single place type (e.g., restaurant, cafe, bakery). Text Search supports exactly one includedType per call\"\n ),\n strictTypeFiltering: z\n .boolean()\n .optional()\n .describe(\n \"Strict type filtering: if true, only results of the same type as includedType are returned (default: loose interpretation)\"\n ),\n priceLevels: z\n .array(z.enum(PRICE_LEVELS))\n .optional()\n .describe(\n 'Server-side economic filter. Pass ALL allowed levels cumulatively up to the budget cap, e.g. budget 30 EUR -> [\"PRICE_LEVEL_INEXPENSIVE\", \"PRICE_LEVEL_MODERATE\"]. Do not include PRICE_LEVEL_FREE'\n ),\n pageSize: z\n .number()\n .int()\n .min(1)\n .max(20)\n .optional()\n .describe(\"Number of results per page (1-20). Use nextPageToken from the response to fetch further pages (up to 60 total)\"),\n pageToken: z\n .string()\n .optional()\n .describe(\"nextPageToken returned by a previous maps_search_places call, to retrieve the next page of results\"),\n languageCode: z.string().optional().describe(\"Language code for results (e.g., 'en', 'it', 'ja')\"),\n includeRaw: z\n .boolean()\n .optional()\n .describe(\n \"Include the original Places API payload: each result gets a raw_place field and the full raw_response is returned (for API-verified validation)\"\n ),\n};\n\nexport type SearchPlacesParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n const apiKey = getCurrentApiKey();\n const placesSearcher = new PlacesSearcher(apiKey);\n const result = await placesSearcher.searchText({\n query: params.query,\n locationBias: params.locationBias,\n openNow: params.openNow,\n minRating: params.minRating,\n includedType: params.includedType,\n strictTypeFiltering: params.strictTypeFiltering,\n priceLevels: params.priceLevels,\n pageSize: params.pageSize,\n pageToken: params.pageToken,\n languageCode: params.languageCode,\n includeRaw: params.includeRaw,\n });\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Failed to search places\" }],\n isError: true,\n };\n }\n\n const payload: Record<string, any> = {\n results: result.data,\n };\n if (result.nextPageToken) payload.nextPageToken = result.nextPageToken;\n if (result.fieldMask) payload.field_mask = result.fieldMask;\n if (params.includeRaw && result.raw_response) payload.raw_response = result.raw_response;\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(payload, null, 2),\n },\n ],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error searching places: ${errorMessage}` }],\n };\n }\n}\n\nexport const SearchPlaces = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_timezone\";\nconst DESCRIPTION =\n \"Get the timezone and current local time for a location. Use when the user asks 'what time is it in Tokyo', needs to coordinate a meeting across timezones, or is planning travel across timezone boundaries. Returns timezone ID, UTC/DST offsets, and computed local time.\";\n\nconst SCHEMA = {\n latitude: z.number().describe(\"Latitude coordinate\"),\n longitude: z.number().describe(\"Longitude coordinate\"),\n timestamp: z\n .number()\n .optional()\n .describe(\"Unix timestamp in ms to query timezone at a specific moment (defaults to now)\"),\n};\n\nexport type TimezoneParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n const apiKey = getCurrentApiKey();\n const placesSearcher = new PlacesSearcher(apiKey);\n const result = await placesSearcher.getTimezone(params.latitude, params.longitude, params.timestamp);\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Failed to get timezone data\" }],\n isError: true,\n };\n }\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(result.data, null, 2) }],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error getting timezone: ${errorMessage}` }],\n };\n }\n}\n\nexport const Timezone = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_weather\";\nconst DESCRIPTION =\n \"Get weather for a location — current conditions, daily forecast (10 days), or hourly forecast (240 hours). Use when the user asks 'what's the weather in Paris', is planning outdoor activities, or needs to pack for a trip. Coverage: most regions supported, but China, Japan, South Korea, Cuba, Iran, North Korea, Syria are unavailable.\";\n\nconst SCHEMA = {\n latitude: z.number().describe(\"Latitude coordinate\"),\n longitude: z.number().describe(\"Longitude coordinate\"),\n type: z\n .enum([\"current\", \"forecast_daily\", \"forecast_hourly\"])\n .optional()\n .describe(\"current = right now, forecast_daily = multi-day outlook, forecast_hourly = hour-by-hour\"),\n forecastDays: z.number().optional().describe(\"Number of forecast days (1-10, only for forecast_daily, default: 5)\"),\n forecastHours: z\n .number()\n .optional()\n .describe(\"Number of forecast hours (1-240, only for forecast_hourly, default: 24)\"),\n};\n\nexport type WeatherParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n const apiKey = getCurrentApiKey();\n const placesSearcher = new PlacesSearcher(apiKey);\n const result = await placesSearcher.getWeather(\n params.latitude,\n params.longitude,\n params.type || \"current\",\n params.forecastDays,\n params.forecastHours\n );\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Failed to get weather data\" }],\n isError: true,\n };\n }\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(result.data, null, 2) }],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error getting weather: ${errorMessage}` }],\n };\n }\n}\n\nexport const Weather = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_explore_area\";\nconst DESCRIPTION =\n \"Explore what's around a location in one call — searches multiple place types, gets details for the top results, and returns a categorized summary. Use when the user asks 'what's around here', 'explore the area near my hotel', or needs a quick overview of a neighborhood. Replaces the manual chain of geocode → search-nearby → place-details. For trip planning: use search_places first to get geographically spread anchor points, then call this tool around each anchor (e.g. 'Gion, Kyoto') — never pass just the city name, as it clusters all results in one area. After results, call static_map to visualize.\";\n\nconst SCHEMA = {\n location: z.string().describe(\"Address or landmark to explore around\"),\n types: z\n .array(z.string())\n .optional()\n .describe(\n \"Place types to search (default: restaurant, cafe, tourist_attraction). Must be Places API (New) type names. Examples: hotel, bar, park, museum\"\n ),\n radius: z.number().optional().describe(\"Search radius in meters (default: 1000)\"),\n topN: z.number().optional().describe(\"Number of top results per type to get details for (default: 3)\"),\n};\n\nexport type ExploreAreaParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n const apiKey = getCurrentApiKey();\n const searcher = new PlacesSearcher(apiKey);\n const result = await searcher.exploreArea(params);\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(result.data, null, 2) }],\n isError: false,\n };\n } catch (error: any) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error exploring area: ${error.message}` }],\n };\n }\n}\n\nexport const ExploreArea = { NAME, DESCRIPTION, SCHEMA, ACTION };\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_plan_route\";\nconst DESCRIPTION =\n \"Plan an optimized multi-stop route in one call — geocodes all stops, uses Routes API waypoint optimization (2 to 25 intermediate stops) to find the most efficient visit order, and returns directions for each leg. Use when the user says 'visit these 5 places efficiently', 'plan a route through A, B, C', or needs a multi-stop itinerary. Replaces the manual chain of geocode → distance-matrix → directions. Waypoint optimization requires at least 4 stops (2 intermediates); with 2 or 3 stops the route is returned in the original order. For multi-day trips: create one plan_route call per day with stops that follow a geographic arc (e.g. east→west) rather than mixing distant areas. After results, call static_map to visualize the route.\";\n\nconst SCHEMA = {\n stops: z.array(z.string()).min(2).describe(\"List of addresses or landmarks to visit (minimum 2)\"),\n mode: z.enum([\"driving\", \"walking\", \"bicycling\", \"transit\"]).optional().describe(\"Travel mode (default: driving)\"),\n optimize: z\n .boolean()\n .optional()\n .describe(\n \"Auto-optimize visit order via Routes API waypoint optimization (default: true). Requires at least 4 stops (2 intermediates) — ignored for 2-3 stops. Set false to keep original order. Not available for transit mode.\"\n ),\n departure_time: z\n .string()\n .optional()\n .describe(\"Departure time in ISO 8601 format (e.g. 2026-03-21T09:00:00Z). Enables traffic-aware routing.\"),\n avoid_tolls: z\n .boolean()\n .optional()\n .describe('Avoid toll roads where reasonable. Only supported with mode \"driving\".'),\n avoid_highways: z\n .boolean()\n .optional()\n .describe('Avoid highways where reasonable. Only supported with mode \"driving\".'),\n};\n\nexport type PlanRouteParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n const apiKey = getCurrentApiKey();\n const searcher = new PlacesSearcher(apiKey);\n const result = await searcher.planRoute(params);\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(result.data, null, 2) }],\n isError: false,\n };\n } catch (error: any) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error planning route: ${error.message}` }],\n };\n }\n}\n\nexport const PlanRoute = { NAME, DESCRIPTION, SCHEMA, ACTION };\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_compare_places\";\nconst DESCRIPTION =\n \"Compare multiple places side-by-side in one call — searches by query, gets details for each result, and optionally calculates distance from your location. Use when the user asks 'which restaurant should I pick', 'compare these hotels', or needs a decision table. Replaces the manual chain of search-places → place-details → distance-matrix.\";\n\nconst SCHEMA = {\n query: z.string().describe(\"Search query (e.g., 'ramen near Shibuya', 'hotels in Taipei')\"),\n userLocation: z\n .object({\n latitude: z.number().describe(\"Your latitude\"),\n longitude: z.number().describe(\"Your longitude\"),\n })\n .optional()\n .describe(\"Your current location — if provided, adds distance and drive time to each result\"),\n limit: z.number().optional().describe(\"Max places to compare (default: 5)\"),\n};\n\nexport type ComparePlacesParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n const apiKey = getCurrentApiKey();\n const searcher = new PlacesSearcher(apiKey);\n const result = await searcher.comparePlaces(params);\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(result.data, null, 2) }],\n isError: false,\n };\n } catch (error: any) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error comparing places: ${error.message}` }],\n };\n }\n}\n\nexport const ComparePlaces = { NAME, DESCRIPTION, SCHEMA, ACTION };\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_air_quality\";\nconst DESCRIPTION =\n \"Get air quality for a location — AQI index, pollutant concentrations, and health recommendations by demographic group (elderly, children, athletes, pregnant women, etc.). Use when the user asks 'is the air safe', 'should I wear a mask', 'good for outdoor exercise', or is planning travel for someone with respiratory/heart conditions. Coverage: global including Japan (unlike weather). Returns both universal AQI and local index (EPA for US, AEROS for Japan, etc.).\";\n\nconst SCHEMA = {\n latitude: z.number().describe(\"Latitude coordinate\"),\n longitude: z.number().describe(\"Longitude coordinate\"),\n includeHealthRecommendations: z\n .boolean()\n .optional()\n .describe(\"Include health advice per demographic group (default: true)\"),\n includePollutants: z\n .boolean()\n .optional()\n .describe(\"Include individual pollutant concentrations — PM2.5, PM10, NO2, O3, CO, SO2 (default: false)\"),\n};\n\nexport type AirQualityParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n const apiKey = getCurrentApiKey();\n const placesSearcher = new PlacesSearcher(apiKey);\n const result = await placesSearcher.getAirQuality(\n params.latitude,\n params.longitude,\n params.includeHealthRecommendations,\n params.includePollutants\n );\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Failed to get air quality data\" }],\n isError: true,\n };\n }\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(result.data, null, 2) }],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error getting air quality: ${errorMessage}` }],\n };\n }\n}\n\nexport const AirQuality = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_static_map\";\nconst DESCRIPTION =\n \"Generate a map image with markers, paths, or routes — returned as an inline image the user can see directly in chat. PROACTIVELY call this tool after explore_area, plan_route, search_nearby, or directions to visualize results on a map — don't wait for the user to ask. Use markers from search results and path from route data. Supports roadmap, satellite, terrain, and hybrid views. Max 640x640 pixels.\";\n\nconst SCHEMA = {\n center: z\n .string()\n .optional()\n .describe('Map center — \"lat,lng\" or address. Optional if markers or path are provided.'),\n zoom: z.number().optional().describe(\"Zoom level 0-21 (0 = world, 15 = streets, 21 = buildings). Default: auto-fit.\"),\n size: z.string().optional().describe('Image size \"WxH\" in pixels. Default: \"600x400\". Max: \"640x640\".'),\n maptype: z.enum([\"roadmap\", \"satellite\", \"terrain\", \"hybrid\"]).optional().describe(\"Map style. Default: roadmap.\"),\n markers: z\n .array(z.string())\n .optional()\n .describe(\n 'Marker descriptors. Each string: \"color:red|label:A|lat,lng\" or \"color:blue|address\". Multiple markers per string separated by |.'\n ),\n path: z\n .array(z.string())\n .optional()\n .describe(\n 'Path descriptors. Each string: \"color:0x0000ff|weight:3|lat1,lng1|lat2,lng2|...\" to draw lines/routes on the map.'\n ),\n};\n\nexport type StaticMapParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n const apiKey = getCurrentApiKey();\n const placesSearcher = new PlacesSearcher(apiKey);\n const result = await placesSearcher.getStaticMap(params);\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Failed to generate static map\" }],\n isError: true,\n };\n }\n\n return {\n content: [\n {\n type: \"image\",\n data: result.data!.base64,\n mimeType: \"image/png\",\n },\n {\n type: \"text\",\n text: `Map generated (${result.data!.size} bytes, ${result.data!.dimensions})`,\n },\n ],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error generating static map: ${errorMessage}` }],\n };\n }\n}\n\nexport const StaticMap = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_batch_geocode\";\nconst DESCRIPTION =\n \"Geocode multiple addresses in one call — up to 50 addresses, returns coordinates for each. Use when the user provides a list of addresses and needs all their coordinates, e.g. 'geocode these 10 offices' or 'get coordinates for all these restaurants'. For more than 50, use the CLI batch-geocode command instead.\";\n\nconst SCHEMA = {\n addresses: z.array(z.string()).min(1).max(50).describe(\"List of addresses or landmark names to geocode (max 50)\"),\n};\n\nexport type BatchGeocodeParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n const apiKey = getCurrentApiKey();\n const searcher = new PlacesSearcher(apiKey);\n const addresses: string[] = params.addresses;\n\n const results = await Promise.all(\n addresses.map(async (address: string) => {\n try {\n const result = await searcher.geocode(address);\n return { address, ...result };\n } catch (error: any) {\n return { address, success: false, error: error.message };\n }\n })\n );\n\n const succeeded = results.filter((r) => r.success).length;\n const failed = results.filter((r) => !r.success).length;\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ total: addresses.length, succeeded, failed, results }, null, 2),\n },\n ],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error batch geocoding: ${errorMessage}` }],\n };\n }\n}\n\nexport const BatchGeocode = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_search_along_route\";\nconst DESCRIPTION =\n \"Search for places along a route between two points — restaurants, cafes, gas stations, etc. ranked by minimal detour time. Use for trip planning to find meals, rest stops, or attractions between landmarks without backtracking. Internally computes the route, then searches along it. Essential for building itineraries where stops should feel 'on the way' rather than 'detour to'.\";\n\nconst SCHEMA = {\n textQuery: z.string().describe(\"What to search for along the route (e.g. 'restaurant', 'coffee shop', 'temple')\"),\n origin: z.string().describe(\"Route start point — address or landmark name\"),\n destination: z.string().describe(\"Route end point — address or landmark name\"),\n mode: z\n .enum([\"driving\", \"walking\", \"bicycling\", \"transit\"])\n .optional()\n .describe(\"Travel mode for the route (default: walking)\"),\n maxResults: z.number().optional().describe(\"Max results to return (default: 5, max: 20)\"),\n};\n\nexport type SearchAlongRouteParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n const apiKey = getCurrentApiKey();\n const searcher = new PlacesSearcher(apiKey);\n const result = await searcher.searchAlongRoute(params);\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Failed to search along route\" }],\n isError: true,\n };\n }\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(result.data, null, 2) }],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error searching along route: ${errorMessage}` }],\n };\n }\n}\n\nexport const SearchAlongRoute = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { z } from \"zod\";\nimport { PlacesSearcher } from \"../../services/PlacesSearcher.js\";\nimport { getCurrentApiKey } from \"../../utils/requestContext.js\";\n\nconst NAME = \"maps_local_rank_tracker\";\nconst DESCRIPTION =\n \"Track a business's local search ranking across a geographic grid (like LocalFalcon). Searches the same keyword(s) from multiple coordinates around a center point to see how rank varies by location. Supports up to 3 keywords for batch scanning. Returns rank at each grid point, top-3 competitors per point, and summary metrics (ARP, ATRP, SoLV). Useful for local SEO analysis.\";\n\nconst SCHEMA = {\n keyword: z\n .string()\n .optional()\n .describe(\"Single search keyword (e.g., 'dentist'). Use 'keywords' for multi-keyword scanning.\"),\n keywords: z\n .array(z.string())\n .min(1)\n .max(3)\n .optional()\n .describe(\n \"Array of 1-3 keywords to scan (e.g., ['dentist', 'dental clinic', 'teeth cleaning']). Overrides 'keyword'.\"\n ),\n placeId: z.string().describe(\"Google Maps place_id of the target business to track\"),\n center: z\n .object({\n latitude: z.number().describe(\"Center latitude of the grid\"),\n longitude: z.number().describe(\"Center longitude of the grid\"),\n })\n .describe(\"Center coordinate for the grid (typically the business location)\"),\n gridSize: z\n .number()\n .int()\n .min(3)\n .max(7)\n .optional()\n .describe(\"Grid dimension (3 = 3×3 = 9 points, 5 = 5×5 = 25 points, 7 = 7×7 = 49 points). Default: 3\"),\n gridSpacing: z\n .number()\n .min(100)\n .max(10000)\n .optional()\n .describe(\"Distance between grid points in meters (100-10000). Default: 1000\"),\n};\n\nexport type LocalRankTrackerParams = z.infer<z.ZodObject<typeof SCHEMA>>;\n\nasync function ACTION(params: any): Promise<{ content: any[]; isError?: boolean }> {\n try {\n // Resolve keywords: keywords array takes priority, fallback to keyword string\n const resolvedKeywords: string[] = params.keywords || (params.keyword ? [params.keyword] : []);\n if (resolvedKeywords.length === 0) {\n return {\n content: [{ type: \"text\", text: \"Either 'keyword' or 'keywords' must be provided.\" }],\n isError: true,\n };\n }\n\n const apiKey = getCurrentApiKey();\n const placesSearcher = new PlacesSearcher(apiKey);\n const result = await placesSearcher.localRankTracker({ ...params, keywords: resolvedKeywords });\n\n if (!result.success) {\n return {\n content: [{ type: \"text\", text: result.error || \"Failed to track local rank\" }],\n isError: true,\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(result.data, null, 2),\n },\n ],\n isError: false,\n };\n } catch (error: any) {\n const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error tracking local rank: ${errorMessage}` }],\n };\n }\n}\n\nexport const LocalRankTracker = {\n NAME,\n DESCRIPTION,\n SCHEMA,\n ACTION,\n};\n","import { Logger } from \"./index.js\";\nimport { ToolConfig } from \"./core/BaseMcpServer.js\";\n\n// Import tool definitions\nimport { SearchNearby, SearchNearbyParams } from \"./tools/maps/searchNearby.js\";\nimport { PlaceDetails, PlaceDetailsParams } from \"./tools/maps/placeDetails.js\";\nimport { Geocode, GeocodeParams } from \"./tools/maps/geocode.js\";\nimport { ReverseGeocode, ReverseGeocodeParams } from \"./tools/maps/reverseGeocode.js\";\nimport { DistanceMatrix, DistanceMatrixParams } from \"./tools/maps/distanceMatrix.js\";\nimport { Directions, DirectionsParams } from \"./tools/maps/directions.js\";\nimport { Elevation, ElevationParams } from \"./tools/maps/elevation.js\";\nimport { SearchPlaces, SearchPlacesParams } from \"./tools/maps/searchPlaces.js\";\nimport { Timezone, TimezoneParams } from \"./tools/maps/timezone.js\";\nimport { Weather, WeatherParams } from \"./tools/maps/weather.js\";\nimport { ExploreArea, ExploreAreaParams } from \"./tools/maps/exploreArea.js\";\nimport { PlanRoute, PlanRouteParams } from \"./tools/maps/planRoute.js\";\nimport { ComparePlaces, ComparePlacesParams } from \"./tools/maps/comparePlaces.js\";\nimport { AirQuality, AirQualityParams } from \"./tools/maps/airQuality.js\";\nimport { StaticMap, StaticMapParams } from \"./tools/maps/staticMap.js\";\nimport { BatchGeocode, BatchGeocodeParams } from \"./tools/maps/batchGeocode.js\";\nimport { SearchAlongRoute, SearchAlongRouteParams } from \"./tools/maps/searchAlongRoute.js\";\nimport { LocalRankTracker, LocalRankTrackerParams } from \"./tools/maps/localRankTracker.js\";\n\n// All Google Maps tools are read-only API queries\nconst MAPS_TOOL_ANNOTATIONS = {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n} as const;\n\ninterface ServerInstanceConfig {\n name: string;\n portEnvVar: string;\n tools: ToolConfig[];\n}\n\nconst serverConfigs: ServerInstanceConfig[] = [\n {\n name: \"MCP-Server\",\n portEnvVar: \"MCP_SERVER_PORT\",\n tools: [\n {\n name: SearchNearby.NAME,\n description: SearchNearby.DESCRIPTION,\n schema: SearchNearby.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: SearchNearbyParams) => SearchNearby.ACTION(params),\n },\n {\n name: PlaceDetails.NAME,\n description: PlaceDetails.DESCRIPTION,\n schema: PlaceDetails.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: PlaceDetailsParams) => PlaceDetails.ACTION(params),\n },\n {\n name: Geocode.NAME,\n description: Geocode.DESCRIPTION,\n schema: Geocode.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: GeocodeParams) => Geocode.ACTION(params),\n },\n {\n name: ReverseGeocode.NAME,\n description: ReverseGeocode.DESCRIPTION,\n schema: ReverseGeocode.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: ReverseGeocodeParams) => ReverseGeocode.ACTION(params),\n },\n {\n name: DistanceMatrix.NAME,\n description: DistanceMatrix.DESCRIPTION,\n schema: DistanceMatrix.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: DistanceMatrixParams) => DistanceMatrix.ACTION(params),\n },\n {\n name: Directions.NAME,\n description: Directions.DESCRIPTION,\n schema: Directions.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: DirectionsParams) => Directions.ACTION(params),\n },\n {\n name: Elevation.NAME,\n description: Elevation.DESCRIPTION,\n schema: Elevation.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: ElevationParams) => Elevation.ACTION(params),\n },\n {\n name: SearchPlaces.NAME,\n description: SearchPlaces.DESCRIPTION,\n schema: SearchPlaces.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: SearchPlacesParams) => SearchPlaces.ACTION(params),\n },\n {\n name: Timezone.NAME,\n description: Timezone.DESCRIPTION,\n schema: Timezone.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: TimezoneParams) => Timezone.ACTION(params),\n },\n {\n name: Weather.NAME,\n description: Weather.DESCRIPTION,\n schema: Weather.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: WeatherParams) => Weather.ACTION(params),\n },\n {\n name: ExploreArea.NAME,\n description: ExploreArea.DESCRIPTION,\n schema: ExploreArea.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: ExploreAreaParams) => ExploreArea.ACTION(params),\n },\n {\n name: PlanRoute.NAME,\n description: PlanRoute.DESCRIPTION,\n schema: PlanRoute.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: PlanRouteParams) => PlanRoute.ACTION(params),\n },\n {\n name: ComparePlaces.NAME,\n description: ComparePlaces.DESCRIPTION,\n schema: ComparePlaces.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: ComparePlacesParams) => ComparePlaces.ACTION(params),\n },\n {\n name: AirQuality.NAME,\n description: AirQuality.DESCRIPTION,\n schema: AirQuality.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: AirQualityParams) => AirQuality.ACTION(params),\n },\n {\n name: StaticMap.NAME,\n description: StaticMap.DESCRIPTION,\n schema: StaticMap.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: StaticMapParams) => StaticMap.ACTION(params),\n },\n {\n name: BatchGeocode.NAME,\n description: BatchGeocode.DESCRIPTION,\n schema: BatchGeocode.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: BatchGeocodeParams) => BatchGeocode.ACTION(params),\n },\n {\n name: SearchAlongRoute.NAME,\n description: SearchAlongRoute.DESCRIPTION,\n schema: SearchAlongRoute.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: SearchAlongRouteParams) => SearchAlongRoute.ACTION(params),\n },\n {\n name: LocalRankTracker.NAME,\n description: LocalRankTracker.DESCRIPTION,\n schema: LocalRankTracker.SCHEMA,\n annotations: MAPS_TOOL_ANNOTATIONS,\n action: (params: LocalRankTrackerParams) => LocalRankTracker.ACTION(params),\n },\n ],\n },\n];\n\nexport function filterTools(tools: ToolConfig[]): ToolConfig[] {\n const raw = process.env.GOOGLE_MAPS_ENABLED_TOOLS?.trim();\n if (!raw || raw === \"*\") return tools;\n\n const enabled = new Set(\n raw\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean)\n );\n const filtered = tools.filter((t) => enabled.has(t.name));\n\n if (filtered.length === 0) {\n Logger.error(`GOOGLE_MAPS_ENABLED_TOOLS matched 0 tools. Available: ${tools.map((t) => t.name).join(\", \")}`);\n return tools;\n }\n\n Logger.log(`GOOGLE_MAPS_ENABLED_TOOLS: ${filtered.length}/${tools.length} tools active`);\n return filtered;\n}\n\nexport default serverConfigs;\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport { isInitializeRequest, ToolAnnotations } from \"@modelcontextprotocol/sdk/types.js\";\nimport express, { Request, Response } from \"express\";\nimport { Server } from \"http\";\nimport { randomUUID } from \"node:crypto\";\nimport { z } from \"zod\";\nimport { Logger } from \"../index.js\";\nimport { ApiKeyManager } from \"../utils/apiKeyManager.js\";\nimport { runWithContext } from \"../utils/requestContext.js\";\n\nconst VERSION = \"0.0.1\";\n\n// Define a structure for tool configurations\nexport interface ToolConfig {\n name: string;\n description: string;\n schema: Record<string, z.ZodTypeAny>;\n annotations?: ToolAnnotations;\n action: (params: any) => Promise<any>;\n}\n\nexport interface SessionContext {\n apiKey?: string;\n transport: StreamableHTTPServerTransport;\n}\n\nexport class BaseMcpServer {\n protected readonly server: McpServer;\n private sessions: { [sessionId: string]: SessionContext } = {};\n private httpServer: Server | null = null;\n private serverName: string;\n private tools: ToolConfig[];\n\n constructor(name: string, tools: ToolConfig[]) {\n this.serverName = name;\n this.tools = tools;\n this.server = this.createMcpServer();\n }\n\n private createMcpServer(): McpServer {\n const server = new McpServer(\n { name: this.serverName, version: VERSION },\n { capabilities: { logging: {}, tools: {} } }\n );\n this.tools.forEach((tool) => {\n server.registerTool(\n tool.name,\n {\n description: tool.description,\n inputSchema: z.object(tool.schema),\n annotations: tool.annotations,\n },\n async (params: any) => tool.action(params)\n );\n });\n return server;\n }\n\n async connect(transport: Transport): Promise<void> {\n await this.server.connect(transport);\n\n // Ensure stdout is only used for JSON messages\n const originalStdoutWrite = process.stdout.write.bind(process.stdout);\n process.stdout.write = (chunk: any, encoding?: any, callback?: any) => {\n if (typeof chunk === \"string\" && !chunk.startsWith(\"{\")) {\n return true; // Silently skip non-JSON messages\n }\n return originalStdoutWrite(chunk, encoding, callback);\n };\n\n Logger.log(`${this.serverName} connected and ready to process requests`);\n }\n\n async startHttpServer(port: number, host: string = \"0.0.0.0\"): Promise<void> {\n const app = express();\n app.use(express.json());\n\n // Handle POST requests for client-to-server communication\n app.post(\"/mcp\", async (req: Request, res: Response) => {\n const sessionId = req.headers[\"mcp-session-id\"] as string | undefined;\n let context: SessionContext;\n\n // Extract API key from headers if provided\n const apiKeyManager = ApiKeyManager.getInstance();\n const requestApiKey = apiKeyManager.getApiKey(req, sessionId ? this.sessions[sessionId]?.apiKey : undefined);\n\n Logger.log(`${this.serverName} API key received from request context`);\n\n if (sessionId && this.sessions[sessionId]) {\n // Reuse existing session\n context = this.sessions[sessionId];\n // Update API key if provided in this request\n if (requestApiKey) {\n context.apiKey = requestApiKey;\n }\n } else if (!sessionId && isInitializeRequest(req.body)) {\n // New initialization request\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: () => randomUUID(),\n onsessioninitialized: (sessionId) => {\n this.sessions[sessionId] = context;\n Logger.log(`[${this.serverName}] New session initialized: ${sessionId}`);\n },\n // DNS rebinding protection is disabled by default for backwards compatibility\n // For production use, enable this:\n // enableDnsRebindingProtection: true,\n // allowedHosts: ['127.0.0.1'],\n });\n\n // Create session context\n context = {\n transport,\n apiKey: requestApiKey,\n };\n\n // Clean up transport when closed\n transport.onclose = () => {\n if (transport.sessionId) {\n delete this.sessions[transport.sessionId];\n Logger.log(`[${this.serverName}] Session closed: ${transport.sessionId}`);\n }\n };\n\n const sessionServer = this.createMcpServer();\n await sessionServer.connect(transport);\n } else {\n // Invalid request\n res.status(400).json({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: \"Bad Request: No valid session ID provided\",\n },\n id: null,\n });\n return;\n }\n\n // Run the request handler with the API key in context\n await runWithContext({ apiKey: context.apiKey, sessionId }, async () => {\n await context.transport.handleRequest(req, res, req.body);\n });\n });\n\n // Reusable handler for GET and DELETE requests\n const handleSessionRequest = async (req: Request, res: Response) => {\n const sessionId = req.headers[\"mcp-session-id\"] as string | undefined;\n if (!sessionId || !this.sessions[sessionId]) {\n res.status(400).send(\"Invalid or missing session ID\");\n return;\n }\n\n const context = this.sessions[sessionId];\n\n // Check for updated API key in headers\n const apiKeyManager = ApiKeyManager.getInstance();\n const requestApiKey = apiKeyManager.getApiKey(req, context.apiKey);\n if (requestApiKey) {\n context.apiKey = requestApiKey;\n }\n\n // Run the request handler with the API key in context\n await runWithContext({ apiKey: context.apiKey, sessionId }, async () => {\n await context.transport.handleRequest(req, res);\n });\n };\n\n // Handle GET requests for server-to-client notifications via SSE\n app.get(\"/mcp\", handleSessionRequest);\n\n // Handle DELETE requests for session termination\n app.delete(\"/mcp\", handleSessionRequest);\n\n const displayHost = host === \"0.0.0.0\" ? \"localhost\" : host;\n this.httpServer = app.listen(port, host, () => {\n Logger.log(`[${this.serverName}] HTTP server listening on ${host}:${port}`);\n Logger.log(`[${this.serverName}] MCP endpoint available at http://${displayHost}:${port}/mcp`);\n });\n }\n\n async startStdio(): Promise<void> {\n const transport = new StdioServerTransport();\n await this.connect(transport);\n }\n\n async stopHttpServer(): Promise<void> {\n if (!this.httpServer) {\n // Changed to Logger.warn and return, as throwing an error might be too harsh if called multiple times.\n Logger.error(`[${this.serverName}] HTTP server is not running or already stopped.`);\n return;\n }\n\n return new Promise((resolve, reject) => {\n this.httpServer!.close((err: Error | undefined) => {\n if (err) {\n Logger.error(`[${this.serverName}] Error stopping HTTP server:`, err);\n reject(err);\n return;\n }\n Logger.log(`[${this.serverName}] HTTP server stopped.`);\n this.httpServer = null;\n const closingSessions = Object.values(this.sessions).map((context) => {\n // Clean up session\n if (context.transport.sessionId) {\n delete this.sessions[context.transport.sessionId];\n }\n return Promise.resolve();\n });\n Promise.all(closingSessions)\n .then(() => {\n Logger.log(`[${this.serverName}] All transports closed.`);\n resolve();\n })\n .catch((transportCloseErr) => {\n // This catch might be redundant if individual transport close errors are handled\n Logger.error(`[${this.serverName}] Error during bulk transport closing:`, transportCloseErr);\n reject(transportCloseErr);\n });\n });\n });\n }\n}\n","import { Request } from \"express\";\n\nexport class ApiKeyManager {\n private static instance: ApiKeyManager;\n private defaultApiKey: string | undefined;\n\n private constructor() {\n // Initialize with environment variable or command-line provided key\n this.defaultApiKey = process.env.GOOGLE_MAPS_API_KEY;\n }\n\n public static getInstance(): ApiKeyManager {\n if (!ApiKeyManager.instance) {\n ApiKeyManager.instance = new ApiKeyManager();\n }\n return ApiKeyManager.instance;\n }\n\n /**\n * Set the default API key (from command line or environment)\n */\n public setDefaultApiKey(key: string): void {\n this.defaultApiKey = key;\n process.env.GOOGLE_MAPS_API_KEY = key;\n }\n\n /**\n * Get API key with priority:\n * 1. HTTP Header (X-Google-Maps-API-Key or Authorization: Bearer)\n * 2. Session-specific API key\n * 3. Default API key (command line or environment)\n */\n public getApiKey(req?: Request, sessionApiKey?: string): string | undefined {\n if (req) {\n // Check for API key in headers\n const headerApiKey = req.headers[\"x-google-maps-api-key\"] as string;\n if (headerApiKey) {\n return headerApiKey;\n }\n\n // Check for Bearer token in Authorization header\n const authHeader = req.headers[\"authorization\"] as string;\n if (authHeader && authHeader.startsWith(\"Bearer \")) {\n return authHeader.substring(7);\n }\n }\n\n // Use session-specific API key if available\n if (sessionApiKey) {\n return sessionApiKey;\n }\n\n // Fall back to default API key\n return this.defaultApiKey;\n }\n\n /**\n * Check if any API key is available\n */\n public hasApiKey(req?: Request, sessionApiKey?: string): boolean {\n return !!this.getApiKey(req, sessionApiKey);\n }\n\n /**\n * Validate API key format (basic validation)\n */\n public isValidApiKeyFormat(key: string): boolean {\n // Google Maps API keys are typically 39 characters long\n // and contain alphanumeric characters, hyphens, and underscores\n return /^[A-Za-z0-9_-]{20,50}$/.test(key);\n }\n}\n","/**\n * @fileoverview Automatic npm-registry update check executed at MCP server\n * startup (stdio and HTTP modes).\n * @details Default-enabled behavior (REQ-082); opt-out via the\n * `MCP_AUTO_UPDATE_DISABLED` environment variable (REQ-083). Fire-and-forget\n * contract: the check never throws, never blocks the caller, performs at most\n * one outbound HTTPS GET, and writes exclusively to stderr (REQ-084, REQ-085).\n */\n\nimport { Logger } from \"../index.js\";\n\n/**\n * Environment variable that disables the automatic update check.\n * Inverse-polarity counterpart of an enable-style variable: unset/empty means\n * enabled (default), a truthy value means disabled.\n */\nexport const AUTO_UPDATE_DISABLED_ENV = \"MCP_AUTO_UPDATE_DISABLED\";\n\n/** Default npm package name probed by the automatic update check. */\nexport const DEFAULT_PACKAGE_NAME = \"mcp-google-map\";\n\n/** Default npm registry base URL (no trailing slash). */\nexport const DEFAULT_REGISTRY_BASE_URL = \"https://registry.npmjs.org\";\n\n/** Default hard deadline for the registry GET before it is abandoned. */\nexport const DEFAULT_UPDATE_CHECK_TIMEOUT_MS = 2000;\n\n/**\n * @brief Minimal logger contract consumed by the update check.\n * @details Structural subset of `Logger` (`src/index.ts`); injectable so tests\n * capture diagnostics without touching stderr.\n */\nexport interface AutoUpdateLogger {\n /** @param args {unknown[]} Diagnostic fragments joined for stderr output. */\n log: (...args: unknown[]) => void;\n /** @param args {unknown[]} Error diagnostic fragments for stderr output. */\n error: (...args: unknown[]) => void;\n}\n\n/**\n * @brief Dependency injection surface of `checkForUpdates`.\n * @details Every field is optional; omitted fields resolve to production\n * defaults (`process.env`, global `fetch`, `Logger`). Injection exists to keep\n * unit tests deterministic and network-free (TST-011).\n */\nexport interface AutoUpdateCheckerDeps {\n /** Running package version (e.g. from `package.json`); no default. */\n currentVersion?: string;\n /** Package name to resolve on the registry. Default: `DEFAULT_PACKAGE_NAME`. */\n packageName?: string;\n /** Registry origin without trailing slash. Default: `DEFAULT_REGISTRY_BASE_URL`. */\n registryBaseUrl?: string;\n /** Fetch implementation used for the registry GET. Default: global `fetch`. */\n fetchImpl?: typeof fetch;\n /** Environment map consulted for `AUTO_UPDATE_DISABLED_ENV`. Default: `process.env`. */\n env?: Record<string, string | undefined>;\n /** Diagnostics sink. Default: `Logger` (stderr). */\n logger?: AutoUpdateLogger;\n /** Registry GET deadline in milliseconds. Default: `DEFAULT_UPDATE_CHECK_TIMEOUT_MS`. */\n timeoutMs?: number;\n}\n\n/** Successful probe outcome: versions between which an upgrade exists. */\nexport interface AutoUpdateResult {\n /** Running package version used for the comparison. */\n currentVersion: string;\n /** Latest version reported by the registry. */\n latestVersion: string;\n}\n\n/**\n * @brief Evaluates the disable flag for the automatic update check.\n * @details Reads `AUTO_UPDATE_DISABLED_ENV` from the given environment map and\n * matches values `1`, `true`, `yes` case-insensitively after trimming; any\n * other value (including unset, empty, `0`, `false`) keeps the check enabled.\n * @param env {Record<string, string | undefined>} Environment map to inspect. Defaults to `process.env`.\n * @return {boolean} True when the update check is disabled; false when enabled.\n * @satisfies REQ-083\n * @note Complexity: O(1). Pure; no side effects.\n */\nexport function isAutoUpdateDisabled(\n env: Record<string, string | undefined> = process.env\n): boolean {\n const raw = env[AUTO_UPDATE_DISABLED_ENV];\n return typeof raw === \"string\" && /^(1|true|yes)$/i.test(raw.trim());\n}\n\n/**\n * @brief Compares two dotted numeric version strings.\n * @details Splits both inputs on `.` into integer segments, right-pads the\n * shorter sequence with zeroes, and returns on the first differing segment.\n * Any non-integer segment (e.g. prerelease suffix `3-beta.1`) forces False, so\n * unparseable or prerelease candidates never trigger an update notice.\n * @param candidate {string} Version reported as available (latest).\n * @param current {string} Version currently running.\n * @return {boolean} True only when `candidate` is strictly newer than `current`.\n * @satisfies REQ-084\n * @note Complexity: O(k) where k is the number of dotted segments. Pure; no side effects.\n */\nexport function isNewerVersion(candidate: string, current: string): boolean {\n const toSegments = (version: string): number[] =>\n version\n .trim()\n .split(\".\")\n .map((segment) => (/^\\d+$/.test(segment) ? Number(segment) : Number.NaN));\n const candidateSegments = toSegments(candidate);\n const currentSegments = toSegments(current);\n if (\n candidateSegments.some((segment) => !Number.isInteger(segment)) ||\n currentSegments.some((segment) => !Number.isInteger(segment))\n ) {\n return false;\n }\n const length = Math.max(candidateSegments.length, currentSegments.length);\n for (let index = 0; index < length; index += 1) {\n const candidatePart = candidateSegments[index] ?? 0;\n const currentPart = currentSegments[index] ?? 0;\n if (candidatePart !== currentPart) {\n return candidatePart > currentPart;\n }\n }\n return false;\n}\n\n/**\n * @brief Runs the automatic update check against the npm registry.\n * @details Resolution order: disabled-flag short-circuit (REQ-083, zero\n * network calls) → running-version guard (missing `currentVersion` aborts with\n * an stderr diagnostic, zero network calls) → single `GET {registry}/{package}/latest`\n * with `timeoutMs` deadline → `response.ok` and `payload.version` validation →\n * `isNewerVersion` gate → stderr upgrade notice (REQ-084). Every failure path\n * (disabled, missing version, non-OK status, malformed payload, network error)\n * returns null, logs to stderr only, and never throws (REQ-085).\n * @param deps {AutoUpdateCheckerDeps} Optional dependency overrides; production defaults when omitted.\n * @return {Promise<AutoUpdateResult | null>} `{ currentVersion, latestVersion }` when a strictly newer version is published; null otherwise.\n * @satisfies REQ-082, REQ-083, REQ-084, REQ-085\n * @note Complexity: O(k) in version segments plus one HTTP round-trip bounded by `timeoutMs`.\n * @warning Must be invoked fire-and-forget (`void checkForUpdates(...)`) so server startup is never awaited on it (REQ-085).\n * @see isAutoUpdateDisabled\n * @see isNewerVersion\n */\nexport async function checkForUpdates(\n deps: AutoUpdateCheckerDeps = {}\n): Promise<AutoUpdateResult | null> {\n const logger = deps.logger ?? Logger;\n const env = deps.env ?? process.env;\n try {\n if (isAutoUpdateDisabled(env)) {\n return null;\n }\n const currentVersion = deps.currentVersion;\n if (!currentVersion) {\n logger.error(\n `⚠️ [${DEFAULT_PACKAGE_NAME}] Automatic update check skipped: running package version is unknown.`\n );\n return null;\n }\n const packageName = deps.packageName ?? DEFAULT_PACKAGE_NAME;\n const registryBaseUrl = deps.registryBaseUrl ?? DEFAULT_REGISTRY_BASE_URL;\n const timeoutMs = deps.timeoutMs ?? DEFAULT_UPDATE_CHECK_TIMEOUT_MS;\n const fetchImpl = deps.fetchImpl ?? fetch;\n const response = await fetchImpl(`${registryBaseUrl}/${packageName}/latest`, {\n headers: { accept: \"application/vnd.npm.install-v1+json\" },\n signal: AbortSignal.timeout(timeoutMs),\n });\n if (!response.ok) {\n logger.error(\n `⚠️ [${DEFAULT_PACKAGE_NAME}] Automatic update check failed: registry responded with HTTP ${response.status}.`\n );\n return null;\n }\n const payload = (await response.json()) as { version?: unknown };\n if (typeof payload?.version !== \"string\") {\n logger.error(\n `⚠️ [${DEFAULT_PACKAGE_NAME}] Automatic update check failed: registry response has no version field.`\n );\n return null;\n }\n if (!isNewerVersion(payload.version, currentVersion)) {\n return null;\n }\n logger.log(\n `⚠️ Update available: ${packageName} ${currentVersion} → ${payload.version}. ` +\n `Upgrade with: npm install -g ${packageName}@latest (or run npx -y ${packageName}@latest).`\n );\n return { currentVersion, latestVersion: payload.version };\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n logger.error(`⚠️ [${DEFAULT_PACKAGE_NAME}] Automatic update check failed: ${message}`);\n return null;\n }\n}\n"],"mappings":"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","names":["z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","NAME","DESCRIPTION","SCHEMA","z","ACTION","z","z","sessionId","resolve","yargs","tasks"]}
@@ -33,6 +33,7 @@ Definite in `.env` (copia da `.env.example`):
33
33
  | `MCP_SERVER_PORT` | `3000` | Porta del trasporto HTTP |
34
34
  | `MCP_SERVER_HOST` | `0.0.0.0` | Interfaccia di bind HTTP (usare `127.0.0.1` per esposizione solo locale) |
35
35
  | `GOOGLE_MAPS_ENABLED_TOOLS` | `*` | Allowlist separata da virgole dei tool esposti (riduce il contesto per l'LLM). Esempio: `maps_search_places,maps_place_details,maps_geocode` |
36
+ | `MCP_AUTO_UPDATE_DISABLED` | unset (check enabled by default) | Set `1`, `true`, or `yes` to disable the automatic update check performed at server startup; any other value keeps it enabled |
36
37
 
37
38
  ## Trasporti
38
39
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-google-map",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Google Maps MCP server — 18 tools for AI agents: geocoding, Places API (New) search with server-side filters, directions, distance matrix and more, via stdio or Streamable HTTP",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -20,7 +20,8 @@
20
20
  "typecheck": "tsc --noEmit",
21
21
  "test": "tsx --test tests/*.unit.test.ts",
22
22
  "test:e2e": "tsx tests/smoke.test.ts",
23
- "prepublishOnly": "npm run typecheck && npm test && npm run build"
23
+ "check:publish-version": "node scripts/check-publish-version.mjs",
24
+ "prepublishOnly": "npm run check:publish-version && npm run typecheck && npm test && npm run build"
24
25
  },
25
26
  "engines": {
26
27
  "node": ">=22"