雖然目前還沒辦法使用Google Cloud Next’26提到的MPC新功能,但發現這個MPC工具跟之前已經不一樣,因此進行分析。
Grounding Lite MCP 的價值不只是「把 Google Maps API 包成工具」,而是讓 LLM 能用 MCP 標準方式取得可信、即時的地理資訊。對需要地點查詢、附近推薦或城市探索的 AI 應用來說,search_places 回傳的地點摘要、Place ID、座標與 Google Maps 來源連結,可以補強 LLM 原本容易缺乏即時性與來源依據的問題。
不過,它比較適合作為「地理資料入口」,而不是完整的應用邏輯本身。實際產品通常還是需要在前端或後端補上地圖視覺化、地點卡片、路線顯示、資料 fallback 與排序規則。也就是說,Grounding Lite MCP 負責讓 LLM 找到可信地點;產品層負責把這些地點變成穩定、可互動的使用體驗。
這篇文章的重點不放在「Grounding Lite MCP 有哪些工具」,因為那些內容在官方文件很快就能查到。比較值得分析的是:它對 LLM 應用架構的價值是什麼?
從 MCP server 設計角度來看,一個好的 MCP 工具不應只是把 API endpoint 一個個暴露給模型,而應該讓模型使用更接近任務需求的高階工具。換句話說,LLM 不應該被迫理解底層 API 的參數、欄位與串接順序,而是能用「搜尋地點」、「查詢天氣」、「計算路線」這種更接近人類意圖的方式取得資料。
Grounding Lite MCP 的設計就比較接近這個方向。它讓 LLM 不必直接面對 Google Maps API 的所有細節,而是透過 MCP tools 取得地點、位置與路線相關資料。對產品來說,這等於多了一層穩定的地理資料工具層:
使用者自然語言需求
↓
LLM 判斷是否需要地理資料
↓
Grounding Lite MCP tools
↓
Google Maps Platform data
↓
LLM 整理回答
↓
產品層補上地圖、卡片、互動與 fallback
這個分層很重要,因為 LLM 擅長理解語意與生成回答,但不適合憑空編造地點資訊。地理資料應該交給可信資料源,LLM 則負責把資料轉成使用者能理解的內容。
假設我們做的是一個對外常見、沒有專案敏感度的功能:
幫我找台北車站附近適合遠端工作的咖啡廳。
如果只靠 LLM 本身回答,可能會遇到幾個問題:
使用 Grounding Lite MCP 後,流程可以變成:
使用者提問
↓
LLM 判斷需要查地點
↓
呼叫 Grounding Lite MCP 的 search_places
↓
取得地點摘要、Place ID、經緯度、Google Maps 來源
↓
LLM 產生推薦內容
↓
前端用經緯度畫 marker
↓
後端可再用 Place ID / 座標串 Places API、Routes API 或其他 Maps API
例如 search_places 回傳:
{
"summary": "台北車站附近有幾間適合遠端工作的咖啡廳:Fika Fika Cafe 提供舒適座位與咖啡選擇 [0]。NOTCH Coffee 適合短暫工作與交通轉乘 [1]。路易莎咖啡台北站前店交通方便,適合臨時會議或等車空檔 [2]。",
"places": [
{
"id": "place_001",
"displayName": "Fika Fika Cafe",
"location": {
"latitude": 25.0463,
"longitude": 121.5175
},
"googleMapsLinks": {
"placeUrl": "https://maps.google.com/..."
}
},
{
"id": "place_002",
"displayName": "NOTCH Coffee",
"location": {
"latitude": 25.0472,
"longitude": 121.5159
},
"googleMapsLinks": {
"placeUrl": "https://maps.google.com/..."
}
},
{
"id": "place_003",
"displayName": "路易莎咖啡台北站前店",
"location": {
"latitude": 25.0458,
"longitude": 121.5162
},
"googleMapsLinks": {
"placeUrl": "https://maps.google.com/..."
}
}
]
}
LLM 可以產生:
台北車站附近可以優先考慮 Fika Fika Cafe [0],適合需要安靜坐一段時間的人。若只是短時間處理工作或等車,NOTCH Coffee [1] 會比較方便。路易莎咖啡台北站前店 [2] 則適合臨時會議或需要交通便利的位置。
這段回答的價值不只在文字本身,而是每個店家背後都有 Place ID、座標與 Google Maps 來源。前端可以用座標畫 marker,後端可以用 Place ID 補詳細資料,文字、地圖與店家卡片就能對齊。
const places = groundingLiteResult.places;
places.forEach((place, index) => {
new google.maps.Marker({
map,
position: {
lat: place.location.latitude,
lng: place.location.longitude,
},
title: `[${index}] ${place.displayName}`,
});
});
如果後續要補「從目前位置走過去要多久」,也可以用座標接 Routes API:
async function computeRoute(origin, destination) {
const res = await fetch(
"https://routes.googleapis.com/directions/v2:computeRoutes",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Goog-Api-Key": process.env.GOOGLE_MAPS_API_KEY!,
"X-Goog-FieldMask":
"routes.duration,routes.distanceMeters,routes.polyline.encodedPolyline",
},
body: JSON.stringify({
origin: {
location: {
latLng: {
latitude: origin.latitude,
longitude: origin.longitude,
},
},
},
destination: {
location: {
latLng: {
latitude: destination.latitude,
longitude: destination.longitude,
},
},
},
travelMode: "WALK",
}),
}
);
return res.json();
}
const route = await computeRoute(
userCurrentLocation,
places[0].location
);
這就是 Grounding Lite MCP 比較適合的定位:讓 LLM 找到可信地點與摘要,其他 Maps API 再補產品需要的地圖、路線與 UI 資料。
官方 demo 是用 Google SDK 加 MCP SDK。簡化後可以這樣理解:
import { GoogleGenAI, mcpToTool } from "@google/genai";
import { Client as McpClient } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
const ai = new GoogleGenAI({
apiKey: process.env.GEMINI_API_KEY!,
});
// 1. 連到 Grounding Lite MCP server
const mcpClient = new McpClient({
name: "maps-grounding-lite-client",
version: "1.0.0",
});
const transport = new StreamableHTTPClientTransport(
new URL("https://mapstools.googleapis.com/mcp"),
{
requestInit: {
headers: {
"X-Goog-Api-Key": process.env.GOOGLE_MAPS_API_KEY!,
},
},
}
);
await mcpClient.connect(transport);
// 2. 把 MCP server 提供的 tools 轉成 Gemini tools
const mapsTool = mcpToTool(mcpClient);
// 3. 建立 Gemini chat,讓模型自行判斷何時呼叫工具
const chat = ai.chats.create({
model: "gemini-2.5-flash",
config: {
tools: [mapsTool],
systemInstruction: `
你是城市探索助理。
當使用者詢問地點、店家、附近推薦時,請使用 search_places。
當使用者詢問天氣時,請使用 lookup_weather。
當使用者詢問兩地距離或交通時間時,請使用 compute_routes。
回答地點時,請保留工具回傳的 index,例如 [0]、[1]、[2]。
`,
},
});
const result = await chat.sendMessage({
message: "幫我找台北車站附近適合遠端工作的咖啡廳",
});
console.log(result.text);
這段的重點是:
const mapsTool = mcpToTool(mcpClient);
也就是不需要自己重新包 search_places、lookup_weather、compute_routes。Grounding Lite MCP server 已經提供 tools,Google SDK 透過 mcpToTool 把它們交給 Gemini 使用。
官方 demo 不是用 LangChain,而是用 Google SDK 加 MCP SDK。若後續改成 LangChain,比較合理的做法也不是自己重寫 tools,而是透過 MCP adapter 直接連到 Grounding Lite MCP server,載入它已經提供的 tools。
簡化概念如下:
import { MultiServerMCPClient } from "@langchain/mcp-adapters";
import { ChatGoogleGenerativeAI } from "@langchain/google-genai";
import { createReactAgent } from "@langchain/langgraph/prebuilt";
const client = new MultiServerMCPClient({
maps: {
transport: "streamable_http",
url: "https://mapstools.googleapis.com/mcp",
headers: {
"X-Goog-Api-Key": process.env.GOOGLE_MAPS_API_KEY!,
},
},
});
// 直接從 Grounding Lite MCP server 載入既有 tools
const tools = await client.getTools();
const llm = new ChatGoogleGenerativeAI({
model: "gemini-2.5-flash",
apiKey: process.env.GEMINI_API_KEY!,
});
const agent = createReactAgent({
llm,
tools,
});
const result = await agent.invoke({
messages: [
{
role: "system",
content: `
你是城市探索助理。
使用者詢問地點、店家、附近推薦時,使用 Grounding Lite MCP 的 search_places。
使用者詢問天氣時,使用 lookup_weather。
使用者詢問兩地距離或交通時間時,使用 compute_routes。
回答地點時,保留工具回傳的地點 index,例如 [0]、[1]、[2]。
`,
},
{
role: "user",
content: "幫我找台北車站附近適合遠端工作的咖啡廳",
},
],
});
console.log(result.messages.at(-1)?.content);
await client.close();
這個版本的定位是:
Grounding Lite MCP:提供 Google Maps 地理資料 tools
LangChain / LangGraph:負責 agent orchestration
Gemini:負責理解問題、決定何時呼叫 tools、整理回答
也就是說,LangChain 不取代 Grounding Lite MCP,而是把它納入 agent 工具層。
Demo 值得參考的地方是,它沒有假設 MCP 回傳的資料一定完整到可以直接支撐 UI,而是在產品層補 fallback。
以「顯示店家路線」為例,如果 MCP 回傳的路線資料足夠讓 LLM 產生文字,但不足以讓前端畫線,後端可以再補一次 Routes API,取得 encodedPolyline。
具體例子:
{
"duration": "8 mins",
"distanceMeters": 650
}
這樣的資料足夠讓 LLM 回答:
從台北車站走到 Fika Fika Cafe [0] 約 8 分鐘。
但如果前端要畫路線,就還需要 polyline。這時後端可以做 fallback:
async function hydrateRoutePolyline(routeResult, origin, destination) {
if (routeResult.polyline?.encodedPolyline) {
return routeResult;
}
const res = await fetch(
"https://routes.googleapis.com/directions/v2:computeRoutes",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Goog-Api-Key": process.env.GOOGLE_MAPS_API_KEY!,
"X-Goog-FieldMask": "routes.polyline.encodedPolyline",
},
body: JSON.stringify({
origin: {
location: {
latLng: {
latitude: origin.latitude,
longitude: origin.longitude,
},
},
},
destination: {
location: {
latLng: {
latitude: destination.latitude,
longitude: destination.longitude,
},
},
},
travelMode: "WALK",
}),
}
);
const data = await res.json();
return {
...routeResult,
polyline: data.routes?.[0]?.polyline,
};
}
這個設計的重點是:
MCP 回傳資料 → 讓 LLM 有地理脈絡
Routes API fallback → 讓前端 UI 能完整呈現
所以 Grounding Lite MCP 不一定要承擔所有產品需求。它負責把「地理資料入口」標準化,產品層再補齊 UI 需要的資料。
另一個值得保留的技巧是 index。當 LLM 回答:
可以先考慮 Fika Fika Cafe [0],適合坐一段時間處理工作。若只是短時間等車或開會,NOTCH Coffee [1] 會比較方便。路易莎咖啡台北站前店 [2] 則適合需要交通便利的位置。
前端可以用 [0]、[1]、[2] 對應到地點陣列:
const placeRegistry = [
{ index: 0, name: "Fika Fika Cafe", placeId: "place_001" },
{ index: 1, name: "NOTCH Coffee", placeId: "place_002" },
{ index: 2, name: "路易莎咖啡台北站前店", placeId: "place_003" },
];
function onPlaceIndexClick(index: number) {
const place = placeRegistry.find((p) => p.index === index);
if (!place) return;
focusMapMarker(place.placeId);
openPlaceCard(place.placeId);
}
這讓 LLM 回答不只是單純文字,而是能和地圖 UI 互動。使用者點 [2] 路易莎咖啡台北站前店,前端就能聚焦到對應 marker 或打開地點卡片。
如果同一輪對話中多次呼叫 search_places,也要維持 unified index。例如:
第一次 search_places:
[0] Fika Fika Cafe
[1] NOTCH Coffee
第二次 search_places:
[2] 路易莎咖啡台北站前店
[3] Cama Coffee
即使最後回答沒有提到 [3] Cama Coffee,也不能把路易莎咖啡台北站前店從 [2] 改成 [1],否則文字中的 index 就會對不到前端 marker。這個設計看起來小,但對「文字 + 地圖 + 地點卡片」的產品體驗很關鍵。
實測時,search_places 是目前最有感的工具。它回傳的不只是地點名稱,而是包含摘要、Place ID、經緯度與 Google Maps 來源,對地點推薦、城市探索、附近搜尋這類情境很有幫助。
尤其對 LLM 來說,這類回傳格式比單純 API 欄位更容易使用,因為它已經提供了可讀性高的摘要,模型可以直接依據摘要整理回答,而不是自行把零散欄位拼成介紹。
但路線能力仍需要保守看待。Grounding Lite MCP 的路線工具比較適合處理兩點之間的距離與時間,不適合承擔複雜路線或多點最佳化。若產品需要更完整的路線顯示、polyline、排序或導航體驗,仍建議搭配 Routes API、Distance Matrix、Route Optimization 或前端地圖元件來補強。
Grounding Lite MCP 比較適合定位成 LLM 的地理資料入口,而不是完整的地圖產品邏輯。
它的優勢是讓 LLM 能用 MCP 標準方式取得可信的 Google Maps 地點資料,並把地點摘要、Place ID、座標與來源一起帶回來。這對地點推薦、附近搜尋、城市探索、商家探索等應用很有價值,因為回答不再只是模型生成,而是能綁定真實地點與地圖資料。
但在地圖呈現、地點詳情、路線 polyline、複雜排序與使用者互動上,仍需要搭配其他 Maps API 或產品層邏輯。比較務實的做法是:讓 Grounding Lite MCP 負責取得可信地點資料,讓前後端補上 UI、路線、資料 fallback 與互動體驗。
Google Maps Platform. Maps Grounding Lite. Google for Developers.
https://developers.google.com/maps/ai/grounding-lite?hl=zh-tw
Google Maps Platform. Grounding Lite MCP Sample App. GitHub.
https://github.com/googlemaps-samples/grounding-lite-mcp-sample-app
Google Maps Platform. Grounding Lite Sample App Demo.
https://grounding-lite-sample-app.web.app/
Block Engineering. Block’s Playbook for Designing MCP Servers.
https://engineering.block.xyz/blog/blocks-playbook-for-designing-mcp-servers
LangChain. Model Context Protocol MCP Adapters. LangChain JS Docs.
https://docs.langchain.com/oss/javascript/langchain/mcp
LangChain. MultiServerMCPClient.getTools Reference. LangChain JS API Reference.
https://reference.langchain.com/javascript/langchain-mcp-adapters/MultiServerMCPClient/getTools