mcp-google-map 0.3.0 β 0.5.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 +5 -1
- package/README.md +126 -81
- package/dist/{chunk-K27FX5QH.js β chunk-NAUIQEK4.js} +2 -2
- package/dist/chunk-NAUIQEK4.js.map +1 -0
- package/dist/cli.d.ts +128 -3
- package/dist/cli.js +1345 -88
- package/dist/cli.js.map +1 -1
- package/dist/index.js +1 -1
- package/docs/CONFIGURATION.md +20 -12
- package/docs/TOOLS.md +1 -1
- package/package.json +9 -6
- package/src/resources/skills/README.md +40 -0
- package/src/resources/skills/manifest.json +14 -0
- package/src/resources/skills/venue-discovery/SKILL.md +304 -0
- package/dist/chunk-K27FX5QH.js.map +0 -1
- package/docs/GEOSCOUT.md +0 -53
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/utils/configResolver.ts","../src/utils/autoUpdate.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/toolProfiles.ts","../src/utils/clientSnippets.ts","../src/utils/cliSettings.ts","../src/utils/cliTargets.ts","../src/utils/cliInstaller.ts","../src/utils/cliShow.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\";\nimport {\n NODE_ENGINE_FLOOR,\n applyExplicitEnvFile,\n describeRuntimeConfig,\n formatConfigDiagnostics,\n resolveEnabledToolNames,\n resolveRuntimeConfig,\n type ResolvedRuntimeConfig,\n} from \"./utils/configResolver.js\";\nimport { describeToolsProfile } from \"./utils/toolProfiles.js\";\nimport { renderClientSnippet, type SnippetClient, type SnippetOptions } from \"./utils/clientSnippets.js\";\nimport { loadCliSettings, saveCliSettings } from \"./utils/cliSettings.js\";\nimport { resolveCliTarget, supportedCliNames } from \"./utils/cliTargets.js\";\nimport {\n installEnabledCliResources,\n resolveSkillsResourcesRoot,\n uninstallEnabledCliResources,\n type CliOperationResult,\n} from \"./utils/cliInstaller.js\";\nimport { buildCliShowReport } from \"./utils/cliShow.js\";\n\n// Get the directory of the current module\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/**\n * @brief Extracts the explicit `--env-file <path>` value from a raw argv array.\n * @details Scans for both `--env-file <path>` and `--env-file=<path>` forms\n * before any command parsing so the file loads before option defaults are\n * captured. First match wins. Complexity O(n) in argv length; pure.\n * @param argv {readonly string[]} Raw process argument vector.\n * @return {string | undefined} Path value when present; undefined otherwise.\n * @satisfies CTN-009\n */\nexport function extractEnvFileOption(argv: readonly string[]): string | undefined {\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n if (arg === \"--env-file\" && i + 1 < argv.length) {\n return argv[i + 1];\n }\n if (arg.startsWith(\"--env-file=\")) {\n return arg.slice(\"--env-file=\".length);\n }\n }\n return undefined;\n}\n\n/**\n * @brief Loads environment files for the current CLI invocation.\n * @details Explicit mode (`envFile` set): loads exactly that file via\n * `applyExplicitEnvFile` and exits 1 with a JSON stderr error when missing β\n * no implicit fallback. Implicit mode: loads `.env` from the current working\n * directory first, then from the package installation directory (dotenv never\n * overrides already-set variables). Complexity O(file count).\n * @param envFile {string | undefined} Explicit `--env-file` value; undefined selects implicit discovery.\n * @return {void}\n * @throws {never} Terminates the process via `process.exit(1)` on a missing explicit file.\n * @see applyExplicitEnvFile\n * @satisfies CTN-007, CTN-009\n */\nfunction loadEnvironment(envFile: string | undefined): void {\n if (envFile !== undefined) {\n const result = applyExplicitEnvFile(envFile);\n if (!result.ok) {\n process.stderr.write(JSON.stringify({ error: result.error }, null, 2) + \"\\n\");\n process.exit(1);\n }\n return;\n }\n // Try to load .env from current directory first, then from package directory\n dotenvConfig({ path: resolve(process.cwd(), \".env\") });\n // Also try to load from the package installation directory\n dotenvConfig({ path: resolve(__dirname, \"../.env\") });\n}\n\n/**\n * @brief Aggregated HTTP startup result across all configured server instances.\n * @details `started`/`failed` count per instance; `servers` holds only the\n * instances that are listening, so a zero-length array with `started === 0`\n * is the reliable-failure signal consumed by the default command (REQ-095).\n */\nexport interface ServerStartupOutcome {\n started: number;\n failed: number;\n servers: BaseMcpServer[];\n}\n\n/**\n * @brief Starts every configured HTTP MCP server instance and reports the outcome.\n * @details Applies flag overrides to the environment, validates each instance\n * port (integer 1-65535), skips invalid instances with remediation guidance\n * while marking them failed (REQ-009), awaits `startHttpServer` so listen\n * errors are caught, installs SIGINT/SIGTERM handlers on success (REQ-096),\n * and returns the aggregate outcome. Default bind host is loopback\n * `127.0.0.1` (REQ-008). Complexity O(instances).\n * @param port {number | undefined} `--port` override written to `MCP_SERVER_PORT`.\n * @param apiKey {string | undefined} `--apikey` override written to `GOOGLE_MAPS_API_KEY`.\n * @param host {string | undefined} `--host` override written to `MCP_SERVER_HOST`.\n * @return {Promise<ServerStartupOutcome>} Per-run counts plus listening servers.\n * @see installShutdownHandlers\n * @satisfies REQ-008, REQ-009, REQ-096\n */\nexport async function startServer(\n port?: number,\n apiKey?: string,\n host?: string\n): Promise<ServerStartupOutcome> {\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 servers: BaseMcpServer[] = [];\n let started = 0;\n let failed = 0;\n\n await Promise.all(\n 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 failed++;\n return;\n }\n\n const serverPort = Number(portString);\n if (!Number.isInteger(serverPort) || serverPort < 1 || serverPort > 65535) {\n Logger.error(\n `β [${config.name}] Invalid port number \"${portString}\" defined in ${config.portEnvVar} (expected integer 1-65535).`\n );\n failed++;\n return;\n }\n\n try {\n const activeTools = filterTools(config.tools);\n const server = new BaseMcpServer(config.name, activeTools);\n const serverHost = process.env.MCP_SERVER_HOST || \"127.0.0.1\";\n Logger.log(`π§ [${config.name}] Initializing MCP Server in HTTP mode on ${serverHost}:${serverPort}...`);\n await server.startHttpServer(serverPort, serverHost);\n servers.push(server);\n started++;\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: ${activeTools.length} available`);\n } catch (error) {\n Logger.error(`β [${config.name}] Failed to start MCP Server on port ${serverPort}:`, error);\n failed++;\n }\n })\n );\n\n if (started > 0) {\n installShutdownHandlers(servers);\n }\n\n Logger.log(\"\");\n Logger.log(started > 0 ? \"π Server initialization completed!\" : \"β No MCP server instance started.\");\n Logger.log(\"π‘ Need help? Check the README.md for configuration details.\");\n return { started, failed, servers };\n}\n\n/** @brief Exit hook signature used by the shutdown handler. */\nexport type ShutdownExitHook = (code: number) => void;\n\n/**\n * @brief Builds a one-shot orderly shutdown handler for HTTP server instances.\n * @details On first invocation it stops every given server via\n * `stopHttpServer()` (transport close + socket close, errors tolerated) and\n * then calls `exitHook(0)`; subsequent invocations are no-ops, so repeated\n * signals never double-stop. Complexity O(servers).\n * @param servers {readonly BaseMcpServer[]} Listening server instances.\n * @param exitHook {ShutdownExitHook} Terminal action; defaults to `process.exit`.\n * @return {(signal: string) => Promise<void>} Reusable async signal handler.\n * @see stopHttpServer\n * @satisfies REQ-096\n */\nexport function createShutdownHandler(\n servers: readonly BaseMcpServer[],\n exitHook: ShutdownExitHook = (code) => process.exit(code)\n): (signal: string) => Promise<void> {\n let invoked = false;\n return async (signal: string) => {\n if (invoked) {\n return;\n }\n invoked = true;\n Logger.log(`πΆ Received ${signal}; shutting down MCP HTTP server...`);\n await Promise.allSettled(servers.map((server) => server.stopHttpServer()));\n exitHook(0);\n };\n}\n\n/**\n * @brief Registers SIGINT/SIGTERM handlers that orderly-stop the given servers.\n * @details Wraps `createShutdownHandler` and attaches it to both signals so\n * Ctrl-C and terminate requests close all HTTP sessions and the listening\n * socket before process exit (REQ-096). Complexity O(1).\n * @param servers {readonly BaseMcpServer[]} Listening server instances.\n * @return {void}\n * @see createShutdownHandler\n * @satisfies REQ-096\n */\nexport function installShutdownHandlers(servers: readonly BaseMcpServer[]): void {\n const handler = createShutdownHandler(servers);\n process.on(\"SIGINT\", () => void handler(\"SIGINT\"));\n process.on(\"SIGTERM\", () => void handler(\"SIGTERM\"));\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/** @brief Selectable live-probe identifier used by `doctor --live --probes`. */\nexport type DoctorProbeId = \"geocoding\" | \"places-new\" | \"routes\";\n\n/** @brief Static definition of one billable live probe executed by doctor. */\nexport interface DoctorLiveProbe {\n readonly id: DoctorProbeId;\n readonly name: string;\n readonly tool: string;\n readonly params: Record<string, unknown>;\n}\n\n/**\n * @brief Registry of the three independent live probes (Geocoding, Places (New), Routes).\n * @details Each probe maps to one cheap `exec` tool call; probes run\n * independently so a single API outage fails exactly one check. Complexity\n * O(1); pure constant.\n * @satisfies REQ-072, REQ-091\n */\nexport const DOCTOR_PROBES: readonly DoctorLiveProbe[] = [\n { id: \"geocoding\", name: \"geocoding-api\", tool: \"geocode\", params: { address: \"Tokyo Tower\" } },\n { id: \"places-new\", name: \"places-api-new\", tool: \"search-places\", params: { query: \"Tokyo Tower\" } },\n {\n id: \"routes\",\n name: \"routes-api\",\n tool: \"directions\",\n params: { origin: \"Tokyo Tower\", destination: \"Tokyo Station\", mode: \"walking\" },\n },\n];\n\n/** @brief Accepted case-insensitive `--probes` spellings per probe id. */\nconst DOCTOR_PROBE_ALIASES: Readonly<Record<string, DoctorProbeId>> = {\n geocoding: \"geocoding\",\n \"geocoding-api\": \"geocoding\",\n \"places-new\": \"places-new\",\n places: \"places-new\",\n \"places-api-new\": \"places-new\",\n routes: \"routes\",\n \"routes-api\": \"routes\",\n};\n\n/** @brief Parsed `--probes` CLI value: either valid probe ids or an error. */\nexport interface DoctorProbesParseResult {\n probes: DoctorProbeId[] | undefined;\n error?: string;\n}\n\n/**\n * @brief Parses the raw `--probes` CLI string into validated probe ids.\n * @details `undefined` input -> `{ probes: undefined }` (probe all three,\n * legacy `--live` behavior). Splits on commas, trims, lowercases, maps through\n * `DOCTOR_PROBE_ALIASES`, dedupes, and rejects unknown names or an empty list\n * with a remediation error. Complexity O(n) in items; pure.\n * @param raw {string | undefined} Raw option value from argv.\n * @return {DoctorProbesParseResult} Validated ids, or `error` describing the invalid input.\n * @satisfies REQ-091\n */\nexport function parseDoctorProbes(raw: string | undefined): DoctorProbesParseResult {\n if (raw === undefined) {\n return { probes: undefined };\n }\n const items = raw\n .split(\",\")\n .map((item) => item.trim().toLowerCase())\n .filter(Boolean);\n if (items.length === 0) {\n return { probes: undefined, error: \"--probes received no probe names (expected: geocoding, places-new, routes)\" };\n }\n const probes: DoctorProbeId[] = [];\n for (const item of items) {\n const id = DOCTOR_PROBE_ALIASES[item];\n if (!id) {\n return { probes: [], error: `unknown probe \"${item}\" (expected: geocoding, places-new, routes)` };\n }\n if (!probes.includes(id)) {\n probes.push(id);\n }\n }\n return { probes };\n}\n\n/**\n * @brief Injectable doctor dependencies for deterministic testing.\n * @details `nodeVersion` overrides `process.versions.node`; `config` overrides\n * environment-derived runtime configuration; `allToolNames` overrides the\n * registered tool-name registry used by the profile check.\n */\nexport interface DoctorOptions {\n probes?: readonly DoctorProbeId[];\n nodeVersion?: string;\n config?: ResolvedRuntimeConfig;\n allToolNames?: readonly string[];\n}\n\n/**\n * @brief Runs the readiness self-check decoupled from server startup.\n * @details Local checks (zero network calls): Node major >=\n * `NODE_ENGINE_FLOOR` (22, aligned with `package.json` `engines`, REQ-070),\n * non-zero package version, API key presence (value hidden), effective\n * configuration diagnostics with masked secrets and per-field sources\n * (REQ-089, zero-match allowlist reported as fail), explicit env-file status,\n * and the per-tool Google API profile of the effective tool set (REQ-090).\n * Live branch: without `options.probes` runs all three probes (legacy\n * `--live`, REQ-072); with `options.probes` runs only the selected subset\n * (REQ-091); each probe fails independently. `success` is false when any\n * check fails; the caller maps it to the exit code.\n * @param packageVersion {string} Installed package version (\"0.0.0\" = unknown).\n * @param apiKey {string | undefined} Resolved API key; never printed.\n * @param live {boolean} True to run billable live probes.\n * @param runner {DoctorToolRunner} Injectable tool runner; defaults to `execTool`.\n * @param options {DoctorOptions} Injectable Node version, config, tool registry, and probe subset.\n * @return {Promise<DoctorReport>} JSON-serializable report with `checks` and aggregate `success`.\n * @see resolveRuntimeConfig\n * @see describeToolsProfile\n * @satisfies REQ-070, REQ-071, REQ-072, REQ-089, REQ-090, REQ-091\n */\nexport async function runDoctor(\n packageVersion: string,\n apiKey: string | undefined,\n live = false,\n runner: DoctorToolRunner = execTool,\n options: DoctorOptions = {}\n): Promise<DoctorReport> {\n const nodeVersion = options.nodeVersion ?? process.versions.node;\n const nodeMajor = Number.parseInt(nodeVersion.split(\".\")[0] ?? \"0\", 10);\n const config = options.config ?? resolveRuntimeConfig(process.env);\n const allToolNames = options.allToolNames ?? serverConfigs[0].tools.map((tool) => tool.name);\n const toolsResolution = resolveEnabledToolNames(allToolNames, config.enabledToolsRaw);\n const diagnostics = describeRuntimeConfig(config);\n const toolsProfile = describeToolsProfile(toolsResolution.names);\n\n const checks: DoctorCheck[] = [\n {\n name: \"node\",\n status: nodeMajor >= NODE_ENGINE_FLOOR ? \"pass\" : \"fail\",\n detail: `Node.js ${nodeVersion} detected; version ${NODE_ENGINE_FLOOR} or newer is required (package.json engines).`,\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 name: \"config\",\n status: toolsResolution.fallback ? \"fail\" : \"pass\",\n detail: toolsResolution.fallback\n ? `GOOGLE_MAPS_ENABLED_TOOLS matched 0 tools; the server falls back to all ${allToolNames.length} tools. Effective configuration: ${formatConfigDiagnostics(diagnostics)}`\n : `Effective configuration: ${formatConfigDiagnostics(diagnostics)}`,\n },\n {\n name: \"env-file\",\n status: \"pass\",\n detail: config.envFile\n ? `Explicit environment file loaded: ${config.envFile}`\n : \"No explicit --env-file requested; implicit .env discovery (current directory, then package directory) applies.\",\n },\n {\n name: \"tools\",\n status: \"pass\",\n detail: `${toolsProfile.toolCount} tool(s) enabled; Google APIs: ${toolsProfile.apis.join(\", \") || \"none\"}; per-tool: ${toolsProfile.tools.map((tool) => `${tool.tool}[${tool.apis.join(\"+\")}]`).join(\", \")}`,\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 selected = options.probes\n ? DOCTOR_PROBES.filter((probe) => (options.probes as readonly DoctorProbeId[]).includes(probe.id))\n : DOCTOR_PROBES;\n\n for (const check of selected) {\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// --------------- Setup Mode ---------------\n\n/** @brief One named onboarding check result (`pass`, `fail`, or `skip`). */\nexport interface SetupCheck {\n name: string;\n status: \"pass\" | \"fail\" | \"skip\";\n detail: string;\n}\n\n/** @brief JSON-serializable outcome of the `setup` command. */\nexport interface SetupReport {\n success: boolean;\n created: boolean;\n checks: SetupCheck[];\n}\n\n/** @brief Injectable filesystem surface used by `runSetup` (tests pass fakes). */\nexport interface SetupFs {\n existsSync(path: string): boolean;\n readFileSync(path: string, encoding: \"utf-8\"): string;\n writeFileSync(path: string, data: string, encoding: \"utf-8\"): void;\n}\n\n/** @brief Injectable dependencies for deterministic `runSetup` testing. */\nexport interface SetupDeps {\n nodeVersion?: string;\n config?: ResolvedRuntimeConfig;\n fs?: SetupFs;\n}\n\n/** @brief Inputs controlling `runSetup` behavior. */\nexport interface SetupOptions {\n packageDir: string;\n targetDir: string;\n writeEnv: boolean;\n}\n\n/**\n * @brief Runs the non-interactive onboarding self-check with optional `.env` scaffolding.\n * @details Zero prompts, zero Google API calls, zero writes unless `writeEnv`\n * is true (REQ-087). Checks: Node major >= `NODE_ENGINE_FLOOR` (22);\n * `.env.example` presence in `packageDir`; `.env` handling in `targetDir` β\n * with `writeEnv` the file is created from the template only when absent and\n * is never overwritten (REQ-088), without it the check reports the current\n * state; API key presence from the resolved configuration (value hidden).\n * `success` is false only when a check fails. Complexity O(1) filesystem ops.\n * @param options {SetupOptions} Directories and the explicit write authorization flag.\n * @param deps {SetupDeps} Injectable Node version, config, and fs surface.\n * @return {Promise<SetupReport>} Report with `created` flag and named checks.\n * @see resolveRuntimeConfig\n * @satisfies PRJ-011, REQ-087, REQ-088\n */\nexport async function runSetup(options: SetupOptions, deps: SetupDeps = {}): Promise<SetupReport> {\n const fsImpl: SetupFs =\n deps.fs ?? {\n existsSync: (path) => existsSync(path),\n readFileSync: (path, encoding) => readFileSync(path, encoding),\n writeFileSync: (path, data, encoding) => writeFileSync(path, data, encoding),\n };\n const nodeVersion = deps.nodeVersion ?? process.versions.node;\n const nodeMajor = Number.parseInt(nodeVersion.split(\".\")[0] ?? \"0\", 10);\n const config = deps.config ?? resolveRuntimeConfig(process.env);\n\n const examplePath = resolve(options.packageDir, \".env.example\");\n const envPath = resolve(options.targetDir, \".env\");\n const checks: SetupCheck[] = [\n {\n name: \"node\",\n status: nodeMajor >= NODE_ENGINE_FLOOR ? \"pass\" : \"fail\",\n detail: `Node.js ${nodeVersion} detected; version ${NODE_ENGINE_FLOOR} or newer is required (package.json engines).`,\n },\n {\n name: \"env-template\",\n status: fsImpl.existsSync(examplePath) ? \"pass\" : \"fail\",\n detail: fsImpl.existsSync(examplePath)\n ? `Template found: ${examplePath}`\n : `Template missing: ${examplePath} (expected next to the installed package).`,\n },\n ];\n\n let created = false;\n if (options.writeEnv) {\n if (fsImpl.existsSync(envPath)) {\n checks.push({\n name: \"env-file\",\n status: \"pass\",\n detail: `${envPath} already exists; left untouched (no overwrite).`,\n });\n } else if (!fsImpl.existsSync(examplePath)) {\n checks.push({\n name: \"env-file\",\n status: \"fail\",\n detail: `Cannot create ${envPath}: template ${examplePath} is missing.`,\n });\n } else {\n try {\n fsImpl.writeFileSync(envPath, fsImpl.readFileSync(examplePath, \"utf-8\"), \"utf-8\");\n created = true;\n checks.push({\n name: \"env-file\",\n status: \"pass\",\n detail: `Created ${envPath} from template; edit it and set GOOGLE_MAPS_API_KEY.`,\n });\n } catch (error: unknown) {\n checks.push({\n name: \"env-file\",\n status: \"fail\",\n detail: `Failed to create ${envPath}: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n }\n } else {\n checks.push({\n name: \"env-file\",\n status: fsImpl.existsSync(envPath) ? \"pass\" : \"skip\",\n detail: fsImpl.existsSync(envPath)\n ? `${envPath} found.`\n : `${envPath} not found; rerun with --write-env to create it from the template.`,\n });\n }\n\n checks.push({\n name: \"api-key\",\n status: config.apiKey ? \"pass\" : \"fail\",\n detail: config.apiKey\n ? `GOOGLE_MAPS_API_KEY is configured (source: ${config.apiKeySource}, value hidden).`\n : \"GOOGLE_MAPS_API_KEY is not configured. Set it in the environment or in .env after scaffolding.\",\n });\n\n return {\n success: checks.every((check) => check.status !== \"fail\"),\n created,\n checks,\n };\n}\n\n// --------------- Snippet Mode ---------------\n\n/**\n * @brief Renders a client registration snippet and routes output per PRJ-008.\n * @details Delegates JSON construction to `renderClientSnippet`, writes the\n * snippet JSON to `stdout` and each guidance note to `stderr` so stdout stays\n * pure JSON; never writes or edits any file. Rendering errors surface as a\n * JSON stderr error with exit code 1. Complexity O(1).\n * @param options {SnippetOptions} Rendering options forwarded to `renderClientSnippet`.\n * @param streams {ExecStreams} Injectable stdout/stderr sinks; defaults to process streams.\n * @return {number} Exit code: 0 on success, 1 on a rendering error.\n * @see renderClientSnippet\n * @satisfies PRJ-010, REQ-092, REQ-093\n */\nexport function runSnippetCommand(\n options: SnippetOptions,\n streams: ExecStreams = { stdout: process.stdout, stderr: process.stderr }\n): number {\n try {\n const snippet = renderClientSnippet(options);\n streams.stdout.write(snippet.json + \"\\n\");\n for (const note of snippet.notes) {\n streams.stderr.write(`[snippet] ${note}\\n`);\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// --------------- CLI Configuration Management ---------------\n\n/**\n * @brief Enables or disables one supported CLI in the persisted settings.\n * @details Resolves the CLI adapter case-insensitively; unsupported names\n * exit 2 with a JSON stderr error listing supported names (REQ-110).\n * Idempotent: enabling an enabled CLI and disabling a disabled CLI succeed\n * without rewriting the settings file (REQ-111). Success prints a JSON\n * result on stdout (PRJ-008).\n * @param name {string} CLI name from the command line.\n * @param enable {boolean} True to enable; false to disable.\n * @param options {object} `{ home?, streams? }`; streams default to process streams.\n * @return {number} Exit code: 0 on success, 2 for an unsupported CLI.\n * @see loadCliSettings\n * @see saveCliSettings\n * @satisfies REQ-110, REQ-111\n */\nexport function runEnableDisableCliCommand(\n name: string,\n enable: boolean,\n options: { home?: string; streams?: ExecStreams } = {}\n): number {\n const streams = options.streams ?? { stdout: process.stdout, stderr: process.stderr };\n const target = resolveCliTarget(name);\n if (target === undefined) {\n streams.stderr.write(\n JSON.stringify({ error: `Unsupported CLI: ${name}. Supported: ${supportedCliNames()}.` }, null, 2) + \"\\n\"\n );\n return 2;\n }\n const settings = loadCliSettings(options.home);\n const already = settings.enabled.includes(target.id);\n if (enable === already) {\n streams.stdout.write(\n JSON.stringify({ cli: target.id, enabled: enable, message: `${target.id} is already ${enable ? \"enabled\" : \"disabled\"}.` }, null, 2) + \"\\n\"\n );\n return 0;\n }\n settings.enabled = enable\n ? [...settings.enabled, target.id]\n : settings.enabled.filter((item) => item !== target.id);\n saveCliSettings(settings, options.home);\n streams.stdout.write(\n JSON.stringify({ cli: target.id, enabled: enable, message: `${enable ? \"Enabled\" : \"Disabled\"} ${target.id}.` }, null, 2) + \"\\n\"\n );\n return 0;\n}\n\n/**\n * @brief Shared handler for the `install` and `uninstall` commands.\n * @details Runs the requested operation over every enabled CLI, prints the\n * aggregate JSON result on stdout, and exits 1 when any per-CLI failure was\n * collected (REQ-116). With zero enabled CLIs prints the enable hint and\n * exits 0 (REQ-119). Diagnostics ride in the JSON `errors` array so stdout\n * stays the single machine-readable channel (PRJ-008).\n * @param operation {\"install\" | \"uninstall\"} Requested reciprocal operation.\n * @param options {object} `{ home?, apiKey?, resourcesRoot, streams? }`.\n * @return {number} Exit code: 0 on success or zero enabled CLIs, 1 on failures.\n * @see installEnabledCliResources\n * @see uninstallEnabledCliResources\n * @satisfies REQ-114, REQ-115, REQ-116, REQ-119\n */\nexport function runInstallUninstallCommand(\n operation: \"install\" | \"uninstall\",\n options: { home?: string; apiKey?: string; resourcesRoot: string; streams?: ExecStreams }\n): number {\n const streams = options.streams ?? { stdout: process.stdout, stderr: process.stderr };\n if (loadCliSettings(options.home).enabled.length === 0) {\n streams.stdout.write(\n JSON.stringify(\n {\n success: true,\n message: \"No CLI enabled. Use 'mcp-google-map enable <cli name>' first.\",\n summaries: [],\n errors: [],\n },\n null,\n 2\n ) + \"\\n\"\n );\n return 0;\n }\n let result: CliOperationResult;\n try {\n result =\n operation === \"install\"\n ? installEnabledCliResources({ home: options.home, apiKey: options.apiKey, resourcesRoot: options.resourcesRoot })\n : uninstallEnabledCliResources({ home: options.home, resourcesRoot: options.resourcesRoot });\n } catch (error: unknown) {\n streams.stderr.write(\n JSON.stringify({ success: false, errors: [error instanceof Error ? error.message : String(error)] }, null, 2) + \"\\n\"\n );\n return 1;\n }\n streams.stdout.write(\n JSON.stringify({ success: result.errors.length === 0, operation, summaries: result.summaries, errors: result.errors }, null, 2) + \"\\n\"\n );\n return result.errors.length > 0 ? 1 : 0;\n}\n\n/**\n * @brief Prints the CLI Configuration and Installation Status tables.\n * @details Delegates rendering to `buildCliShowReport` and writes the report\n * text to stdout (human-readable exception to PRJ-008). Manifest or render\n * failures surface as a JSON stderr error with exit code 1.\n * @param options {object} `{ home?, resourcesRoot, streams? }`.\n * @return {number} Exit code: 0 on success, 1 on a report failure.\n * @see buildCliShowReport\n * @satisfies REQ-117, REQ-118, REQ-119\n */\nexport function runShowCommand(\n options: { home?: string; resourcesRoot: string; streams?: ExecStreams }\n): number {\n const streams = options.streams ?? { stdout: process.stdout, stderr: process.stderr };\n try {\n streams.stdout.write(buildCliShowReport(options) + \"\\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// --------------- 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 // Load environment files before command dispatch: explicit --env-file wins\n // over the implicit cwd/package .env discovery chain.\n loadEnvironment(extractEnvFileOption(process.argv));\n\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(\"probes\", {\n type: \"string\",\n description: \"Comma-separated subset of live probes: geocoding, places-new, routes (default: all three)\",\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 [\"$0 doctor --live --probes geocoding,routes\", \"Probe only the selected APIs\"],\n ]),\n async (argv) => {\n const parsedProbes = parseDoctorProbes(argv.probes as string | undefined);\n if (parsedProbes.error) {\n process.stderr.write(JSON.stringify({ error: parsedProbes.error }, null, 2) + \"\\n\");\n process.exitCode = 1;\n return;\n }\n const report = await runDoctor(packageVersion, argv.apikey as string | undefined, argv.live as boolean, undefined, {\n probes: parsedProbes.probes,\n config: resolveRuntimeConfig(process.env, { envFile: extractEnvFileOption(process.argv) }),\n });\n process.stdout.write(JSON.stringify(report, null, 2) + \"\\n\");\n process.exitCode = report.success ? 0 : 1;\n }\n )\n .command(\n \"setup\",\n \"Non-interactive onboarding: verify local readiness, optionally scaffold .env\",\n (yargs) =>\n yargs\n .option(\"write-env\", {\n type: \"boolean\",\n default: false,\n description: \"Create .env from .env.example in --env-dir when it does not exist (never overwrites)\",\n })\n .option(\"env-dir\", {\n type: \"string\",\n default: process.cwd(),\n description: \"Directory where .env is looked up / created\",\n })\n .example([\n [\"$0 setup\", \"Check readiness without writing anything\"],\n [\"$0 setup --write-env\", \"Also scaffold .env from the package template\"],\n ]),\n async (argv) => {\n const report = await runSetup({\n packageDir: resolve(__dirname, \"..\"),\n targetDir: argv.envDir as string,\n writeEnv: argv.writeEnv as boolean,\n });\n process.stdout.write(JSON.stringify(report, null, 2) + \"\\n\");\n process.exitCode = report.success ? 0 : 1;\n }\n )\n .command(\n \"snippet\",\n \"Print an MCP client registration snippet (JSON on stdout; never writes files)\",\n (yargs) =>\n yargs\n .option(\"client\", {\n type: \"string\",\n choices: [\"generic\", \"claude\", \"cursor\", \"pi\"],\n default: \"generic\",\n description: \"Target client (selects the documented target file)\",\n })\n .option(\"transport\", {\n type: \"string\",\n choices: [\"stdio\", \"http\"],\n default: \"stdio\",\n description: \"MCP transport of the snippet\",\n })\n .option(\"launcher\", {\n type: \"string\",\n choices: [\"npx\", \"node\", \"bin\"],\n default: \"npx\",\n description: \"stdio launcher command\",\n })\n .option(\"command\", {\n type: \"string\",\n description: \"Absolute path to dist/cli.js (required for --launcher node)\",\n })\n .option(\"host\", {\n type: \"string\",\n default: \"127.0.0.1\",\n description: \"Host used in the URL (transport http)\",\n })\n .option(\"port\", {\n type: \"number\",\n default: 3000,\n description: \"Port used in the URL (transport http)\",\n })\n .option(\"env-key\", {\n type: \"string\",\n description: 'Emit a ${NAME} variable reference instead of a literal placeholder (expansion is client-specific)',\n })\n .option(\"name\", {\n type: \"string\",\n default: \"mcp-google-map\",\n description: \"Server name inside mcpServers\",\n })\n .example([\n [\"$0 snippet --client claude\", \"stdio snippet using the npx launcher\"],\n [\"$0 snippet --client pi --launcher node --command /abs/path/dist/cli.js\", \"stdio snippet with an explicit artifact\"],\n [\"$0 snippet --transport http --port 3100\", \"HTTP URL snippet\"],\n ]),\n (argv) => {\n process.exitCode = runSnippetCommand({\n client: argv.client as SnippetClient,\n transport: argv.transport as \"stdio\" | \"http\",\n launcher: argv.launcher as \"npx\" | \"node\" | \"bin\",\n commandPath: argv.command as string | undefined,\n host: argv.host as string,\n port: argv.port as number,\n envKey: argv.envKey as string | undefined,\n serverName: argv.name as string,\n });\n }\n )\n .command(\n \"enable <cli>\",\n \"Enable MCP-server and skill installation for a supported CLI\",\n (yargs) =>\n yargs\n .positional(\"cli\", {\n type: \"string\",\n describe: `CLI name: ${supportedCliNames()}`,\n })\n .option(\"home\", {\n type: \"string\",\n description: \"Home-directory override for the settings file (default: user home)\",\n })\n .example([[\"$0 enable pi\", \"Enable pi for install/uninstall/show\"]]),\n (argv) => {\n process.exitCode = runEnableDisableCliCommand(argv.cli as string, true, {\n home: argv.home as string | undefined,\n });\n }\n )\n .command(\n \"disable <cli>\",\n \"Disable MCP-server and skill installation for a supported CLI\",\n (yargs) =>\n yargs\n .positional(\"cli\", {\n type: \"string\",\n describe: `CLI name: ${supportedCliNames()}`,\n })\n .option(\"home\", {\n type: \"string\",\n description: \"Home-directory override for the settings file (default: user home)\",\n })\n .example([[\"$0 disable claude\", \"Disable claude for install/uninstall/show\"]]),\n (argv) => {\n process.exitCode = runEnableDisableCliCommand(argv.cli as string, false, {\n home: argv.home as string | undefined,\n });\n }\n )\n .command(\n \"install\",\n \"Register the mcp-google-map stdio server and install packaged skills for every enabled CLI\",\n (yargs) =>\n yargs\n .option(\"home\", {\n type: \"string\",\n description: \"Home-directory override for CLI configuration paths (default: user home)\",\n })\n .option(\"apikey\", {\n alias: \"k\",\n type: \"string\",\n description: \"Google Maps API key embedded in the registered entry (prefer GOOGLE_MAPS_API_KEY)\",\n default: resolveRuntimeConfig(process.env, { envFile: extractEnvFileOption(process.argv) }).apiKey,\n })\n .example([[\"$0 install\", \"Register the server and skills in every enabled CLI\"]]),\n (argv) => {\n process.exitCode = runInstallUninstallCommand(\"install\", {\n home: argv.home as string | undefined,\n apiKey: argv.apikey as string | undefined,\n resourcesRoot: resolveSkillsResourcesRoot(resolve(__dirname, \"..\")),\n });\n }\n )\n .command(\n \"uninstall\",\n \"Remove the mcp-google-map server entry and managed skills from every enabled CLI\",\n (yargs) =>\n yargs\n .option(\"home\", {\n type: \"string\",\n description: \"Home-directory override for CLI configuration paths (default: user home)\",\n })\n .example([[\"$0 uninstall\", \"Reciprocal removal of install for every enabled CLI\"]]),\n (argv) => {\n process.exitCode = runInstallUninstallCommand(\"uninstall\", {\n home: argv.home as string | undefined,\n resourcesRoot: resolveSkillsResourcesRoot(resolve(__dirname, \"..\")),\n });\n }\n )\n .command(\n \"show\",\n \"Show CLI configuration and installation status tables (human-readable)\",\n (yargs) =>\n yargs\n .option(\"home\", {\n type: \"string\",\n description: \"Home-directory override for CLI configuration paths (default: user home)\",\n })\n .example([[\"$0 show\", \"Print CLI Configuration and Installation Status tables\"]]),\n (argv) => {\n process.exitCode = runShowCommand({\n home: argv.home as string | undefined,\n resourcesRoot: resolveSkillsResourcesRoot(resolve(__dirname, \"..\")),\n });\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 (default 127.0.0.1 loopback; 0.0.0.0 for all interfaces)\",\n default: process.env.MCP_SERVER_HOST || \"127.0.0.1\",\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)\n .then((outcome) => {\n if (outcome.started === 0) {\n process.exit(1);\n }\n })\n .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 .option(\"env-file\", {\n type: \"string\",\n global: true,\n description: \"Load environment variables from this exact file (error if missing; no implicit .env fallback)\",\n })\n .help()\n .parse();\n}\n","import { config as dotenvConfig } from \"dotenv\";\nimport { existsSync } from \"fs\";\nimport { isAutoUpdateDisabled } from \"./autoUpdate.js\";\n\n/**\n * @brief Minimum Node.js major version required by `package.json` `engines`.\n * @details Single source of truth shared by the `doctor` local check and the\n * `setup` onboarding check so both enforce exactly the runtime floor declared\n * for the package (CTN-005). Complexity O(1); pure constant.\n * @satisfies CTN-005, REQ-070\n */\nexport const NODE_ENGINE_FLOOR = 22;\n\n/**\n * @brief Default HTTP bind address (loopback) used when no host is configured.\n * @details Loopback default limits unintended network exposure; callers that\n * need all interfaces pass `--host 0.0.0.0` or set `MCP_SERVER_HOST=0.0.0.0`\n * (REQ-008, PKG-018). Complexity O(1); pure constant.\n * @satisfies REQ-008\n */\nexport const DEFAULT_HTTP_HOST = \"127.0.0.1\";\n\n/**\n * @brief Default HTTP port used when no port is configured.\n * @details Fallback port mirroring the historical default; overridable via\n * `--port` or `MCP_SERVER_PORT` (REQ-008). Complexity O(1); pure constant.\n * @satisfies REQ-008\n */\nexport const DEFAULT_HTTP_PORT = 3000;\n\n/**\n * @brief Higher-priority values that override environment-derived configuration.\n * @details Flags parsed from CLI arguments; every field optional. `flag`\n * source wins over `environment` which wins over `default`.\n */\nexport interface RuntimeConfigOverrides {\n apiKey?: string;\n host?: string;\n port?: number;\n envFile?: string;\n}\n\n/** @brief Origin tag attached to each resolved configuration field. */\nexport type RuntimeConfigSource = \"flag\" | \"environment\" | \"default\";\n\n/**\n * @brief Typed snapshot of every runtime configuration field with per-field source.\n * @details Produced exclusively by `resolveRuntimeConfig`; consumed by all CLI\n * commands and `doctor` diagnostics (DES-015). `port` is undefined when the\n * configured value cannot be parsed to an integer; `portRaw` preserves the\n * original string for remediation messages.\n */\nexport interface ResolvedRuntimeConfig {\n apiKey: string | undefined;\n apiKeySource: \"flag\" | \"environment\" | \"none\";\n host: string;\n hostSource: RuntimeConfigSource;\n port: number | undefined;\n portRaw: string | undefined;\n portSource: RuntimeConfigSource;\n enabledToolsRaw: string | undefined;\n enabledToolsSource: RuntimeConfigSource;\n autoUpdateDisabled: boolean;\n envFile: string | undefined;\n}\n\n/**\n * @brief Resolves runtime configuration from an environment map plus flag overrides.\n * @details Priority per field: overrides (`flag`) > environment map\n * (`environment`) > built-in default (`default`). Port parsing: flag port used\n * as-is; environment string parsed with `Number` and left undefined when not a\n * finite integer (raw preserved in `portRaw`). `enabledToolsRaw` keeps the\n * trimmed `GOOGLE_MAPS_ENABLED_TOOLS` string; empty string normalizes to\n * undefined. `autoUpdateDisabled` delegates to `isAutoUpdateDisabled`. Pure:\n * reads inputs only, mutates nothing. Complexity O(1).\n * @param env {Record<string, string | undefined>} Environment map; defaults to `process.env`.\n * @param overrides {RuntimeConfigOverrides} Flag-derived overrides; defaults to none.\n * @return {ResolvedRuntimeConfig} Fully typed configuration with per-field sources.\n * @see isAutoUpdateDisabled\n * @see validateHttpEndpoint\n * @satisfies DES-015\n */\nexport function resolveRuntimeConfig(\n env: Record<string, string | undefined> = process.env,\n overrides: RuntimeConfigOverrides = {}\n): ResolvedRuntimeConfig {\n const envPort = env.MCP_SERVER_PORT?.trim() || undefined;\n\n let port: number | undefined;\n let portRaw: string | undefined;\n let portSource: RuntimeConfigSource;\n if (overrides.port !== undefined) {\n port = overrides.port;\n portRaw = String(overrides.port);\n portSource = \"flag\";\n } else if (envPort !== undefined) {\n const parsed = Number(envPort);\n port = Number.isFinite(parsed) ? parsed : undefined;\n portRaw = envPort;\n portSource = \"environment\";\n } else {\n port = DEFAULT_HTTP_PORT;\n portRaw = undefined;\n portSource = \"default\";\n }\n\n const apiKey = overrides.apiKey ?? env.GOOGLE_MAPS_API_KEY;\n const enabledToolsRaw = env.GOOGLE_MAPS_ENABLED_TOOLS?.trim() || undefined;\n\n return {\n apiKey,\n apiKeySource: overrides.apiKey !== undefined ? \"flag\" : apiKey ? \"environment\" : \"none\",\n host: overrides.host ?? env.MCP_SERVER_HOST ?? DEFAULT_HTTP_HOST,\n hostSource: overrides.host !== undefined ? \"flag\" : env.MCP_SERVER_HOST ? \"environment\" : \"default\",\n port,\n portRaw,\n portSource,\n enabledToolsRaw,\n enabledToolsSource: enabledToolsRaw ? \"environment\" : \"default\",\n autoUpdateDisabled: isAutoUpdateDisabled(env),\n envFile: overrides.envFile,\n };\n}\n\n/**\n * @brief Masks a secret value for safe inclusion in reports and diagnostics.\n * @details `undefined`/empty -> `unset`; length <= 8 -> `****`; otherwise first\n * four characters + `****` + last four characters. The raw secret never\n * appears in the output. Pure; complexity O(n) in value length.\n * @param value {string | undefined} Secret to mask (e.g. Google Maps API key).\n * @return {string} Masked representation safe for stderr/stdout reports.\n * @satisfies DES-016, REQ-089\n */\nexport function maskSecret(value: string | undefined): string {\n if (!value) {\n return \"unset\";\n }\n if (value.length <= 8) {\n return \"****\";\n }\n return `${value.slice(0, 4)}****${value.slice(-4)}`;\n}\n\n/**\n * @brief Per-field effective-value diagnostic structure with masked secrets.\n * @details Every field carries its resolved value (masked when secret) and its\n * `RuntimeConfigSource`; produced by `describeRuntimeConfig` and embedded in\n * `doctor` local reports.\n */\nexport interface ConfigDiagnostics {\n apiKey: { value: string; source: \"flag\" | \"environment\" | \"none\" };\n httpHost: { value: string; source: RuntimeConfigSource };\n httpPort: { value: number | null; raw: string | null; source: RuntimeConfigSource };\n enabledTools: { value: string; source: RuntimeConfigSource };\n autoUpdateCheck: { enabled: boolean };\n envFile: { value: string | null };\n}\n\n/**\n * @brief Builds a serializable diagnostic view of a resolved configuration.\n * @details Maps `ResolvedRuntimeConfig` to `ConfigDiagnostics`, masking the API\n * key via `maskSecret` so the result is safe to print. Complexity O(1); pure.\n * @param config {ResolvedRuntimeConfig} Configuration produced by `resolveRuntimeConfig`.\n * @return {ConfigDiagnostics} Masked, source-annotated diagnostics.\n * @see maskSecret\n * @satisfies REQ-089, DES-016\n */\nexport function describeRuntimeConfig(config: ResolvedRuntimeConfig): ConfigDiagnostics {\n return {\n apiKey: { value: maskSecret(config.apiKey), source: config.apiKeySource },\n httpHost: { value: config.host, source: config.hostSource },\n httpPort: {\n value: config.port ?? null,\n raw: config.portRaw ?? null,\n source: config.portSource,\n },\n enabledTools: { value: config.enabledToolsRaw ?? \"*\", source: config.enabledToolsSource },\n autoUpdateCheck: { enabled: !config.autoUpdateDisabled },\n envFile: { value: config.envFile ?? null },\n };\n}\n\n/**\n * @brief Formats config diagnostics as one compact human-readable line.\n * @details Joins `key=value (source)` fragments; the API key is pre-masked by\n * `describeRuntimeConfig`. Used as `doctor` check detail text. Complexity O(1).\n * @param diagnostics {ConfigDiagnostics} Output of `describeRuntimeConfig`.\n * @return {string} Single-line `;`-separated diagnostic string.\n * @see describeRuntimeConfig\n * @satisfies REQ-089\n */\nexport function formatConfigDiagnostics(diagnostics: ConfigDiagnostics): string {\n return [\n `host=${diagnostics.httpHost.value} (${diagnostics.httpHost.source})`,\n `port=${diagnostics.httpPort.value ?? \"invalid\"} (raw: ${diagnostics.httpPort.raw ?? \"n/a\"}, ${diagnostics.httpPort.source})`,\n `apiKey=${diagnostics.apiKey.value} (${diagnostics.apiKey.source})`,\n `enabledTools=${diagnostics.enabledTools.value} (${diagnostics.enabledTools.source})`,\n `updateCheck=${diagnostics.autoUpdateCheck.enabled ? \"enabled\" : \"disabled\"}`,\n ].join(\"; \");\n}\n\n/**\n * @brief Outcome of HTTP endpoint validation over a resolved configuration.\n * @details `valid` is false when `errors` is non-empty; each error is a\n * remediation-oriented message.\n */\nexport interface HttpEndpointValidation {\n valid: boolean;\n errors: string[];\n}\n\n/**\n * @brief Validates the HTTP bind endpoint of a resolved configuration.\n * @details Rules: port must be defined, an integer in 1..65535; host must be a\n * non-empty string. Returns every violated rule as a remediation message.\n * Pure; complexity O(1).\n * @param config {ResolvedRuntimeConfig} Configuration to validate.\n * @return {HttpEndpointValidation} `valid` plus per-rule error messages.\n * @satisfies REQ-009\n */\nexport function validateHttpEndpoint(config: ResolvedRuntimeConfig): HttpEndpointValidation {\n const errors: string[] = [];\n if (config.port === undefined || !Number.isInteger(config.port) || config.port < 1 || config.port > 65535) {\n errors.push(`invalid MCP_SERVER_PORT value \"${config.portRaw ?? config.port}\" (expected integer 1-65535)`);\n }\n if (!config.host || config.host.trim().length === 0) {\n errors.push(\"empty MCP_SERVER_HOST value (expected a non-empty bind address)\");\n }\n return { valid: errors.length === 0, errors };\n}\n\n/**\n * @brief Result of loading an explicit `--env-file` file.\n * @details `ok` false carries an `error` message suitable for CLI JSON errors.\n */\nexport interface ExplicitEnvFileResult {\n ok: boolean;\n error?: string;\n}\n\n/**\n * @brief Loads exactly one explicit environment file via dotenv.\n * @details Checks existence first (dotenv silently ignores missing files) and\n * returns `{ ok: false, error }` when absent; otherwise loads the file without\n * overriding already-set process variables. Complexity O(file size).\n * @param path {string} Absolute or relative path to the environment file.\n * @return {ExplicitEnvFileResult} `{ ok: true }` on load; `{ ok: false, error }` when missing.\n * @satisfies CTN-009\n */\nexport function applyExplicitEnvFile(path: string): ExplicitEnvFileResult {\n if (!existsSync(path)) {\n return { ok: false, error: `env file not found: ${path}` };\n }\n dotenvConfig({ path });\n return { ok: true };\n}\n\n/**\n * @brief Result of resolving the `GOOGLE_MAPS_ENABLED_TOOLS` allowlist.\n * @details `names` is the effective tool-name list; `matched` counts allowlist\n * hits; `fallback` is true when the allowlist matched zero tools and the full\n * set is returned (REQ-012); `requested` lists the parsed allowlist items.\n */\nexport interface EnabledToolsResolution {\n names: string[];\n matched: number;\n fallback: boolean;\n requested: string[];\n}\n\n/**\n * @brief Resolves the enabled-tool allowlist against the full tool registry.\n * @details Semantics: unset, empty, or `*` -> full set (REQ-010); at least one\n * matching name -> the named subset, items trimmed and empties ignored\n * (REQ-011); zero matches -> full set with `fallback: true` (REQ-012). Pure;\n * complexity O(n + m) with n registry names and m allowlist items.\n * @param allToolNames {readonly string[]} Full registered tool-name registry.\n * @param raw {string | undefined} Raw `GOOGLE_MAPS_ENABLED_TOOLS` value.\n * @return {EnabledToolsResolution} Effective names plus resolution metadata.\n * @satisfies REQ-010, REQ-011, REQ-012, PRJ-006\n */\nexport function resolveEnabledToolNames(\n allToolNames: readonly string[],\n raw: string | undefined\n): EnabledToolsResolution {\n const trimmed = raw?.trim();\n if (!trimmed || trimmed === \"*\") {\n return { names: [...allToolNames], matched: allToolNames.length, fallback: false, requested: [] };\n }\n\n const requested = trimmed\n .split(\",\")\n .map((item) => item.trim())\n .filter(Boolean);\n const enabled = new Set(requested);\n const names = allToolNames.filter((name) => enabled.has(name));\n\n if (names.length === 0) {\n return { names: [...allToolNames], matched: 0, fallback: true, requested };\n }\n return { names, matched: names.length, fallback: false, requested };\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","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 { resolveEnabledToolNames } from \"./utils/configResolver.js\";\nimport { 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\n/**\n * @brief Applies the `GOOGLE_MAPS_ENABLED_TOOLS` allowlist to a tool registry.\n * @details Delegates allowlist semantics to `resolveEnabledToolNames` (unset,\n * empty, or `*` -> full set; >=1 match -> subset; 0 matches -> full set plus\n * stderr error). Logs the active-count line only when a strict subset is\n * selected, preserving legacy output. Complexity O(n + m).\n * @param tools {ToolConfig[]} Full tool registry.\n * @return {ToolConfig[]} Effective tool list (never empty for a non-empty input).\n * @see resolveEnabledToolNames\n * @satisfies PRJ-006, REQ-010, REQ-011, REQ-012\n */\nexport function filterTools(tools: ToolConfig[]): ToolConfig[] {\n const resolution = resolveEnabledToolNames(\n tools.map((tool) => tool.name),\n process.env.GOOGLE_MAPS_ENABLED_TOOLS\n );\n\n if (resolution.fallback) {\n Logger.error(`GOOGLE_MAPS_ENABLED_TOOLS matched 0 tools. Available: ${tools.map((t) => t.name).join(\", \")}`);\n return tools;\n }\n\n if (resolution.matched !== tools.length) {\n Logger.log(`GOOGLE_MAPS_ENABLED_TOOLS: ${resolution.matched}/${tools.length} tools active`);\n }\n\n const enabled = new Set(resolution.names);\n return tools.filter((tool) => enabled.has(tool.name));\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 /**\n * @brief Starts the Streamable HTTP listener and resolves once it is accepting connections.\n * @details Builds the Express app with the `/mcp` POST/GET/DELETE handlers,\n * then wraps `app.listen` in a Promise that resolves from the listen callback\n * and rejects on the server `error` event (e.g. EADDRINUSE), so callers get\n * a reliable startup outcome instead of an unhandled error. Default host is\n * loopback `127.0.0.1` (REQ-008); pass `0.0.0.0` to bind all interfaces.\n * @param port {number} TCP port to listen on (1-65535).\n * @param host {string} Bind address; defaults to `127.0.0.1`.\n * @return {Promise<void>} Resolves when listening; rejects with the listen error.\n * @throws {Error} Rejects when the HTTP listener emits an error (port in use, permission denied).\n * @satisfies REQ-008, REQ-095\n */\n async startHttpServer(port: number, host: string = \"127.0.0.1\"): 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 await new Promise<void>((resolve, reject) => {\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 resolve();\n });\n this.httpServer!.on(\"error\", (error: Error) => reject(error));\n });\n }\n\n async startStdio(): Promise<void> {\n const transport = new StdioServerTransport();\n await this.connect(transport);\n }\n\n /**\n * @brief Stops the HTTP listener and closes every session transport in order.\n * @details Idempotent: when no listener exists it logs and resolves. Otherwise\n * it detaches the server reference, clears the session map, awaits\n * `transport.close()` for every session (errors tolerated via allSettled),\n * calls `closeAllConnections` when available, and finally closes the socket.\n * Wired to SIGINT/SIGTERM through `installShutdownHandlers` (REQ-096).\n * @return {Promise<void>} Resolves after the socket closes; rejects when `server.close` errors.\n * @throws {Error} Rejects with the `server.close` error.\n * @satisfies REQ-096\n */\n async stopHttpServer(): Promise<void> {\n const server = this.httpServer;\n if (!server) {\n Logger.error(`[${this.serverName}] HTTP server is not running or already stopped.`);\n return;\n }\n\n this.httpServer = null;\n const closingSessions = Object.values(this.sessions);\n this.sessions = {};\n await Promise.allSettled(closingSessions.map((context) => context.transport.close()));\n if (closingSessions.length > 0) {\n Logger.log(`[${this.serverName}] All transports closed.`);\n }\n\n return new Promise((resolve, reject) => {\n server.closeAllConnections?.();\n server.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 resolve();\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 * @brief Identifier of a Google Maps Platform API consumed by a tool.\n * @details Stable machine-readable ids used across tool profiles, `doctor`\n * local reports, and documentation tables.\n */\nexport type GoogleApiId =\n | \"geocoding\"\n | \"places-new\"\n | \"routes\"\n | \"timezone\"\n | \"elevation\"\n | \"static-maps\"\n | \"weather\"\n | \"air-quality\";\n\n/**\n * @brief Human-readable Google Cloud Console names for each `GoogleApiId`.\n * @details Matches the service display names in the Google Cloud Console so\n * diagnostics map one-to-one onto enablement screens. Complexity O(1); pure.\n */\nexport const GOOGLE_API_LABELS: Readonly<Record<GoogleApiId, string>> = {\n geocoding: \"Geocoding API\",\n \"places-new\": \"Places API (New)\",\n routes: \"Routes API\",\n timezone: \"Time Zone API\",\n elevation: \"Maps Elevation API\",\n \"static-maps\": \"Maps Static API\",\n weather: \"Weather API\",\n \"air-quality\": \"Air Quality API\",\n};\n\n/**\n * @brief Dependency profile of one MCP tool.\n * @details `apis` lists every Google API the tool can call at runtime\n * (including dependencies reached through composite resolution such as\n * address geocoding or text-search fallback); `dependsOnTools` lists the\n * sibling tools whose operations the composite tool chains internally.\n */\nexport interface ToolApiProfile {\n readonly tool: string;\n readonly apis: readonly GoogleApiId[];\n readonly dependsOnTools: readonly string[];\n}\n\n/**\n * @brief Machine-readable tool -> Google API dependency registry (18 entries).\n * @details Covers every tool of PRJ-001. Composite tools\n * (`maps_explore_area`, `maps_plan_route`, `maps_compare_places`,\n * `maps_search_along_route`, `maps_local_rank_tracker`, `maps_batch_geocode`)\n * list both the union of the Google APIs their chain can reach and the tool\n * names they compose. Complexity O(1); pure constant data.\n * @satisfies PRJ-009\n */\nexport const TOOL_API_PROFILES: Readonly<Record<string, ToolApiProfile>> = {\n maps_geocode: { tool: \"maps_geocode\", apis: [\"geocoding\"], dependsOnTools: [] },\n maps_reverse_geocode: { tool: \"maps_reverse_geocode\", apis: [\"geocoding\"], dependsOnTools: [] },\n maps_batch_geocode: { tool: \"maps_batch_geocode\", apis: [\"geocoding\"], dependsOnTools: [\"maps_geocode\"] },\n maps_search_nearby: {\n tool: \"maps_search_nearby\",\n apis: [\"places-new\", \"geocoding\"],\n dependsOnTools: [\"maps_geocode\"],\n },\n maps_search_places: { tool: \"maps_search_places\", apis: [\"places-new\"], dependsOnTools: [] },\n maps_place_details: { tool: \"maps_place_details\", apis: [\"places-new\"], dependsOnTools: [] },\n maps_directions: { tool: \"maps_directions\", apis: [\"routes\"], dependsOnTools: [] },\n maps_distance_matrix: { tool: \"maps_distance_matrix\", apis: [\"routes\"], dependsOnTools: [] },\n maps_elevation: { tool: \"maps_elevation\", apis: [\"elevation\"], dependsOnTools: [] },\n maps_timezone: { tool: \"maps_timezone\", apis: [\"timezone\"], dependsOnTools: [] },\n maps_weather: { tool: \"maps_weather\", apis: [\"weather\"], dependsOnTools: [] },\n maps_air_quality: { tool: \"maps_air_quality\", apis: [\"air-quality\"], dependsOnTools: [] },\n maps_static_map: { tool: \"maps_static_map\", apis: [\"static-maps\"], dependsOnTools: [] },\n maps_explore_area: {\n tool: \"maps_explore_area\",\n apis: [\"places-new\", \"geocoding\"],\n dependsOnTools: [\"maps_geocode\", \"maps_search_nearby\", \"maps_place_details\"],\n },\n maps_plan_route: {\n tool: \"maps_plan_route\",\n apis: [\"routes\", \"geocoding\", \"places-new\"],\n dependsOnTools: [\"maps_geocode\", \"maps_search_places\", \"maps_directions\"],\n },\n maps_compare_places: {\n tool: \"maps_compare_places\",\n apis: [\"places-new\", \"routes\"],\n dependsOnTools: [\"maps_search_places\", \"maps_place_details\", \"maps_distance_matrix\"],\n },\n maps_search_along_route: {\n tool: \"maps_search_along_route\",\n apis: [\"routes\", \"places-new\"],\n dependsOnTools: [\"maps_directions\", \"maps_search_places\"],\n },\n maps_local_rank_tracker: {\n tool: \"maps_local_rank_tracker\",\n apis: [\"places-new\"],\n dependsOnTools: [\"maps_place_details\", \"maps_search_places\"],\n },\n};\n\n/**\n * @brief Looks up the dependency profile of one tool.\n * @details Direct registry access; unknown names return undefined so callers\n * decide whether to skip or report. Complexity O(1).\n * @param toolName {string} MCP tool name (e.g. `maps_geocode`).\n * @return {ToolApiProfile | undefined} Profile when registered; undefined otherwise.\n * @satisfies PRJ-009\n */\nexport function getToolProfile(toolName: string): ToolApiProfile | undefined {\n return TOOL_API_PROFILES[toolName];\n}\n\n/**\n * @brief Aggregated API-dependency summary for a set of enabled tools.\n * @details `tools` keeps per-tool ordering of the input; `apis` is the deduped,\n * registry-order union of required `GoogleApiId`s across all given tools.\n */\nexport interface ToolsProfileSummary {\n toolCount: number;\n apis: GoogleApiId[];\n tools: Array<{ tool: string; apis: GoogleApiId[]; dependsOnTools: string[] }>;\n}\n\n/**\n * @brief Aggregates tool/API profiles for the enabled tool set.\n * @details Maps each name through `TOOL_API_PROFILES` (unknown names and\n * duplicates are skipped), unions the required APIs in registry order without\n * duplicates, and echoes per-tool dependencies. No network access.\n * Complexity O(n) in tool names plus O(n*a) API union work.\n * @param toolNames {readonly string[]} Effective enabled tool names.\n * @return {ToolsProfileSummary} Per-tool profiles and aggregated API union.\n * @see getToolProfile\n * @satisfies PRJ-009, REQ-090\n */\nexport function describeToolsProfile(toolNames: readonly string[]): ToolsProfileSummary {\n const tools: ToolsProfileSummary[\"tools\"] = [];\n const apiOrder: GoogleApiId[] = [];\n const seenApis = new Set<GoogleApiId>();\n const seenTools = new Set<string>();\n\n for (const name of toolNames) {\n if (seenTools.has(name)) {\n continue;\n }\n const profile = TOOL_API_PROFILES[name];\n if (!profile) {\n continue;\n }\n seenTools.add(name);\n tools.push({\n tool: profile.tool,\n apis: [...profile.apis],\n dependsOnTools: [...profile.dependsOnTools],\n });\n for (const api of profile.apis) {\n if (!seenApis.has(api)) {\n seenApis.add(api);\n apiOrder.push(api);\n }\n }\n }\n\n return { toolCount: tools.length, apis: apiOrder, tools };\n}\n","/**\n * @brief Literal placeholder written into snippets when no `--env-key` is set.\n * @details Safe-by-default: valid on every MCP client because it contains no\n * variable-expansion syntax; the user replaces it with a real key.\n * @satisfies REQ-093\n */\nexport const API_KEY_PLACEHOLDER = \"<your-google-maps-api-key>\";\n\n/** @brief Supported MCP client targets; selects the documented target file. */\nexport type SnippetClient = \"generic\" | \"claude\" | \"cursor\" | \"pi\";\n\n/** @brief Supported MCP transports for the generated registration entry. */\nexport type SnippetTransport = \"stdio\" | \"http\";\n\n/** @brief stdio launcher strategy: `npx` one-shot, `node` with a script path, or the installed `bin`. */\nexport type SnippetLauncher = \"npx\" | \"node\" | \"bin\";\n\n/**\n * @brief Options controlling snippet rendering.\n * @details All fields optional; defaults: client `generic`, transport `stdio`,\n * launcher `npx`, serverName `mcp-google-map`, HTTP host `127.0.0.1`, port 3000.\n */\nexport interface SnippetOptions {\n client?: SnippetClient;\n transport?: SnippetTransport;\n launcher?: SnippetLauncher;\n commandPath?: string;\n host?: string;\n port?: number;\n envKey?: string;\n serverName?: string;\n}\n\n/**\n * @brief Rendered snippet plus stderr guidance notes.\n * @details `json` is a complete pretty-printed `mcpServers` registration\n * object (parses with `JSON.parse`); `notes` are human guidance lines the CLI\n * prints on stderr so stdout stays pure JSON (PRJ-008).\n */\nexport interface SnippetResult {\n json: string;\n notes: string[];\n}\n\n/** @brief Default loopback host used for HTTP snippet URLs. */\nconst SNIPPET_DEFAULT_HOST = \"127.0.0.1\";\n\n/** @brief Default port used for HTTP snippet URLs. */\nconst SNIPPET_DEFAULT_PORT = 3000;\n\n/**\n * @brief Target configuration file documented per `SnippetClient`.\n * @details Drives the stderr note that tells the user where to paste the\n * snippet; the JSON shape (`mcpServers`) is identical for all clients.\n */\nconst SNIPPET_CLIENT_TARGETS: Readonly<Record<SnippetClient, string>> = {\n generic: \"your MCP client configuration file\",\n claude: \"Claude Desktop: claude_desktop_config.json\",\n cursor: \"Cursor: .cursor/mcp.json\",\n pi: \"pi CLI: ~/.pi/agent/mcp.json (user) or .pi/mcp.json (project)\",\n};\n\n/**\n * @brief Renders a valid MCP-client registration snippet without writing files.\n * @details stdio transport: launcher `npx` -> `npx -y mcp-google-map --stdio`;\n * `bin` -> installed `mcp-google-map --stdio`; `node` -> `node <commandPath>\n * --stdio` and throws when `commandPath` is missing. HTTP transport: emits\n * `{ url: \"http://<host>:<port>/mcp\" }`. The `env` block embeds\n * `API_KEY_PLACEHOLDER` by default; a provided `envKey` switches the value to\n * the literal `${<envKey>}` and adds a note that variable expansion is\n * client-specific (REQ-093). Pure: no filesystem or network access; output is\n * JSON.stringify'd with 2-space indent. Complexity O(1).\n * @param options {SnippetOptions} Rendering options; defaults apply when omitted.\n * @return {SnippetResult} Pretty-printed JSON snippet plus stderr notes.\n * @throws {Error} When launcher is `node` and `commandPath` is missing.\n * @satisfies PRJ-010, REQ-092, REQ-093\n */\nexport function renderClientSnippet(options: SnippetOptions = {}): SnippetResult {\n const client = options.client ?? \"generic\";\n const transport = options.transport ?? \"stdio\";\n const serverName = options.serverName ?? \"mcp-google-map\";\n\n const notes: string[] = [`Paste this snippet into ${SNIPPET_CLIENT_TARGETS[client]}.`];\n notes.push(\"This command prints the snippet only; it never writes or edits configuration files.\");\n\n let entry: Record<string, unknown>;\n if (transport === \"http\") {\n const host = options.host ?? SNIPPET_DEFAULT_HOST;\n const port = options.port ?? SNIPPET_DEFAULT_PORT;\n entry = { url: `http://${host}:${port}/mcp` };\n notes.push(`Start the server first: mcp-google-map --host ${host} --port ${port}.`);\n } else {\n const launcher = options.launcher ?? \"npx\";\n if (launcher === \"node\" && !options.commandPath) {\n throw new Error('--launcher node requires --command <path> pointing at dist/cli.js');\n }\n const command = launcher === \"npx\" ? \"npx\" : launcher === \"bin\" ? \"mcp-google-map\" : \"node\";\n const args =\n launcher === \"npx\"\n ? [\"-y\", \"mcp-google-map\", \"--stdio\"]\n : launcher === \"bin\"\n ? [\"--stdio\"]\n : [options.commandPath as string, \"--stdio\"];\n if (launcher === \"npx\") {\n notes.push(\"The npx launcher runs the published package; npm must be available on PATH.\");\n }\n const apiKeyValue = options.envKey ? `\\${${options.envKey}}` : API_KEY_PLACEHOLDER;\n entry = { command, args, env: { GOOGLE_MAPS_API_KEY: apiKeyValue } };\n if (options.envKey) {\n notes.push(\n `Variable references (\\${${options.envKey}}) are client-specific: confirm your client expands environment variables before relying on them.`\n );\n } else {\n notes.push(`Replace ${API_KEY_PLACEHOLDER} with your Google Maps API key.`);\n }\n }\n\n const json = JSON.stringify({ mcpServers: { [serverName]: entry } }, null, 2);\n return { json, notes };\n}\n","/**\n * @file cliSettings.ts\n * @brief Persist the enabled-CLI set for the CLI configuration-management commands.\n * @details Stores `{\"enabled\": [\"<cli>\", ...]}` at\n * `<home>/.config/<SETTINGS_PROGRAM_NAME>/config.json`. The settings directory\n * segment is the distribution program name `mcp-google-map` (DES-021):\n * program-owned, never a shared or generic directory such as `skills`.\n * Loading tolerates missing, unreadable, non-object, or malformed content by\n * returning normalized defaults; saving serializes with two-space\n * indentation plus a trailing newline, writes a sibling temporary file,\n * and replaces the target atomically.\n * @satisfies DES-018, DES-021\n */\n\nimport { mkdirSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\n\n/**\n * @brief Distribution program name owning the settings directory.\n * @details Single source of truth for the settings directory segment\n * (DES-021): `.config/<SETTINGS_PROGRAM_NAME>/config.json`. Program-owned\n * by `mcp-google-map`; a shared or generic name such as `skills` is\n * forbidden. Keep in sync with the `package.json` `name` field.\n * @satisfies DES-021\n */\nexport const SETTINGS_PROGRAM_NAME = \"mcp-google-map\";\n\n/**\n * @brief Ordered path segments of the settings file relative to the home root.\n * @details `.config/<SETTINGS_PROGRAM_NAME>/config.json`; first element is\n * the XDG-style dotdir, second the program-owned directory name (DES-021).\n * @satisfies DES-018, DES-021\n */\nconst CLI_SETTINGS_RELATIVE = [\".config\", SETTINGS_PROGRAM_NAME, \"config.json\"] as const;\n\n/**\n * @brief Canonical server key used in every CLI MCP configuration.\n * @details Registered and removed under this exact name in JSON `mcpServers`\n * maps and TOML `mcp_servers` tables.\n */\nexport const MCP_SERVER_NAME = \"mcp-google-map\";\n\n/**\n * @brief User settings shape consumed by enable/disable/install/uninstall/show.\n * @details `enabled` lists canonical CLI names in persistence order.\n */\nexport interface CliSettings {\n enabled: string[];\n}\n\n/**\n * @brief Resolve the user settings file path for a home root.\n * @details Joins the effective home directory with\n * `.config/<SETTINGS_PROGRAM_NAME>/config.json` β the program-owned path\n * derived from the distribution name, never a shared directory (DES-021).\n * @param home {string | undefined} Home-directory override; defaults to `os.homedir()`.\n * @return {string} Absolute settings file path.\n * @satisfies DES-018, DES-021\n */\nexport function resolveCliSettingsPath(home?: string): string {\n const root = home ?? (process.env.HOME ?? process.cwd());\n return resolve(root, ...CLI_SETTINGS_RELATIVE);\n}\n\n/**\n * @brief Normalize an arbitrary parsed value into unique non-empty strings.\n * @param value {unknown} Candidate JSON value.\n * @return {string[]} Unique strings in first-seen order; empty for non-lists.\n */\nfunction uniqueStrings(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n const result: string[] = [];\n for (const item of value) {\n if (typeof item === \"string\" && item.length > 0 && !result.includes(item)) {\n result.push(item);\n }\n }\n return result;\n}\n\n/**\n * @brief Load the user settings with normalized defaults.\n * @details Reads JSON from `resolveCliSettingsPath`; missing, unreadable,\n * malformed, or non-object content yields `{ enabled: [] }`. Never throws.\n * @param home {string | undefined} Home-directory override.\n * @return {CliSettings} Normalized settings object.\n * @satisfies DES-018, DES-021\n */\nexport function loadCliSettings(home?: string): CliSettings {\n try {\n const raw: unknown = JSON.parse(readFileSync(resolveCliSettingsPath(home), \"utf-8\"));\n if (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) {\n return { enabled: [] };\n }\n return { enabled: uniqueStrings((raw as Record<string, unknown>).enabled) };\n } catch {\n return { enabled: [] };\n }\n}\n\n/**\n * @brief Persist settings to the user settings file atomically.\n * @details Creates parent directories, serializes with two-space indentation\n * and a trailing newline, writes `<file>.tmp`, then renames over the target\n * so readers never observe a partial file. Target path is the program-owned\n * `.config/<SETTINGS_PROGRAM_NAME>/config.json` (DES-021).\n * @param settings {CliSettings} Settings object to persist.\n * @param home {string | undefined} Home-directory override.\n * @return {string} Written settings file path.\n * @throws {Error} With descriptive message when directory creation, writing,\n * or replacement fails; the temporary file is best-effort removed.\n * @post The settings file contains the serialized `settings` object.\n * @satisfies DES-018, DES-021\n */\nexport function saveCliSettings(settings: CliSettings, home?: string): string {\n const path = resolveCliSettingsPath(home);\n const temporary = `${path}.tmp`;\n try {\n mkdirSync(join(path, \"..\"), { recursive: true });\n writeFileSync(temporary, JSON.stringify({ enabled: uniqueStrings(settings.enabled) }, null, 2) + \"\\n\", \"utf-8\");\n renameSync(temporary, path);\n } catch (error: unknown) {\n throw new Error(`settings write failed: ${error instanceof Error ? error.message : String(error)}`);\n }\n return path;\n}\n","/**\n * @file cliTargets.ts\n * @brief Provide per-CLI MCP-configuration and skills-destination adapters.\n * @details Defines one adapter for each supported CLI agent (`pi`,\n * `openclaw`, `codex`, `antigravity`, `claude`) resolving the MCP\n * configuration file and the skills destination directory from an injectable\n * home root. MCP registration applies read-modify-write: JSON targets merge\n * the `mcpServers[\"mcp-google-map\"]` entry preserving every unrelated key;\n * the TOML target (codex) appends or removes the `[mcp_servers.<name>]`\n * table without touching other tables. Skill synchronization copies packaged\n * skill directories with overwrite and prunes stale files inside managed\n * skill directories only, preserving unmanaged destination entries. Paths\n * adopted from the reference `skills` installer targets.\n * @satisfies DES-017, DES-019, DES-020, REQ-110, REQ-112, REQ-113\n */\n\nimport {\n cpSync,\n existsSync,\n mkdirSync,\n readFileSync,\n readdirSync,\n renameSync,\n rmSync,\n statSync,\n writeFileSync,\n} from \"node:fs\";\nimport { join, relative, resolve } from \"node:path\";\n\n/**\n * @brief Canonical identifiers of the supported CLI agents.\n * @details Registry order: pi, openclaw, codex, antigravity, claude.\n */\nexport type CliTargetId = \"pi\" | \"openclaw\" | \"codex\" | \"antigravity\" | \"claude\";\n\n/**\n * @brief MCP-server registration entry written into CLI configurations.\n * @details stdio launcher shape consumed by every supported CLI agent.\n */\nexport interface McpServerRegistration {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n}\n\n/**\n * @brief Configuration format of one CLI's MCP configuration file.\n * @details `json` targets expose a `mcpServers` object map; `toml` targets\n * expose `mcp_servers` tables (codex `config.toml`).\n */\nexport type CliConfigFormat = \"json\" | \"toml\";\n\n/**\n * @brief Adapter describing one supported CLI installation target.\n * @details Pure path/format descriptor; all operations are module functions\n * parameterized by the adapter so each CLI stays data-driven.\n */\nexport interface CliTarget {\n id: CliTargetId;\n configFormat: CliConfigFormat;\n mcpConfigPath(home?: string): string;\n skillsDir(home?: string): string;\n}\n\n/** @brief Resolve the effective home root. */\nfunction homeRoot(home?: string): string {\n return home ?? (process.env.HOME ?? process.cwd());\n}\n\n/** @brief pi adapter: `~/.pi/agent/mcp.json` + `~/.pi/agent/skills`. */\nconst PI_TARGET: CliTarget = {\n id: \"pi\",\n configFormat: \"json\",\n mcpConfigPath: (home) => join(homeRoot(home), \".pi\", \"agent\", \"mcp.json\"),\n skillsDir: (home) => join(homeRoot(home), \".pi\", \"agent\", \"skills\"),\n};\n\n/** @brief openclaw adapter: `~/.openclaw/openclaw.json` + workspace skills. */\nconst OPENCLAW_TARGET: CliTarget = {\n id: \"openclaw\",\n configFormat: \"json\",\n mcpConfigPath: (home) => join(homeRoot(home), \".openclaw\", \"openclaw.json\"),\n skillsDir: (home) => join(homeRoot(home), \".openclaw\", \"workspace\", \"skills\"),\n};\n\n/** @brief codex adapter: `~/.codex/config.toml` + `~/.codex/skills`. */\nconst CODEX_TARGET: CliTarget = {\n id: \"codex\",\n configFormat: \"toml\",\n mcpConfigPath: (home) => join(homeRoot(home), \".codex\", \"config.toml\"),\n skillsDir: (home) => join(homeRoot(home), \".codex\", \"skills\"),\n};\n\n/** @brief antigravity adapter: `~/.gemini/settings.json` + config skills. */\nconst ANTIGRAVITY_TARGET: CliTarget = {\n id: \"antigravity\",\n configFormat: \"json\",\n mcpConfigPath: (home) => join(homeRoot(home), \".gemini\", \"settings.json\"),\n skillsDir: (home) => join(homeRoot(home), \".gemini\", \"config\", \"skills\"),\n};\n\n/** @brief claude adapter: `~/.claude.json` + `~/.claude/skills`. */\nconst CLAUDE_TARGET: CliTarget = {\n id: \"claude\",\n configFormat: \"json\",\n mcpConfigPath: (home) => join(homeRoot(home), \".claude.json\"),\n skillsDir: (home) => join(homeRoot(home), \".claude\", \"skills\"),\n};\n\n/**\n * @brief Registry of supported CLI adapters keyed by canonical name.\n * @details Insertion order defines the `show` CLI Configuration table order\n * and the supported-name listing in diagnostics.\n * @satisfies REQ-110, REQ-117\n */\nexport const CLI_TARGETS: Record<CliTargetId, CliTarget> = {\n pi: PI_TARGET,\n openclaw: OPENCLAW_TARGET,\n codex: CODEX_TARGET,\n antigravity: ANTIGRAVITY_TARGET,\n claude: CLAUDE_TARGET,\n};\n\n/**\n * @brief Resolve a CLI adapter by user-supplied name.\n * @details Trims surrounding whitespace and lowercases before the registry\n * lookup, matching `pi`, `openclaw`, `codex`, `antigravity`, `claude`\n * case-insensitively.\n * @param name {string} CLI name from the command line.\n * @return {CliTarget | undefined} Matching adapter; undefined when unsupported.\n * @satisfies REQ-110\n */\nexport function resolveCliTarget(name: string): CliTarget | undefined {\n return CLI_TARGETS[name.trim().toLowerCase() as CliTargetId];\n}\n\n/**\n * @brief Comma-separated list of supported CLI names for diagnostics.\n * @return {string} Ordered `pi, openclaw, codex, antigravity, claude`.\n * @satisfies REQ-110\n */\nexport function supportedCliNames(): string {\n return (Object.keys(CLI_TARGETS) as CliTargetId[]).join(\", \");\n}\n\n/**\n * @brief Read and parse a JSON MCP configuration file.\n * @details Missing files yield `{}`; malformed JSON throws so the caller can\n * fail that CLI without ever overwriting the user's file.\n * @param configPath {string} Target configuration file path.\n * @return {Record<string, unknown>} Parsed JSON object.\n * @throws {Error} When the file exists but is not valid JSON.\n */\nfunction readJsonConfig(configPath: string): Record<string, unknown> {\n if (!existsSync(configPath)) return {};\n const parsed: unknown = JSON.parse(readFileSync(configPath, \"utf-8\"));\n if (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new Error(`configuration is not a JSON object: ${configPath}`);\n }\n return parsed as Record<string, unknown>;\n}\n\n/**\n * @brief Serialize and atomically write a JSON object to a file.\n * @details Two-space indentation, trailing newline, sibling `.tmp` write\n * followed by rename; parent directories are created on demand.\n * @param configPath {string} Target file path.\n * @param value {Record<string, unknown>} Object to serialize.\n * @return {void}\n * @throws {Error} When serialization, writing, or renaming fails.\n * @satisfies DES-019\n */\nfunction writeJsonConfig(configPath: string, value: Record<string, unknown>): void {\n const temporary = `${configPath}.tmp`;\n mkdirSync(join(configPath, \"..\"), { recursive: true });\n writeFileSync(temporary, JSON.stringify(value, null, 2) + \"\\n\", \"utf-8\");\n renameSync(temporary, configPath);\n}\n\n/**\n * @brief Register an MCP-server entry in a JSON `mcpServers` configuration.\n * @details Read-modify-write: parses the file (missing files start as `{}`),\n * upserts `mcpServers.<serverName>` leaving every unrelated key untouched,\n * and replaces the file atomically.\n * @param configPath {string} JSON configuration file path.\n * @param serverName {string} Server key inside `mcpServers`.\n * @param entry {McpServerRegistration} Registration entry to upsert.\n * @return {void}\n * @throws {Error} When the existing file is malformed or the write fails.\n * @satisfies DES-019, REQ-112\n */\nexport function writeJsonMcpServerEntry(\n configPath: string,\n serverName: string,\n entry: McpServerRegistration\n): void {\n const config = readJsonConfig(configPath);\n const mcpServers = (config.mcpServers ?? {}) as Record<string, unknown>;\n if (mcpServers === null || typeof mcpServers !== \"object\" || Array.isArray(mcpServers)) {\n throw new Error(`mcpServers is not an object: ${configPath}`);\n }\n mcpServers[serverName] = entry;\n config.mcpServers = mcpServers;\n writeJsonConfig(configPath, config);\n}\n\n/**\n * @brief Remove an MCP-server entry from a JSON `mcpServers` configuration.\n * @details Deletes `mcpServers.<serverName>` when present and rewrites the\n * file atomically; an empty `mcpServers` object is kept to minimize\n * disruption. Missing files are a successful no-op.\n * @param configPath {string} JSON configuration file path.\n * @param serverName {string} Server key inside `mcpServers`.\n * @return {boolean} True when an entry was removed; false when absent.\n * @throws {Error} When the existing file is malformed or the write fails.\n * @satisfies DES-019, REQ-115\n */\nexport function removeJsonMcpServerEntry(configPath: string, serverName: string): boolean {\n if (!existsSync(configPath)) return false;\n const config = readJsonConfig(configPath);\n const mcpServers = config.mcpServers;\n if (mcpServers === undefined) return false;\n if (mcpServers === null || typeof mcpServers !== \"object\" || Array.isArray(mcpServers)) {\n throw new Error(`mcpServers is not an object: ${configPath}`);\n }\n const map = mcpServers as Record<string, unknown>;\n if (!(serverName in map)) return false;\n delete map[serverName];\n config.mcpServers = map;\n writeJsonConfig(configPath, config);\n return true;\n}\n\n/**\n * @brief Read one MCP-server entry from a JSON configuration.\n * @param configPath {string} JSON configuration file path.\n * @param serverName {string} Server key inside `mcpServers`.\n * @return {McpServerRegistration | undefined} Entry when registered; undefined otherwise.\n */\nexport function readJsonMcpServerEntry(\n configPath: string,\n serverName: string\n): McpServerRegistration | undefined {\n try {\n const config = readJsonConfig(configPath);\n const mcpServers = config.mcpServers;\n if (mcpServers === null || typeof mcpServers !== \"object\" || Array.isArray(mcpServers)) {\n return undefined;\n }\n return (mcpServers as Record<string, McpServerRegistration>)[serverName];\n } catch {\n return undefined;\n }\n}\n\n/**\n * @brief Escape a value as a TOML basic string.\n * @details Escapes backslash and double-quote characters.\n * @param value {string} Raw string value.\n * @return {string} Quoted TOML basic string.\n */\nfunction tomlString(value: string): string {\n return `\"${value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"`;\n}\n\n/**\n * @brief Header line of one managed server's TOML table.\n * @param serverName {string} Server key inside `mcp_servers`.\n * @return {string} Exact `[mcp_servers.<serverName>]` header line.\n */\nfunction tomlSectionHeader(serverName: string): string {\n return `[mcp_servers.${serverName}]`;\n}\n\n/**\n * @brief Remove one managed server's TOML table from raw content.\n * @details Deletes the `[mcp_servers.<name>]` header line plus its body up to\n * the next top-level `[` table header or EOF, collapsing the resulting\n * duplicate blank separators. Other tables are preserved byte-for-byte.\n * @param content {string} Raw TOML document content.\n * @param serverName {string} Server key inside `mcp_servers`.\n * @return {string} Content with the managed table removed.\n */\nfunction removeTomlSection(content: string, serverName: string): string {\n const lines = content.split(\"\\n\");\n const header = tomlSectionHeader(serverName);\n const kept: string[] = [];\n let skipping = false;\n for (const line of lines) {\n if (skipping) {\n if (line.trimStart().startsWith(\"[\")) {\n skipping = false;\n } else {\n continue;\n }\n } else if (line.trim() === header) {\n skipping = true;\n while (kept.length > 0 && kept[kept.length - 1].trim() === \"\") {\n kept.pop();\n }\n continue;\n }\n kept.push(line);\n }\n while (kept.length > 0 && kept[kept.length - 1].trim() === \"\") {\n kept.pop();\n }\n return kept.length > 0 ? kept.join(\"\\n\") + \"\\n\" : \"\";\n}\n\n/**\n * @brief Detect one managed server's TOML table in raw content.\n * @param content {string} Raw TOML document content.\n * @param serverName {string} Server key inside `mcp_servers`.\n * @return {boolean} True when the `[mcp_servers.<name>]` header line exists.\n */\nfunction hasTomlSection(content: string, serverName: string): boolean {\n return content.split(\"\\n\").some((line) => line.trim() === tomlSectionHeader(serverName));\n}\n\n/**\n * @brief Serialize a registration entry as TOML table lines.\n * @param entry {McpServerRegistration} Registration entry.\n * @return {string[]} `command`, optional `args`, and optional `env` lines.\n */\nfunction registrationToTomlLines(entry: McpServerRegistration): string[] {\n const lines = [`command = ${tomlString(entry.command)}`];\n if (entry.args !== undefined) {\n lines.push(`args = [${entry.args.map((arg) => tomlString(arg)).join(\", \")}]`);\n }\n if (entry.env !== undefined) {\n const pairs = Object.entries(entry.env).map(([key, value]) => `${tomlString(key)} = ${tomlString(value)}`);\n if (pairs.length > 0) lines.push(`env = { ${pairs.join(\", \")} }`);\n }\n return lines;\n}\n\n/**\n * @brief Register an MCP-server table in a TOML configuration file.\n * @details Reads the file (missing files start empty), removes any existing\n * managed table, then appends the fresh `[mcp_servers.<name>]` table. Other\n * tables are preserved; the write is atomic via sibling `.tmp` + rename.\n * @param configPath {string} TOML configuration file path.\n * @param serverName {string} Server key inside `mcp_servers`.\n * @param entry {McpServerRegistration} Registration entry to write.\n * @return {void}\n * @throws {Error} When reading or writing fails.\n * @satisfies DES-019, REQ-112\n */\nexport function writeTomlMcpServerSection(\n configPath: string,\n serverName: string,\n entry: McpServerRegistration\n): void {\n const previous = existsSync(configPath) ? readFileSync(configPath, \"utf-8\") : \"\";\n const base = removeTomlSection(previous, serverName);\n const table = [tomlSectionHeader(serverName), ...registrationToTomlLines(entry), \"\"].join(\"\\n\");\n const content = base.length > 0 ? base.replace(/\\n*$/, \"\\n\") + table : table;\n const temporary = `${configPath}.tmp`;\n mkdirSync(join(configPath, \"..\"), { recursive: true });\n writeFileSync(temporary, content, \"utf-8\");\n renameSync(temporary, configPath);\n}\n\n/**\n * @brief Remove an MCP-server table from a TOML configuration file.\n * @details Missing files and absent tables are successful no-ops; otherwise\n * the managed table is removed and the file is rewritten atomically.\n * @param configPath {string} TOML configuration file path.\n * @param serverName {string} Server key inside `mcp_servers`.\n * @return {boolean} True when a table was removed; false when absent.\n * @throws {Error} When reading or writing fails.\n * @satisfies DES-019, REQ-115\n */\nexport function removeTomlMcpServerSection(configPath: string, serverName: string): boolean {\n if (!existsSync(configPath)) return false;\n const previous = readFileSync(configPath, \"utf-8\");\n if (!hasTomlSection(previous, serverName)) return false;\n const content = removeTomlSection(previous, serverName);\n const temporary = `${configPath}.tmp`;\n writeFileSync(temporary, content, \"utf-8\");\n renameSync(temporary, configPath);\n return true;\n}\n\n/**\n * @brief Detect one managed server's TOML table in a configuration file.\n * @param configPath {string} TOML configuration file path.\n * @param serverName {string} Server key inside `mcp_servers`.\n * @return {boolean} True when the managed table header exists.\n */\nexport function hasTomlMcpServerSection(configPath: string, serverName: string): boolean {\n if (!existsSync(configPath)) return false;\n return hasTomlSection(readFileSync(configPath, \"utf-8\"), serverName);\n}\n\n/**\n * @brief Recursively list relative file paths under a directory.\n * @param root {string} Directory to scan.\n * @return {string[]} POSIX-style relative file paths; empty when the directory is absent.\n */\nfunction listFilesRecursive(root: string): string[] {\n if (!existsSync(root)) return [];\n const files: string[] = [];\n const walk = (dir: string): void => {\n for (const entry of readdirSync(dir)) {\n const full = join(dir, entry);\n if (statSync(full).isDirectory()) {\n walk(full);\n } else {\n files.push(relative(root, full).split(\"\\\\\").join(\"/\"));\n }\n }\n };\n walk(root);\n return files;\n}\n\n/**\n * @brief Synchronize one packaged skill directory into a destination.\n * @details Creates the destination, recursively copies every packaged file\n * with overwrite, then deletes destination files and directories absent from\n * the package β strictly inside the managed skill directory, so sibling\n * unmanaged skills are never touched. Pruning runs deepest-first.\n * @param source {string} Packaged skill directory containing `SKILL.md`.\n * @param destination {string} Target `<skillsDir>/<skill-id>` path.\n * @return {void}\n * @throws {Error} When copying or pruning fails.\n * @pre `source` MUST exist.\n * @post `destination` mirrors exactly the packaged skill tree.\n * @satisfies DES-020\n */\nexport function syncSkillTree(source: string, destination: string): void {\n mkdirSync(destination, { recursive: true });\n cpSync(source, destination, { recursive: true, force: true });\n const expected = new Set(listFilesRecursive(source));\n const existing = listFilesRecursive(destination);\n existing.sort((a, b) => b.length - a.length);\n for (const rel of existing) {\n if (expected.has(rel)) continue;\n rmSync(join(destination, rel), { recursive: true, force: true });\n }\n}\n\n/**\n * @brief Remove one managed skill directory from a skills destination.\n * @details Missing directories are successful no-ops; nothing outside the\n * named directory is touched and no directory is created.\n * @param skillDir {string} Managed `<skillsDir>/<skill-id>` path.\n * @return {void}\n * @throws {Error} When recursive deletion fails.\n * @satisfies DES-020, REQ-115\n */\nexport function removeSkillDir(skillDir: string): void {\n rmSync(skillDir, { recursive: true, force: true });\n}\n\n/**\n * @brief Compare one packaged skill directory with its installed copy.\n * @details Every packaged regular file must exist in the destination with\n * identical bytes; extra destination files are ignored (staleness is judged\n * only on packaged content).\n * @param source {string} Packaged skill directory.\n * @param destination {string} Installed skill directory.\n * @return {string} `OK` when all packaged files match, `MISSING` when the\n * package or destination is absent, `STALE` on byte mismatch.\n */\nexport function compareSkillTree(source: string, destination: string): \"OK\" | \"MISSING\" | \"STALE\" {\n const packaged = listFilesRecursive(source);\n if (packaged.length === 0) return \"MISSING\";\n if (!existsSync(destination)) return \"MISSING\";\n for (const rel of packaged) {\n const target = join(destination, ...rel.split(\"/\"));\n if (!existsSync(target)) return \"MISSING\";\n if (readFileSync(target) .toString(\"utf-8\") !== readFileSync(join(source, ...rel.split(\"/\"))).toString(\"utf-8\")) {\n return \"STALE\";\n }\n }\n return \"OK\";\n}\n\n/**\n * @brief Detect whether a CLI has the managed server entry registered.\n * @param target {CliTarget} CLI adapter.\n * @param serverName {string} Managed server key.\n * @param home {string | undefined} Home-directory override.\n * @return {boolean} True when the entry/table is present and parseable.\n */\nexport function isServerRegistered(target: CliTarget, serverName: string, home?: string): boolean {\n const configPath = target.mcpConfigPath(home);\n if (target.configFormat === \"toml\") {\n return hasTomlMcpServerSection(configPath, serverName);\n }\n return readJsonMcpServerEntry(configPath, serverName) !== undefined;\n}\n\n/**\n * @brief Write or remove the managed server entry for one CLI target.\n * @param target {CliTarget} CLI adapter.\n * @param serverName {string} Managed server key.\n * @param entry {McpServerRegistration | undefined} Entry to register;\n * undefined removes the entry.\n * @param home {string | undefined} Home-directory override.\n * @return {void}\n * @throws {Error} When the configuration read-modify-write fails.\n * @satisfies DES-019, REQ-112, REQ-115\n */\nexport function applyServerRegistration(\n target: CliTarget,\n serverName: string,\n entry: McpServerRegistration | undefined,\n home?: string\n): void {\n const configPath = target.mcpConfigPath(home);\n if (target.configFormat === \"toml\") {\n if (entry === undefined) {\n removeTomlMcpServerSection(configPath, serverName);\n } else {\n writeTomlMcpServerSection(configPath, serverName, entry);\n }\n return;\n }\n if (entry === undefined) {\n removeJsonMcpServerEntry(configPath, serverName);\n } else {\n writeJsonMcpServerEntry(configPath, serverName, entry);\n }\n}\n","/**\n * @file cliInstaller.ts\n * @brief Orchestrate MCP-server registration and skill installation for enabled CLIs.\n * @details Loads the enabled-CLI settings, reads the packaged skills\n * manifest, and for each enabled CLI registers the stdio `mcp-google-map`\n * entry in that CLI's MCP configuration plus synchronizes every manifest\n * skill into that CLI's skills directory. Uninstallation is the exact\n * reciprocal operation. Per-CLI failures are collected without stopping the\n * remaining CLIs.\n * @satisfies PRJ-015, DES-020, REQ-114, REQ-115, REQ-116\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport { loadCliSettings, MCP_SERVER_NAME } from \"./cliSettings.js\";\nimport {\n applyServerRegistration,\n CLI_TARGETS,\n type CliTargetId,\n removeSkillDir,\n syncSkillTree,\n} from \"./cliTargets.js\";\n\n/**\n * @brief One manifest skill entry from `src/resources/skills/manifest.json`.\n * @details `id` names the packaged `<id>/` directory holding `SKILL.md`.\n */\nexport interface ManifestSkill {\n id: string;\n name: string;\n version: string;\n path: string;\n description: string;\n}\n\n/**\n * @brief Per-CLI outcome of one install or uninstall run.\n * @details `server` counts the MCP registration (0 or 1); `skills` counts\n * processed manifest skills for that CLI.\n */\nexport interface CliOperationSummary {\n cli: string;\n server: number;\n skills: number;\n}\n\n/**\n * @brief Aggregate outcome of one install or uninstall run.\n * @details Both lists are empty when no CLI is enabled (REQ-116, REQ-119).\n */\nexport interface CliOperationResult {\n summaries: CliOperationSummary[];\n errors: string[];\n}\n\n/**\n * @brief Build the stdio MCP-server registration entry.\n * @details Launcher `npx -y mcp-google-map --stdio`; `env` embeds\n * `GOOGLE_MAPS_API_KEY` only when resolved at install time, matching the\n * prebuilt-package-first Quick Start.\n * @param apiKey {string | undefined} Resolved Google Maps API key.\n * @return {object} Registration entry consumed by every supported CLI.\n * @satisfies REQ-114\n */\nexport function buildServerRegistration(apiKey: string | undefined): {\n command: string;\n args: string[];\n env: Record<string, string>;\n} {\n const env: Record<string, string> = {};\n if (apiKey !== undefined && apiKey.length > 0) {\n env.GOOGLE_MAPS_API_KEY = apiKey;\n }\n return { command: \"npx\", args: [\"-y\", MCP_SERVER_NAME, \"--stdio\"], env };\n}\n\n/**\n * @brief Resolve the packaged skills root for the running installation.\n * @details Checks `<packageRoot>/src/resources/skills` β the layout used\n * both by from-source runs and by the published npm package, which ships the\n * same subtree (PKG-024).\n * @param packageRoot {string} Package installation root.\n * @return {string} Absolute skills resources root.\n * @throws {Error} When the skills root directory is missing.\n */\nexport function resolveSkillsResourcesRoot(packageRoot: string): string {\n const candidate = resolve(packageRoot, \"src\", \"resources\", \"skills\");\n if (!existsSync(candidate)) {\n throw new Error(`skills resources root not found: ${candidate}`);\n }\n return candidate;\n}\n\n/**\n * @brief Load and validate the packaged skills manifest.\n * @param resourcesRoot {string} Skills resources root directory.\n * @return {ManifestSkill[]} Manifest entries in file order.\n * @throws {Error} When the manifest is missing, malformed, or lists a missing\n * `SKILL.md` path.\n */\nexport function loadSkillsManifest(resourcesRoot: string): ManifestSkill[] {\n const manifestPath = join(resourcesRoot, \"manifest.json\");\n if (!existsSync(manifestPath)) {\n throw new Error(`skills manifest not found: ${manifestPath}`);\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(readFileSync(manifestPath, \"utf-8\"));\n } catch (error: unknown) {\n throw new Error(`skills manifest is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);\n }\n const skills = (parsed as { skills?: unknown } | null)?.skills;\n if (!Array.isArray(skills)) {\n throw new Error(`skills manifest has no skills array: ${manifestPath}`);\n }\n return skills.map((entry) => {\n const skill = entry as Partial<ManifestSkill>;\n if (typeof skill.id !== \"string\" || typeof skill.path !== \"string\") {\n throw new Error(`skills manifest entry is missing id or path: ${manifestPath}`);\n }\n if (!existsSync(join(resourcesRoot, skill.path))) {\n throw new Error(`manifest skill file not found: ${join(resourcesRoot, skill.path)}`);\n }\n return {\n id: skill.id,\n name: skill.name ?? skill.id,\n version: skill.version ?? \"\",\n path: skill.path,\n description: skill.description ?? \"\",\n };\n });\n}\n\n/**\n * @brief Install the MCP server entry and every manifest skill per enabled CLI.\n * @details For each enabled CLI in settings order: registers the stdio entry\n * via `applyServerRegistration`, then synchronizes each manifest skill\n * directory `<resourcesRoot>/<skill-id>` into `<skillsDir>/<skill-id>`.\n * Failures are collected per CLI and remaining CLIs still run.\n * @param options {object} `{ home?, apiKey, resourcesRoot }`.\n * @return {CliOperationResult} Per-CLI summaries and failure diagnostics.\n * @throws {Error} When the skills manifest cannot be loaded (all CLIs fail).\n * @satisfies REQ-114, REQ-116\n */\nexport function installEnabledCliResources(options: {\n home?: string;\n apiKey: string | undefined;\n resourcesRoot: string;\n}): CliOperationResult {\n const manifest = loadSkillsManifest(options.resourcesRoot);\n const entry = buildServerRegistration(options.apiKey);\n const result: CliOperationResult = { summaries: [], errors: [] };\n for (const cli of loadCliSettings(options.home).enabled) {\n const target = CLI_TARGETS[cli as CliTargetId];\n if (target === undefined) {\n result.errors.push(`Unsupported CLI: ${cli}`);\n continue;\n }\n try {\n applyServerRegistration(target, MCP_SERVER_NAME, entry, options.home);\n let skills = 0;\n for (const skill of manifest) {\n syncSkillTree(join(options.resourcesRoot, skill.id), join(target.skillsDir(options.home), skill.id));\n skills += 1;\n }\n result.summaries.push({ cli: target.id, server: 1, skills });\n } catch (error: unknown) {\n result.errors.push(`${target.id}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n return result;\n}\n\n/**\n * @brief Remove the MCP server entry and managed skills per enabled CLI.\n * @details Reciprocal of `installEnabledCliResources`: removes the managed\n * server entry and deletes each manifest skill directory. Missing entries\n * count as removed without failure; per-CLI failures are collected and\n * remaining CLIs still run.\n * @param options {object} `{ home?, resourcesRoot }`.\n * @return {CliOperationResult} Per-CLI summaries and failure diagnostics.\n * @throws {Error} When the skills manifest cannot be loaded (all CLIs fail).\n * @satisfies REQ-115, REQ-116\n */\nexport function uninstallEnabledCliResources(options: {\n home?: string;\n resourcesRoot: string;\n}): CliOperationResult {\n const manifest = loadSkillsManifest(options.resourcesRoot);\n const result: CliOperationResult = { summaries: [], errors: [] };\n for (const cli of loadCliSettings(options.home).enabled) {\n const target = CLI_TARGETS[cli as CliTargetId];\n if (target === undefined) {\n result.errors.push(`Unsupported CLI: ${cli}`);\n continue;\n }\n try {\n applyServerRegistration(target, MCP_SERVER_NAME, undefined, options.home);\n let skills = 0;\n for (const skill of manifest) {\n removeSkillDir(join(target.skillsDir(options.home), skill.id));\n skills += 1;\n }\n result.summaries.push({ cli: target.id, server: 0, skills });\n } catch (error: unknown) {\n result.errors.push(`${target.id}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n return result;\n}\n","/**\n * @file cliShow.ts\n * @brief Render the CLI Configuration and Installation Status report tables.\n * @details Builds the human-readable `show` output: a CLI Configuration\n * table covering every supported CLI (enabled state, MCP configuration\n * path, skills destination path) and an Installation Status table listing\n * the managed MCP server and every manifest skill per enabled CLI with\n * OK / MISSING / STALE detection.\n * @satisfies REQ-117, REQ-118, REQ-119\n */\n\nimport { join } from \"node:path\";\nimport { relative, resolve } from \"node:path\";\nimport { loadCliSettings, MCP_SERVER_NAME } from \"./cliSettings.js\";\nimport { CLI_TARGETS, compareSkillTree, isServerRegistered, type CliTargetId } from \"./cliTargets.js\";\nimport { loadSkillsManifest } from \"./cliInstaller.js\";\n\n/**\n * @brief Maximum rendered width of one table cell in characters.\n * @details Long values wrap on word boundaries, mirroring the reference\n * `skills show` renderer.\n */\nconst MAX_CELL_WIDTH = 48;\n\n/**\n * @brief Status value for a resource whose destination matches the package.\n */\nconst STATUS_OK = \"OK\";\n/** @brief Status value for a resource with a missing destination. */\nconst STATUS_MISSING = \"MISSING\";\n/** @brief Status value for a resource whose destination differs from the package. */\nconst STATUS_STALE = \"STALE\";\n\n/**\n * @brief Wrap one cell value into fixed-width lines on word boundaries.\n * @details Collapses whitespace, splits overlong tokens into `width`-sized\n * chunks, and greedily packs words without exceeding `width`.\n * @param text {string} Cell value to wrap.\n * @param width {number} Maximum line width in characters; MUST be positive.\n * @return {string[]} Rendered lines; `[\"\"]` for an empty value.\n */\nfunction wrapCell(text: string, width: number): string[] {\n const normalized = String(text).split(/\\s+/).filter((word) => word.length > 0);\n if (normalized.length === 0) return [\"\"];\n const lines: string[] = [];\n let current = \"\";\n for (let word of normalized) {\n while (word.length > width) {\n if (current.length > 0) {\n lines.push(current);\n current = \"\";\n }\n lines.push(word.slice(0, width));\n word = word.slice(width);\n }\n if (current.length === 0) {\n current = word;\n } else if (current.length + 1 + word.length <= width) {\n current = `${current} ${word}`;\n } else {\n lines.push(current);\n current = word;\n }\n }\n if (current.length > 0) lines.push(current);\n return lines.length > 0 ? lines : [\"\"];\n}\n\n/**\n * @brief Render an ASCII grid table with aligned and wrapped cells.\n * @details Column widths are the longest cell capped by `maxWidth`; every\n * row is emitted between `+---+` borders and multi-line cells are padded to\n * the row height.\n * @param headers {string[]} Column header labels.\n * @param rows {string[][]} Row cell values.\n * @param maxWidth {number} Maximum column width in characters.\n * @return {string} Rendered table text without trailing newline.\n */\nexport function renderAsciiTable(headers: string[], rows: string[][], maxWidth = MAX_CELL_WIDTH): string {\n const widths = headers.map((header, index) => {\n const lengths = [header.length, ...rows.map((row) => (row[index] ?? \"\").length)];\n return Math.max(1, Math.min(Math.max(...lengths), Math.max(1, maxWidth)));\n });\n const border = \"+\" + widths.map((width) => \"-\".repeat(width + 2)).join(\"+\") + \"+\";\n const renderRow = (cells: string[]): string[] => {\n const wrapped = cells.map((cell, index) => wrapCell(cell ?? \"\", widths[index]));\n const height = Math.max(...wrapped.map((part) => part.length));\n const lines: string[] = [];\n for (let line = 0; line < height; line += 1) {\n const parts = wrapped.map((part, index) => (part[line] ?? \"\").padEnd(widths[index]));\n lines.push(\"| \" + parts.join(\" | \") + \" |\");\n }\n return lines;\n };\n const output = [border, ...renderRow(headers), border];\n for (const row of rows) {\n output.push(...renderRow(row));\n output.push(border);\n }\n return output.join(\"\\n\");\n}\n\n/**\n * @brief Build the CLI Configuration table rows.\n * @details One row per supported CLI in registry order: enabled yes/no,\n * home-relative MCP configuration path, and home-relative skills directory.\n * @param home {string | undefined} Home-directory override.\n * @return {string[][]} `(CLI, Enabled, MCP Config Path, Skills Config Path)` rows.\n * @satisfies REQ-117\n */\nfunction buildCliRows(home?: string): string[][] {\n const root = home ?? (process.env.HOME ?? process.cwd());\n const enabled = new Set(loadCliSettings(home).enabled);\n return (Object.keys(CLI_TARGETS) as CliTargetId[]).map((id) => {\n const target = CLI_TARGETS[id];\n return [\n target.id,\n enabled.has(id) ? \"yes\" : \"no\",\n relative(resolve(root), resolve(target.mcpConfigPath(home))).split(\"\\\\\").join(\"/\"),\n relative(resolve(root), resolve(target.skillsDir(home))).split(\"\\\\\").join(\"/\"),\n ];\n });\n}\n\n/**\n * @brief Build the Installation Status table rows.\n * @details Emits rows only for enabled CLIs: one `Server` row for the\n * managed `mcp-google-map` entry plus one `Skill` row per manifest skill,\n * each with OK / MISSING / STALE detection.\n * @param home {string | undefined} Home-directory override.\n * @param resourcesRoot {string} Packaged skills resources root.\n * @return {string[][]} `(Type, Name, CLI, Enabled, Installed)` rows.\n * @satisfies REQ-118\n */\nfunction buildInstallRows(home: string | undefined, resourcesRoot: string): string[][] {\n const enabled = loadCliSettings(home).enabled;\n const manifest = loadSkillsManifest(resourcesRoot);\n const rows: string[][] = [];\n for (const cli of enabled) {\n const target = CLI_TARGETS[cli as CliTargetId];\n if (target === undefined) continue;\n rows.push([\n \"Server\",\n MCP_SERVER_NAME,\n target.id,\n \"yes\",\n isServerRegistered(target, MCP_SERVER_NAME, home) ? STATUS_OK : STATUS_MISSING,\n ]);\n for (const skill of manifest) {\n rows.push([\n \"Skill\",\n skill.id,\n target.id,\n \"yes\",\n compareSkillTree(join(resourcesRoot, skill.id), join(target.skillsDir(home), skill.id)),\n ]);\n }\n }\n return rows;\n}\n\n/**\n * @brief Build the complete `show` report text.\n * @details Renders the CLI Configuration table (always, REQ-119) and the\n * Installation Status table (empty when no CLI is enabled), in this order,\n * separated by a blank line. Manifest load failures propagate so the command\n * handler reports a JSON error.\n * @param options {object} `{ home?, resourcesRoot }`.\n * @return {string} Report text with two titled tables.\n * @throws {Error} When the skills manifest cannot be loaded.\n * @satisfies REQ-117, REQ-118, REQ-119\n */\nexport function buildCliShowReport(options: { home?: string; resourcesRoot: string }): string {\n return [\n \"CLI Configuration\",\n renderAsciiTable([\"CLI\", \"Enabled\", \"MCP Config Path\", \"Skills Config Path\"], buildCliRows(options.home)),\n \"\",\n \"Installation Status\",\n renderAsciiTable([\"Type\", \"Name\", \"CLI\", \"Enabled\", \"Installed\"], buildInstallRows(options.home, options.resourcesRoot)),\n ].join(\"\\n\");\n}\n\nexport { STATUS_OK, STATUS_MISSING, STATUS_STALE };\n"],"mappings":"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","names":["dotenvConfig","resolve","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","readFileSync","writeFileSync","existsSync","existsSync","mkdirSync","readFileSync","renameSync","writeFileSync","join","existsSync","readFileSync","join","resolve","resolve","existsSync","join","readFileSync","join","relative","resolve","relative","resolve","join","dotenvConfig","resolve","existsSync","readFileSync","writeFileSync","yargs","tasks"]}
|