Google Maps Platform の Grounding Lite 構想 の一部として、MCP エンドポイント が公開されました。
さっそく mapstools.googleapis.com/mcp を試してみます。
ドキュメント
Grounding Lite
MCP Reference: mapstools.googleapis.com
https://developers.google.com/maps/ai/grounding-lite/reference/mcp?utm_source=chatgpt.com&hl=ja
何ができる?
search_places(場所検索)lookup_weather(天気)compute_routes(経路)
現時点で、mapstools.googleapis.com が提供する公式 MCP では、上記の3つのみが利用可能です。
それ以外の情報(クチコミ情報)などは、別途 API を呼び出す必要があります。
とはいえ、Google ADK では、Agent 側に独自の Tool を追加できるため、
公式 MCP で不足する情報(クチコミ等)は、
Places API(Place Details)を呼び出す Tool を別途追加して補完できます。
試してみる
Google ADK で動かす
今回は、公式ドキュメントで例示されている Google ADK を使って試しました。
https://google.github.io/adk-docs/tools-custom/mcp-tools
各種サービスを有効化する必要がある
AI サービス
今回の MCP を利用するには Google Maps API Key が必要です。
また、Agent として Gemini を使う場合は、Gemini API Key または Vertex AI の認証情報が別途必要になります。
API Services を有効化する
gcloud beta services enable mapstools.googleapis.com --project=PROJECT_ID
gcloud beta services mcp enable mapstools.googleapis.com --project=PROJECT_ID
# 有効化できたか確認
gcloud beta services mcp list --enabled --project=_PROJECT_ID_
※ローカルの gcloud では未対応な場合があります。mapstools.googleapis.com の有効化に関しては、Cloud Shell から実行します。
コード
公式 MCPに、Place Details を呼び出す Tool を追加しています。
※ 本コードは検証・学習用途のサンプルです。
※ Google Places API の利用には課金設定が必要になる場合があります。
※ reviews(クチコミ)は API 仕様上、常に多数取得できるわけではありません(最大5件程度)。
import os
import json
import urllib.parse
import urllib.request
import urllib.error
from dotenv import load_dotenv
from typing import Any, Dict, List, Optional
from google.adk.agents.llm_agent import Agent
from google.adk.tools.mcp_tool.mcp_toolset import MCPToolset
from google.adk.tools.mcp_tool.mcp_session_manager import StreamableHTTPConnectionParams
load_dotenv(dotenv_path=os.path.join(os.path.dirname(__file__), ".env"))
MAPS_MCP_URL = "https://mapstools.googleapis.com/mcp"
PLACES_API_BASE_URL = "https://places.googleapis.com/v1"
def _get_places_api_key() -> str:
return os.getenv("GOOGLE_PLACES_API_KEY") or os.getenv("GOOGLE_MAPS_API_KEY", "")
def _http_get_json(url: str, headers: Dict[str, str], timeout_sec: int = 30) -> Dict[str, Any]:
req = urllib.request.Request(url, headers=headers, method="GET")
try:
with urllib.request.urlopen(req, timeout=timeout_sec) as resp:
raw = resp.read().decode("utf-8")
except urllib.error.HTTPError as e:
body = ""
try:
body = e.read().decode("utf-8")
except Exception:
body = ""
raise RuntimeError(f"HTTP {e.code}: {body or e.reason}") from e
except urllib.error.URLError as e:
raise RuntimeError(f"ネットワークエラー: {e.reason}") from e
try:
return json.loads(raw) if raw else {}
except json.JSONDecodeError as e:
raise RuntimeError("JSON のパースに失敗しました") from e
def get_place_details(
place_id: str,
language_code: str = "ja",
region_code: str = "",
max_reviews: int = 5,
field_mask: str = "",
) -> Dict[str, Any]:
"""Google Places API の Place Details を取得します(reviews 等)。
Args:
place_id: Google Maps/Places の place_id
language_code: 例: "ja", "en"
region_code: 例: "JP"(任意)
max_reviews: 返す reviews の最大件数(0-20 推奨)
field_mask: 取得フィールド(未指定なら reviews など最低限)
"""
api_key = _get_places_api_key()
if not api_key:
return {
"status": "error",
"error": "API Key が未設定です。GOOGLE_PLACES_API_KEY または GOOGLE_MAPS_API_KEY を設定してください。",
}
if not place_id:
return {"status": "error", "error": "place_id が空です。"}
safe_max_reviews = max(0, min(int(max_reviews), 20))
effective_field_mask = (
field_mask.strip()
or "displayName,formattedAddress,rating,userRatingCount,reviews,websiteUri,internationalPhoneNumber"
)
query = {"languageCode": language_code}
if region_code.strip():
query["regionCode"] = region_code.strip()
url = f"{PLACES_API_BASE_URL}/places/{urllib.parse.quote(place_id)}?{urllib.parse.urlencode(query)}"
headers = {
"X-Goog-Api-Key": api_key,
"X-Goog-FieldMask": effective_field_mask,
}
try:
data = _http_get_json(url, headers=headers, timeout_sec=30)
except Exception as e:
return {
"status": "error",
"place_id": place_id,
"error": str(e),
"hint": "Places API が有効化され、課金設定が必要な場合があります。",
}
reviews_raw: List[Dict[str, Any]] = data.get("reviews") or []
reviews_raw = reviews_raw[:safe_max_reviews] if safe_max_reviews else []
def _review_text(r: Dict[str, Any]) -> str:
text = r.get("text") or {}
if isinstance(text, dict):
return (text.get("text") or "").strip()
if isinstance(text, str):
return text.strip()
return ""
reviews: List[Dict[str, Any]] = []
review_texts: List[str] = []
for r in reviews_raw:
if not isinstance(r, dict):
continue
t = _review_text(r)
if t:
review_texts.append(t)
reviews.append(
{
"rating": r.get("rating"),
"text": t,
"publishTime": r.get("publishTime"),
"authorName": (r.get("authorAttribution") or {}).get("displayName"),
"relativePublishTimeDescription": r.get("relativePublishTimeDescription"),
}
)
display_name = data.get("displayName") or {}
name_text = display_name.get("text") if isinstance(display_name, dict) else None
return {
"status": "success",
"place_id": place_id,
"place": {
"name": name_text or data.get("name"),
"formattedAddress": data.get("formattedAddress"),
"rating": data.get("rating"),
"userRatingCount": data.get("userRatingCount"),
"websiteUri": data.get("websiteUri"),
"internationalPhoneNumber": data.get("internationalPhoneNumber"),
"reviews": reviews,
},
"review_texts": review_texts,
# "raw": data, # デバッグ用
}
maps_toolset = MCPToolset(
connection_params=StreamableHTTPConnectionParams(
url=MAPS_MCP_URL,
headers={
"X-Goog-Api-Key": os.getenv("GOOGLE_MAPS_API_KEY", ""),
},
timeout=120,
)
)
instruction = """
あなたは Google Maps のエキスパートです。
このエージェントは、以下を行えます:
- Google Maps 検索(place_id の特定、位置情報の取得)
- 天気情報の取得
- 経路・距離の計算
- Places API による Place Details 取得(reviews/住所/評価など)
注意:
- Maps MCP ツール単体ではクチコミ本文は取得できないため、必要なら get_place_details を使ってください。
""".strip()
# エージェントの定義
root_agent = Agent(
model="gemini-2.5-flash",
name="maps_agent",
description="An agent that can use Google Maps (Google-hosted MCP server).",
instruction=instruction,
tools=[
maps_toolset,
get_place_details,
],
)
いざテスト
Web UI 起動
$ adk web --port 8000
INFO: Started server process [88832]
INFO: Waiting for application startup.
+-----------------------------------------------------------------------------+
| ADK Web Server started |
| |
| For local testing, access at http://127.0.0.1:8000. |
+-----------------------------------------------------------------------------+
INFO: Application startup complete.
質問1:店を探してもらう
純正 MCP に含まれている機能です。
Q: 東銀座駅に近いマクドナルドはどこ?

ちゃんと検索してくれました。
質問2:経路を計算させる
純正 MCP に含まれている機能です。
Q: 東銀座を出て、 その2店舗をはしごしたら、何分かかる?

経路検索です。
難易度の高い計算です。もともとあった機能ですが、MCP 経由でもきちんと機能しました。
質問3:クチコミを取得しておく
これは公式 MCP の機能ではなく、
Agent に追加した独自 Tool(Places API: Place Details)による取得です。
Q: その2店舗のクチコミを列挙してください。

2回 Place Details を実施していることがわかります。
きちんと取得できています。

