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

好きを形に。家系ラーメンを探すMCP Appsを作った

好きを形に。家系ラーメンを探すMCP Appsを作った

Avatar for yuki yamazaki

yuki yamazaki

September 13, 2026

More Decks by yuki yamazaki

Other Decks in Programming

Transcript

  1. MCP Apps で何か作ってみたかった 以前 MCP について調べたことがあり、その流れで MCP Apps が気になっていました。チャット の中に操作できる画面が出せると知って、単純に面白そうだと思いました。

    そのときの資料 — MCP とは何か / 2026-07-28 の仕様で何が変わったのか speakerdeck.com/y_yamazaki/mcp-toha-nani-ka-2026-07-28-no-shiyou-de-nani-ga-kawata-no-ka 4
  2. おさらい:MCP は AI と外部をつなぐ共通規格 自分で MCP サーバーを立てて「こんな機能があるよ」と宣言すると、AI が会話の流れから判断 して呼び出してくれます。 こちらが用意するもの

    機能(tool)の名前・説明・引数。 今回なら「近くの家系を探す(緯度・経度)」。 AI がやること 「横浜駅の近くの家系を教えて」から、 どの機能を使うかを判断して呼び出す。 ただし、MCP が返せるのはテキストだけ。インタラクティブ UI は表示されない 11
  3. MCP Apps は、MCP にインタラクティブな UI を加えたもの MCP だけのとき 文字しか返せない 1.

    壱八家 (クリーミー / 261m) 神奈川県 横浜市 西区高島2丁目 営業: 11:00-23:00 // MCP Apps のとき を返すと、チャットの中で描画される <地図> <検索フォーム> <店舗カード> // HTML 会話の中に触れる画面が出る。押す・選ぶ・絞り込むができる。 読めるけれど、地図で見たい・条件を変えたい、には応えられない。 12
  4. 実装は、2 つ登録するだけ ① tool + データを返す係 「近くの家系を探す」 ② resource 画面の

    HTML を返す係 = MCP Apps チャットに画面が出る 側に「この画面を使って」と書いて紐づける // tool registerAppTool(server, "find-nearby-iekei-ramen", { _meta: { ui: { resourceUri } }, }); // resource // ← ここが紐づけ 側は、ビルド済みの HTML を返すだけ registerAppResource(server, resourceUri, ...); ポイントは _meta.ui.resourceUri の一行。これで「この機能にはこの画面」が決まります。 13
  5. しかも、公式が Skill を配っている AI コーディングエージェント向けに create-mcp-app という Skill が公式配布されています。 Skill

    をインストールすれば、エージェントが MCP Apps の作り方を理解した状態で始められます。 # Claude Code の場合 /plugin marketplace add modelcontextprotocol/ext-apps /plugin install mcp-apps@modelcontextprotocol-ext-apps # ほかのエージェント(Cursor / Codex / Gemini CLI など) npx skills add modelcontextprotocol/ext-apps Skill を入れれば、プロンプトだけで動くものが作れる 今回のアプリも、まずこの Skill に雛形を作ってもらうところから始めました。 出典: modelcontextprotocol.io/extensions/apps/build 14
  6. 3 つの機能 01 検索フォーム 02 現在地から探す 03 地図から探す 都道府県・味の傾向・キーワードで全国から絞る 位置情報か地名から、近い順に

    5 店舗を提案する 全国 646 店舗を日本地図にプロットする 画面は 1 つで、タブで切り替わります。使うときは「横浜駅の近くの家系ラーメンを教えて」と話しかけるだけ。 16
  7. いちばん手間がかかったのはデータ集め グルメサイトの API は規約と料金の面で使えません。 OpenStreetMap から取りました。誰でも自由に使える地図データベースです。 752 47 件の候補 25

    都道府県 分 0 円 都道府県ごとに 1 回、47 回投げたクエリ(Overpass API) area["admin_level"="4"]["name"="神奈川県"]; ← 県で範囲を絞る // ( 家 nwr["cuisine"~"ramen"]["name"~" "]; ← nwr["name"~" | "]; ← ); 家系 町田商店 ラーメン屋で店名に「家」 店名に「家系」か「町田商店」 全国を 1 回で取ろうとするとタイムアウトするので、県ごとに分けました。条件はわざとゆるくして、絞り込みは手元でやります。 17
  8. 集めた 752 件を、どう振り分けたか 公式な定義がないので、店名から推測するしかありません。3 つのルールを順に当てました。 ① 明らかに違うものを外す ラーメン屋ですらないもの(杉田家住宅=重要文化財)、別系統の有名店(本家第一旭・無敵家) 106 件

    → 確定 ② 家系と断定できるもの 店名かブランドに「家系」を含む、または既知の家系ブランド 25 個のどれかと一致する 409 件 → 可能性あり ③ 断定はできないが怪しいもの ラーメン屋で、支店名を除いた店名が「家」で終わる(他ジャンルの語を含むものは除く) 237 件 残った 646 店舗がアプリのデータ。白か黒かを決めず、確信度は UI のバッジで区別する 18
  9. 白状すると、味のデータは無い OpenStreetMap に「濃さ」は載っていません。「味の傾向」で絞れると言っておきながら、中身 は既知のブランドからの推定です。 味の傾向 直系・濃厚 クリーミー チェーン・万人向け 情報なし 割り当てた根拠

    吉村家 / 杉田家 / 厚木家 などのブランド名 壱六家 / 壱八家 / 魂心家 などのブランド名 町田商店 / 壱角家 などのブランド名 ブランドから判定できなかった 店舗数 17 30 229 370 646 店のうち 370 店は「情報なし」 19
  10. 構成:月 0 円で動いています Claude 会話して機能を呼ぶ → Cloudflare Workers MCP サーバー本体

    → コードに同梱 店舗 JSON と画面 HTML Workers にはファイルシステムが無いので、データも画面もビルド時にコードへ埋め込みます。 読み取り専用なので、そもそも保存先が要りません。 配信サイズは 407 KB。無料枠の上限 3 MB に対して 13% でした。 20
  11. まとめ MCP Apps は公式が Skill を配っているので、実装で困ることはありませんでした。 今回はコードを触っていません。 時間のほとんどは、どんなアプリを作りたいかを書く、作る前のプロンプトに使いました。 作るところは AI

    に任せきりでした。 そのぶん効いてきたのが、データ集めと、家系かどうかの判定です。 技術と関係ないところをどこまで網羅できるかが、そのまま出来を決めると感じました。 21
  12. 参考資料 今回作った MCP Apps — ソースコード一式 github.com/yamazaki-yuki-23/iekei-ramen-mcp-apps MCP 公式サイト —

    仕様と SDK の一次情報 modelcontextprotocol.io MCP Apps SDK — tool と resource の登録例が揃っている github.com/modelcontextprotocol/ext-apps OpenStreetMap — 店舗データの出典(ODbL) openstreetmap.org/copyright 22