google-maps-mcp

mcp
Security Audit
Warn
Health Warn
  • License — License: GPL-3.0
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 8 GitHub stars
Code Warn
  • process.env — Environment variable access in src/index.ts
  • process.env — Environment variable access in src/maps-client.ts
  • network request — Outbound network request in src/maps-client.ts
  • process.env — Environment variable access in src/tools/routes.ts
Permissions Pass
  • Permissions — No dangerous permissions requested
Purpose
This MCP server acts as a bridge between AI assistants and the Google Maps Platform REST APIs. It provides real-time access to geospatial data, enabling features like turn-by-turn directions, place searches, and distance calculations.

Security Assessment
The overall risk is Low. The tool strictly makes outbound network requests to the official Google Maps APIs using your own API key, which is exactly its intended purpose. There is no evidence of hardcoded secrets, malicious code, or dangerous permissions. Environment variable access is used securely to handle your Google Maps API key and an optional authentication token, following standard practices. It does not appear to execute arbitrary shell commands or access unexpected local sensitive files.

Quality Assessment
The project is in its early stages with low community visibility (8 GitHub stars), meaning it has not been extensively peer-reviewed. However, the codebase is highly active, with recent updates pushed just days ago. It is properly licensed under GPL-3.0, making it fully open-source and legally safe to use. The developer has kept the footprint minimal by relying on only two runtime dependencies, which significantly reduces the attack surface.

Verdict
Use with caution due to low community adoption, but the code itself appears safe and well-structured.
SUMMARY

MCP Server for Google Maps (using Places, Routes & Maps REST API)

README.md

google-maps-mcp

A TypeScript Model Context Protocol (MCP) server that exposes Google Maps Platform APIs as tools for LLMs. Gives AI assistants real, structured map data — directions, transit routes, place search, address validation, photos, elevation, and more — instead of guessing from training data.

Works with Claude Desktop and any other MCP-compatible client.


Features

15 tools across three categories:

Category Tools
Maps Static map image URL, embed URL (iframe), elevation data, Street View image URL
Routes Turn-by-turn directions (drive/walk/cycle/transit), distance matrix, multi-stop route optimization
Places Geocoding / reverse geocoding, place details, text search, nearby search, autocomplete, photos, address validation, timezone

Transport: HTTP Streamable (stateful sessions, SSE keep-alive) — the modern MCP transport, compatible with mcp-remote and all HTTP-capable clients.

Minimal footprint: only two runtime dependencies (@modelcontextprotocol/sdk, zod). All Google Maps calls use Node.js built-in fetch against REST APIs — no Google SDK required.


Prerequisites

  • Node.js 22+ (or Docker)
  • mcp-remote — install once globally: npm install -g mcp-remote
  • A Google Maps Platform API key with the relevant APIs enabled (see below)
  • A Google Cloud project with billing enabled

APIs to enable in Google Cloud Console

Go to APIs & Services → Library and enable:

API Used by
Maps Static API maps_static_map
Street View Static API maps_street_view
Maps Embed API maps_embed_url
Elevation API maps_elevation
Geocoding API places_geocode
Time Zone API places_timezone
Places API (New) places_details, places_text_search, places_nearby_search, places_autocomplete, places_photos
Address Validation API places_address_validation
Routes API routes_compute, routes_matrix
Route Optimization API routes_optimize (optional)

You can restrict the key to these APIs and to your server's IP for production use.


Quick Start

Option A — Run with Docker (recommended)

docker run -d \
  --name google-maps-mcp \
  -p 127.0.0.1:3003:3003 \
  -e GOOGLE_MAPS_API_KEY=your_key_here \
  -e MCP_AUTH_TOKEN=your_secret_token \
  ghcr.io/apurvaumredkar/google-maps-mcp:latest

Verify:

curl http://localhost:3003/health
# {"status":"ok","service":"google-maps-mcp"}

Option B — npm / npx

No install required — run directly with npx:

GOOGLE_MAPS_API_KEY=your_key_here \
MCP_AUTH_TOKEN=your_secret_token \
npx mcp-server-google-maps
# google-maps-mcp listening on port 3003

Or install globally:

npm install -g mcp-server-google-maps
GOOGLE_MAPS_API_KEY=your_key_here MCP_AUTH_TOKEN=your_secret_token mcp-server-google-maps

Set PORT= to change the default port (3003).


Option C — Build from source

git clone https://github.com/apurvaumredkar/google-maps-mcp.git
cd google-maps-mcp
npm install
npm run build

Create a .env file (or export the vars):

GOOGLE_MAPS_API_KEY=your_key_here
MCP_AUTH_TOKEN=your_secret_token
# Optional — only needed for routes_optimize:
GOOGLE_CLOUD_PROJECT_ID=your_project_id

Start the server:

GOOGLE_MAPS_API_KEY=... MCP_AUTH_TOKEN=... npm start
# google-maps-mcp listening on port 3003

