@cablate/mcp-google-map 0.0.36 → 0.0.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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,0 +1,66 @@
1
+ ---
2
+ name: mcp-google-map-project
3
+ description: Project knowledge for developing and maintaining @cablate/mcp-google-map. Architecture, Google Maps API guide, GIS domain knowledge, and design decisions. Read this skill to onboard onto the project or make informed development decisions.
4
+ version: 0.0.1
5
+ compatibility:
6
+ - claude-code
7
+ - cursor
8
+ - vscode-copilot
9
+ ---
10
+
11
+ # mcp-google-map — Project Knowledge
12
+
13
+ ## Overview
14
+
15
+ This skill contains everything needed to develop, maintain, and extend the `@cablate/mcp-google-map` MCP server. Reading these files gives you full context on architecture, API specifics, domain knowledge, and the reasoning behind design decisions.
16
+
17
+ For the **agent skill** (how to USE the tools), see `skills/google-maps/SKILL.md`.
18
+
19
+ ---
20
+
21
+ ## Quick Orientation
22
+
23
+ | Aspect | Summary |
24
+ |--------|---------|
25
+ | **What** | MCP server providing Google Maps tools for AI agents |
26
+ | **Stack** | TypeScript, Node.js, Express, MCP SDK, Zod |
27
+ | **Tools** | 17 tools (14 atomic + 3 composite) |
28
+ | **Transports** | stdio, Streamable HTTP, standalone exec CLI |
29
+ | **APIs** | Places API (New), Directions, Geocoding, Elevation, Timezone, Weather, Air Quality, Static Maps, Search Along Route |
30
+
31
+ ---
32
+
33
+ ## Reference Files
34
+
35
+ | File | Content | When to read |
36
+ |------|---------|--------------|
37
+ | `references/architecture.md` | System architecture, 3-layer design, transport modes, tool registration flow, 9-file checklist, code map | **Start here** when onboarding. Also read when adding new tools. |
38
+ | `references/google-maps-api-guide.md` | All Google Maps API endpoints used, pricing, coverage limits, rate limits, common gotchas, Places New vs Legacy | When debugging API errors, evaluating new APIs, or checking costs |
39
+ | `references/geo-domain-knowledge.md` | GIS fundamentals — coordinates, distance, geocoding, place types, spatial search, map projection, Japan-specific knowledge | When making tool design decisions that involve geographic concepts |
40
+ | `references/decisions.md` | 10 Architecture Decision Records (ADR) with context and rationale | When asking "why was X built this way?" or considering changes to existing design |
41
+
42
+ ---
43
+
44
+ ## How to Add a New Tool
45
+
46
+ See `references/architecture.md` § "9-File Tool Change Checklist" for the complete procedure. Summary:
47
+
48
+ 1. Create `src/tools/maps/<toolName>.ts` (NAME, DESCRIPTION, SCHEMA, ACTION)
49
+ 2. Register in `src/config.ts`
50
+ 3. Add exec case in `src/cli.ts`
51
+ 4. Add to `tests/smoke.test.ts` (expectedTools + API call test)
52
+ 5. Update `README.md` (count + table + exec list + project structure)
53
+ 6. Update `skills/google-maps/SKILL.md` (Tool Map)
54
+ 7. Update `skills/google-maps/references/tools-api.md` (params + chaining)
55
+ 8. Check `server.json` and `package.json` descriptions
56
+
57
+ ---
58
+
59
+ ## When to Update This Skill
60
+
61
+ | Trigger | What to update |
62
+ |---------|----------------|
63
+ | Architecture change | `references/architecture.md` |
64
+ | New Google Maps API integrated | `references/google-maps-api-guide.md` |
65
+ | New design decision made | `references/decisions.md` (add ADR) |
66
+ | New GIS concept relevant to tools | `references/geo-domain-knowledge.md` |
@@ -0,0 +1,135 @@
1
+ # Architecture Reference
2
+
3
+ ## System Architecture Overview
4
+
5
+ Three-layer architecture with a shared entry point:
6
+
7
+ ```
8
+ CLI / HTTP / stdio
9
+ |
10
+ BaseMcpServer <- MCP protocol layer (tool registration, transport)
11
+ |
12
+ Tool ACTION() <- thin dispatch, calls PlacesSearcher
13
+ |
14
+ PlacesSearcher <- service facade (composition, filtering, response shaping)
15
+ / \
16
+ GoogleMapsTools NewPlacesService
17
+ (Legacy REST SDK) (Places API New gRPC/REST client)
18
+ ```
19
+
20
+ | Layer | Files | Responsibility |
21
+ |---|---|---|
22
+ | Entry | `src/cli.ts` | Parse CLI args, select transport mode, instantiate server |
23
+ | Protocol | `src/core/BaseMcpServer.ts` | Register tools, handle MCP sessions, route HTTP/stdio |
24
+ | Tool | `src/tools/maps/*.ts` | Declare NAME, DESCRIPTION, SCHEMA, ACTION |
25
+ | Config | `src/config.ts` | Assemble ToolConfig[], attach MAPS_TOOL_ANNOTATIONS |
26
+ | Facade | `src/services/PlacesSearcher.ts` | Orchestrate multi-step / composite tools |
27
+ | API client (legacy) | `src/services/toolclass.ts` | Wrap `@googlemaps/google-maps-services-js` SDK |
28
+ | API client (new) | `src/services/NewPlacesService.ts` | Wrap `@googlemaps/places` gRPC client |
29
+ | Auth | `src/utils/apiKeyManager.ts` | API key priority resolution |
30
+ | Context | `src/utils/requestContext.ts` | Per-request AsyncLocalStorage propagation |
31
+
32
+ ---
33
+
34
+ ## Transport Modes
35
+
36
+ | Mode | Entry | How to activate | Notes |
37
+ |---|---|---|---|
38
+ | **HTTP (Streamable)** | `cli.ts` → `BaseMcpServer.startHttpServer()` | default, or `--port` | Listens on `/mcp` (POST/GET/DELETE); sessions tracked by UUID header `mcp-session-id` |
39
+ | **stdio** | `cli.ts` → `BaseMcpServer.startStdio()` | `--stdio` flag | Used by Claude Desktop, Cursor; stdout reserved for JSON-RPC, all logs go to stderr |
40
+ | **exec CLI** | `cli.ts` → `execTool()` | `mcp-google-map exec <tool> '<json>'` | No MCP protocol; directly calls `PlacesSearcher` method and prints JSON to stdout; used for scripting/piping |
41
+
42
+ ### HTTP Session Lifecycle
43
+
44
+ ```
45
+ POST /mcp (no session-id, isInitializeRequest)
46
+ -> create StreamableHTTPServerTransport
47
+ -> create new McpServer, connect transport
48
+ -> store in sessions[uuid]
49
+
50
+ POST /mcp (mcp-session-id header)
51
+ -> reuse existing session context
52
+ -> update apiKey if header present
53
+
54
+ DELETE /mcp (mcp-session-id header)
55
+ -> terminate session, clean up transport
56
+ ```
57
+
58
+ ---
59
+
60
+ ## Tool Registration Flow
61
+
62
+ ```
63
+ src/tools/maps/weather.ts exports Weather.{NAME, DESCRIPTION, SCHEMA, ACTION}
64
+ |
65
+ src/config.ts builds ToolConfig[] array, attaches MAPS_TOOL_ANNOTATIONS
66
+ |
67
+ src/cli.ts passes config.tools[] to new BaseMcpServer(name, tools)
68
+ |
69
+ BaseMcpServer.createMcpServer() calls server.registerTool(name, {description, inputSchema, annotations}, action)
70
+ |
71
+ @modelcontextprotocol/sdk exposes tool to MCP client
72
+ ```
73
+
74
+ `MAPS_TOOL_ANNOTATIONS` applied to all tools:
75
+
76
+ ```ts
77
+ { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }
78
+ ```
79
+
80
+ ---
81
+
82
+ ## API Key Management
83
+
84
+ Priority order (highest to lowest):
85
+
86
+ | Priority | Source | Header / Variable |
87
+ |---|---|---|
88
+ | 1 | HTTP request header | `X-Google-Maps-API-Key` |
89
+ | 2 | HTTP Authorization header | `Authorization: Bearer <key>` |
90
+ | 3 | Session-specific key | stored per `mcp-session-id` |
91
+ | 4 | CLI argument | `--apikey` / `-k` |
92
+ | 5 | Environment variable | `GOOGLE_MAPS_API_KEY` |
93
+ | 6 | `.env` file | loaded by `dotenv` at startup from `cwd` or package dir |
94
+
95
+ **Flow in HTTP mode**: `ApiKeyManager.getApiKey(req)` resolves key → stored in `SessionContext.apiKey` → propagated via `runWithContext()` (AsyncLocalStorage) → tool action reads from context or `process.env`.
96
+
97
+ **Flow in exec mode**: `--apikey` arg → directly passed to `new PlacesSearcher(apiKey)` constructor.
98
+
99
+ ---
100
+
101
+ ## Adding a New Tool — 9-File Checklist
102
+
103
+ From `CLAUDE.md`:
104
+
105
+ | # | File | What to update |
106
+ |---|---|---|
107
+ | 1 | `src/tools/maps/<toolName>.ts` | Define NAME, DESCRIPTION, SCHEMA, ACTION |
108
+ | 2 | `src/config.ts` | Add to `tools[]` array with annotations |
109
+ | 3 | `src/cli.ts` | Add to `EXEC_TOOLS` const + `switch` case in `execTool()` |
110
+ | 4 | `tests/smoke.test.ts` | Add to `expectedTools` array + update tool count assertions |
111
+ | 5 | `README.md` | Update tool count (header, comparison table, Server Info, exec mode) + Available Tools table + Project Structure |
112
+ | 6 | `skills/google-maps/SKILL.md` | Add row to Tool Map table |
113
+ | 7 | `skills/google-maps/references/tools-api.md` | Add parameter docs + chaining patterns |
114
+ | 8 | `server.json` | Update description if it mentions tool count |
115
+ | 9 | `package.json` | Update description if it mentions tool count |
116
+
117
+ Missing any file causes doc/behavior mismatch. Verify all before opening a PR.
118
+
119
+ ---
120
+
121
+ ## Code Map
122
+
123
+ | File | Purpose |
124
+ |---|---|
125
+ | `src/cli.ts` | CLI entry point — parses args, selects transport, dispatches exec mode |
126
+ | `src/config.ts` | Assembles ToolConfig[] array from all tool modules |
127
+ | `src/core/BaseMcpServer.ts` | MCP server core — tool registration, HTTP session management, stdio transport |
128
+ | `src/index.ts` | Package entry — exports Logger and re-exports public API |
129
+ | `src/services/PlacesSearcher.ts` | Service facade — orchestrates multi-step composite tools (planRoute, exploreArea, comparePlaces, searchAlongRoute) |
130
+ | `src/services/toolclass.ts` | Legacy Google Maps SDK wrapper — geocode, directions, distanceMatrix, elevation, timezone, weather, airQuality, staticMap |
131
+ | `src/services/NewPlacesService.ts` | Places API (New) client — searchNearby, searchText, getPlaceDetails via gRPC |
132
+ | `src/tools/maps/*.ts` | Individual tool definitions (17 files) — each exports NAME, DESCRIPTION, SCHEMA, ACTION |
133
+ | `src/utils/apiKeyManager.ts` | Singleton — resolves API key priority from headers / session / env |
134
+ | `src/utils/requestContext.ts` | AsyncLocalStorage — propagates API key within a single request lifecycle |
135
+ | `tests/smoke.test.ts` | Integration smoke tests — validates tool list, basic API calls |
@@ -0,0 +1,149 @@
1
+ # Architecture Decision Records — mcp-google-map
2
+
3
+ > Format: Decision / Context / Rationale
4
+ > Sources: dev-roadmap-spec.md, CLAUDE.md, project history
5
+
6
+ ---
7
+
8
+ ## ADR-001: Unified `maps_` Prefix for All Tool Names
9
+
10
+ **Decision**: All tools are named with the `maps_` prefix (e.g., `maps_geocode`, `maps_search_nearby`). This was applied as a breaking change when the namespace was standardized.
11
+
12
+ **Context**: Early tool names were inconsistent — some had prefixes, some did not. As the tool count grew and the server was listed on MCP registries, namespace collisions with other MCP servers became a concern. Claude's tool selection also benefits from a clear namespace signal.
13
+
14
+ **Rationale**:
15
+ - Consistent namespace prevents collision when multiple MCP servers are active simultaneously.
16
+ - The `maps_` prefix gives Claude a strong disambiguation signal — it knows these tools are geospatial without reading descriptions.
17
+ - Breaking change was accepted early (pre-stable) to avoid accumulating technical debt. All 9 files in the Tool Change Checklist must be updated together on any rename.
18
+
19
+ ---
20
+
21
+ ## ADR-002: `compare_places` Retained as a Composite Tool
22
+
23
+ **Decision**: `maps_compare_places` is a single tool that internally fetches details for multiple places and returns a structured comparison. It is not decomposed into atomic `place_details` calls that the AI chains together.
24
+
25
+ **Context**: An alternative design would have the AI call `maps_place_details` N times and synthesize the comparison itself. During testing, this produced inconsistent output quality and required users to explicitly orchestrate the chain.
26
+
27
+ **Rationale**:
28
+ - Users ask "compare these restaurants" and expect a comparison table, not raw data to synthesize.
29
+ - Composite tools reduce chaining overhead and produce deterministic, structured output.
30
+ - The Geo-Reasoning Benchmark (GRB) validates this: Composite Efficiency Score (CES) rewards using 1 call instead of N calls. `compare_places` is the reference case for this metric.
31
+ - User preference confirmed: users do not want to manually chain atomic calls for comparison tasks.
32
+
33
+ ---
34
+
35
+ ## ADR-003: `maps_weather` and `maps_air_quality` as Separate Tools
36
+
37
+ **Decision**: Weather and air quality are exposed as two independent tools, not combined into a single `maps_environment` tool.
38
+
39
+ **Context**: A natural grouping might combine weather and air quality into one "environmental conditions" call. Both return ambient data about a location.
40
+
41
+ **Rationale**:
42
+ - **Different APIs**: Weather uses one endpoint; Air Quality uses `POST https://airquality.googleapis.com/v1/currentConditions:lookup` — a completely separate Google service requiring separate API enablement.
43
+ - **Different geographic coverage**: Weather API does not support Japan. Air Quality API fully supports Japan (including AEROS local index). Combining them would require complex conditional logic and mislead users about availability.
44
+ - **Different data structures and use cases**: Weather is for planning (will it rain?). Air quality is for health decisions (should I wear a mask? can elderly parents go outside?). The 7-demographic health recommendation field in air quality has no analogue in weather.
45
+ - **Independent billing**: Separate pricing makes cost attribution cleaner.
46
+
47
+ ---
48
+
49
+ ## ADR-004: `maps_isochrone` Not Built
50
+
51
+ **Decision**: Isochrone generation (travel-time polygons) is excluded from the roadmap, marked as "Skip for now."
52
+
53
+ **Context**: Isochrones are a commonly requested GIS feature — "show me everywhere I can reach in 30 minutes." They are valuable for real estate analysis, event planning, and accessibility research.
54
+
55
+ **Rationale**:
56
+ - **Google has no native isochrone API.** All alternative implementations have disqualifying problems:
57
+ - Mapbox Isochrone API: mature, but introduces a second vendor (Mapbox key) alongside Google — breaks the single-provider positioning.
58
+ - OpenRouteService: free but rate-limited and stability uncertain for production use.
59
+ - Distance Matrix grid approximation: 24+ API calls per isochrone at ~$0.12/request; prohibitively expensive and low-accuracy.
60
+ - **Core value is visual**: An isochrone polygon is only meaningful when rendered on a map. Without `maps_static_map` to display it, returning raw GeoJSON coordinates is not useful to AI or users. The feature was deprioritized until static map rendering was in place.
61
+ - **Revisit path**: If built later, the best approach is Distance Matrix 8-direction probing + `maps_static_map` to render an approximated polygon. Estimated effort: 8 hours.
62
+
63
+ ---
64
+
65
+ ## ADR-005: `maps_validate_address` Not Built
66
+
67
+ **Decision**: Address validation (checking if a postal address is deliverable) is excluded from the tool set.
68
+
69
+ **Context**: Google's Address Validation API provides USPS CASS-certified validation, deliverability flags, and address correction. It could theoretically be useful for any tool that takes address inputs.
70
+
71
+ **Rationale**:
72
+ - **Cost**: $17 per 1,000 requests — 3.4× the cost of standard geocoding. This is prohibitive for conversational AI use where users make casual address queries.
73
+ - **Wrong use case**: Address validation is designed for backend pipelines (e-commerce checkout, CRM deduplication, bulk mailing). It requires structured postal input and returns structured postal corrections — not a natural fit for natural-language AI conversations.
74
+ - **Coverage gap**: Only 38 countries supported; excludes most of Asia and Africa. A tool that silently fails for Tokyo or Mumbai addresses would create confusing UX.
75
+ - **Existing alternative**: `maps_geocode` already handles 60% of "is this address valid?" scenarios by returning whether a geocode succeeded and providing the `formatted_address` canonical form.
76
+
77
+ ---
78
+
79
+ ## ADR-006: Spatial Context / Session Memory Not Built
80
+
81
+ **Decision**: There is no persistent spatial context or session memory layer in the MCP server. The server does not remember previously queried locations or build a "current location" state across calls.
82
+
83
+ **Context**: A proposed feature was to maintain implicit state — if a user asks "find coffee shops" after previously mentioning "I'm in Shinjuku," the server would remember Shinjuku and use it as the implicit location for the next search.
84
+
85
+ **Rationale**:
86
+ - **Claude's conversation history already solves this.** Claude reads its own prior messages and can extract previously mentioned locations. A server-side memory layer would duplicate capability that already exists in the LLM.
87
+ - **Composite tools reduce chaining need.** Tools like `maps_explore_area` and `maps_plan_route` accept multi-intent inputs that would otherwise require chaining with location state.
88
+ - **Implementation risks outweigh benefits**:
89
+ - Implicit state leakage: state from one user's session could bleed into another in concurrent scenarios.
90
+ - Debugging opacity: errors become harder to trace when the server has hidden state.
91
+ - stdio transport has no session concept — each stdio connection is stateless by design.
92
+ - **User value assessed at 3/10.** In testing, users could not perceive a meaningful difference. The friction of unexpected state (wrong implicit location) outweighed the convenience.
93
+
94
+ ---
95
+
96
+ ## ADR-007: stdio as Primary Transport
97
+
98
+ **Decision**: The MCP server uses stdio (standard input/output) as its primary transport mechanism. HTTP/SSE is secondary.
99
+
100
+ **Context**: MCP servers can expose transport via stdio (subprocess model) or HTTP+SSE (network server model). Both are valid per the MCP specification.
101
+
102
+ **Rationale**:
103
+ - **MCP Registry requirement**: The official MCP registry and most client integrations (Claude Desktop, Claude Code, Cursor) prefer or require stdio-based servers for local installation.
104
+ - **Security model**: stdio servers run as a subprocess of the client, inheriting the client's trust context. No network port exposure, no authentication complexity.
105
+ - **Deployment simplicity**: `npx mcp-google-map` works out of the box without configuring ports, firewalls, or SSL.
106
+ - **Statelessness aligns with stdio**: Each stdio connection represents one session. This reinforces ADR-006 (no spatial context) — the transport model naturally discourages stateful designs.
107
+
108
+ ---
109
+
110
+ ## ADR-008: Search Along Route Uses Direct REST Calls
111
+
112
+ **Decision**: The "search along route" capability calls the Google Maps REST API directly rather than using the official `@googlemaps/google-maps-services-js` client library.
113
+
114
+ **Context**: Most tools in this project use the official client library for consistency and type safety. The route-based search requires fetching a polyline and then querying points along it — a pattern not natively supported by the client library.
115
+
116
+ **Rationale**:
117
+ - **Client library may not expose the required parameters or patterns** for buffered route searches. The REST API is always the source of truth; the client library is a convenience wrapper.
118
+ - **Direct REST calls are straightforward**: for GET requests with query parameters, `axios` or `fetch` is sufficient and keeps the implementation explicit.
119
+ - **Type safety can be maintained** by defining TypeScript interfaces for the REST response shapes — same outcome as using the library, without library constraints.
120
+ - This is an exception to the general project preference for the client library, justified by the specific technical requirement.
121
+
122
+ ---
123
+
124
+ ## ADR-009: MCP Prompt Templates Removed
125
+
126
+ **Decision**: MCP Prompt Templates (slash commands like `/travel-planner`) were evaluated and ultimately not shipped as a feature.
127
+
128
+ **Context**: The roadmap spec (P1-1) proposed implementing MCP's `prompts` primitive to expose slash commands in clients like Claude Desktop. The intended value was giving non-technical users a one-click entry into geo agent mode.
129
+
130
+ **Rationale**:
131
+ - **Client support is low and inconsistent.** As of evaluation, most MCP clients either do not render prompt templates as slash commands or render them inconsistently. The feature would benefit a small fraction of users.
132
+ - **SKILL.md already covers the use case** for Claude Code users — the skill system provides rich scenario guidance, chaining patterns, and example recipes that go beyond what prompt templates support.
133
+ - **Maintenance cost**: Prompt template content would need to stay in sync with tool capabilities, adding to the already-significant 9-file update checklist (CLAUDE.md ADR).
134
+ - **Revisit condition**: If MCP client support for prompts reaches broad adoption (Claude Desktop, VS Code extension, Cursor all render them consistently), this should be reconsidered. The 6-hour implementation estimate is low.
135
+
136
+ ---
137
+
138
+ ## ADR-010: Travel Planning Uses "Tool-Driven Diffusion," Not AI Prior Knowledge
139
+
140
+ **Decision**: Travel planning workflows are designed so the AI discovers ground truth by calling tools, not by relying on training-data knowledge of specific places, hours, or transit schedules.
141
+
142
+ **Context**: An AI could answer "what time does Kinkaku-ji open?" from training data. It could suggest a Tokyo itinerary without any tool calls based on memorized "best of Tokyo" patterns. This is faster but fragile.
143
+
144
+ **Rationale**:
145
+ - **Training data goes stale.** Business hours change, places close, new venues open. A tool call to `maps_place_details` returns current data; training knowledge reflects a past snapshot.
146
+ - **Specificity requires data.** A user asking for restaurants near their hotel requires the actual hotel coordinates, not generic neighborhood knowledge. The tool call chain (geocode hotel → search nearby → get details) produces a personalized result that training data cannot replicate.
147
+ - **Verifiability and trust.** When the AI cites data from a tool response (e.g., "Fushimi Inari opens at 6 AM according to Google Maps"), users can verify the source. When it speaks from training data, there is no audit trail.
148
+ - **The SKILL.md geo-domain knowledge** (temple hours, transit rules, energy curves) is intentionally at the *pattern* level — it tells the AI *how* to plan, not *what* specific facts are. The facts come from tools. This separation is the core design principle.
149
+ - Practical implementation: always geocode place names (don't assume coordinates), always fetch operating hours from `maps_place_details` (don't assume 9–5), always calculate transit time with `maps_directions` (don't estimate from distance).