Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 17 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@

Give your AI agent the ability to understand the physical world β€” geocode, route, search, and reason about locations.

- **16 tools** β€” 13 atomic + 3 composite (explore-area, plan-route, compare-places)
- **17 tools** β€” 14 atomic + 3 composite (explore-area, plan-route, compare-places)
- **3 modes** β€” stdio, StreamableHTTP, standalone exec CLI
- **Agent Skill** β€” built-in skill definition teaches AI how to chain geo tools ([`skills/google-maps/`](./skills/google-maps/))

### vs Google Grounding Lite

| | This project | [Grounding Lite](https://cloud.google.com/blog/products/ai-machine-learning/announcing-official-mcp-support-for-google-services) |
|---|---|---|
| Tools | **16** | 3 |
| Tools | **17** | 3 |
| Geocoding | Yes | No |
| Step-by-step directions | Yes | No |
| Elevation | Yes | No |
Expand Down Expand Up @@ -63,6 +63,7 @@ Special thanks to [@junyinnnn](https://github.com/junyinnnn) for helping add sup
| `maps_air_quality` | Get air quality index, pollutant concentrations, and health recommendations by demographic group. |
| `maps_static_map` | Generate a map image with markers, paths, or routes β€” returned inline for the user to see directly. |
| `maps_batch_geocode` | Geocode up to 50 addresses in one call β€” returns coordinates for each. |
| `maps_search_along_route` | Search for places along a route between two points β€” ranked by minimal detour time. |
| **Composite Tools** | |
| `maps_explore_area` | Explore what's around a location β€” searches multiple place types and gets details in one call. |
| `maps_plan_route` | Plan an optimized multi-stop route β€” geocodes, finds best order, returns directions. |
Expand Down Expand Up @@ -116,7 +117,7 @@ Then configure your MCP client:
### Server Information

- **Transport**: stdio (`--stdio`) or Streamable HTTP (default)
- **Tools**: 16 Google Maps tools (13 atomic + 3 composite)
- **Tools**: 16 Google Maps tools (14 atomic + 3 composite)

### CLI Exec Mode (Agent Skill)

Expand All @@ -127,7 +128,7 @@ npx @cablate/mcp-google-map exec geocode '{"address":"Tokyo Tower"}'
npx @cablate/mcp-google-map exec search-places '{"query":"ramen in Tokyo"}'
```

All 16 tools available: `geocode`, `reverse-geocode`, `search-nearby`, `search-places`, `place-details`, `directions`, `distance-matrix`, `elevation`, `timezone`, `weather`, `air-quality`, `static-map`, `batch-geocode-tool`, `explore-area`, `plan-route`, `compare-places`. See [`skills/google-maps/`](./skills/google-maps/) for the agent skill definition and full parameter docs.
All 17 tools available: `geocode`, `reverse-geocode`, `search-nearby`, `search-places`, `place-details`, `directions`, `distance-matrix`, `elevation`, `timezone`, `weather`, `air-quality`, `static-map`, `batch-geocode-tool`, `search-along-route`, `explore-area`, `plan-route`, `compare-places`. See [`skills/google-maps/`](./skills/google-maps/) for the agent skill definition and full parameter docs.

### Batch Geocode

Expand Down Expand Up @@ -236,6 +237,7 @@ src/
β”‚ β”œβ”€β”€ airQuality.ts # maps_air_quality tool
β”‚ β”œβ”€β”€ staticMap.ts # maps_static_map tool
β”‚ β”œβ”€β”€ batchGeocode.ts # maps_batch_geocode tool
β”‚ β”œβ”€β”€ searchAlongRoute.ts # maps_search_along_route tool
β”‚ β”œβ”€β”€ exploreArea.ts # maps_explore_area (composite)
β”‚ β”œβ”€β”€ planRoute.ts # maps_plan_route (composite)
β”‚ └── comparePlaces.ts # maps_compare_places (composite)
Expand All @@ -245,10 +247,18 @@ src/
tests/
└── smoke.test.ts # Smoke + E2E test suite
skills/
└── google-maps/
β”œβ”€β”€ SKILL.md # Agent skill definition
β”œβ”€β”€ google-maps/ # Agent Skill β€” how to USE the tools
β”‚ β”œβ”€β”€ SKILL.md # Tool map, recipes, invocation
β”‚ └── references/
β”‚ β”œβ”€β”€ tools-api.md # Tool parameters + scenario recipes
β”‚ └── travel-planning.md # Travel planning methodology
└── project-docs/ # Project Skill β€” how to DEVELOP/MAINTAIN
β”œβ”€β”€ SKILL.md # Architecture overview + onboarding
└── references/
└── tools-api.md # Tool parameter reference
β”œβ”€β”€ architecture.md # System design, code map, 9-file checklist
β”œβ”€β”€ google-maps-api-guide.md # API endpoints, pricing, gotchas
β”œβ”€β”€ geo-domain-knowledge.md # GIS fundamentals, Japan context
└── decisions.md # 10 ADRs (design decisions + rationale)
```

## Tech Stack
Expand Down
6 changes: 5 additions & 1 deletion skills/google-maps/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Without this Skill, the agent can only guess or refuse when asked "how do I get

## Tool Map

16 tools in five categories β€” pick by scenario:
17 tools in five categories β€” pick by scenario:

### Place Discovery
| Tool | When to use | Example |
Expand All @@ -52,6 +52,7 @@ Without this Skill, the agent can only guess or refuse when asked "how do I get
|------|-------------|---------|
| `directions` | How to get from A to B | "Route from Taipei Main Station to the airport" |
| `distance-matrix` | Compare distances across multiple points | "Which of these 3 hotels is closest to the airport?" |
| `search-along-route` | Find places along a route (meals, stops) ranked by detour time | "Restaurants between Fushimi Inari and Kiyomizu-dera" |

### Environment
| Tool | When to use | Example |
Expand Down Expand Up @@ -102,3 +103,6 @@ npx @cablate/mcp-google-map exec <tool> '<json_params>' [-k API_KEY]
| File | Content | When to read |
|------|---------|--------------|
| `references/tools-api.md` | Full parameter specs, response formats, 7 scenario recipes, and decision guide | When you need exact parameters, response shapes, or multi-tool workflow patterns |
| `references/travel-planning.md` | Travel planning methodology β€” 6-layer model, Search Along Route, anti-patterns | When planning multi-day trips β€” **read before Recipe 1** |

> For **project development** knowledge (architecture, API guide, GIS domain, design decisions), see `skills/project-docs/SKILL.md`.
84 changes: 72 additions & 12 deletions skills/google-maps/references/tools-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,36 @@ Chaining patterns:

---

## search-along-route

Search for places along a route between two points. Results ranked by minimal detour time β€” perfect for finding meals, cafes, or attractions "on the way" between landmarks.

```bash
exec search-along-route '{"textQuery": "restaurant", "origin": "Fushimi Inari, Kyoto", "destination": "Kiyomizu-dera, Kyoto", "mode": "walking"}'
```

| Param | Type | Required | Description |
|-------|------|----------|-------------|
| textQuery | string | yes | What to search for ("restaurant", "cafe", "temple") |
| origin | string | yes | Route start point |
| destination | string | yes | Route end point |
| mode | string | no | walking, driving, bicycling, transit (default: walking) |
| maxResults | number | no | Max results (default: 5, max: 20) |

Response:
```json
{
"places": [
{ "name": "SUSHI MATSUHIRO", "rating": 5.0, "location": { "lat": 34.968, "lng": 135.771 } }
],
"route": { "distance": "4.0 km", "duration": "58 mins", "polyline": "..." }
}
```

Key for trip planning: use this between consecutive anchors to find **along-the-way** stops instead of searching at endpoints.

---

## explore-area (composite)

Explore a neighborhood in one call. Internally chains geocode β†’ search-nearby (per type) β†’ place-details (top N).
Expand Down Expand Up @@ -392,23 +422,53 @@ Use these recipes when the user's question maps to a multi-step workflow. Think

This is the most common complex scenario. The goal is a time-ordered itinerary with routes between stops.

> **Read `references/travel-planning.md` first** β€” it contains the full methodology, anti-patterns, and time budget guidelines.

**Steps:**
1. `geocode` β€” Resolve all mentioned landmarks to coordinates
2. `search-nearby` β€” Find restaurants/attractions near each landmark (use coordinates from step 1)
3. `place-details` β€” Get ratings, hours, reviews for top candidates (use place_id from step 2)
4. `distance-matrix` β€” Compare travel times between all candidate stops to find the optimal order
5. `directions` β€” Generate turn-by-turn routes between stops in the final order
1. `search-places` β€” Search "top attractions in {city}" β†’ geographically diverse **anchor points**
2. **Design arcs** — Group nearby anchors into same-day arcs. One direction per day (south→north).
3. `search-along-route` β€” Between each pair of anchors, find restaurants/cafes **along the walking route** (ranked by minimal detour)
4. `place-details` β€” Get ratings, hours for top candidates
5. `plan-route` β€” Validate each day's route. Use `optimize: false` (you already know the geographic order).
6. `weather` + `air-quality` β€” Adjust for conditions
7. `static-map` β€” **Always** visualize each day with numbered markers + path

**Key decisions:**
- If the user says "near X", use `search-nearby`. If they say "best Y in Z", use `search-places`.
- Always check `opening_hours` from `place-details` before including in itinerary.
- Use `distance-matrix` to order stops efficiently, THEN use `directions` for the final route.
- **Use `search-along-route` for meals and breaks** β€” not explore_area or search_nearby. Along-route results are on the path, not random nearby points.
- **Never backtrack**: stops progress in one direction per day.
- Alternate activity types: temple β†’ food β†’ walk β†’ shrine β†’ cafe.
- Budget 5-7 stops per day max. Major temples = 90-120 min.
- Edge landmarks (geographically isolated) go at start or end of a day.
- **Always generate a map** for each day.

**Example flow (Kyoto 2-day):**
```
search_places("top attractions in Kyoto")
β†’ Fushimi Inari(south), Kiyomizu(east), Kinkaku-ji(north), Arashiyama(west)

Day 1 arc: south→center — Fushimi → Kiyomizu → Gion → Pontocho
Day 2 arc: center→west — Nishiki → Nijo Castle → Arashiyama

search_along_route("restaurant", "Fushimi Inari", "Kiyomizu-dera", "walking")
β†’ finds lunch options ALONG the 4km route (not at endpoints)

search_along_route("kaiseki restaurant", "Gion, Kyoto", "Arashiyama, Kyoto")
β†’ finds dinner along the afternoon route

plan_route(Day 1 stops, optimize:false) β†’ static_map(Day 1)
plan_route(Day 2 stops, optimize:false) β†’ static_map(Day 2)
```

**Example output shape:**
**Example output:**
```
Morning: Tokyo Tower (9:00) β†’ 12 min walk β†’ Zojoji Temple (9:30)
Lunch: Sushi Dai (11:30) β˜…4.6 β€” 2.1 km, 8 min by transit
Afternoon: TeamLab (14:00) β†’ Odaiba area
Day 1: South β†’ Center arc
08:30 Fushimi Inari (90 min) β†’ 25 min transit
10:30 Kiyomizu-dera (90 min) β†’ walk down Sannen-zaka
12:30 [along-route find] Gion lunch β˜…4.7 (75 min)
14:00 Yasaka Shrine (30 min) β†’ 15 min walk
14:45 Pontocho stroll + cafe (45 min)
17:30 Dinner near Kawaramachi
[map with markers 1-6 and walking path]
```

---
Expand Down
136 changes: 136 additions & 0 deletions skills/google-maps/references/travel-planning.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# Travel Planning Best Practices

## Core Principle

Real travel planning is **directional exploration**, not point collection.

A human plans: "Start south at Fushimi Inari, walk up to Kiyomizu-dera, eat lunch somewhere along the way in Gion, then head west to Arashiyama for evening."

An algorithm plans: "Here are the top 10 rated places. Optimizing shortest path..."

The difference is **arc thinking** β€” one direction per day, discovering things along the way.

---

## The 6-Layer Decision Model

Human travel planners think in layers. Each layer constrains the next.

### Layer 1: Anchor Discovery
**What:** Find 4-6 must-visit landmarks spread across the city.
**Tool:** `search_places("top attractions in {city}")`
**Why it works:** Google's algorithm returns geographically diverse results. Kyoto β†’ Fushimi(south), Kiyomizu(east), Kinkaku-ji(north), Arashiyama(west) β€” natural 8kmΓ—10km spread.

### Layer 2: Arc Design
**What:** Connect anchors into one-directional arcs per day. Edge landmarks go at start/end of a day.
**Tool:** `distance_matrix` between anchors to understand spatial relationships.
**Rule:** Never backtrack. Each day sweeps one direction (south→north, east→west).

Example:
```
Day 1: Fushimi(south) → Kiyomizu(east) → Gion → Pontocho(center) [south→center arc]
Day 2: Nishiki(center) → Nijo Castle → train → Arashiyama(west) [center→west arc]
```

### Layer 3: Time-Slot Matching
**What:** Assign anchors to times based on **experience quality**, not distance.
**Tool:** None β€” this is AI knowledge.
**Examples:**
- Fushimi Inari = **early morning** (fewer crowds, best light for photos, hiking needs fresh legs)
- Outdoor temples = **morning to afternoon** (natural light)
- Shopping districts = **afternoon** (all stores open)
- Scenic areas = **late afternoon** (golden hour light)
- Fine dining = **evening at the final stop** (no rush to next destination)

### Layer 4: Along-Route Filling
**What:** Between two anchors, find what's **on the way** β€” not at the destination.
**Tool:** `search_along_route(textQuery, origin, destination)`
**This is the key differentiator.** Results are ranked by minimal detour time, not proximity to a point.

```
search_along_route("restaurant", "Fushimi Inari, Kyoto", "Kiyomizu-dera, Kyoto", "walking")
β†’ Finds restaurants ALONG the 4km walking route, not clustered at either end
```

### Layer 5: Meal Embedding
**What:** Meals appear where the traveler **will be** at mealtime, not where the "best restaurant" is.
**Logic:**
1. Estimate what time the traveler reaches each arc segment
2. Lunch (~12:00) β†’ search_along_route("lunch restaurant", previous_stop, next_stop)
3. Dinner (~18:00) β†’ search_nearby at the day's final area (no rush)

**Anti-pattern:** "I searched for the best restaurant in the whole city" β†’ it's 3km off the route.
**Correct:** "You'll be near Gion around noon β€” here are options along the way."

### Layer 6: Rhythm Validation
**What:** Check the itinerary feels human, not robotic.
**Tool:** `plan_route(stops, optimize: false)` to get actual times, `weather` for conditions.
**Checklist:**
- [ ] Not 5 temples in a row (alternate: temple β†’ food β†’ walk β†’ shrine β†’ cafe)
- [ ] Major temples get 90-120 min, not 30 min
- [ ] Walking per day < 10km (suggest transit for >2km gaps)
- [ ] Lunch 11:30-13:00, dinner 17:30-19:30
- [ ] 5-7 stops per day max (including meals)
- [ ] Final stop: call `static_map` with markers + path to visualize

---

## Tool Call Sequence

```
Phase 1 β€” Skeleton (2-3 calls)
search_places("top attractions in {city}") β†’ anchors
distance_matrix(all anchors) β†’ spatial relationships

Phase 2 β€” Arc + Fill (2-4 calls per day)
search_along_route("restaurant", stop_A, stop_B) β†’ along-route meals
search_along_route("cafe", stop_B, stop_C) β†’ along-route breaks

Phase 3 β€” Environment (2 calls)
weather(city coords) β†’ rain β†’ move indoor activities
air_quality(city coords) β†’ bad AQI β†’ reduce outdoor time

Phase 4 β€” Validate + Visualize (2 calls per day)
plan_route(day_stops, optimize: false) β†’ verify times/distances
static_map(markers + path) β†’ map for each day

Total: ~12-16 calls for a 2-day trip
```

---

## Anti-Patterns

| Anti-Pattern | Symptom | Fix |
|-------------|---------|-----|
| Single-point explosion | `explore_area("Kyoto")` β†’ all within 1km | search_places for anchors first |
| Backtracking | east→west→east→west | One direction per day |
| No along-route search | Meals at endpoints only | `search_along_route` between stops |
| Distance-optimal ordering | Ignores time-of-day quality | AI assigns time slots before routing |
| No map output | Text/JSON only | Always `static_map` after each day's route |
| Over-scheduling | 12 stops in one day | Max 5-7 stops including meals |
| Same-type clustering | 5 temples consecutively | Alternate activity types |

---

## Time Budget

| Activity | Duration |
|----------|----------|
| Major temple/shrine | 60-120 min |
| Small shrine / photo spot | 15-30 min |
| Museum | 90-180 min |
| Market / shopping street | 60-90 min |
| Sit-down meal | 60-120 min |
| Quick meal / street food | 20-40 min |
| Cafe break | 30-45 min |
| Walking <1km | 10-15 min |
| Transit between areas | 20-40 min |

---

## When to Read This

- User says "plan a trip", "create an itinerary", "plan X days in Y"
- Trip plan clusters all stops in one area
- Building multi-day travel content
Loading
Loading