はじめに
「CookForYou」は、LINEのMini App上で動くレシピ管理サービスです。ユーザーがLINEで食材の写真を送ると、AIがレシピを提案し、保存・検索できるようになっています。
最近、強く感じていることがあります。
「近い将来、すべてのインターフェースはAIを通して行われるようになる」
検索も、予約も、買い物も、AIとの会話の中で完結する世界がすぐそこまで来ている。そうなったとき、自分のサービスがAIから使える状態になっていなければ、ユーザーとの接点を失ってしまう。
そう考えたとき、CookForYouのレシピデータもAIから直接アクセスできるようにしておくべきだと思いました。「最近作った和食のレシピを教えて」と聞くだけで、自分のレシピDBを検索してくれる。それを実現するために、MCP(Model Context Protocol)サーバーを作ってみました。
作りたかったものと障壁
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サーバーは認証付きで公開できること。つまり、あなたのデータにアクセスできるのはあなただけです。
今回つくったもの
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つ:
- Cloudflare WorkersがMCPサーバーとOAuth管理の両方を担う
- LINE Loginはユーザーの識別にのみ使用し、トークンはサーバーに保存しない
- 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のログイン画面にリダイレクトされます。
Step 4: 認証完了 → ツールが使えるように
LINEで認証するとブラウザは自動で閉じ、Claude Desktopに戻ります。これでMCPツールが使えるようになります。
2回目以降
一度認証すると、refresh tokenで自動更新されるため、通常はログインし直す必要がありません。refresh tokenも期限切れした場合は再度認証フローが走りますが、承認Cookieが残っているのでダイアログはスキップされ、LINEのセッションも残っていればほぼワンタップで完了します。
実際に使ってみる
レシピ検索
Claudeに自然言語で聞くだけで、自分のレシピDBを検索してくれます。
レシピ詳細
検索結果から特定のレシピの詳細を聞くと、材料・手順・栄養情報まで取得できます。
技術的なポイント
1. Supabase RLSによるデータ保護
Supabaseの**Row Level Security(RLS)**を活用しているので、MCPサーバー側で「このユーザーのデータだけ返す」というフィルタリングを実装する必要がありません。認証済みのSupabaseクライアントを使えば、自動的にそのユーザーのデータだけが返ります。
// LINE UserIDに紐づくSupabaseユーザーとして認証
const supabase = await authenticateAsLineUser(lineUserId);
// ← このクライアントで何をクエリしても自分のデータしか返らない
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サーバーが作れます。