Option D — Docker Compose (self-hosted stack)

Add to your docker-compose.yml:

services:
  google-maps-mcp:
    build: .
    container_name: google-maps-mcp
    restart: unless-stopped
    ports:
      - "127.0.0.1:3003:3003"
    environment:
      - GOOGLE_MAPS_API_KEY=${GOOGLE_MAPS_API_KEY}
      - MCP_AUTH_TOKEN=${MCP_AUTH_TOKEN}
      - GOOGLE_CLOUD_PROJECT_ID=${GOOGLE_CLOUD_PROJECT_ID:-}

Environment Variables

Variable Required Description
GOOGLE_MAPS_API_KEY Yes Your Google Maps Platform API key
MCP_AUTH_TOKEN No Secret token clients must send in the X-Api-Key header. Omit for local-only use; set when exposing the server over a network or proxy. Generate with openssl rand -hex 32
PORT No HTTP port (default: 3003)
GOOGLE_CLOUD_PROJECT_ID No Required only for routes_optimize (Route Optimization API)

Connecting a Client

This server works with any MCP-compatible client — Claude Desktop, LM Studio, Cursor, or any other tool that supports the Model Context Protocol. The config format may differ per client, but the endpoint and auth are the same.

The server exposes a single endpoint: POST/GET http://localhost:3003/mcp

If MCP_AUTH_TOKEN is set, all requests must include the header:

X-Api-Key: <MCP_AUTH_TOKEN>

If MCP_AUTH_TOKEN is not set, no header is required (suitable for local-only use).

Claude Desktop (example)

Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):

{
  "mcpServers": {
    "google-maps": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "http://localhost:3003/mcp",
        "--header",
        "X-Api-Key: your_secret_token"
      ]
    }
  }
}

Tool Reference

Maps

maps_static_map — Static Map Image

Returns a direct image URL for a static map.

Parameter Type Default Description
center string required Address or lat,lng
zoom integer 13 Zoom level 0–21
size string 640x480 Image dimensions WxH in pixels
maptype enum roadmap roadmap | satellite | terrain | hybrid
markers string Marker spec e.g. color:red|48.8566,2.3522
path string Path spec for drawing routes
format enum png png | jpg | gif
scale enum 1 1 = standard, 2 = HiDPI/retina
language string BCP 47 language code for labels
region string ISO 3166-1 alpha-2 region code

maps_embed_url — Maps Embed URL

Returns an iframe-ready embed URL.

Parameter Type Description
mode enum place | directions | search | view | streetview
q string Place/search query (place, search modes)
center string lat,lng for view/streetview mode
zoom integer Zoom level
origin / destination string For directions mode
waypoints string Pipe-separated waypoints
maptype enum roadmap | satellite

maps_elevation — Elevation Data

Returns elevation in metres above sea level.

Parameter Type Description
locations string Pipe-separated lat,lng pairs
path string Pipe-separated lat,lng path
samples integer Number of samples along path (2–512)

maps_street_view — Street View Image

Returns a direct Street View panorama image URL.

Parameter Type Default Description
location string Address or lat,lng
pano string Specific panorama ID (overrides location)
size string 640x480 Image size WxH
heading number Camera heading 0–360°
pitch number Camera pitch -90° to 90°
fov number 90 Field of view 10–120°
source enum outdoor to exclude indoor panoramas

Routes

routes_compute — Compute Route

Turn-by-turn directions with real-time traffic.

Parameter Type Default Description
origin string required Address or lat,lng
destination string required Address or lat,lng
travel_mode enum DRIVE DRIVE | WALK | BICYCLE | TRANSIT | TWO_WHEELER
intermediates string[] Waypoints between origin and destination
departure_time string ISO 8601 datetime for traffic-aware routing
avoid_tolls boolean false Avoid toll roads
avoid_highways boolean false Avoid highways
avoid_ferries boolean false Avoid ferries
units enum METRIC METRIC | IMPERIAL
compute_alternative_routes boolean false Return up to 3 alternatives

routes_matrix — Route Distance Matrix

Compute travel time/distance between multiple origins and destinations simultaneously.

Parameter Type Default Description
origins string[] required Up to 25 addresses or lat,lng strings
destinations string[] required Up to 25 addresses or lat,lng strings
travel_mode enum DRIVE DRIVE | WALK | BICYCLE | TRANSIT
departure_time string ISO 8601 datetime
units enum METRIC METRIC | IMPERIAL

routes_optimize — Optimize Multi-Stop Route

Optimizes stop order to minimize total travel. Requires GOOGLE_CLOUD_PROJECT_ID.

Parameter Type Description
vehicle_start string Start location — must be lat,lng (geocode first if needed)
vehicle_end string End location (defaults to start)
visits object[] Array of { address, label?, duration_minutes? } — addresses must be lat,lng
travel_mode enum DRIVING | WALKING

