Skip to content

Commit 3f98e6d

Browse files
cablateclaude
andauthored
feat: proactive map visualization + travel planning skill (#51)
* feat: proactive map visualization + travel planning best practices Problems fixed: 1. AI never calls static_map unless explicitly asked → added PROACTIVELY hint to static_map description 2. Trip plans cluster in one area → added district-based exploration hints to explore_area and plan_route descriptions 3. No travel planning methodology → new references/travel-planning.md with anti-patterns, time budgets, correct flow Changes: - static_map: "PROACTIVELY call after explore_area, plan_route, etc." - explore_area: "call multiple times with district names, not city name" - plan_route: "geographic arc per day, call static_map after" - New: references/travel-planning.md (complete methodology) - Recipe 1 rewritten: district-first, always-visualize approach - SKILL.md: added travel-planning.md to reference table Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: tool-driven travel planning — search_places as anchor discovery Replaces AI-knowledge-dependent district approach with tool-driven flow: 1. search_places("top attractions in {city}") → naturally diverse anchors 2. Cluster anchors by proximity → assign to days as geographic arcs 3. explore_area around each anchor → find supporting restaurants/cafes 4. plan_route per day → static_map per day Verified: search_places("top attractions in Kyoto") returns points spanning 8km×10.7km across Fushimi/Higashiyama/Kinkaku-ji/Arashiyama — natural geographic diversity without needing pre-knowledge of city districts. Also: static_map description now says PROACTIVELY call after other tools. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: add maps_search_along_route + travel planning methodology overhaul Search Along Route (new tool): - Uses Google Places searchText API with searchAlongRouteParameters - Internally: directions(A→B) → get polyline → searchText along polyline - Results ranked by minimal detour time, not proximity - Tested: Fushimi Inari→Kiyomizu-dera finds 5 along-route restaurants Tool description improvements: - static_map: PROACTIVELY call after search/route tools - explore_area: use district names not city name - plan_route: geographic arc per day Travel planning methodology (references/travel-planning.md): - Tool-driven geographic spread via search_places anchors - 6-layer decision model from research - Anti-pattern table + time budget guidelines - Search Along Route as core filling mechanism All 9 files synced (16 → 17 tools). 132 smoke test assertions, 0 failures. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: complete project knowledge skill package 6 reference files forming a comprehensive knowledge package: New files: - architecture.md — system architecture, transport modes, tool registration, code map - google-maps-api-guide.md — API endpoints, pricing, coverage, common gotchas - geo-domain-knowledge.md — GIS fundamentals, coordinates, spatial search, Japan context - decisions.md — 10 ADRs with context and rationale Updated files: - travel-planning.md — complete 6-layer model with Search Along Route - tools-api.md — Recipe 1 rewritten with search_along_route, added tool docs - SKILL.md — expanded reference table (6 files, 3 categories) Reading this skill package gives full capability to maintain, develop, and make informed decisions about this project. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: split skills into agent skill + project-docs skill Agent Skill (skills/google-maps/) — how to USE the tools: - SKILL.md, tools-api.md, travel-planning.md Project Docs Skill (skills/project-docs/) — how to DEVELOP/MAINTAIN: - SKILL.md, architecture.md, google-maps-api-guide.md, geo-domain-knowledge.md, decisions.md (10 ADRs) Separation ensures the agent skill stays focused on tool usage (published to skill registries) while project knowledge lives in its own skill for developer onboarding. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style: fix prettier formatting for CI Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 5e542f1 commit 3f98e6d

19 files changed

Lines changed: 1204 additions & 35 deletions

README.md

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66

77
Give your AI agent the ability to understand the physical world — geocode, route, search, and reason about locations.
88

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

1313
### vs Google Grounding Lite
1414

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

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

121122
### CLI Exec Mode (Agent Skill)
122123

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

130-
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.
131+
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.
131132

132133
### Batch Geocode
133134

@@ -236,6 +237,7 @@ src/
236237
│ ├── airQuality.ts # maps_air_quality tool
237238
│ ├── staticMap.ts # maps_static_map tool
238239
│ ├── batchGeocode.ts # maps_batch_geocode tool
240+
│ ├── searchAlongRoute.ts # maps_search_along_route tool
239241
│ ├── exploreArea.ts # maps_explore_area (composite)
240242
│ ├── planRoute.ts # maps_plan_route (composite)
241243
│ └── comparePlaces.ts # maps_compare_places (composite)
@@ -245,10 +247,18 @@ src/
245247
tests/
246248
└── smoke.test.ts # Smoke + E2E test suite
247249
skills/
248-
└── google-maps/
249-
├── SKILL.md # Agent skill definition
250+
├── google-maps/ # Agent Skill — how to USE the tools
251+
│ ├── SKILL.md # Tool map, recipes, invocation
252+
│ └── references/
253+
│ ├── tools-api.md # Tool parameters + scenario recipes
254+
│ └── travel-planning.md # Travel planning methodology
255+
└── project-docs/ # Project Skill — how to DEVELOP/MAINTAIN
256+
├── SKILL.md # Architecture overview + onboarding
250257
└── references/
251-
└── tools-api.md # Tool parameter reference
258+
├── architecture.md # System design, code map, 9-file checklist
259+
├── google-maps-api-guide.md # API endpoints, pricing, gotchas
260+
├── geo-domain-knowledge.md # GIS fundamentals, Japan context
261+
└── decisions.md # 10 ADRs (design decisions + rationale)
252262
```
253263

254264
## Tech Stack

skills/google-maps/SKILL.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ Without this Skill, the agent can only guess or refuse when asked "how do I get
3535

3636
## Tool Map
3737

38-
16 tools in five categories — pick by scenario:
38+
17 tools in five categories — pick by scenario:
3939

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

5657
### Environment
5758
| Tool | When to use | Example |
@@ -102,3 +103,6 @@ npx @cablate/mcp-google-map exec <tool> '<json_params>' [-k API_KEY]
102103
| File | Content | When to read |
103104
|------|---------|--------------|
104105
| `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 |
106+
| `references/travel-planning.md` | Travel planning methodology — 6-layer model, Search Along Route, anti-patterns | When planning multi-day trips — **read before Recipe 1** |
107+
108+
> For **project development** knowledge (architecture, API guide, GIS domain, design decisions), see `skills/project-docs/SKILL.md`.

skills/google-maps/references/tools-api.md

Lines changed: 72 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,36 @@ Chaining patterns:
294294

295295
---
296296

297+
## search-along-route
298+
299+
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.
300+
301+
```bash
302+
exec search-along-route '{"textQuery": "restaurant", "origin": "Fushimi Inari, Kyoto", "destination": "Kiyomizu-dera, Kyoto", "mode": "walking"}'
303+
```
304+
305+
| Param | Type | Required | Description |
306+
|-------|------|----------|-------------|
307+
| textQuery | string | yes | What to search for ("restaurant", "cafe", "temple") |
308+
| origin | string | yes | Route start point |
309+
| destination | string | yes | Route end point |
310+
| mode | string | no | walking, driving, bicycling, transit (default: walking) |
311+
| maxResults | number | no | Max results (default: 5, max: 20) |
312+
313+
Response:
314+
```json
315+
{
316+
"places": [
317+
{ "name": "SUSHI MATSUHIRO", "rating": 5.0, "location": { "lat": 34.968, "lng": 135.771 } }
318+
],
319+
"route": { "distance": "4.0 km", "duration": "58 mins", "polyline": "..." }
320+
}
321+
```
322+
323+
Key for trip planning: use this between consecutive anchors to find **along-the-way** stops instead of searching at endpoints.
324+
325+
---
326+
297327
## explore-area (composite)
298328

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

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

425+
> **Read `references/travel-planning.md` first** — it contains the full methodology, anti-patterns, and time budget guidelines.
426+
395427
**Steps:**
396-
1. `geocode` — Resolve all mentioned landmarks to coordinates
397-
2. `search-nearby` — Find restaurants/attractions near each landmark (use coordinates from step 1)
398-
3. `place-details` — Get ratings, hours, reviews for top candidates (use place_id from step 2)
399-
4. `distance-matrix` — Compare travel times between all candidate stops to find the optimal order
400-
5. `directions` — Generate turn-by-turn routes between stops in the final order
428+
1. `search-places` — Search "top attractions in {city}" → geographically diverse **anchor points**
429+
2. **Design arcs** — Group nearby anchors into same-day arcs. One direction per day (south→north).
430+
3. `search-along-route` — Between each pair of anchors, find restaurants/cafes **along the walking route** (ranked by minimal detour)
431+
4. `place-details` — Get ratings, hours for top candidates
432+
5. `plan-route` — Validate each day's route. Use `optimize: false` (you already know the geographic order).
433+
6. `weather` + `air-quality` — Adjust for conditions
434+
7. `static-map`**Always** visualize each day with numbered markers + path
401435

402436
**Key decisions:**
403-
- If the user says "near X", use `search-nearby`. If they say "best Y in Z", use `search-places`.
404-
- Always check `opening_hours` from `place-details` before including in itinerary.
405-
- Use `distance-matrix` to order stops efficiently, THEN use `directions` for the final route.
437+
- **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.
438+
- **Never backtrack**: stops progress in one direction per day.
439+
- Alternate activity types: temple → food → walk → shrine → cafe.
440+
- Budget 5-7 stops per day max. Major temples = 90-120 min.
441+
- Edge landmarks (geographically isolated) go at start or end of a day.
442+
- **Always generate a map** for each day.
443+
444+
**Example flow (Kyoto 2-day):**
445+
```
446+
search_places("top attractions in Kyoto")
447+
→ Fushimi Inari(south), Kiyomizu(east), Kinkaku-ji(north), Arashiyama(west)
448+
449+
Day 1 arc: south→center — Fushimi → Kiyomizu → Gion → Pontocho
450+
Day 2 arc: center→west — Nishiki → Nijo Castle → Arashiyama
451+
452+
search_along_route("restaurant", "Fushimi Inari", "Kiyomizu-dera", "walking")
453+
→ finds lunch options ALONG the 4km route (not at endpoints)
454+
455+
search_along_route("kaiseki restaurant", "Gion, Kyoto", "Arashiyama, Kyoto")
456+
→ finds dinner along the afternoon route
457+
458+
plan_route(Day 1 stops, optimize:false) → static_map(Day 1)
459+
plan_route(Day 2 stops, optimize:false) → static_map(Day 2)
460+
```
406461

407-
**Example output shape:**
462+
**Example output:**
408463
```
409-
Morning: Tokyo Tower (9:00) → 12 min walk → Zojoji Temple (9:30)
410-
Lunch: Sushi Dai (11:30) ★4.6 — 2.1 km, 8 min by transit
411-
Afternoon: TeamLab (14:00) → Odaiba area
464+
Day 1: South → Center arc
465+
08:30 Fushimi Inari (90 min) → 25 min transit
466+
10:30 Kiyomizu-dera (90 min) → walk down Sannen-zaka
467+
12:30 [along-route find] Gion lunch ★4.7 (75 min)
468+
14:00 Yasaka Shrine (30 min) → 15 min walk
469+
14:45 Pontocho stroll + cafe (45 min)
470+
17:30 Dinner near Kawaramachi
471+
[map with markers 1-6 and walking path]
412472
```
413473

414474
---
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# Travel Planning Best Practices
2+
3+
## Core Principle
4+
5+
Real travel planning is **directional exploration**, not point collection.
6+
7+
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."
8+
9+
An algorithm plans: "Here are the top 10 rated places. Optimizing shortest path..."
10+
11+
The difference is **arc thinking** — one direction per day, discovering things along the way.
12+
13+
---
14+
15+
## The 6-Layer Decision Model
16+
17+
Human travel planners think in layers. Each layer constrains the next.
18+
19+
### Layer 1: Anchor Discovery
20+
**What:** Find 4-6 must-visit landmarks spread across the city.
21+
**Tool:** `search_places("top attractions in {city}")`
22+
**Why it works:** Google's algorithm returns geographically diverse results. Kyoto → Fushimi(south), Kiyomizu(east), Kinkaku-ji(north), Arashiyama(west) — natural 8km×10km spread.
23+
24+
### Layer 2: Arc Design
25+
**What:** Connect anchors into one-directional arcs per day. Edge landmarks go at start/end of a day.
26+
**Tool:** `distance_matrix` between anchors to understand spatial relationships.
27+
**Rule:** Never backtrack. Each day sweeps one direction (south→north, east→west).
28+
29+
Example:
30+
```
31+
Day 1: Fushimi(south) → Kiyomizu(east) → Gion → Pontocho(center) [south→center arc]
32+
Day 2: Nishiki(center) → Nijo Castle → train → Arashiyama(west) [center→west arc]
33+
```
34+
35+
### Layer 3: Time-Slot Matching
36+
**What:** Assign anchors to times based on **experience quality**, not distance.
37+
**Tool:** None — this is AI knowledge.
38+
**Examples:**
39+
- Fushimi Inari = **early morning** (fewer crowds, best light for photos, hiking needs fresh legs)
40+
- Outdoor temples = **morning to afternoon** (natural light)
41+
- Shopping districts = **afternoon** (all stores open)
42+
- Scenic areas = **late afternoon** (golden hour light)
43+
- Fine dining = **evening at the final stop** (no rush to next destination)
44+
45+
### Layer 4: Along-Route Filling
46+
**What:** Between two anchors, find what's **on the way** — not at the destination.
47+
**Tool:** `search_along_route(textQuery, origin, destination)`
48+
**This is the key differentiator.** Results are ranked by minimal detour time, not proximity to a point.
49+
50+
```
51+
search_along_route("restaurant", "Fushimi Inari, Kyoto", "Kiyomizu-dera, Kyoto", "walking")
52+
→ Finds restaurants ALONG the 4km walking route, not clustered at either end
53+
```
54+
55+
### Layer 5: Meal Embedding
56+
**What:** Meals appear where the traveler **will be** at mealtime, not where the "best restaurant" is.
57+
**Logic:**
58+
1. Estimate what time the traveler reaches each arc segment
59+
2. Lunch (~12:00) → search_along_route("lunch restaurant", previous_stop, next_stop)
60+
3. Dinner (~18:00) → search_nearby at the day's final area (no rush)
61+
62+
**Anti-pattern:** "I searched for the best restaurant in the whole city" → it's 3km off the route.
63+
**Correct:** "You'll be near Gion around noon — here are options along the way."
64+
65+
### Layer 6: Rhythm Validation
66+
**What:** Check the itinerary feels human, not robotic.
67+
**Tool:** `plan_route(stops, optimize: false)` to get actual times, `weather` for conditions.
68+
**Checklist:**
69+
- [ ] Not 5 temples in a row (alternate: temple → food → walk → shrine → cafe)
70+
- [ ] Major temples get 90-120 min, not 30 min
71+
- [ ] Walking per day < 10km (suggest transit for >2km gaps)
72+
- [ ] Lunch 11:30-13:00, dinner 17:30-19:30
73+
- [ ] 5-7 stops per day max (including meals)
74+
- [ ] Final stop: call `static_map` with markers + path to visualize
75+
76+
---
77+
78+
## Tool Call Sequence
79+
80+
```
81+
Phase 1 — Skeleton (2-3 calls)
82+
search_places("top attractions in {city}") → anchors
83+
distance_matrix(all anchors) → spatial relationships
84+
85+
Phase 2 — Arc + Fill (2-4 calls per day)
86+
search_along_route("restaurant", stop_A, stop_B) → along-route meals
87+
search_along_route("cafe", stop_B, stop_C) → along-route breaks
88+
89+
Phase 3 — Environment (2 calls)
90+
weather(city coords) → rain → move indoor activities
91+
air_quality(city coords) → bad AQI → reduce outdoor time
92+
93+
Phase 4 — Validate + Visualize (2 calls per day)
94+
plan_route(day_stops, optimize: false) → verify times/distances
95+
static_map(markers + path) → map for each day
96+
97+
Total: ~12-16 calls for a 2-day trip
98+
```
99+
100+
---
101+
102+
## Anti-Patterns
103+
104+
| Anti-Pattern | Symptom | Fix |
105+
|-------------|---------|-----|
106+
| Single-point explosion | `explore_area("Kyoto")` → all within 1km | search_places for anchors first |
107+
| Backtracking | east→west→east→west | One direction per day |
108+
| No along-route search | Meals at endpoints only | `search_along_route` between stops |
109+
| Distance-optimal ordering | Ignores time-of-day quality | AI assigns time slots before routing |
110+
| No map output | Text/JSON only | Always `static_map` after each day's route |
111+
| Over-scheduling | 12 stops in one day | Max 5-7 stops including meals |
112+
| Same-type clustering | 5 temples consecutively | Alternate activity types |
113+
114+
---
115+
116+
## Time Budget
117+
118+
| Activity | Duration |
119+
|----------|----------|
120+
| Major temple/shrine | 60-120 min |
121+
| Small shrine / photo spot | 15-30 min |
122+
| Museum | 90-180 min |
123+
| Market / shopping street | 60-90 min |
124+
| Sit-down meal | 60-120 min |
125+
| Quick meal / street food | 20-40 min |
126+
| Cafe break | 30-45 min |
127+
| Walking <1km | 10-15 min |
128+
| Transit between areas | 20-40 min |
129+
130+
---
131+
132+
## When to Read This
133+
134+
- User says "plan a trip", "create an itinerary", "plan X days in Y"
135+
- Trip plan clusters all stops in one area
136+
- Building multi-day travel content

0 commit comments

Comments
 (0)