Skip to main content
Glama
ikeike443
by ikeike443

fatsecret-mcp

CI

Персональный удалённый MCP-сервер (Model Context Protocol), который позволяет Claude искать в базе продуктов/рецептов FatSecret и читать/записывать ваш дневник питания, вес и журнал упражнений прямо в диалоге. Развёрнут на бесплатном тарифном плане Vercel Hobby. Родственный проект для fitness-mcp (Hevy) — один MCP-сервер на продукт, использующий тот же шаблон аутентификации.

Лицензия

MIT

Статус

  • Поиск (этап 2): реализован — search_foods, get_food_detail, search_recipes, get_recipe_detail, find_food_by_barcode. Авторизация пользователя FatSecret не требуется; нужны только OAuth 2.0 Client ID/Secret из консоли разработчика FatSecret.

  • Дневник/вес/упражнения/профиль (этап 4): реализовано, но не проверено на реальном аккаунте FatSecret — на момент создания проекта регистрации в FatSecret API не существовало (см. «Что не проверено» ниже). Прежде чем полагаться на метод, сверьте точные имена полей с реальным аккаунтом и обновите код/тесты, если что-то не совпадает.

  • Скрипт настройки трёхстороннего OAuth1 (этап 3): реализован (scripts/fatsecret-oauth-setup.ts), но ещё не запускался с реальным аккаунтом FatSecret.

Два уровня аутентификации

Этот сервер находится между Claude и FatSecret, и каждая из этих двух связей аутентифицируется совершенно по-разному — это главное, что нужно понять, прежде чем касаться кода.

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

① Claude ↔ этот сервер — один общий секрет, тот же шаблон, что и в fitness-mcp. Claude отправляет Authorization: Bearer <MCP_BEARER_TOKEN> в каждом запросе; lib/auth.ts проверяет его. Поскольку опция статического заголовка у Claude всё ещё ограничена бета-доступом, этот сервер также запускает собственный минимальный сервер авторизации OAuth 2.1 (lib/oauth.ts, /api/oauth/authorize, /api/oauth/token), чтобы стандартные поля OAuth Client ID/Secret от Claude работали как постоянно доступный запасной вариант — полное обоснование см. в README fitness-mcp, здесь оно применимо без изменений.

② этот сервер ↔ FatSecret — вот здесь всё сложнее, чем в fitness-mcp, потому что сам FatSecret использует две разные версии OAuth для двух разных типов методов API, и это никак не обойти — так спроектирован API FatSecret, а не наш выбор:

Категория методов FatSecret

Примеры методов

Как этот сервер аутентифицируется

Подписанный запрос (без участия конкретного пользователя)

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

OAuth 2.0 Client Credentialslib/fatsecret/appAuth.ts получает и кэширует токен уровня приложения (app-level bearer token) с oauth.fatsecret.com. Полностью автоматически; после разовой регистрации разработчика участие человека не требуется.

Подписанный и делегированный запрос (чтение/запись вашего аккаунта FatSecret)

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

