MOSH Tech Meetup #5 あなたが「好きなこと」× エンジニアリング


大好きなアレをMCPにしてみた


ぶりお @burio_16

ぶりおの写真

自己紹介

  • ぶりお(@burio_16)
  • しがない2年目フロントエンドエンジニア
  • Tottenham Hotspur FCが大好き

Q.ぶりおと言えばなんでしょう?

A.タコス!!!!!🌮

CTOを名乗っています

Chief
Tacos
Ojisan

好きなこと×エンジニアリング

タコス×MCP

Burio de Tacosをリリースしました!!Burio de Tacosのタコス店一覧と地図

web:tacos.burio16.com mcp:tacos.burio16.com/mcp

コンセプト

  • 自他共に認めるタコスおじさんが好きなタコスを共有したい!
  • あくまで自分が行ったことある店しか掲載しない
  • やってみたかったMCP Appsにも対応したい

技術スタック

  • フロントエンド:React 19 / TanStack Router / TanStack Query / MapLibre GL / Tailwind CSS
  • バックエンド:Hono / MCP SDK / Drizzle ORM
  • 言語:TypeScript
  • インフラ:Cloudflare Workers / D1 / R2 / Images / Alchemy
  • ツールチェイン:Vite+

デモ

MCP Appsとは?

  • MCPサーバーが、Toolとui://形式のUIを紐づけて提供する
  • ホストはToolの実行結果を渡し、UIをiframe内に表示する
  • UIからToolの再実行や入力ができ、地図・グラフ・フォームなどを会話内で操作できる
  • あくまでMCPの拡張機能の一つであり、非対応ホストでは通常のテキスト結果として動作する

1. ToolをUIに紐づける

公式Quickstartの時刻表示アプリを抜粋

ts
const resourceUri = "ui://get-time/mcp-app.html";

registerAppTool(
  server,
  "get-time",
  {
    title: "Get Time",
    inputSchema: {},
    _meta: { ui: { resourceUri } },
  },
  async () => {
    const time = new Date().toISOString();
    return { content: [{ type: "text", text: time }] };
  },
);

2. UI Resourceを登録

同じURIで、iframeに表示するHTMLをResourceとして返す

ts
registerAppResource(
  server,
  "Get Time UI",
  resourceUri,
  { mimeType: RESOURCE_MIME_TYPE },
  async () => {
    const html = await fs.readFile("dist/mcp-app.html", "utf-8");
    return {
      contents: [{
        uri: resourceUri,
        mimeType: RESOURCE_MIME_TYPE,
        text: html,
      }],
    };
  },
);

MCP Appsが向いているケース

  • 複雑なデータ探索:地図・グラフを操作して深掘りする
  • 選択肢の多い設定:フォームでまとめて入力・検証する
  • リッチメディア:PDF・3D・画像をその場で閲覧する
  • リアルタイム監視:メトリクス・ログを継続的に更新する
  • 複数ステップの作業:レビュー・承認を状態付きで進める

tacos mcp使って
お気に入りのタコス屋
見つけてください!

お店の提案はGitHubのissueから!

皆様良きタコスライフを🌮

¡Gracias!