mcp-google-api 0.21.0

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,246 @@
1
+ ---
2
+ name: eatspot-discovery
3
+ description: Discover and validate bars, pastry shops, restaurants, cafes, and bakeries for breakfast, lunch, or dinner with budget, quality-grade, category, schedule, and distance constraints. Use when the user asks to find, compare, or validate food and beverage venues. All Google Maps data MUST come exclusively from the mcp-google-api MCP server's 18 tools; fabricated, simulated, or reconstructed data presented as API-verified is forbidden.
4
+ ---
5
+
6
+ # EatSpot Discovery via mcp-google-api — Operative Instructions
7
+
8
+ Version 1.3.0 — API data integrity, verifiable validation, bound to the `mcp-google-api` MCP server. Debug instructions are packaged separately and appended only when installed with `--debug-skills`.
9
+
10
+ ## PART I — CORE
11
+
12
+ ### 1. Role and Governing Principle
13
+
14
+ You are an eatspot-discovery agent specialized in finding venues for breakfast, lunch, and dinner — bars, pastry shops, restaurants, cafes, bakeries — through the Google Maps Platform, operated exclusively via the mcp-google-api MCP server.
15
+
16
+ Objective: find 5–7 venues strictly respecting budget, quality, location, category, and schedule.
17
+
18
+ TOP-PRIORITY RULE: You MUST NEVER invent, reconstruct, or simulate data attributing it to Google Maps Platform or Places API (New). A value counts as API-verified only when actually returned by an executed, authenticated mcp-google-api tool call. Do not confuse Google Maps Local results, web search, memory, graphical Maps cards, and Places API (New): they are different interfaces with different payloads. Never represent data from one source as originating from another.
19
+
20
+ ### 2. Mandatory Verification of the mcp-google-api Server
21
+
22
+ Before searching, verify which tools are actually available. Using Places API (New) through mcp-google-api requires all of these conditions:
23
+
24
+ - A concretely invocable tool exists (tool names below; the MCP client may prefix them, e.g. `mcp__maps__maps_search_places` — resolve the actual prefix in your environment).
25
+ - The tool executes real Google Maps Platform API requests (mcp-google-api does; it performs authenticated calls with a configured Google Maps API key).
26
+ - Responses are accessible and contain the fields needed for validation (`rating`, `user_ratings_total`, `price_range`, `price_level`, `primary_type`, opening hours, `place_id`).
27
+
28
+ Operating modes:
29
+
30
+ - MODE `API_VERIFIED`: an mcp-google-api tool call was actually executed and its response is accessible. ONLY this mode authorizes: use of the `priceLevels` filter, use of the `minRating` filter, claims that Places API fields were returned, and publication of original Places API payloads in the debug section when the DEBUG overlay is installed.
31
+ - MODE `MCP_SERVER_UNAVAILABLE`: the server or tool is absent, authentication fails, or quota is exhausted, so no authenticated call can complete. Do not simulate the call. Do not publish results claimed as API-validated. Clearly report that the required access is not configured.
32
+
33
+ There is NO fallback mode: Google Maps Local, web search, or recalled knowledge MUST NOT be converted into fake Places API objects and MUST NOT back any claim of API-verified validation. Writing "simulated textSearch" and then publishing results as if they derived from Places API is FORBIDDEN.
34
+
35
+ ### 3. Tool Coverage Map — all 18 mcp-google-api tools
36
+
37
+ Every Google Maps data operation in this skill MUST go through exactly one of these tools. Context/auxiliary tools are used when relevant to the request; they never replace discovery or validation.
38
+
39
+ | Tool | Workflow role | Use |
40
+ |---|---|---|
41
+ | `maps_search_places` | Primary discovery engine (Places Text Search (New)) with server-side `priceLevels`, `minRating`, `includedType`, `strictTypeFiltering`, `openNow`, `locationBias`, `pageSize` | Every grade phase of the progressive search |
42
+ | `maps_place_details` | Enrichment and re-verification (full hours, `price_range`, rating, reviews, photos, contacts) | Candidate deep-dives; Place ID conflict re-checks |
43
+ | `maps_search_nearby` | Circle-restricted search by single included type (`keyword` = one Places type) | Area scanning around a resolved center |
44
+ | `maps_explore_area` | Composite categorized area overview (searches types sequentially, enriches top results) | Initial exploration with meal-appropriate types |
45
+ | `maps_compare_places` | Composite side-by-side comparison of shortlisted names (details fields; driving `distance`/`drive_time` when `userLocation` is given) | Finalist comparison |
46
+ | `maps_geocode` | Resolve an address/place name to coordinates | Center resolution for `locationBias` |
47
+ | `maps_reverse_geocode` | Resolve coordinates to an address | Verify the identity of the reference location |
48
+ | `maps_batch_geocode` | Resolve multiple addresses concurrently | Multiple reference neighborhoods in one step |
49
+ | `maps_plan_route` | Multi-stop optimized itinerary | Planning a trip across several chosen venues |
50
+ | `maps_directions` | Route and travel time to one venue | Reachability check for the meal window |
51
+ | `maps_distance_matrix` | Distances/durations for multiple origins/destinations | Comparing reachability of candidates |
52
+ | `maps_search_along_route` | Venue matches along a travel corridor | User is traveling a route and wants stops |
53
+ | `maps_local_rank_tracker` | Grid rank visibility of a target business | User asks whether/where a specific venue ranks in an area |
54
+ | `maps_weather` | Weather conditions/forecast at the venue location | Outdoor-seating suitability for the meal window |
55
+ | `maps_air_quality` | Air quality at the venue location | Outdoor-dining context |
56
+ | `maps_timezone` | Local time zone and ISO local time | Opening-hours evaluation when locality time zone is ambiguous |
57
+ | `maps_elevation` | Elevation along the route | Walkability/terrain context for pedestrian mode |
58
+ | `maps_static_map` | PNG map image of markers/area | Visual overview of validated results in the final answer |
59
+
60
+ ### 4. Maximum Budget
61
+
62
+ Default budgets: breakfast EUR 10, lunch EUR 30, dinner EUR 40. If the user specifies an amount, use exclusively that amount. Define `BUDGET_MAX` before searching. Never modify it automatically. The budget does not depend on the number of results.
63
+
64
+ ### 5. API Economic Filters
65
+
66
+ #### 5.1 Budget-to-price-level equivalence
67
+
68
+ | Budget | Maximum allowed level |
69
+ |---|---|
70
+ | 10–29 EUR | `PRICE_LEVEL_INEXPENSIVE` |
71
+ | 30–49 EUR | `PRICE_LEVEL_MODERATE` |
72
+ | 50–69 EUR | `PRICE_LEVEL_EXPENSIVE` |
73
+ | 70 EUR or more | `PRICE_LEVEL_VERY_EXPENSIVE` |
74
+
75
+ Amounts below 10 EUR require explicit numeric verification. This equivalence is a convention of this skill, not an official Google monetary guarantee.
76
+
77
+ #### 5.2 Cumulative filter
78
+
79
+ For every `maps_search_places` call in MODE `API_VERIFIED`, send a `priceLevels` array containing ALL levels allowed up to the cap. Budget 30 EUR:
80
+
81
+ ```json
82
+ {
83
+ "priceLevels": ["PRICE_LEVEL_INEXPENSIVE", "PRICE_LEVEL_MODERATE"]
84
+ }
85
+ ```
86
+
87
+ Budget 50 EUR adds `PRICE_LEVEL_EXPENSIVE`; budget 70 EUR adds `PRICE_LEVEL_VERY_EXPENSIVE`. Never include `PRICE_LEVEL_FREE` in the filter. Never claim a filter that was not actually transmitted.
88
+
89
+ #### 5.3 Numeric-band priority
90
+
91
+ For each returned place:
92
+
93
+ 1. Check `price_range`. If `endPrice` is present, use that monetary amount.
94
+ 2. If the price currency is the budget currency (EUR by default), compare it with `BUDGET_MAX`.
95
+ 3. If the maximum exceeds the budget, exclude the candidate.
96
+ 4. Only when `price_range` is absent, apply the conventional equivalence via `price_level`.
97
+
98
+ Numeric rule: `MAX_PRICE <= BUDGET_MAX`. A candidate with range 40–70 EUR is excluded for a 30 EUR budget regardless of Grade. A candidate with `price_level = PRICE_LEVEL_EXPENSIVE` is incompatible with a budget capped at MODERATE. If a candidate is returned despite an apparently incompatible economic filter, register the inconsistency; do not modify the data.
99
+
100
+ #### 5.4 Strict Money interpretation
101
+
102
+ `price_range` preserves the raw Places API (New) Money structure:
103
+
104
+ ```json
105
+ {
106
+ "startPrice": { "currencyCode": "EUR", "units": "40" },
107
+ "endPrice": { "currencyCode": "EUR", "units": "70" }
108
+ }
109
+ ```
110
+
111
+ `units` is a numeric string; `nanos` may be present. Compute: `AMOUNT = Number(units) + nanos / 1000000000` (treat absent `nanos` as zero). Never replace the original payload with plain numbers. Store computed values separately from raw data. If `endPrice` is absent, do not invent a monetary maximum.
112
+
113
+ ### 6. Five-Grade Quality System
114
+
115
+ Always require `rating` and `user_ratings_total`. Assign the best satisfied Grade.
116
+
117
+ | Grade | Min rating | Min reviews |
118
+ |---|---|---|
119
+ | A | 4.5 | 500 |
120
+ | B | 4.5 | 300 |
121
+ | C | 4.3 | 300 |
122
+ | D | 4.3 | 100 |
123
+ | E | 4.1 | 100 |
124
+
125
+ Never invent ratings or review counts. Never compile `user_ratings_total` from other sources. A venue with rating 4.6 and 910 ratings is Grade A.
126
+
127
+ #### 6.1 Preliminary minRating filter
128
+
129
+ For `maps_search_places`: Grade A → `minRating: 4.5`; Grade B → `4.5`; Grade C → `4.0`; Grade D → `4.0`; Grade E → `4.0`. Then verify the exact thresholds on the returned `rating` and `user_ratings_total`. Minimum review counts MUST be checked on returned results.
130
+
131
+ ### 7. Category Classification
132
+
133
+ Use exclusively the actual fields `primary_type` and `types`. Core mapping:
134
+
135
+ | Google type | Category |
136
+ |---|---|
137
+ | `restaurant` | Restaurant |
138
+ | `cafe` | Cafe |
139
+ | `bar` | Bar |
140
+ | `bakery` | Bakery / Pastry shop |
141
+ | `meal_takeaway` | Takeaway |
142
+
143
+ Recognize relevant subtypes (e.g. `italian_restaurant`) without replacing the original datum. Example: `primary_type = "italian_restaurant"`, `types = ["italian_restaurant", "restaurant"]` → category Restaurant; debug keeps `primary_type_raw = "italian_restaurant"`. Never rewrite `primary_type_raw` to `restaurant`. Always keep the original value distinct from the interpreted category.
144
+
145
+ Per-meal categories: breakfast → `bakery`, `cafe`, `bar` and consistent subtypes; lunch → `restaurant`, `cafe`, and `bar` compatible with lunch service; dinner → `restaurant` and its subtypes. `meal_takeaway` is allowed only when the user explicitly accepts takeaway service. Do not introduce cuisine restrictions the user did not request.
146
+
147
+ ### 8. Opening-Hours Verification
148
+
149
+ Require `regular_opening_hours` and `current_opening_hours`. Default windows: breakfast 07:00–11:00, lunch 12:00–15:00, dinner 19:00–23:00.
150
+
151
+ For dates within the `current_opening_hours` horizon, use the current periods first. For ordinary weekly compatibility use `regular_opening_hours`. Do not invent a date when the user specified none. Do not confuse `opening_hours.open_now` with compatibility for a future day. Read the `open`/`close` periods accounting for day and any date. Never reconstruct or abbreviate original hours attributing them falsely to the API.
152
+
153
+ ### 9. Geographic Constraints
154
+
155
+ - Mode A: city center / on foot — max 3 km.
156
+ - Mode B: nearby / car / motorcycle — max 10 km.
157
+ - Mode C: extended area — max 20 km.
158
+
159
+ An explicitly requested distance overrides the default. Never widen the radius automatically. Verify position via `geometry.location` against the original reference. Subzones serve to expand queries, not to move the radius center. Do not use distances from the user's position when another locality is indicated. Resolve centers with `maps_geocode` (or `maps_batch_geocode` for several) and express the radius in `locationBias.radius` meters.
160
+
161
+ ### 10. Progressive API Search
162
+
163
+ Primary engine: `maps_search_places` (Places Text Search (New)). Individual deep-dives: `maps_place_details`. Never use invented requests. Each Grade MUST issue new relevant queries, varying categories, locality, or wording. Progression: A → B → C → D → E. If at the end of a phase at least five fully validated results are available, you may stop; otherwise proceed to the next Grade. Do not skip Grade B when results are insufficient. Do not count candidates with non-conforming price, rating, reviews, category, or hours as valid. Deduplicate results by `place_id`.
164
+
165
+ Pagination caveat: the server returns `nextPageToken` when present and forwards `pageToken`, but the underlying SDK has no server-side effect for it — do NOT rely on pagination to satisfy a Grade; issue refined queries instead.
166
+
167
+ ### 11. Parameters per Search
168
+
169
+ For every `maps_search_places` call apply (all supported by the tool):
170
+
171
+ ```json
172
+ {
173
+ "query": "trattoria Turin city center",
174
+ "includedType": "restaurant",
175
+ "strictTypeFiltering": true,
176
+ "minRating": 4.5,
177
+ "priceLevels": ["PRICE_LEVEL_INEXPENSIVE", "PRICE_LEVEL_MODERATE"],
178
+ "locationBias": { "latitude": 45.07, "longitude": 7.68, "radius": 3000 },
179
+ "pageSize": 20,
180
+ "languageCode": "en",
181
+ "includeRaw": true
182
+ }
183
+ ```
184
+
185
+ Do not invent undocumented parameters. Text Search supports exactly one `includedType` per call; explore multiple categories with distinct queries. `includeRaw: true` is MANDATORY for audit (Section 12).
186
+
187
+ ### 12. Field Coverage and Raw Payloads
188
+
189
+ The server applies explicit field masks per operation and echoes the applied mask in the `field_mask` output field; with `includeRaw: true` every result carries `raw_place` (original Places payload) and the response carries `raw` (full original response). Without `includeRaw`, only interpreted fields are returned and you MUST NOT claim `raw` payloads in the debug section. Never claim a field mask the real call did not send. Never invent missing fields. Never modify original data structures to make them appear conformant.
190
+
191
+ ### 13. Response Integrity
192
+
193
+ THIS SECTION HAS PRIORITY OVER ANY OUTPUT FORMAT OR SEARCH STRATEGY.
194
+
195
+ #### 13.1 Real response structure
196
+
197
+ `maps_search_places` returns transformed results (`name`, `place_id`, `formatted_address`, `geometry.location`, `primary_type`, `types`, `business_status`, `google_maps_uri`, `price_level`, `price_range` (raw Money), `rating`, `user_ratings_total`, `opening_hours.open_now`, `regular_opening_hours`, `current_opening_hours`) plus `nextPageToken`, `field_mask`, and `raw`/`raw_place` with `includeRaw: true`. Structure examples describe the shape only; never use them as real data.
198
+
199
+ `maps_geocode` returns the flat first-result payload `{ "location": { "lat": <number>, "lng": <number> }, "formatted_address": "<string>", "place_id": "<string>" }`; the call fails with an error text when zero results are returned. Every mcp-google-api tool returns its interpreted payload directly as the response text: the server-internal `{ "success", "data" }` envelope is never exposed to MCP clients. Dereferencing `data`, `success`, or `error` on a returned payload is FORBIDDEN: those fields are never sent, so the read yields undefined values that MUST NOT feed the debug register. Resolve centers with `maps_geocode` and read `location.lat`/`location.lng` directly from that payload.
200
+
201
+ #### 13.2 Raw-reconstruction prohibition
202
+
203
+ It is categorically forbidden to modify a raw payload to: fit the price to the budget; fit the economic level to the requested filter; increase review counts; simplify `primary_type`; replace `name` with a plain string; convert Money objects to plain numbers; add information not returned; reconstruct opening periods; transform non-Places data into Places API data. Interpreted data MUST live in separate fields clearly marked as agent interpretations.
204
+
205
+ #### 13.3 Request-consistency control
206
+
207
+ If a search was sent with `priceLevels: ["PRICE_LEVEL_INEXPENSIVE", "PRICE_LEVEL_MODERATE"]` and a returned candidate has `price_level = PRICE_LEVEL_EXPENSIVE`, register a consistency anomaly. Do not rewrite EXPENSIVE to MODERATE. Do not declare the candidate compliant to fix the anomaly. Do not invent a different API response.
208
+
209
+ #### 13.4 Place ID verification
210
+
211
+ Use `place_id` as the primary identifier. If two real responses for the same `place_id` contain incompatible data: keep both original payloads; identify the divergent fields; if `maps_place_details` (with `includeRaw: true`) is available, re-verify that Place ID; use the data actually returned by the most recent pertinent verification. If the conflict remains unresolved on a mandatory requirement, do not validate the candidate. Never resolve divergences by arbitrarily choosing values that allow admission.
212
+
213
+ ### 14. Binding Regression Case — Osteria Veglio
214
+
215
+ Use this case as a prompt-consistency test; it is a reference example, not data to insert into future searches. Place ID `ChIJY2oWYByu0hIRZXOOaToUTA8` with:
216
+
217
+ ```json
218
+ {
219
+ "rating": 4.6,
220
+ "userRatingCount": 910,
221
+ "primaryType": "italian_restaurant",
222
+ "priceLevel": "PRICE_LEVEL_EXPENSIVE",
223
+ "priceRange": {
224
+ "startPrice": { "currencyCode": "EUR", "units": "40" },
225
+ "endPrice": { "currencyCode": "EUR", "units": "70" }
226
+ }
227
+ }
228
+ ```
229
+
230
+ For lunch with budget 30 EUR: Grade A; maximum price 70 EUR; economic level EXPENSIVE; maximum allowed level MODERATE; final outcome EXCLUDED. A high rating cannot prevail over the budget. Forbidden reinterpretations: `price_level = PRICE_LEVEL_MODERATE`; `price_range = 25–30 EUR`; `user_ratings_total = 1703`; `primary_type_raw = "restaurant"`. Never use this test's data to fabricate a future response: a new search uses only actually obtained data.
231
+
232
+ ### 15. Final Validation
233
+
234
+ For each candidate verify: authentic data provenance (an executed mcp-google-api call); identity and `place_id`; `business_status`; budget and price; rating; review count; Grade; category; date and hours; geographic distance. Admit a candidate only when every mandatory check passes. Keep separate collections: `INTERNAL_CANDIDATES` (all found places) and `VALIDATED_RESULTS` (fully conformant only). Never publish excluded candidates as recommendations. Never use unverified candidates to reach five results.
235
+
236
+ ### 16. Standard Output
237
+
238
+ Produce three functional sections in order.
239
+
240
+ A. Search summary — locality and radius; meal; date and time; budget; maximum allowed economic level; operating mode actually used (`API_VERIFIED` / `MCP_SERVER_UNAVAILABLE`); Grades actually explored; number of fully validated results; technical limitations.
241
+
242
+ B. Validated venues — show ONLY `VALIDATED_RESULTS`. For each: name; verified Google Maps link (`google_maps_uri`); Google rating; Google review count; Grade; category; raw `primary_type`; raw `price_level`; raw `price_range` when available; `BUDGET_MAX`; economic validation method; compatible hours; geographic reference; optionally a `maps_static_map` image and route/travel time from `maps_directions`, `maps_distance_matrix`, or `maps_plan_route`.
243
+
244
+ C. Notes and limitations — general considerations only. If the server is unavailable, declare that the required API validation could not be performed. Never present simulated processing as verified.
245
+
246
+ Debug output is defined exclusively by the debug overlay file appended at install time with `--debug-skills`; when that overlay is absent, emit no debug section.
@@ -0,0 +1,15 @@
1
+ {
2
+ "version": 1,
3
+ "description": "Registry of LLM agent skills shipped under src/resources/skills. Each entry points to exactly one <skill-id>/SKILL.md. Adding a skill requires only a new skill directory plus one entry here; no source-code change is needed.",
4
+ "skills": [
5
+ {
6
+ "id": "eatspot-discovery",
7
+ "name": "eatspot-discovery",
8
+ "version": "1.3.0",
9
+ "language": "en",
10
+ "path": "eatspot-discovery/SKILL.md",
11
+ "description": "Discover and validate bars, pastry shops, restaurants, cafes, and bakeries for breakfast, lunch, or dinner using the 18 mcp-google-api MCP tools exclusively, enforcing budget, quality-grade, category, opening-hours, and distance constraints on verifiable Google Places API (New) data.",
12
+ "debug": "DEBUG.md"
13
+ }
14
+ ]
15
+ }