Skip to main content
Glama
ikeike443
by ikeike443

fatsecret-mcp

CI

Claude が FatSecret の食品/レシピデータベースを検索し、自分のフードダイアリー、体重、運動ログを会話の中で直接読み書きできるようにする、個人用のリモート MCP (Model Context Protocol) サーバーです。Vercel の無料 Hobby プランにデプロイされています。fitness-mcp (Hevy) の姉妹プロジェクトで、製品ごとに1つの MCP サーバーを用意し、同じ認証パターンを共有しています。

ライセンス

MIT

ステータス

  • 検索 (Phase 2): 実装済み — search_foods, get_food_detail, search_recipes, get_recipe_detail, find_food_by_barcode。FatSecret ユーザー認証は不要で、FatSecret のデベロッパーコンソールの OAuth 2.0 Client ID/Secret のみが必要です。

  • ダイアリー/体重/運動/プロフィール (Phase 4): 実装済みですが、実際の FatSecret アカウントでは未検証です — この開発中には FatSecret API の登録が存在しなかったためです (下記の「未検証の内容」を参照)。各メソッドの正確なフィールド名を、実際のアカウントで確認してから使用し、不整合があればコード/テストを更新してください。

  • 3-legged OAuth1 セットアップスクリプト (Phase 3): 実装済み (scripts/fatsecret-oauth-setup.ts)。実際の FatSecret アカウントに対してはまだ実行していません。

2つの認証レイヤー

このサーバーは Claude と FatSecret の間に位置し、その2つの関係はそれぞれまったく異なる方法で認証されます — コードに触れる前に理解しておくべき主な点です。

Claude  <──①── this server (fatsecret-mcp)  ──②──>  FatSecret API

① Claude ↔ このサーバー — 共有シークレット1つで、fitness-mcp と同じパターンです。Claude は毎回のリクエストで Authorization: Bearer <MCP_BEARER_TOKEN> を送信し、lib/auth.ts がそれをチェックします。Claude の静的ヘッダーオプションはまだベータ限定であるため、このサーバーは独自の最小限の OAuth 2.1 認可サーバー (lib/oauth.ts, /api/oauth/authorize, /api/oauth/token) も実行し、Claude の標準的な OAuth Client ID/Secret フィールドが常に利用可能なフォールバックとして動作するようにしています — 詳細な理由は fitness-mcp の README を参照してください。ここにもそのまま当てはまります。

② このサーバー ↔ FatSecret — ここが fitness-mcp より複雑な点です。FatSecret 自体が API メソッドの種類によって2つの異なる OAuth バージョン を使用しており、これを回避する方法はありません。FatSecret の API がそう設計されているからで、ここでの選択ではありません。

FatSecret メソッドカテゴリ

メソッド例

このサーバーの認証方法

署名付きリクエスト (特定のユーザーは関与しない)

foods.search, food.get, recipes.search, recipe.get, food.find_id_for_barcode

OAuth 2.0 クライアント資格情報lib/fatsecret/appAuth.tsoauth.fatsecret.com からアプリレベルのベアラートークンを取得してキャッシュします。完全に自動で、一度デベロッパー登録をすれば以降は人の操作は不要です。

署名付き&委任リクエスト (あなたの FatSecret アカウントの読み書き)

food_entries.*, food_entry.*, weights.get_month, weight.update, exercise_entries.*, profile.get, foods.get_favorites

OAuth 1.0a、3-legged、HMAC-SHA1 署名 — lib/fatsecret/oauth1.ts。FatSecret はこれらのメソッドで OAuth 2.0 をまったくサポートしていないため、ここで OAuth1 を避ける方法はありません。このため、ブラウザで FatSecret にログインしてこのアプリを承認する、一度だけの対話型認可 (後述の Phase 3) が必要です。取得したアクセストークン/シークレットは、その後は自動的にずっと再利用されます (Phase 3 の注意事項を参照)。

具体的には、search_foods/get_food_detail/search_recipes/get_recipe_detail/find_food_by_barcode は、FatSecret アプリを登録して FATSECRET_CLIENT_ID/FATSECRET_CLIENT_SECRET を設定すればすぐに動作します。他のすべてのツールは、さらに FATSECRET_CONSUMER_KEY/FATSECRET_CONSUMER_SECRET (OAuth1 — 同じ FatSecret アプリの別の資格情報ペア) と FATSECRET_ACCESS_TOKEN/FATSECRET_ACCESS_TOKEN_SECRET (セットアップスクリプトを一度実行して取得) が必要です。