OAuth 1.0a, трёхсторонний, с подписью HMAC-SHA1 — lib/fatsecret/oauth1.ts. FatSecret вообще не поддерживает OAuth 2.0 для этих методов, поэтому OAuth1 здесь не избежать. Требуется одноразовая интерактивная авторизация (этап 3 ниже): вы входите в FatSecret в браузере и одобряете приложение; полученные access token/secret затем автоматически переиспользуются бессрочно (см. оговорку в разделе «Этап 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 (приложение)

Искать по названию в базе продуктов FatSecret

get_food_detail

чтение

OAuth2 (приложение)

Полная информация о питательности на порцию для одного продукта

search_recipes

чтение

OAuth2 (приложение)

Искать в базе рецептов FatSecret

get_recipe_detail

чтение

OAuth2 (приложение)

Полный состав ингредиентов/инструкций для одного рецепта

find_food_by_barcode

чтение

OAuth2 (приложение)

Сопоставить GTIN-13 штрихкод с foodId — требуется scope barcode, возможно только для Premier

get_food_diary

чтение

OAuth1 (пользователь)

Список записей дневника питания за дату

get_favorite_foods

чтение

OAuth1 (пользователь)

Список избранных продуктов

get_most_eaten_foods

чтение

OAuth1 (пользователь)

Список наиболее часто употребляемых продуктов, опционально по приёму пищи

get_recently_eaten_foods

чтение

OAuth1 (пользователь)

Список недавно съеденных продуктов, опционально по приёму пищи

get_weight_history

чтение

OAuth1 (пользователь)

Список записей веса за месяц — возможно, только для Premier

get_exercise_diary

чтение

OAuth1 (пользователь)

Список записей упражнений за дату

get_profile

чтение

OAuth1 (пользователь)

Получить сводку профиля пользователя FatSecret

create_food_diary_entry

запись

OAuth1 (пользователь)

Добавить продукт в дневник

update_food_diary_entry

запись

OAuth1 (пользователь)

Обновить существующую запись в дневнике

delete_food_diary_entry

запись

OAuth1 (пользователь)

Удалить запись из дневника

update_weight

запись

OAuth1 (пользователь)

Добавить/обновить запись веса — возможно, только для Premier

create_exercise_entry

запись

OAuth1 (пользователь)

Добавить запись об упражнении

Инструменты записи по умолчанию работают в режиме dry-run

Та же архитектура, что и в 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.

    • Проверьте, какие области (scopes) включает ваш тариф (basic / premier / barcode / ...) — сообщается, что weights.get_month/weight.update/find_food_by_barcode требуют Premier или областей barcode/premier; сверьте со своим тарифом и при необходимости измените FATSECRET_OAUTH2_SCOPE.

    • Внесите свои исходящие IP-адреса в белый список для запросов токенов OAuth2 — FatSecret требует этого (до 15 адресов/диапазонов). При развёртывании на Vercel нужен статический исходящий IP (например, через поддерживаемый Vercel исходящий прокси/дополнение); в стандартных бессерверных функциях Vercel фиксированного IP нет.

  2. Один раз запустите локальный dev-сервер, чтобы прогнать смоук-тест поиска (для этапа 2 нужен только шаг 1):

    npm install
    cp .env.example .env.local   # fill in FATSECRET_CLIENT_ID/SECRET + the MCP_BEARER_TOKEN/OAuth trio
    vercel dev
  3. Выполните одноразовую настройку трёхстороннего OAuth1 (нужна для всех инструментов, кроме 5 поисковых/детальных) — см. этап 3 ниже.

  4. Разверните на Vercel — см. «Развёртывание» ниже.

Локальная разработка

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.

Этап 3: одноразовая настройка трёхстороннего OAuth1

Каждому инструменту, кроме search_foods/get_food_detail/search_recipes/get_recipe_detail/find_food_by_barcode, нужны access token/secret OAuth1, привязанные к вашему аккаунту FatSecret. Получите их один раз:

npm run fatsecret:oauth-setup

Скрипт (scripts/fatsecret-oauth-setup.ts) сделает следующее:

  1. Запросит неавторизованный временный токен (request token) у FatSecret.

  2. Выведет URL авторизации — откройте его, войдите в FatSecret и одобрите. FatSecret покажет код подтверждения.

  3. Запросит ввод этого кода, после чего обменяет его на постоянные access token/secret.

  4. Запишет FATSECRET_ACCESS_TOKEN/FATSECRET_ACCESS_TOKEN_SECRET в .env.local.

Затем добавьте эти же два значения в переменные окружения Vercel (.env.local никогда не разворачивается) — см. «Развёрты

Согласно документации FatSecret, этот токен доступа не истекает. Если он когда-либо будет отозван (например, вы удалите доступ приложения в настройках учётной записи FatSecret), просто повторно запустите скрипт, чтобы получить новый, — как и в случае с паттерном derive() из fitness-mcp: потеря учётных данных здесь не катастрофа, а исправление одной командой, просто на этот раз интерактивной, а не детерминированным повторным выводом.

Генерация секретов для Claude из одной запоминающейся парольной фразы

MCP_BEARER_TOKEN, OAUTH_CLIENT_ID и OAUTH_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/SECRET, FATSECRET_CONSUMER_KEY/SECRET, FATSECRET_ACCESS_TOKEN/SECRET) — они берутся из консоли разработчика FatSecret и скрипта настройки OAuth1, а не из этой парольной фразы.

