Skip to main content
Glama

places-new-mcp

A small MCP server and CLI over Google Places API (New), Geocoding API v4 and the Routes API. Every call sends a field mask, answers come back as compact JSON, identical calls are cached for the session, and each session has a hard upstream call budget.

The problem

Google moved the old Places API, Directions API and Distance Matrix API to Legacy on March 1, 2025. Legacy services cannot be enabled in new Cloud projects, so new agents have to use Places API (New) and the Routes API. Those APIs bill by the fields you ask for, and returning every field is both the most expensive SKU and a wall of JSON for an agent. This lab gives an agent eight read-only tools with cheap defaults, a tier ceiling and a call budget.

Related MCP server: Google Places MCP Server

Quickstart

bun install --frozen-lockfile

# Keyless: replay synthetic responses (invented places, real response shapes; only the demo queries answer)
bun run src/cli.ts geocode "123 Sample St, Sampletown, EX 00000" --fixtures
bun run src/cli.ts text-search "coffee near Example Market Hall, Sampletown" --limit 5 --fixtures

# Live: put a key in .env (see .env.example), then
bun run src/cli.ts details <placeId> --fields displayName,rating,regularOpeningHours
bun run src/cli.ts route --from "1600 Amphitheatre Parkway, Mountain View, CA" --to "place_id:<id>" --mode WALK

# MCP server (stdio)
bun run src/cli.ts serve            # live
bun run src/cli.ts serve --fixtures # keyless demo

MCP client config (Claude Code .mcp.json, Cursor mcp.json):

{
  "mcpServers": {
    "places": {
      "command": "bun",
      "args": ["run", "/path/to/places-new-mcp/src/cli.ts", "serve"],
      "env": { "GOOGLE_MAPS_API_KEY": "${GOOGLE_MAPS_API_KEY}", "PLACES_MCP_BUDGET": "25" }
    }
  }
}

Restrict the key in Google Cloud to Places API (New) (places.googleapis.com), Geocoding API and Routes API (routes.googleapis.com). Our live run used a project with geocoding-backend.googleapis.com (console name "Geocoding API") enabled; we did not confirm whether Geocoding v4 is metered under a different service name.

Tools

Tool

Google API

Default field mask bills

places_text_search

Places API (New) places:searchText

Text Search Pro

places_nearby_search

Places API (New) places:searchNearby

Nearby Search Pro (no Essentials tier exists)

place_details

Places API (New) places/{id}

Place Details Pro

places_autocomplete

Places API (New) places:autocomplete

Autocomplete Requests; returns a sessionToken to reuse on place_details

geocode_address

Geocoding API v4 geocode/address/{address}

Geocoding

reverse_geocode

Geocoding API v4 geocode/location/{lat},{lng}

Geocoding

compute_route

Routes API directions/v2:computeRoutes

Compute Routes Essentials (traffic-aware: Pro, two-wheeler: Enterprise)

session_status

none

free: calls used, remaining, cache hits, refused, calls per SKU

Cost controls:

  • Field masks everywhere. X-Goog-FieldMask on every request; a transport refuses to send one without it. * is refused. Place fields come from a curated list (27 fields) with the tier Google's docs assign to each (src/fields.ts). The priciest field sets the SKU, and the tool reports it in meta.sku.

  • Tier ceiling. PLACES_MCP_MAX_TIER (default enterprise) refuses Enterprise + Atmosphere fields unless raised.

  • Budget. PLACES_MCP_BUDGET (default 25) upstream calls per session; past it, tools return budget_exceeded without touching the network.

  • Cache. In-memory, per session, PLACES_MCP_CACHE_TTL_S (default 60 s, 0 disables). Cache hits are free.

  • Compact JSON. Flat {id, name, address, lat, lng, type, mapsUrl, rating, ratings, price, phone, website, openNow, hours}; empty keys dropped; OPERATIONAL status dropped; reverse geocode trimmed to 5 results.

Measured

Keyless run of the real MCP server (in-memory MCP client). Keyless numbers come from synthetic responses (fixtures/synthetic/): invented values in the same JSON shape (key paths, nesting, status codes) as real Google responses. tests/shape.test.ts checks that shape against real responses recorded locally on 2026-10-21 (kept in the gitignored .recorded-local/, never published). Byte counts depend on the invented values, so read them as illustrative. The proof against the real APIs is the live smoke test (tests/live.test.ts: text search, geocode, route, plus a cache hit), which passed with a key on 2026-10-21. Produced by bun run report; full output in reports/places-new-mcp.md and reports/places-new-mcp.json.

Step

Tool

Billed SKU (from field mask)

Mask fields

Response bytes (synthetic, masked)

Compact bytes

Smaller by

text-search-default

places_text_search

Text Search Pro

7

1863

1238

33.5%

nearby-cafes

places_nearby_search

Nearby Search Pro

5

1356

736

45.7%

details-default

place_details

Place Details Pro

6

355

240

32.4%