公開ツール

ツール

種別

必要な認証

説明

search_foods

読み取り

OAuth2 (app)

FatSecret の食品データベースを名前で検索

get_food_detail

読み取り

OAuth2 (app)

1つの食品の1食あたりの完全な栄養情報

search_recipes

読み取り

OAuth2 (app)

FatSecret のレシピデータベースを検索

get_recipe_detail

読み取り

OAuth2 (app)

1つのレシピの完全な材料/作り方

find_food_by_barcode

読み取り

OAuth2 (app)

GTIN-13 バーコードを foodId に解決 — barcode スコープが必要で、おそらく Premier 限定

get_food_diary

読み取り

OAuth1 (user)

指定日のフードダイアリーエントリを一覧表示

get_favorite_foods

読み取り

OAuth1 (user)

お気に入りの食品を一覧表示

get_most_eaten_foods

読み取り

OAuth1 (user)

よく食べられている食品を一覧表示 (食事単位で指定可能)

get_recently_eaten_foods

読み取り

OAuth1 (user)

最近食べた食品を一覧表示 (食事単位で指定可能)

get_weight_history

読み取り

OAuth1 (user)

1か月分の体重エントリを一覧表示 — おそらく Premier 限定

get_exercise_diary

読み取り

OAuth1 (user)

指定日の運動エントリを一覧表示

get_profile

読み取り

OAuth1 (user)

ユーザーの FatSecret プロフィール概要を取得

create_food_diary_entry

書き込み

OAuth1 (user)

食品をダイアリーに記録

update_food_diary_entry

書き込み

OAuth1 (user)

既存のダイアリーエントリを更新

delete_food_diary_entry

書き込み

OAuth1 (user)

ダイアリーエントリを削除

update_weight

書き込み

OAuth1 (user)

体重エントリを記録/更新 — おそらく Premier 限定

create_exercise_entry

書き込み

OAuth1 (user)

運動エントリを記録

書き込みツールはデフォルトでドライラン

fitness-mcp と同じ設計です: すべての書き込みツールは confirm: true 引数を必要とします。ツールの説明には、呼び出し側の LLM に対し、書き込まれる内容を正確にユーザーに表示し、最初に明示的な承認を得るよう指示しています。これは構造的な注意喚起であって保証ではありません — ツールを呼び出すかどうかを決定するのと同じ LLM が confirm も設定するため、また認証レイヤーに読み取り/書き込みツールのスコープ分離がないため、有効な MCP_BEARER_TOKEN を持つ呼び出し元はどのツールでも呼び出せます。

未検証の内容

