Skip to main content
Glama
sKuangster

Google Maps MCP Server

by sKuangster

Google Maps MCP Server

A general-purpose Google Maps MCP server: geocoding, place search, place details, directions, distance matrices, and time zone lookup over the Model Context Protocol, served over authenticated streamable HTTP.

Tools

Tool

Description

get_geocode_address

Address -> latitude/longitude + resolved address

get_reverse_geocode

Latitude/longitude -> human-readable address + place_id

find_nearby_places

Category-based nearby place search (ranked by rating)

best_places_near

Geocode an address and search nearby in one call

get_directions_between

Directions between two points (driving/walking/transit/bicycling): distance, duration, step summary

get_distance_matrix

Travel time/distance between multiple origins and destinations at once

get_place_details

place_id -> phone, hours, website, price level, rating, review snippets

get_time_zone

Latitude/longitude -> time zone ID/name, UTC offset, current local time

create_embedded_map

Ordered stops (2-22) + travel mode -> embedded interactive multi-stop route map (MCP Apps) with an open-in-Google-Maps fallback link

enrich_location

Place -> Google hours/details + parsed website extract + web search, with an open/closed verdict for a planned visit_time

Supported place categories: food_and_drink, entertainment_and_recreation, shopping, sports, automotive, health_and_wellness, lodging.

Directions and distance-matrix inputs accept street addresses, place names, or "lat,lng" strings.

Itinerary planning

find_nearby_places results include each place's coordinates, and its docstring teaches the calling model the walking-center pattern: recenter each follow-up search on the previously chosen stop instead of searching a whole area from one fixed center, so multi-stop plans cluster geographically. enrich_location validates that each stop is open at its planned visit time, and create_embedded_map renders the finished itinerary. The embedded map is an MCP Apps view (map_app.html) served from ui://google-maps/itinerary-map.html; hosts without MCP Apps support still get the fallback maps link. Transit itineraries render per-leg maps because the Maps Embed API does not support waypoints in transit mode.

Setup

pip install -r requirements.txt
copy .env.example .env   # then fill in real values
python server.py         # serves http://localhost:8000/mcp

.env lives next to server.py and needs:

Variable

Purpose

GOOGLE_MAPS_API_KEY

Google Maps Platform API key

MCP_SHARED_SECRET

Secret clients must send in the X-MCP-Secret header. Generate with python -c "import secrets; print(secrets.token_urlsafe(32))"

The server refuses to start if MCP_SHARED_SECRET is unset.

Authentication

Requests to /mcp are accepted with either credential; everything else gets 401:

  1. X-MCP-Secret header matching MCP_SHARED_SECRET — for Claude Code and scripts.

  2. OAuth 2.1 Bearer token — for claude.ai / Claude Desktop custom connectors. The server implements the MCP authorization spec itself (metadata discovery, dynamic client registration, PKCE authorization-code flow with refresh tokens): connecting from Claude opens a consent page where you enter the shared secret once, and Claude holds tokens from then on. Tokens are stateless HMAC-signed blobs keyed off MCP_SHARED_SECRET, so they survive restarts, and rotating the secret revokes all of them. OAuth redirect targets are restricted to Claude's callback URLs and loopback addresses; extend with a comma-separated OAUTH_EXTRA_REDIRECTS env var if needed.

GET /healthz and the OAuth endpoints (/.well-known/*, /register, /authorize, /token) are the only unauthenticated routes.

Required Google Cloud APIs

Enable these in your Google Cloud project:

  • Geocoding API

  • Places API (New)

  • Routes API (used for directions and distance matrix — the legacy Directions/Distance Matrix APIs are not available to new Google Cloud projects)

  • Time Zone API

  • Maps Embed API (embedded itinerary maps — free of charge, unlimited). Embed URLs expose their API key client-side; optionally set MAPS_EMBED_API_KEY to a separate HTTP-referrer-restricted key.

Cost control

The quota-sensitive endpoints are wrapped with an in-memory TTL cache plus a minimum-interval throttle (see cost_control.py):

Endpoint

Cache TTL

Throttle

Directions (computeRoutes)

5 min

1 call / 0.5 s

Distance Matrix (computeRouteMatrix)

5 min

1 call / 1 s

Place Details

1 hour

1 call / 0.5 s

Website fetch (enrich_location)

1 hour

1 call / 1 s

DuckDuckGo search (enrich_location)

1 hour

1 call / 1 s

enrich_location's web search uses keyless DuckDuckGo (ddgs); from datacenter IPs it can occasionally rate-limit, in which case that leg of the response degrades to an error field while Google data and the website extract still come back. Name-to-place_id resolution uses Text Search with an ID-only field mask, which is a free SKU.

Repeated identical calls are served from cache and never hit Google. Cheap endpoints (Geocoding, Time Zone) call the API directly. Note that every distance-matrix element (origins × destinations) is billed as a request, so the tool caps inputs at 10 origins × 10 destinations. The cache is per-process: it resets on restart, which on Render's free tier includes spin-down after idle periods.

Deploying to Render (free tier)

The repo ships a Render blueprint (free-tier Python web service).

  1. Push this repo to GitHub (already done if you're reading this there).

  2. In the Render dashboard, click New → Blueprint, connect the GitHub repo, and accept the defaults from render.yaml.

  3. When prompted for environment variables, set GOOGLE_MAPS_API_KEY and MCP_SHARED_SECRET (generate a fresh secret for production; don't reuse your local one).

  4. Deploy. Your MCP endpoint is https://<your-service>.onrender.com/mcp, and https://<your-service>.onrender.com/healthz should return {"status": "ok"} without auth.

Free-tier caveat: Render spins the instance down after ~15 minutes without inbound traffic, and the 30–60 s cold start is longer than claude.ai's connector timeout. To prevent this, the server pings its own /healthz every 10 minutes while running on Render (see start_keep_alive in server.py), keeping the instance warm around the clock. One always-on service fits within the free tier's 750 instance-hours/month.

Pushing to main auto-deploys the service.

Connecting Claude

claude.ai / Claude Desktop (custom connector, OAuth)

  1. Go to Settings → Connectors → Add custom connector.

  2. Enter https://<your-service>.onrender.com/mcp as the URL. Leave the Advanced settings (OAuth client ID/secret) empty — the server supports dynamic client registration.

  3. Click Add, then Connect. You'll be redirected to the server's consent page: enter your MCP_SHARED_SECRET and click Authorize.

Free-tier note: if the Render service has spun down, the consent page or first connection attempt may time out while it cold-starts — retry after ~30 s.

Claude Code — either auth method works:

# Header auth (no browser round-trip):
claude mcp add --transport http google-maps \
  https://<your-service>.onrender.com/mcp \
  --header "X-MCP-Secret: <your-secret>"

# Or OAuth: add without the header, then run /mcp in a session and
# pick "Authenticate" — a browser opens the same consent page.

Project layout

File

Role

client.py

Google Maps API wrappers, Pydantic models, enums — errors propagate naturally

server.py

MCP tool definitions (try/except at the boundary), auth middleware, HTTP transport

enrichment.py

Location enrichment: website extract, web search, deterministic hours verdict

map_app.html

MCP Apps view for create_embedded_map (rendered by the host in a sandboxed iframe)

oauth.py

Stateless OAuth 2.1 authorization server (metadata, registration, PKCE flow)

cost_control.py

TTL cache + throttle decorator for expensive endpoints

render.yaml

Render free-tier deployment blueprint

tests/

pytest suite for the pure logic (embed URLs, hours verdicts, snippet extraction)

Run tests with pip install -r requirements-dev.txt then python -m pytest.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sKuangster/Google-Maps-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server