1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

LINE Mini Appで動くレシピサービスのMCPサーバーを作ってみた

1
Last updated at Posted at 2026-02-26

goal-and-barrier.png

はじめに

「CookForYou」は、LINEのMini App上で動くレシピ管理サービスです。ユーザーがLINEで食材の写真を送ると、AIがレシピを提案し、保存・検索できるようになっています。

最近、強く感じていることがあります。

「近い将来、すべてのインターフェースはAIを通して行われるようになる」

検索も、予約も、買い物も、AIとの会話の中で完結する世界がすぐそこまで来ている。そうなったとき、自分のサービスがAIから使える状態になっていなければ、ユーザーとの接点を失ってしまう。

そう考えたとき、CookForYouのレシピデータもAIから直接アクセスできるようにしておくべきだと思いました。「最近作った和食のレシピを教えて」と聞くだけで、自分のレシピDBを検索してくれる。それを実現するために、MCP(Model Context Protocol)サーバーを作ってみました。

Before/After


作りたかったものと障壁

MCPの話に入る前に、どんなものを作りたかったのか、どんなところに障壁があったのかを整理しておきます。

作りたかったこと

  • 自分だけのレシピにアクセスできる:AIから自分のレシピDBを検索・参照できるようにしたい
  • RLSなどを再利用したい:既存のSupabaseのRow Level Securityをそのまま活かし、MCPサーバー側でユーザーごとのフィルタリングを自前実装する必要がないようにしたい

この2つを満たすものを作りたかったのですが、一つ大きな障壁がありました。

障壁:認証情報をどこにどう持たせるか

CookForYouはLINE Loginでユーザーを識別しています。しかし、Supabase AuthはLINEをネイティブプロバイダーとしてサポートしていません。そのため、LINEの認証情報をどこにどうやって持たせるか、設計段階で迷いました。


MCPとは?

**MCP(Model Context Protocol)**は、Anthropicが策定したオープンプロトコルで、AIアシスタント(Claude等)が外部のデータやツールにアクセスするための共通規格です。

従来、AIに自分のデータを使わせるにはプロンプトにコピペするしかありませんでした。MCPを使えば、AIが必要に応じてあなたのサービスのAPIを直接呼び出せます。

MCPの概念図

重要なのは、MCPサーバーは認証付きで公開できること。つまり、あなたのデータにアクセスできるのはあなただけです。


今回つくったもの

CookForYouのレシピデータにClaude DesktopからアクセスできるリモートMCPサーバーを、Cloudflare Workers上に構築しました。(※現在は検証用の環境でのみ動作しており、一般公開はしていません)

技術スタック

要素 技術
MCPサーバー Cloudflare Workers + Durable Objects
認証 LINE Login (OAuth 2.0)
データベース Supabase (PostgreSQL + RLS)
MCPフレームワーク @modelcontextprotocol/sdk + agents
OAuth管理 @cloudflare/workers-oauth-provider

実装したMCPツール(3つ)

ツール名 できること
search_recipes キーワード・タグでレシピを検索
get_recipe_detail レシピの詳細(材料・手順・栄養情報)を取得

アーキテクチャ

アーキテクチャ図

ポイントは3つ:

  1. Cloudflare WorkersがMCPサーバーとOAuth管理の両方を担う
  2. LINE Loginはユーザーの識別にのみ使用し、トークンはサーバーに保存しない
  3. SupabaseはRLS(Row Level Security)でデータを保護しているので、認証済みユーザーは自分のデータにしかアクセスできない

認証フロー

ここが今回一番面白い部分です。「Claude DesktopからLINEログインする」という体験は初めての方も多いのではないでしょうか。

認証フロー

初回接続のステップ

Step 1: Claude Desktopが接続を試みる

Claude Desktopの設定ファイルにMCPサーバーのURLを追加するだけです。

{
  "mcpServers": {
    "cookforyou": {
      "command": "npx",
      "args": ["mcp-remote", "https://cookforyou-mcp.example.com/mcp"]
    }
  }
}

Step 2: 承認ダイアログ

初回アクセス時、ブラウザが自動で開き、承認ダイアログが表示されます。

承認ダイアログ

Step 3: LINE Login

「LINEでログインして許可」ボタンを押すと、LINEのログイン画面にリダイレクトされます。

LINE Login画面

Step 4: 認証完了 → ツールが使えるように

