Skip to main content
Glama
README.md
# maps-fetcher-mcp

MCP server + CLI: fetch any Google Maps place by link — full business
metadata plus ALL gallery photos and videos at max resolution.

## Install

```bash
pip install maps-fetcher-mcp          # or: uv pip install maps-fetcher-mcp
maps-fetcher-setup                    # one-time: browser download (~120MB)
```

## Use as an MCP server (any MCP client)

```json
{
  "mcpServers": {
    "maps_fetcher": {
      "command": "maps-fetcher-mcp"
    }
  }
}
```

Works in: Hermes Agent, Claude Desktop, Cursor, opencode, Cline, Zed —
anything that speaks MCP (stdio).

## Use as a CLI

```bash
maps-fetcher "https://maps.app.goo.gl/XXXX"                  # everything
maps-fetcher "https://maps.app.goo.gl/XXXX" --include info   # metadata only (~20s)
maps-fetcher "https://maps.app.goo.gl/XXXX" --include photos
maps-fetcher "https://maps.app.goo.gl/XXXX" --include videos
maps-fetcher --list                                          # what's been fetched
```

## Tools exposed (MCP)

| Tool | Purpose | Typical time |
|---|---|---|
| `get_place_info` | metadata only: name, phone, rating, address, hours, coords | ~20s |
| `get_place_media` | media only (`kind`: photos / videos / both) | 40-220s |
| `fetch_maps_place` | one-shot everything (`include`: all/info/photos/videos/media) | 60-220s |
| `list_maps_places` | previously fetched places | instant |

Same place re-fetched within 24h reuses the scrape (~2s).

## What it handles

- Short links resolved + canonicalized; search links rejected cleanly
- Video tiles disguised as photos; DASH/HLS manifests muxed with audio
- Expired URLs, avatar junk, motion-blur frames, perceptual duplicates
  (quarantined, not deleted), gapless file numbering
- Nondeterministic gallery lazy-loading: scrape retried and merged
- Bot-wall detection (reCAPTCHA / unusual-traffic) with clean errors;
  stealth browser via Patchright, plain Playwright fallback
- Security: google-host allowlist for all media downloads, per-file and
  per-place size caps, decompression-bomb guard, no secrets

## Output

```
<root>/<place-slug>/
  photos/photo_01.jpg ...   videos/video_01.mp4 ...   quarantine/
  info_pw.json              contact_sheet.jpg
```

Default root: `/mnt/d/Projects/maps-data-fetcher/places` (WSL layout;
override with `output_dir` or `MAPS_FETCHER_ROOT`).

## Limits

Unofficial scraping — good for batch collection at low volume. Google
markup changes can break it (fixes usually small). Not for high-volume
production; use the paid Google Places API for that. CAPTCHAs are
detected and reported, not auto-solved.

## Dev

Source layout: `maps_fetcher/core.py` (engine), `mcp_server.py` (MCP
tools), `cli.py` (CLI), `setup.py` (browser install helper).

TDQS

B3.3/5.0

Scored across 4 tools

Disambiguation2/5

There is significant overlap: fetch_maps_place with include='info' does exactly what get_place_info does, and with include='media' does what get_place_media does. While the descriptions clarify the intended use cases, an agent may struggle to pick the right tool since fetch_maps_place is a superset. The tools are not clearly distinct in purpose.

Naming Consistency2/5

The naming mixes conventions: 'get_place_info' and 'get_place_media' follow a get_place_N pattern, but 'fetch_maps_place' uses a different verb (fetch) and noun order, and 'list_maps_places' uses plural. The pattern is not consistent across all tools, though the tools are readable.

Tool Count4/5

At 4 tools, the server is well-scoped for a maps fetcher. However, the presence of get_place_info and get_place_media is redundant given fetch_maps_place can achieve the same via its include parameter, suggesting the count could be trimmed to 2–3 tools without losing functionality.

Completeness4/5

The core lifecycle for fetching Google Maps place data is covered: retrieving metadata, media, or both, plus listing previously fetched places. There are no obvious dead ends for the stated purpose. Missing delete/update operations are not essential for a fetcher, so the surface feels complete.

Maintenance

ActivityMaintained
ResponsivenessNo issues