details-enterprise

place_details

Place Details Enterprise

9

1134

437

61.5%

autocomplete

places_autocomplete

Autocomplete Requests

6

1715

1271

25.9%

geocode

geocode_address

Geocoding (v4)

5

239

206

13.8%

reverse-geocode

reverse_geocode

Geocoding (v4)

5

2976

963

67.6%

route-drive

compute_route

Compute Routes Essentials

7

184

154

16.3%

total

9822

5245

46.6%

  • reverse-geocode: the synthetic response has 14 results (as many as the real one did); the tool keeps the top 5 by default (client-side trim, same bill).

  • Same text search repeated in-session: served from cache = true (no upstream call, no budget used).

  • fields: ["*"]: field_mask_refused before any network call.

  • editorialSummary (Enterprise + Atmosphere) with the default max tier enterprise: field_mask_refused.

  • Invalid place id (synthetic copy of the Google 400 shape): google_INVALID_ARGUMENT.

  • Session after the run: 9 budgeted calls of 25 (served by the synthetic transport, no network), 1 cache hit(s), 2 refused.

  • Budget 2, four different calls: ok, ok, budget_exceeded, budget_exceeded.

What we verified about the idea's claims

Checked on 2026-10-21 against Google's own pages (each showed "Last updated 2026-10-20 UTC"):

Claim

Result

Source

Legacy Places API closed to new projects

Confirmed. "Legacy services are not available in new Cloud projects but remain fully supported for existing projects." Places API legacy date: March 1, 2025.

Legacy products and features

...from Oct 5, 2026

Not confirmed. Google's legacy date is March 1, 2025. Neither the legacy page, the deprecations page nor the Places release notes has an October 2026 entry.

same

Existing projects keep working, at least 12 months notice

Confirmed. "we will provide at least a 12-month notice prior to the decommission"; no decommission date set.

Legacy products and features

Directions / Distance Matrix replaced by Routes API

Confirmed. Both Legacy since March 1, 2025, replacement Routes API (directions/v2:computeRoutes, distanceMatrix/v2:computeRouteMatrix).

Legacy page, Routes migration guide

"Geocoding v4"

Confirmed it exists. Preview April 30, 2025; GA March 30, 2026. Endpoints under geocode.googleapis.com/v4/geocode/..., field mask via X-Goog-FieldMask. Our live calls to /v4/geocode/address and /v4/geocode/location returned HTTP 200.

Geocoding release notes, v4 overview, Choose fields

"Field agents still scrape Maps HTML; few ship a clean MCP"

Not verified. Market claim; we did not measure it.

none

Limits

  • Caching and Google's terms. Google's Places policies say "You must not pre-fetch, cache, or store Places API content beyond the allowed exceptions"; place IDs are exempt. The cache here is in-memory, per process, never written to disk and expires after 60 s by default, meant to absorb an agent repeating the same call in one task. Check the Maps Service Terms for your use; set PLACES_MCP_CACHE_TTL_S=0 to turn it off.

  • No Google content in the repo. Keyless tests and the demo use synthetic responses with invented values. Real responses are recorded only to .recorded-local/ (gitignored) for the shape check. In fixture mode only the demo requests answer, and their answers describe fictional places.

  • Attribution. If you show place content to people, Google requires Maps attribution and author credit for photos/reviews. Photos and reviews are not exposed by this server.

  • SKU labels are estimates. Tiers are copied from Google's docs on 2026-10-21 for the 27 supported fields. Routes tier logic covers traffic-aware (Pro) and two-wheeler (Enterprise) only. We did not verify the Geocoding API v4 SKU name. The bill in Google Cloud is the source of truth. No prices are quoted here.

  • Budget scope. One budget per process/MCP connection, not per key or per day. Use Cloud quotas and budget alerts for hard limits.

  • Not included: Route Matrix, Places photos, reviews, Address Validation, Geocoding v4 SearchDestinations (Experimental/Preview), and Gemini summaries (an MCP client is already an LLM; summarizing compact JSON again would add cost).

  • Legacy APIs are never called. No maps.googleapis.com/maps/api/... endpoint is used; a test enforces this for the synthetic fixtures.

Development

bun run check   # install, skills layout, biome, tsc, tests, report, bun audit, gitleaks
bun test        # live smoke runs only if GOOGLE_MAPS_API_KEY is set (3 calls); PLACES_MCP_SKIP_LIVE=1 skips it
bun run fixtures:synthetic  # regenerate fixtures/synthetic (keyless, deterministic)
bun run record              # record real responses to gitignored .recorded-local/ (9 field-masked calls); enables tests/shape.test.ts

Not affiliated

Not affiliated with, endorsed by, or sponsored by Google LLC. Google Maps Platform, Places API and Routes API are trademarks of Google LLC.


Built by SkilledDragon LLC. Questions: hello@skilleddragon.com. Apache-2.0 (see LICENSE and NOTICE).

Related MCP Connectors

Related MCP Servers