このプロジェクトの開発中には FatSecret API の登録が存在しませんでした (その手順には人間の操作が必要です — 下記のセットアップを参照)。そのため:

  • search_foods/get_food_detail/search_recipes/get_recipe_detail/profile.get/food_entries.get/weights.get_month のメソッド名と主要パラメータは、動作中のサードパーティ製 FatSecret クライアント実装と照合して確認されています (推測ではありません) — 出典は git 履歴を参照してください。

  • food.find_id_for_barcode のレスポンス構造、weight.update のパラメータ名、および exercise_entries.* のすべては、ベストエフォートでの再構成であり、その理由とともに lib/fatsecret/*.ts 内にインラインで明記されています。これらは検証済みの事実ではなく、強力な出発点として扱ってください。

  • 登録後、実際のアカウントで下記の手動検証チェックリストを実行し、見つかったフィールド名の不一致を修正してください (lib/fatsecret/*.test.ts のユニットテストも合わせて更新が必要です)。

セットアップ

  1. FatSecret Platform API アプリを登録してください (https://platform.fatsecret.com/)。次のものが取得できます:

    • OAuth 2.0 Client ID/Secret (FATSECRET_CLIENT_ID/FATSECRET_CLIENT_SECRET 用)。

    • OAuth 1.0 Consumer Key/Secret (FATSECRET_CONSUMER_KEY/FATSECRET_CONSUMER_SECRET 用) — 同じアプリの別のペアで、上記の OAuth2 資格情報とは異なります。

    • プランに含まれるスコープを確認してください (basic / premier / barcode / ...) — weights.get_month/weight.update/find_food_by_barcode は Premier または barcode/premier スコープが必要と報告されています。自分のプランで確認し、必要に応じて FATSECRET_OAUTH2_SCOPE を調整してください。

    • OAuth2 トークンリクエスト用に送信元 IP を許可リストに追加してください — FatSecret はこれを必須としています (最大15のアドレス/レンジ)。Vercel にデプロイする場合、静的送信元 IP (例: Vercel 対応の egress プロキシ/アドオン) が必要です。Vercel のデフォルトのサーバーレス関数には固定 IP がありません。

  2. ローカル開発サーバーを一度実行して検索のスモークテストをします (Phase 2 はステップ1のみで十分です):

    npm install
    cp .env.example .env.local   # fill in FATSECRET_CLIENT_ID/SECRET + the MCP_BEARER_TOKEN/OAuth trio
    vercel dev
  3. 一度だけの 3-legged OAuth1 セットアップを実行します (検索/詳細の5つのツール以外のすべてに必要) — 下記の Phase 3 を参照。

  4. Vercel にデプロイします — 下記の Deploy を参照。

ローカル開発

npm install
cp .env.example .env.local   # fill in real values
vercel dev

スモークテスト ($MCP_BEARER_TOKEN を置き換えてください):

curl -X POST http://localhost:3000/api/mcp \
  -H "Authorization: Bearer $MCP_BEARER_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

上記の17ツールが返るはずです。トークンが欠落している、または誤ったリクエストは 401 になるはずです。

Phase 3: 一度だけの 3-legged OAuth1 セットアップ

search_foods/get_food_detail/search_recipes/get_recipe_detail/find_food_by_barcode 以外のすべてのツールには、あなたの FatSecret アカウントに紐づく OAuth1 アクセストークン/シークレットが必要です。一度取得してください:

npm run fatsecret:oauth-setup

これ (scripts/fatsecret-oauth-setup.ts) は次のことを行います:

  1. FatSecret から未認可のリクエストトークンを要求します。

  2. 認可 URL を表示します — それを開いて FatSecret にログインし、承認してください。FatSecret は確認コードを表示します。

  3. そのコードを貼り付けるよう求め、それを永続的なアクセストークン/シークレットと交換します。

  4. FATSECRET_ACCESS_TOKEN/FATSECRET_ACCESS_TOKEN_SECRET.env.local に書き込みます。

その後、同じ2つの値を Vercel の環境変数にも追加してください (.env.local はデプロイされません) — 下記の Deploy を参照。

FatSecretのドキュメントによると、このアクセストークンは期限切れになりません。万一失効した場合(例: FatSecretのアカウント設定でアプリのアクセスを削除した場合)、スクリプトを再実行して新しいものを取得するだけです。ここでの資格情報の喪失は大災害ではなく、単一コマンドで修正できます。ただし、今回は決定論的な再導出ではなく、対話的なものです。精神としてはfitness-mcpのderive()パターンを参照しています。

記憶に残る1つのパスフレーズからClaude向けシークレットを生成する

MCP_BEARER_TOKENOAUTH_CLIENT_IDOAUTH_CLIENT_SECRET(レイヤー① — Claude ↔ このサーバー間で、上記のFatSecret認証情報とは無関係)は、すべて単一のマスターパスフレーズから決定論的に導出できます。したがって、保存された値を失っても大災害にはなりません — 再導出するだけです:

derive() {
  if [ -z "$MASTER_PASSPHRASE" ]; then
    printf "Master passphrase: "
    read -rs MASTER_PASSPHRASE
    echo
  fi
  echo -n "$1" | openssl dgst -sha256 -hmac "$MASTER_PASSPHRASE" -hex | awk '{print $2}'
}

derive "fatsecret-mcp:bearer-token"        # → MCP_BEARER_TOKEN
derive "fatsecret-mcp:oauth-client-id"     # → OAUTH_CLIENT_ID
derive "fatsecret-mcp:oauth-client-secret" # → OAUTH_CLIENT_SECRET

ラベル文字列はシークレットではありません(このREADMEに保持しても安全です)— パスフレーズだけがシークレットです。同じパスフレーズでderiveを再実行すると、常に同じ値が再現されます。これはFatSecret側の認証情報(FATSECRET_CLIENT_ID/SECRETFATSECRET_CONSUMER_KEY/SECRETFATSECRET_ACCESS_TOKEN/SECRET)には当てはまりません。これらはFatSecretの開発者コンソールとOAuth1セットアップスクリプトから取得され、このパスフレーズから取得されるわけではありません。

テスト

テストは3層あり、すべてのプッシュ/PRでCI(.github/workflows/ci.yml)で実行されます。実際のFatSecretシークレットを必要としないため、公開リポジトリでも同じように動作します:

npm run test        # unit + integration (vitest) — pure logic, plus the real Next.js
                     # route handler exercised with fetch mocked
npm run build
npm run test:e2e     # starts a real `next start` server and hits it over real HTTP
                      # (node's built-in test runner, no extra dependency)
  • ユニットテストlib/**/*.test.ts): ベアラートークン検証、OAuth2.1コード署名/PKCE/リダイレクトURI許可リスト(RFC 7636テストベクターを含む)、FatSecret OAuth2クライアント資格情報トークンの取得/キャッシュ/更新(lib/fatsecret/appAuth.test.ts)、独立した再実装と相互検証したOAuth1 HMAC-SHA1署名(lib/fatsecret/oauth1.test.ts)、およびすべてのlib/fatsecret/*.tsレスポンス形状の正規化(単一オブジェクトと配列、数値文字列と数値、空レスポンスの特殊性)。

  • 統合テストtest/integration/*.test.ts): 実際のapp/api/mcp/route.tsハンドラーを実際のlib/fatsecret/*モジュールに接続し、fetchのみモック化。OAuth2(署名付きリクエスト)とOAuth1(署名・委任)の両方のツールパス、およびすべての書き込みツールの確認ゲートをカバー。実際の/api/oauth/authorize/api/oauth/tokenルート、.well-known OAuthメタデータルートも含む。

  • E2Eテストtest/e2e/*.e2e.test.mjs): 本番ビルドを起動し、実際のHTTP上で検証します — ヘルスチェック、認証不正・欠落時の401、tools/listが17のツールすべてを返すこと、OAuthディスカバリメタデータ、完全な認可コード+PKCEラウンドトリップ。実際のFatSecretデータは使用しません(CIは設計上、実際の認証情報を持ちません)。

実際のFatSecretアカウントで手動検証する

CIは実際のFatSecretデータに一切触れません。また、上記の「未検証の内容」のとおり、このサーバーが想定するFatSecretの正確なレスポンス形状の一部は、実際のアカウントではまったく確認されていません。登録してOAuth1セットアップスクリプトを実行したら、次のチェックリストを実施し、見つけた不一致を修正してください:

  1. 実際のFATSECRET_CLIENT_ID/FATSECRET_CLIENT_SECRET.env.localに設定し、vercel devを実行して、実際のクエリでsearch_foodsを呼び出します(例: 上記のスモークテストのcurlパターンでtools/callを使用)。実際の結果が返り、そのうちの1つでget_food_detailが妥当な栄養数値を返すことを確認します。

  2. 同様にsearch_recipesget_recipe_detailを呼び出します。

  3. プランにbarcodeスコープが含まれる場合は、実際の製品のバーコードでfind_food_by_barcodeを呼び出し、レスポンス形状がlib/fatsecret/foods.tsRawFindIdForBarcodeResponseと一致することを確認します。一致しない場合は修正します。

  4. npm run fatsecret:oauth-setupを実行し、get_profileget_food_diaryを呼び出します。lib/fatsecret/profile.ts/lib/fatsecret/diary.tsのフィールド名が実際のレスポンスと一致することを確認します(これらはドキュメントから再構築したもので、キャプチャしたものではありません)。

  5. confirm: trueと明らかに使い捨てのエントリでcreate_food_diary_entryを呼び出し、同じ日付のget_food_diaryで、食品/分量/量/食事が正しく表示されることを確認します。その後、update_food_diary_entryで更新し、delete_food_diary_entryで削除します — それぞれが往復することを確認します。

  6. プランに体重追跡が含まれる場合は、confirm: trueupdate_weightを呼び出し、get_weight_historyに反映されることを確認します。

  7. create_exercise_entryget_exercise_diaryは、このコードベースで最も検証が進んでいないペアです(lib/fatsecret/exercise.tsの冒頭の警告を参照)。これに依存する前に、https://platform.fatsecret.com/docs/guidesで正確なメソッド名/パラメータを確認してください。検証だけでなく、実際の修正が必要になる可能性があります。

  8. 実際のFatSecret認証情報をコミットせず、このチェックリストをCIで実行しないでください。

環境変数

変数

目的

FATSECRET_CLIENT_ID / FATSECRET_CLIENT_SECRET

OAuth 2.0 クライアント資格情報 — 署名付きリクエストメソッド(検索/詳細ツール)

FATSECRET_OAUTH2_SCOPE

任意。スペース区切りのOAuth2スコープ。デフォルトはbasic。必要に応じてbarcode/premierを追加

FATSECRET_FOOD_GET_METHOD

任意。デフォルトはfood.get.v4。プランにv4アクセスがない場合は(例: food.get)で上書き

FATSECRET_CONSUMER_KEY / FATSECRET_CONSUMER_SECRET

OAuth 1.0 コンシューマーキー/シークレット — 一度きりのセットアップスクリプトとすべての署名付き・委任呼び出しの両方に署名します

FATSECRET_ACCESS_TOKEN / FATSECRET_ACCESS_TOKEN_SECRET

OAuth 1.0 アクセストークン/シークレット(あなたのFatSecretアカウント用) — npm run fatsecret:oauth-setup(フェーズ3)で取得

MCP_BEARER_TOKEN

このサーバーがすべてのリクエストで要求する共有シークレット、およびOAuthフローが発行するaccess_token

OAUTH_CLIENT_ID / OAUTH_CLIENT_SECRET

このサーバー自身の最小限のOAuth認可サーバー用の認証情報

OAUTH_ALLOWED_REDIRECT_HOSTS

任意。/api/oauth/authorizeredirect_uriのカンマ区切り許可リスト。デフォルトはclaude.ai,claude.com

これらはVercelプロジェクトの環境変数(本番+プレビュー)に設定します。実際の値をコミットしないでください — .env.exampleは名前を文書化しているだけです。

デプロイ

  1. vercel link

  2. vercel env add FATSECRET_CLIENT_ID(上記の表の変数のうち値を持つものすべてについて繰り返します — 最低限FATSECRET_CLIENT_ID/SECRETMCP_BEARER_TOKENOAUTH_CLIENT_ID/SECRET。OAuth1セットアップスクリプトを実行したら、FATSECRET_CONSUMER_*/FATSECRET_ACCESS_TOKEN*のペアも追加します)

  3. VercelダッシュボードでこのGitHubリポジトリを接続してmainへのプッシュで自動デプロイするか、手動でvercel --prodを実行します。

  4. デプロイしたURLを確認します(Vercelの共有名前空間ではfatsecret-mcp.vercel.appがすでに使用されている可能性があるため、プロジェクト → 設定 → ドメインを確認してください)。

  5. OAuth2トークンリクエストのために、FatSecret開発者コンソールでそのデプロイの送信元IPを許可リストに登録します(セットアップ手順1を参照)— Vercelのサーバーレス関数はデフォルトでは固定IPを持たないため、本番環境で最も問題になりやすい手順です。