LINEで認証するとブラウザは自動で閉じ、Claude Desktopに戻ります。これでMCPツールが使えるようになります。

ツール一覧

2回目以降

一度認証すると、refresh tokenで自動更新されるため、通常はログインし直す必要がありません。refresh tokenも期限切れした場合は再度認証フローが走りますが、承認Cookieが残っているのでダイアログはスキップされ、LINEのセッションも残っていればほぼワンタップで完了します。


実際に使ってみる

レシピ検索

Claudeに自然言語で聞くだけで、自分のレシピDBを検索してくれます。

レシピ検索の様子

レシピ詳細

検索結果から特定のレシピの詳細を聞くと、材料・手順・栄養情報まで取得できます。

レシピ詳細_mcp_approval
レシピ詳細


技術的なポイント

1. Supabase RLSによるデータ保護

Supabaseの**Row Level Security(RLS)**を活用しているので、MCPサーバー側で「このユーザーのデータだけ返す」というフィルタリングを実装する必要がありません。認証済みのSupabaseクライアントを使えば、自動的にそのユーザーのデータだけが返ります。

// LINE UserIDに紐づくSupabaseユーザーとして認証
const supabase = await authenticateAsLineUser(lineUserId);
// ← このクライアントで何をクエリしても自分のデータしか返らない

RLSの仕組み

2. LINEトークンはサーバーに保存しない

LINE Loginのアクセストークンはcallback時にユーザーの識別に使うだけで、サーバーに永続化しません。認証後のMCPクライアントとの通信は、Cloudflare OAuthProviderが発行する独自のOAuthトークンで行います。

トークンの役割分担

3. Durable Objectsによるセッション管理

最新のMCP仕様では、ステートレスな通信が可能な Streamable HTTP が標準となっています。Cloudflare WorkersのDurable Objectsを使うことで、各ユーザーのMCPセッション(認証情報や状態)を独立したインスタンスで管理できます。

export class CookForYouMCP extends McpAgent<Env, Record<string, never>, Props> {
  server = new McpServer({ name: "CookForYou", version: "1.0.0" });

  async init() {
    // this.props にはOAuth認証時に保存したユーザー情報が入っている
    const { lineUserId, supabaseUserId } = this.props;
    // ツールを登録
    registerSearchRecipes(this.server, ...);
    registerGetRecipeDetail(this.server, ...);
    registerListTags(this.server, ...);
    registerSuggestMenu(this.server, ...);
  }
}

設計判断の裏側:認証アーキテクチャをどう選んだか

技術的なポイントを紹介しましたが、ここに至るまでにはいくつかの検討と断念がありました。設計判断の過程を共有します。

認証アーキテクチャの選択

最初の候補:Supabase OAuth 2.1 Server

CookForYouはもともとSupabase Authで認証を管理しています。であれば、2025年末にパブリックベータになったSupabase Auth OAuth 2.1 Server機能を使うのが最も自然な選択肢に見えました。

Supabase AuthをそのままOAuth 2.1のAuthorization Serverとして使えば、MCPクライアントからのOAuthフローをSupabaseが全部処理してくれる。/.well-known/oauth-authorization-serverのメタデータ公開も、PKCEも、Dynamic Client Registrationも、全部Supabaseがやってくれる。自分で認証サーバーを作る必要がない。理想的です。

しかし、一つ致命的な問題がありました。

Supabase AuthはLINE Loginをネイティブプロバイダーとしてサポートしていません。

Supabase Authがサポートしているソーシャルログインは、Google、GitHub、Discord、Apple等で、LINEは含まれていません。さらに、カスタムOIDCプロバイダーの汎用サポートもまだ実装されていないため、LINEを後から追加することもできません。

Supabase OAuth 2.1 Serverの認証画面では、Supabase上で有効化されているログイン方法のみが使えます。LINE Loginが使えないとなると、ユーザーがMCP経由でログインする手段がありません。

選んだ方法:workers-oauth-provider

そこで採用したのが、Cloudflareが公式に提供している@cloudflare/workers-oauth-providerです。

このライブラリはCloudflare Workers上にOAuth 2.1プロバイダーを構築するもので、MCP仕様が要求するすべてのOAuth仕様(RFC 8414、RFC 9728、RFC 7591等)に対応しています。そして認証プロバイダーに対して非依存で設計されているため、LINE LoginでもGitHub OAuthでも、任意の認証フローを自由に組み込めます。