Places

places_geocode — Geocode / Reverse Geocode

Convert addresses ↔ coordinates.

Parameter Type Description
address string Address to geocode
latlng string lat,lng for reverse geocoding
region string ISO 3166-1 alpha-2 region bias
components string Component filter e.g. country:FR|postal_code:75001

places_details — Place Details

Full details for a place by its Google Place ID.

Parameter Type Description
place_id string Google Place ID
fields string Comma-separated field mask (has sensible default)
language_code string Response language

places_text_search — Search Places by Text

Find places matching a natural language query.

Parameter Type Description
query string e.g. "best ramen in Tokyo"
location_bias_lat/lng number Bias results toward this location
location_bias_radius_m number Bias circle radius
max_results integer 1–20, default 10
min_rating number Minimum average star rating (0–5)
open_now boolean Only currently open places
included_type string Filter by place type e.g. restaurant
price_levels enum[] PRICE_LEVEL_FREEPRICE_LEVEL_VERY_EXPENSIVE

places_nearby_search — Search Nearby Places

Find places near a coordinate within a radius.

Parameter Type Description
latitude / longitude number Center of search
radius_m number Search radius in metres (max 50,000)
included_types string[] Place type filters
excluded_types string[] Place types to exclude
max_results integer 1–20, default 10
rank_preference enum DISTANCE | POPULARITY

places_autocomplete — Place Autocomplete

Predict place names from partial input.

Parameter Type Description
input string Partial text to complete
location_bias_lat/lng number Bias toward this location
included_primary_types string[] Type filter
country_codes string[] ISO 3166-1 alpha-2 country filter
include_query_predictions boolean Also return query predictions

places_photos — Place Photos

Get photo URLs for a place.

Parameter Type Default Description
place_id string required Google Place ID
max_photos integer 3 Max photos to return (1–10)
max_width_px integer 1200 Max photo width in pixels
max_height_px integer 900 Max photo height in pixels

places_address_validation — Validate Address

Validate and standardize a postal address.

Parameter Type Description
address_lines string[] Address lines
region_code string ISO 3166-1 alpha-2 country code
locality string City/town
administrative_area string State/province
postal_code string Postal code
enable_usps_cass boolean USPS CASS validation (US only)

places_timezone — Get Timezone

Get IANA timezone and UTC/DST offset for any coordinates.

Parameter Type Description
latitude / longitude number Location
timestamp integer Unix timestamp for DST calculation (defaults to now)
language string Response language

Architecture

src/
├── index.ts         # Raw Node.js HTTP server, auth, stateful session management
├── server.ts        # McpServer instantiation + tool registration
├── maps-client.ts   # Typed fetch wrappers for all Google Maps REST APIs
└── tools/
    ├── maps.ts      # 4 tools: static map, embed, elevation, street view
    ├── routes.ts    # 3 tools: compute route, matrix, optimize
    └── places.ts    # 8 tools: geocode, details, text search, nearby, autocomplete,
                     #          photos, address validation, timezone

Key design decisions:

  • Raw node:http instead of Express — required for correct interop with the MCP SDK's internal Hono-based request handling. Express pre-consumes the request body stream in a way that breaks StreamableHTTPServerTransport.
  • Stateful session mapmcp-remote and SSE keep-alive require sessions to persist across requests. Sessions are keyed by Mcp-Session-Id header and cleaned up on transport close.
  • Auth before body read — the X-Api-Key check happens on the header before any body stream is touched, so rejected requests drain cleanly.
  • Auth split for Google APIs — legacy REST APIs (Static Maps, Geocoding, Elevation, Timezone, Street View) use ?key= query param; new APIs (Places v1, Routes v2, Address Validation) use X-Goog-Api-Key header.

Development

npm run dev    # TypeScript watch mode (tsc --watch)
npm run build  # Compile to dist/
npm start      # Run compiled server

Rebuild Docker image after changes

docker compose build google-maps-mcp
docker compose up -d google-maps-mcp

Testing the MCP endpoint

# Health check (no auth required)
curl http://localhost:3003/health

# MCP initialize (auth required)
TOKEN=your_secret_token
curl -s -X POST http://localhost:3003/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "X-Api-Key: $TOKEN" \
  -d '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1"}},"id":1}'

# List tools (use session ID from Mcp-Session-Id response header)
SESSION=<Mcp-Session-Id from above>
curl -s -X POST http://localhost:3003/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "X-Api-Key: $TOKEN" \
  -H "Mcp-Session-Id: $SESSION" \
  -d '{"jsonrpc":"2.0","method":"tools/list","id":2}'

Windows/WSL gotcha: if your .env file has Windows CRLF line endings, extract values with tr -d '\r':

TOKEN=$(grep MCP_AUTH_TOKEN .env | cut -d= -f2 | tr -d '\r')

Reviews (0)

No results found