Claudeに接続する

カスタムコネクタは、claude.ai(Web)またはデスクトップアプリから追加することしかできません — モバイルアプリからはできません。そこで追加すると、モバイルから自動的に使用できます。

  1. claude.aiで: 設定 → コネクタ → カスタムコネクタを追加。

  2. 名前: FatSecret。URL: https://<your-deployment>/api/mcp

  3. アカウントに「Request headers」ベータ版がある場合: そこにAuthorization: Bearer <MCP_BEARER_TOKEN>を追加し、手順5に進みます。

  4. それ以外の場合は、詳細設定を開き、OAuth Client ID / OAuth Client Secretに、Vercelで設定したOAUTH_CLIENT_ID / OAUTH_CLIENT_SECRETの値を入力します。Claudeは、このサーバーの.well-knownメタデータを介して/authorizeおよび/tokenエンドポイントを自動的に検出します。

  5. 保存します。Claudeに上記の17のツールが表示されるはずです。

次のように試してください: 「バナナのカロリーを教えて」(バナナのカロリーを教えてください)、または「今日の朝食にバナナを1本記録して」(今日の朝食にバナナを1本記録する — Phase 3/4がセットアップされ、検証されたら)。

謝辞

3-legged OAuth1フローの設計は、fcoury/fatsecret-mcp(MIT)に基づいています。これはOAuthフロー自体をMCPツールとして公開するものです。このプロジェクトは、マルチユーザー利用ではなく単一の個人用FatSecretアカウント向けに構築されているため、代わりにスタンドアロンのセットアップスクリプト(scripts/fatsecret-oauth-setup.ts)として一度だけ実行します。ここからコードはコピーされていません。

-
license - not tested
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • Personal assistant MCP server with search, execute, packages, jobs, secrets, and integrations.

  • MCP server for Withings health data — sleep, activity, heart, and body metrics.

  • GibsonAI MCP server: manage your databases with natural language

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ikeike443/fatsecret-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server