Google Maps MCP Server
# Google Maps MCP Server
<div align="center">
[](https://opensource.org/licenses/MIT)
[](https://python.org)
[](https://github.com/jlowin/fastmcp)
[](https://playwright.dev)
[](https://modelcontextprotocol.io)
[](https://github.com/adityak74/google-maps-mcp/actions)
<p align="center">
<b>Production-ready, 100% open-source Model Context Protocol (MCP) server for Google Maps.</b><br>
Search places, read place details, extract reviews, photo feeds, business updates, and reviewer histories with zero API keys and zero Google Cloud billing.
</p>
[Quick Start](#-quick-start) •
[Features](#-features) •
[Tool Reference](#-tool-reference) •
[Client Setup](#-client-configuration) •
[Architecture](#-architecture) •
[Contributing](#-contributing)
</div>
---
## 🌟 Features
- 🆓 **100% Free & Open Source**: No Google Cloud project, no Google Places API billing, and no third-party subscription keys (like HasData) required.
- ⚡ **Built on Latest FastMCP 4.0**: Full compliance with the official Model Context Protocol specifications (stdio & streamable HTTP).
- 🧩 **Complete HasData Schema Parity**: Standardized JSON data output matching HasData's Google Maps tool contracts (`localResults`, `placeResults`, `reviews`, `topics`, `photos`, `posts`, `contributor`).
- 🛡️ **Anti-Bot & Stealth Engine**: Automatic GDPR / cookie consent dismissal, user-agent emulation, and WebGL canvas stealth to prevent automated session blocking.
- 🎯 **Direct Place & Query Resolution**: Gracefully resolves both broad regional keyword searches and direct place URL / single-business matches.
- 🍪 **Optional Session Persistence**: Full support for `STORAGE_STATE` / cookies to bypass Google Maps "Limited View" restrictions for signed-in sessions.
---
## ⚖️ How It Compares
| Feature | Official Google Places API | HasData MCP (Hosted) | **This Open Source MCP** |
| :--- | :---: | :---: | :---: |
| **Price** | Paid (Pay per call / Google Cloud) | Paid (HasData subscription / credits) | **100% Free** |
| **API Keys Required** | Yes (GCP Project & Billing) | Yes (`HASDATA_API_KEY`) | **None** |
| **Source Code** | Closed | Closed Source (Hosted endpoint only) | **Full MIT Open Source** |
| **FastMCP Version** | Custom / Older | Remote Proxy | **FastMCP 4.0+ Native** |
| **Review Topics & Clustering** | ❌ (Limited) | ✅ Yes | ✅ **Yes** |
| **Contributor Review History** | ❌ No | ✅ Yes | ✅ **Yes** |
| **Self-Hosted Privacy** | ❌ Hosted by Google | ❌ Proxy through HasData | ✅ **Runs locally on your machine** |
---
## 🏗️ Architecture
```mermaid
flowchart LR
subgraph Client["MCP Client (Claude Desktop / Cursor / Claude Code)"]
LLM[LLM / Chat Model]
end
subgraph MCP["Google Maps MCP Server (FastMCP 4.0)"]
Router[FastMCP Tool Router]
Models[Pydantic HasData Schemas]
subgraph Extractors["Async Extractors"]
E1[search_places]
E2[get_place_details]
E3[get_place_reviews]
E4[get_place_photos]
E5[get_place_posts]
E6[get_contributor_reviews]
end
BrowserMgr[BrowserManager Singleton]
end
subgraph Web["Google Maps"]
GMap[(Google Maps Live Web)]
end
Client <-->|stdio / JSON-RPC| Router
Router --> Extractors
Extractors --> Models
Extractors <--> BrowserMgr
BrowserMgr <-->|Playwright Chromium Stealth| GMap
```
---
## 🚀 Quick Start
### 1. Installation via `uv`
We recommend [uv](https://github.com/astral-sh/uv) for fast, isolated Python execution.
```bash
# Clone the repository
git clone https://github.com/adityak74/google-maps-mcp.git
cd google-maps-mcp
# Install dependencies and Chromium browser
uv sync
uv run playwright install chromium
```
### 2. Verify Installation
Run the test suite to ensure everything is operating cleanly:
```bash
uv run pytest -v
```
---
## 💻 Client Configuration
### Claude Desktop
Add the server to your `claude_desktop_config.json` (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS or `%APPDATA%\Claude\claude_desktop_config.json` on Windows):
```json
{
"mcpServers": {
"google-maps": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/TO/google-maps-mcp",
"run",
"google-maps-mcp"
]
}
}
}
```
### Cursor
Add to your project's `.cursor/mcp.json`:
```json
{
"mcpServers": {
"google-maps": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/TO/google-maps-mcp",
"run",
"google-maps-mcp"
]
}
}
}
```
### Claude Code CLI
```bash
claude mcp add google-maps -- uv --directory /ABSOLUTE/PATH/TO/google-maps-mcp run google-maps-mcp
```
### Windsurf / Codeium
Add to `~/.codeium/windsurf/mcp_config.json`:
```json
{
"mcpServers": {
"google-maps": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/TO/google-maps-mcp",
"run",
"google-maps-mcp"
]
}
}
}
```
---
## 🛠️ Tool Reference
All 6 tools return clean, structured JSON conforming to HasData's schema definitions.
### 1. `google_maps_search`
Search Google Maps for places matching a keyword query, ranked as Google Maps ranks them.
- **Parameters**:
- `q` (*str*, required): Search term (e.g. `"best coffee in Seattle"`, `"plumber near me"`).
- `ll` (*str*, optional): Geographic center pin and zoom as `@lat,lng,zoomz` (e.g. `"@47.6062,-122.3321,14z"`).
- `hl` (*str*, optional, default: `"en"`): Two-letter interface language code.
- `gl` (*str*, optional, default: `"us"`): Two-letter country region code.
- `start` (*int*, optional, default: `0`): Pagination offset.
```json
{
"localResults": [
{
"position": 1,
"title": "Taj Palace",
"address": "92 THF Blvd, Chesterfield, MO 63005",
"rating": 4.4,
"phone": "(636) 728-1000",
"type": "Indian restaurant",
"website": "https://tajpalacestl.com/",
"gpsCoordinates": { "latitude": 38.6671397, "longitude": -90.5892454 }
}
],
"pagination": { "start": 0, "count": 1, "hasMore": false }
}
```
---
### 2. `google_maps_place_details`
Retrieve comprehensive listing information for a specific place.
- **Parameters**:
- `placeId` (*str*, optional): Google Maps place identifier or direct place URL.
- `dataId` (*str*, optional): Feature data ID (hex representation).
- `query` (*str*, optional): Fallback search query if ID is not known.
- `hl` (*str*, optional, default: `"en"`): Language code.
```json
{
"placeResults": {
"title": "Taj Palace",
"address": "92 THF Blvd, Chesterfield, MO 63005",
"rating": 4.4,
"phone": "(636) 728-1000",
"type": "Indian restaurant",
"website": "https://tajpalacestl.com/",
"images": [
"https://lh5.googleusercontent.com/p/AF1Qip...=w400-h300-k-no"
]
}
}
```
---
### 3. `google_maps_reviews`
Scrape the review feed for a place with sorting, review topics, and pagination.
- **Parameters**:
- `placeId` (*str*, optional): Place ID or URL.
- `dataId` (*str*, optional): Feature data ID.
- `sortBy` (*str*, optional, default: `"mostRelevant"`): `"mostRelevant"`, `"newestFirst"`, `"ratingHigh"`, or `"ratingLow"`.
- `topicId` (*str*, optional): Filter reviews mentioning a specific topic chip.
- `num` (*int*, optional, default: `20`): Maximum number of reviews to extract.
```json
{
"placeInfo": { "title": "Taj Palace" },
"topics": [
{ "id": "lunch_buffet", "keyword": "lunch buffet", "mentions": 42 },
{ "id": "chicken_tikka", "keyword": "chicken tikka", "mentions": 28 }
],
"reviews": [
{
"rating": 5.0,
"snippet": "Outstanding Indian food and attentive service!",
"date": "2 weeks ago",
"user": { "name": "Sarah Miller", "contributorId": "106033685843245983748" },
"response": { "snippet": "Thank you Sarah, we hope to see you again soon!" }
}
]
}
```
---
### 4. `google_maps_photos`
Retrieve photo feeds categorized by section (`All`, `Menu`, `Atmosphere`, `Inside`, etc.).
- **Parameters**:
- `placeId` (*str*, optional) / `dataId` (*str*, optional).
- `categoryId` (*str*, optional): Category tab filter (e.g. `"Menu"`).
- `limit` (*int*, optional, default: `20`): Maximum photos to return.
```json
{
"categories": ["All", "Menu", "Inside", "Vibe"],
"photos": [
{
"image": "https://lh5.googleusercontent.com/p/AF1Qip...=w1080-h720",
"thumbnail": "https://lh5.googleusercontent.com/p/AF1Qip...=w400-h300"
}
]
}
```
---
### 5. `google_maps_posts`
Retrieve updates, announcements, offers, and posts published by the business listing.
- **Parameters**:
- `placeId` (*str*, optional) / `dataId` (*str*, optional).
- `limit` (*int*, optional, default: `10`): Maximum posts to return.
```json
{
"posts": [
{
"snippet": "Join us for our Weekend Grand Buffet starting this Saturday at 11:30 AM!",
"date": "3 days ago"
}
]
}
```
---
### 6. `google_maps_contributor_reviews`
Retrieve reviews written by a specific reviewer across all locations they evaluated. Ideal for reviewer credibility and local guide network analysis.
- **Parameters**:
- `contributorId` (*str*, required): Contributor ID or profile link.
- `num` (*int*, optional, default: `20`): Maximum reviews to return.
```json
{
"contributor": {
"name": "David Kim",
"level": "Level 6 Local Guide",
"points": 1450,
"contributions": "Level 6 Local Guide · 1,450 points"
},
"reviews": [
{
"placeInfo": { "title": "Artisan Bakery" },
"rating": 5.0,
"snippet": "Best sourdough loaf in town.",
"date": "1 month ago"
}
]
}
```
---
## 🔒 Advanced: Authentication & Google Maps Limited View
In 2024–2026, Google introduced a **"Limited View"** for unauthenticated browser sessions in certain geographical regions or unverified IPs. In this mode, Google temporarily restricts public review feeds behind a sign-in prompt.
To bypass this restriction and access full review feeds unconditionally:
1. **Save Authenticated Cookies / Storage State:**
Use Playwright CLI to log into your Google account once and export your cookies:
```bash
uv run playwright codegen --save-storage=google_state.json https://www.google.com/maps
```
2. **Pass Environment Variable:**
Provide the path to `STORAGE_STATE` in your client config or shell:
```bash
export STORAGE_STATE="/absolute/path/to/google_state.json"
```
Or inside your MCP client config:
```json
"env": {
"STORAGE_STATE": "/absolute/path/to/google_state.json"
}
```
---
## 🧪 Testing & Development
Run all test suites including models, utilities, extractors, and server tool registrations:
```bash
# Run pytest with coverage/verbose reporting
uv run pytest -v
# Run only extractor DOM tests
uv run pytest tests/test_extractors.py -v
# Run in headed mode for visual browser debugging
HEADLESS=false uv run pytest tests/test_browser.py -v
```
---
## 🤝 Contributing
Contributions, issues, and feature requests are welcome!
Feel free to check the [issues page](https://github.com/adityak74/google-maps-mcp/issues).
1. Fork the Project
2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
3. Commit your Changes (`git commit -m 'feat: add some amazing feature'`)
4. Push to the Branch (`git push origin feature/AmazingFeature`)
5. Open a Pull Request
---
## 📄 License
Distributed under the MIT License. See [`LICENSE`](LICENSE) for more information.
---
<div align="center">
<sub>Built with ❤️ by <a href="https://github.com/adityak74">Aditya Karnam</a> and the open-source MCP community.</sub>
</div>
TDQS
Scored across 6 tools
Each tool targets a distinct aspect of Google Maps data: place search, individual place details, reviews, photos, posts, and contributor review history. Even though place_details can accept a query, its purpose as a single-place lookup is clearly separated from the ranked search tool.
All tools share the google_maps_ prefix and use snake_case, making the namespace cohesive. Some names are noun-based (reviews, photos, posts) while others are verb- or resource-oriented, but the overall pattern is predictable and readable.
Six tools is a well-scoped set for a Google Maps place-data server. Each tool covers a meaningful, distinct retrieval use case without unnecessary overlap or bloat.
The set thoroughly covers place discovery and place-specific content feeds, but notable Google Maps capabilities like geocoding, directions, and place autocomplete are missing. As a read-only place information server it is fairly complete, but as a general Google Maps MCP server it has gaps.