Upgrade to Pro — share decks privately, control downloads, hide ads and more …

MCP Appsでつくるチャット駆動な地図アプリ

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

MCP Appsでつくるチャット駆動な地図アプリ

Avatar for Shinsuke Nakamori

Shinsuke Nakamori

September 09, 2026

More Decks by Shinsuke Nakamori

Other Decks in Programming

Transcript

  1. 01 自己紹介 中森 紳介 所属・担当 株式会社 MIERUNE / エンジニアリングマネージャー 最近の関心

    お芋関連の期間限定商品が出始めたので、いっぱい食べたい。 でも月見バーガーも食べたい。 好きなJCT 生麦JCT 羽田から横浜方面に向かう際、以下の2択から選べる素敵なJCT → みなとみらいの「THE・横浜」な景色を見ながら走るルート → 車好きの聖地・大黒PAに寄りつつ、ベイブリッジを渡るルート ↑ 文字で読んでも、どこなのかよく分かりませんね 本名じゃない時
  2. 02 モチベーション 地図 × AI で、まず思いつくかたち 地図アプリ 地図 主役 チャット

    付け足し 既存ユーザー(既にGISを使っている人)は便利になる!...が 「地図アプリを導入していること」が入口になっているので、 新規ユーザー獲得には繋がりにくい
  3. 02 モチベーション チャットから地図を呼び出す チャット 主役 生麦JCTあたりの地図を見せて 地図 LLM が必要に応じて呼び出す 〈このまま会話が続く〉

    入口は、すでに普及しているチャットアプリ 地図アプリの導入は要らない※ 地図で見せるかどうかは、人間が思いつかなく ても LLM 側で判断できる GISを使っていない人が、地図での可視化を体験するきっかけを作れるのでは ※ とはいえ MCPサーバーを繋ぐ手間は残るので、導入の手間がゼロでは無いのが現状
  4. 03 チャットに埋め込むアプリ 好きなテンプレートで作れる 基本テンプレート 以下のフレームワークが用意されている vanillajs preact solid react vue

    svelte 実例のカタログ(20件ほど) pdf PDF.js のビューア。arxiv などの URL も開ける sheet-music ABC記法を楽譜として描画し、その場で再生できる system-monitor CPU・メモリを2秒ごとに取得してグラフ表示 map-serverというCesiumJSを使ったテンプレートも用意されているが、 今回は使い慣れている svelte-maplibre-gl を使いたかったので、Svelte のテンプレートを使用した github.com/modelcontextprotocol/ext-apps
  5. 04 仕組み MCP Apps は3つの環境で動いている ① ホスト環境(Claude Desktop) Claude(LLM) ホスト(AppBridge)

    MCPプロトコル ② MCPサーバー環境 リソース取得 UIリソース (mcp-app.html) postMessage ツール (show-map) ③ サンドボックス iframe UI (MapLibre が地図を描画) チャット欄に表示される部分
  6. 04 仕組み HTML はどうやって iframe に届くのか ① ホスト環境(Claude Desktop) Claude(LLM)

    ホスト(AppBridge) MCPプロトコル ② MCPサーバー環境 リソース取得 UIリソース (mcp-app.html) postMessage iframe と外の世界をつなぐ、唯一の橋 ツール (show-map) ③ サンドボックス iframe UI (MapLibre が地図を描画) チャット欄に表示される部分
  7. 04 仕組み 補足 UI を出しているのは LLM ではない Claude(LLM) tools/call を発行して

    データを受け取るだけ 「UI を表示しよう」とは 判断していない ホスト ツール定義の ui:// の紐づきを見て UI を取得・表示する 決定的なプログラムの処理であって LLM の判断ではない URI がズレると、データは正常に返るのに UI だけが描画されない
  8. 04 仕組み 補足 ツール実行から地図表示までの流れ Claude(LLM) — 接続時 — — 実行時

    — ホスト(AppBridge) サンドボックス iframe tools/list ツール定義:show-map には ui://map が紐づく tools/call show-map サーバーへ転送 結果 = データのみ(center/zoom の JSON) 結果を Claude へ転送(中身はホストも保持) ホストの定型処理:ツール定義に ui://map が紐づいているかを機械的にチェック → あれば UI 表示フローを起動(LLM の判断・指示ではない) resources/read ui://map(紐づいた URI を読む) HTML 文字列(mcp-app.html) HTML を流し込み iframe 生成 postMessage(保持していた入力+結果データ) ここで初めて MapLibre が地図を描画 MCPサーバー
  9. 04 仕組み 地図タイルは外部から取ってくる ① ホスト環境(Claude Desktop) Claude(LLM) ホスト(AppBridge) MCPプロトコル ②

    MCPサーバー環境 リソース取得 UIリソース (mcp-app.html) postMessage ツール (show-map) ③ サンドボックス iframe UI (MapLibre が地図を描画) チャット欄に表示される部分 fetch 外部リソース (地図タイル等)
  10. 04 仕組み サンドボックス iframe は外と繋がっていない ① ホスト環境(Claude Desktop) Claude(LLM) ホスト(AppBridge)

    MCPプロトコル ② MCPサーバー環境 リソース取得 UIリソース (mcp-app.html) postMessage ツール (show-map) ③ サンドボックス iframe UI (MapLibre が地図を描画) チャット欄に表示される部分 宣言していないオリジンへの通信は、デフォルトで全部遮断される fetch 外部リソース (地図タイル等)
  11. 04 仕組み 通信したいオリジンは自分で宣言する _meta: { ui: { csp: { connectDomains:

    [ "https://<tile-origin>", "blob:", ], resourceDomains: [ "https://<tile-origin>", "blob:", "data:", ], }, }, } 実装は合っているのに、背景地図が出ない 宣言したオリジンだけを許可するホワイトリスト方式 背景地図も外部から取得するので、宣言しないと取得できない
  12. 04 仕組み 地図の操作をフィードバックするには ① ホスト環境(Claude Desktop) ② MCPサーバー環境 ツール (show-map)

    Claude(LLM) コンテキストに反映 ホスト(AppBridge) リソース取得 updateModelContext UIリソース (mcp-app.html) ③ サンドボックス iframe UI (MapLibre が地図を描画) チャット欄に表示される部分 fetch 外部リソース (地図タイル等) 地図操作をトリガーにコンテキストを更新して、LLMにフィードバックする
  13. 05 まとめ まとめ 1 チャットの中に任意の UI を出せる MCP Apps で、会話に埋め込む地図やフォームを構築できる

    2 UI が動くのはサンドボックス環境 外の世界からは切り離された環境に置かれている 3 外との出入りは、自分で設定する タイル等の外部通信はホワイトリストで定義、 LLM へのフィードバックはイベントトリガーでコンテキスト更新