Тестирование

Три уровня, все выполняются в CI (.github/workflows/ci.yml) при каждом push/PR — ни одному из них не нужны настоящие секреты 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): проверка bearer-токена, подпись кода OAuth2.1/PKCE/разрешение redirect-URI (включая тестовый вектор RFC 7636), получение/кэширование/обновление токена FatSecret OAuth2 Client Credentials (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 (Signed Request) и OAuth1 (Signed & Delegated), а также требование подтверждения для каждого записывающего инструмента; реальные маршруты /api/oauth/authorize и /api/oauth/token; маршруты метаданных OAuth .well-known.

  • E2E (test/e2e/*.e2e.test.mjs): запускает production-сборку и выполняет проверки по реальному HTTP — health check, 401 при неверной или отсутствующей авторизации, tools/list возвращает все 17 инструментов, метаданные обнаружения OAuth и полный цикл authorization-code + PKCE. Не задействует реальные данные FatSecret (в CI намеренно нет настоящих учётных данных).

Ручная проверка с реальной учётной записью FatSecret

CI никогда не обращается к реальным данным FatSecret, и, согласно разделу «Что не проверено» выше, некоторые предположения этого сервера о точной форме ответов FatSecret вообще не проверялись на реальном аккаунте. После регистрации и запуска скрипта настройки OAuth1 пройдитесь по этому чек-листу и исправьте все найденные расхождения:

  1. Укажите реальные FATSECRET_CLIENT_ID/FATSECRET_CLIENT_SECRET в .env.local, запустите vercel dev и вызовите search_foods с реальным запросом (например, через описанный выше smoke-test с curl, используя tools/call) — убедитесь, что возвращаются реальные результаты, а get_food_detail по одному из них возвращает адекватные данные о питании.

  2. Вызовите search_recipes и get_recipe_detail аналогично.

  3. Если ваш тариф включает область доступа barcode, вызовите find_food_by_barcode со штрихкодом реального продукта и убедитесь, что форма ответа соответствует RawFindIdForBarcodeResponse из lib/fatsecret/foods.ts — если нет, исправьте.

  4. Запустите npm run fatsecret:oauth-setup, затем вызовите get_profile и get_food_diary — убедитесь, что имена полей в lib/fatsecret/profile.ts/lib/fatsecret/diary.ts соответствуют реальному ответу (они были восстановлены по документации, а не перехвачены из реальных данных).

  5. Вызовите create_food_diary_entry с confirm: true и заведомо тестовой записью, затем get_food_diary за ту же дату и убедитесь, что запись появляется с правильными продуктом/порцией/количеством/приёмом пищи. Затем обновите её через update_food_diary_entry и удалите через delete_food_diary_entry — убедитесь, что каждая операция проходит полный цикл.

  6. Если ваш тариф включает отслеживание веса, вызовите update_weight с confirm: true и убедитесь, что get_weight_history отражает это.

  7. create_exercise_entry и get_exercise_diary — наименее проверенная пара в этой кодовой базе (см. предупреждение в начале lib/fatsecret/exercise.ts) — сверьте точное имя метода и параметры с https://platform.fatsecret.com/docs/guides, прежде чем полагаться на этот функционал; возможно, потребуются реальные исправления, а не только проверка.

  8. Никогда не коммитьте реальные учётные данные FatSecret и никогда не запускайте этот чек-лист в CI.

Переменные окружения

Переменная

Назначение

FATSECRET_CLIENT_ID / FATSECRET_CLIENT_SECRET

OAuth 2.0 Client Credentials — методы Signed Request (инструменты поиска/детализации)

FATSECRET_OAUTH2_SCOPE

Необязательно. OAuth2 scope(s), разделённые пробелами, по умолчанию basic. Добавьте barcode/premier при необходимости

FATSECRET_FOOD_GET_METHOD

Необязательно. По умолчанию food.get.v4; измените (например, food.get), если ваш тариф не включает доступ к v4

FATSECRET_CONSUMER_KEY / FATSECRET_CONSUMER_SECRET

OAuth 1.0 Consumer Key/Secret — подписывает и одноразовый скрипт настройки, и каждый вызов Signed & Delegated

FATSECRET_ACCESS_TOKEN / FATSECRET_ACCESS_TOKEN_SECRET

OAuth 1.0 токен доступа/секрет для вашей учётной записи FatSecret — получен через npm run fatsecret:oauth-setup (этап 3)

MCP_BEARER_TOKEN

Общий секрет, который этот сервер требует при каждом запросе, и access_token, который выдаёт наш OAuth-поток

OAUTH_CLIENT_ID / OAUTH_CLIENT_SECRET

Учётные данные для собственного минимального OAuth-сервера авторизации этого сервера

OAUTH_ALLOWED_REDIRECT_HOSTS

Необязательно. Разрешённые хосты через запятую для redirect_uri из /api/oauth/authorize. По умолчанию claude.ai,claude.com

Развёртывание

  1. vercel link

  2. vercel env add FATSECRET_CLIENT_ID (повторите для каждой переменной из таблицы выше, для которой у вас есть значение — как минимум FATSECRET_CLIENT_ID/SECRET, MCP_BEARER_TOKEN, OAUTH_CLIENT_ID/SECRET; добавьте пару FATSECRET_CONSUMER_*/FATSECRET_ACCESS_TOKEN*, как только запустите скрипт настройки OAuth1)

  3. Подключите этот GitHub-репозиторий в панели Vercel для автоматического развёртывания при пуше в main или запустите vercel --prod вручную.

  4. Запомните URL развёртывания (проверьте Project → Settings → Domains, поскольку fatsecret-mcp.vercel.app может быть уже занят в общем пространстве имён Vercel).

  5. Добавьте исходящий IP этого развёртывания в список разрешённых в консоли разработчика FatSecret для запросов токена OAuth2 (см. шаг 1 раздела «Настройка») — это шаг, который с наибольшей вероятностью станет проблемой в продакшене, поскольку серверless-функции Vercel по умолчанию не имеют фиксированного IP.

Подключение к Claude

Пользовательские коннекторы можно только добавить через claude.ai (веб) или настольное приложение — не через мобильное приложение. После добавления они автоматически доступны на мобильных устройствах.

  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 значениями OAUTH_CLIENT_ID / OAUTH_CLIENT_SECRET, заданными в Vercel. Claude автоматически обнаружит конечные точки /authorize и /token через метаданные .well-known этого сервера.

  5. Сохраните. Claude должен показать перечисленные выше 17 инструментов.

Попробуйте спросить: «バナナのカロリーを教えて» (скажи, сколько калорий в банане) или «今日の朝食にバナナを1本記録して» (запиши один банан на завтрак сегодня — после настройки и проверки этапов 3/4).

Благодарности

Дизайн трёхстороннего OAuth1-потока основывался на fcoury/fatsecret-mcp (MIT), который предоставляет OAuth-поток в виде самих MCP-инструментов; этот проект вместо этого запускает его один раз как отдельный скрипт настройки (scripts/fatsecret-oauth-setup.ts), поскольку он предназначен для одной личной учётной записи FatSecret, а не для

-
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