Cloudflareが公式のGitHub OAuthサンプルを提供しているので、その認証部分をLINE Login用に書き換えるだけで済みました。

将来の拡張性:外部API連携への道

workers-oauth-providerを選んだもう一つの理由は、将来の拡張性です。

現在のCookForYouでは、LINE Loginはユーザーの識別にのみ使用しており、認証後にLINEのAPIを継続的に呼び出す必要はありません。しかし、将来的に外部サービスとの連携ツールを追加したくなるケースは十分にあり得ます。

例えば、Google連携を追加して「今週のGoogleカレンダーの予定に合わせて献立を提案して」というツールを作りたくなったらどうなるか。MCPリクエストのたびにGoogle Calendar APIを叩く必要があるので、Googleのaccess token / refresh tokenを安全に保持し続けなければなりません。

workers-oauth-providerにはこのユースケースに対応する仕組みが備わっています。upstreamプロバイダーのトークンを暗号化してWorkers KVに自動保存し、MCPリクエスト時に復号して外部APIに使うことができます。KVへの暗号化・保存・復号はライブラリが自動で処理し、ストレージにはシークレットそのものではなくハッシュのみが保存されるため、仮にKVが漏洩してもトークンが直接露出しません。

今の実装では使っていませんが、同じアーキテクチャの上で将来の外部API連携にも対応できる。workers-oauth-providerを選んだことで、この拡張パスが最初から確保されています。


環境構成

liff-app(CookForYouのフロントエンド)と同様に、環境ごとにwrangler設定ファイルを分けています。

cookforyou-mcp/
├── wrangler.jsonc          # ローカル開発 (OAuth有り、local Supabase)
├── wrangler.noauth.jsonc   # ローカル開発 (OAuth無し、ツールテスト用)
├── wrangler.dev.jsonc      # dev環境デプロイ
├── wrangler.stg.jsonc      # stg環境デプロイ
└── wrangler.prod.jsonc     # prod環境デプロイ
{
  "dev": "wrangler dev",
  "dev:noauth": "wrangler dev -c wrangler.noauth.jsonc",
  "deploy:dev": "wrangler deploy -c wrangler.dev.jsonc",
  "deploy:stg": "wrangler deploy -c wrangler.stg.jsonc",
  "deploy:prod": "wrangler deploy -c wrangler.prod.jsonc"
}

ローカル開発のTips

OAuth無しモード

ツールの動作確認だけしたいときは、OAuthをバイパスするdevモードが便利です。DEV_LINE_USER_ID.dev.varsに設定しておけば、認証なしで直接ツールを呼び出せます。

npm run dev:noauth
# → MCP Inspector (npx @modelcontextprotocol/inspector) で接続してテスト

フルOAuthフローのテスト

cloudflaredでトンネルを作れば、ローカルでもLINE Login付きのフルフローをテストできます。

npm run dev                        # wrangler dev 起動
cloudflared tunnel --url http://localhost:8788  # HTTPSトンネル作成
# → 発行されたURLをLINE DevelopersのCallback URLに登録
# → Claude Desktopの設定でmcp-remote経由で接続

ローカル開発構成


まとめ

MCPサーバーを作ることで、既存のLINE Mini Appサービスのデータに、Claude DesktopなどのAIアシスタントから直接アクセスできるようになりました。

実装してみて感じたこと:

  • MCPの仕様自体はシンプル。ツールの定義と実行関数を書くだけ
  • 認証が一番大変。リモートMCPサーバーではOAuth 2.0フローの実装が必要で、今回はLINE Login + Cloudflare OAuthProviderの組み合わせで実現した
  • Supabase RLSとの相性が良い。認証さえ通せば、データアクセスの権限管理はDB側が担ってくれる
  • Cloudflare Workersは理想的なホスティング先。Durable ObjectsがMCPのステートフル接続を支え、OAuthProviderライブラリがトークン管理を担ってくれる

既にSupabaseとLINE Loginを使っているサービスなら、MCPサーバーの追加は比較的少ない労力で実現できます。自分のサービスのデータをAIから使えるようにしたい方は、ぜひ試してみてください。(※本機能は現在、開発・検証中につき一般公開はしておりません)

締めの画像


テンプレート公開しています

今回の実装をベースに、LINE Login + Supabase で認証するリモートMCPサーバーのテンプレートを公開しました。サンプルツール付きで、src/tools/ を書き換えるだけで自分のサービス用のMCPサーバーが作れます。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?