fatsecret-mcp
fatsecret-mcp
Персональный удалённый MCP-сервер (Model Context Protocol), который позволяет Claude искать в базе продуктов/рецептов FatSecret и читать/записывать ваш дневник питания, вес и журнал упражнений прямо в диалоге. Развёрнут на бесплатном тарифном плане Vercel Hobby. Родственный проект для fitness-mcp (Hevy) — один MCP-сервер на продукт, использующий тот же шаблон аутентификации.
Лицензия
Статус
Поиск (этап 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 | Примеры методов | Как этот сервер аутентифицируется |
Подписанный запрос (без участия конкретного пользователя) |
| OAuth 2.0 Client Credentials — |
Подписанный и делегированный запрос (чтение/запись вашего аккаунта FatSecret) |
| OAuth 1.0a, трёхсторонний, с подписью HMAC-SHA1 — |
Если конкретно: 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 (получаются однократным запуском скрипта настройки).
Доступные инструменты
Инструмент | Тип | Требуемая аутентификация | Описание |
| чтение | OAuth2 (приложение) | Искать по названию в базе продуктов FatSecret |
| чтение | OAuth2 (приложение) | Полная информация о питательности на порцию для одного продукта |
| чтение | OAuth2 (приложение) | Искать в базе рецептов FatSecret |
| чтение | OAuth2 (приложение) | Полный состав ингредиентов/инструкций для одного рецепта |
| чтение | OAuth2 (приложение) | Сопоставить GTIN-13 штрихкод с foodId — требуется scope |
| чтение | OAuth1 (пользователь) | Список записей дневника питания за дату |
| чтение | OAuth1 (пользователь) | Список избранных продуктов |
| чтение | OAuth1 (пользователь) | Список наиболее часто употребляемых продуктов, опционально по приёму пищи |
| чтение | OAuth1 (пользователь) | Список недавно съеденных продуктов, опционально по приёму пищи |
| чтение | OAuth1 (пользователь) | Список записей веса за месяц — возможно, только для Premier |
| чтение | OAuth1 (пользователь) | Список записей упражнений за дату |
| чтение | OAuth1 (пользователь) | Получить сводку профиля пользователя FatSecret |
| запись | OAuth1 (пользователь) | Добавить продукт в дневник |
| запись | OAuth1 (пользователь) | Обновить существующую запись в дневнике |
| запись | OAuth1 (пользователь) | Удалить запись из дневника |
| запись | OAuth1 (пользователь) | Добавить/обновить запись веса — возможно, только для Premier |
| запись | 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).
Настройка
Зарегистрируйте приложение 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 нет.
Один раз запустите локальный dev-сервер, чтобы прогнать смоук-тест поиска (для этапа 2 нужен только шаг 1):
npm install cp .env.example .env.local # fill in FATSECRET_CLIENT_ID/SECRET + the MCP_BEARER_TOKEN/OAuth trio vercel devВыполните одноразовую настройку трёхстороннего OAuth1 (нужна для всех инструментов, кроме 5 поисковых/детальных) — см. этап 3 ниже.
Разверните на 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) сделает следующее:
Запросит неавторизованный временный токен (request token) у FatSecret.
Выведет URL авторизации — откройте его, войдите в FatSecret и одобрите. FatSecret покажет код подтверждения.
Запросит ввод этого кода, после чего обменяет его на постоянные access token/secret.
Запишет
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 пройдитесь по этому чек-листу и исправьте все найденные расхождения:
Укажите реальные
FATSECRET_CLIENT_ID/FATSECRET_CLIENT_SECRETв.env.local, запуститеvercel devи вызовитеsearch_foodsс реальным запросом (например, через описанный выше smoke-test сcurl, используяtools/call) — убедитесь, что возвращаются реальные результаты, аget_food_detailпо одному из них возвращает адекватные данные о питании.Вызовите
search_recipesиget_recipe_detailаналогично.Если ваш тариф включает область доступа
barcode, вызовитеfind_food_by_barcodeсо штрихкодом реального продукта и убедитесь, что форма ответа соответствуетRawFindIdForBarcodeResponseизlib/fatsecret/foods.ts— если нет, исправьте.Запустите
npm run fatsecret:oauth-setup, затем вызовитеget_profileиget_food_diary— убедитесь, что имена полей вlib/fatsecret/profile.ts/lib/fatsecret/diary.tsсоответствуют реальному ответу (они были восстановлены по документации, а не перехвачены из реальных данных).Вызовите
create_food_diary_entryсconfirm: trueи заведомо тестовой записью, затемget_food_diaryза ту же дату и убедитесь, что запись появляется с правильными продуктом/порцией/количеством/приёмом пищи. Затем обновите её черезupdate_food_diary_entryи удалите черезdelete_food_diary_entry— убедитесь, что каждая операция проходит полный цикл.Если ваш тариф включает отслеживание веса, вызовите
update_weightсconfirm: trueи убедитесь, чтоget_weight_historyотражает это.create_exercise_entryиget_exercise_diary— наименее проверенная пара в этой кодовой базе (см. предупреждение в началеlib/fatsecret/exercise.ts) — сверьте точное имя метода и параметры с https://platform.fatsecret.com/docs/guides, прежде чем полагаться на этот функционал; возможно, потребуются реальные исправления, а не только проверка.Никогда не коммитьте реальные учётные данные FatSecret и никогда не запускайте этот чек-лист в CI.
Переменные окружения
Переменная | Назначение |
| OAuth 2.0 Client Credentials — методы Signed Request (инструменты поиска/детализации) |
| Необязательно. OAuth2 scope(s), разделённые пробелами, по умолчанию |
| Необязательно. По умолчанию |
| OAuth 1.0 Consumer Key/Secret — подписывает и одноразовый скрипт настройки, и каждый вызов Signed & Delegated |
| OAuth 1.0 токен доступа/секрет для вашей учётной записи FatSecret — получен через |
| Общий секрет, который этот сервер требует при каждом запросе, и access_token, который выдаёт наш OAuth-поток |
| Учётные данные для собственного минимального OAuth-сервера авторизации этого сервера |
| Необязательно. Разрешённые хосты через запятую для |
Развёртывание
vercel linkvercel env add FATSECRET_CLIENT_ID(повторите для каждой переменной из таблицы выше, для которой у вас есть значение — как минимумFATSECRET_CLIENT_ID/SECRET,MCP_BEARER_TOKEN,OAUTH_CLIENT_ID/SECRET; добавьте паруFATSECRET_CONSUMER_*/FATSECRET_ACCESS_TOKEN*, как только запустите скрипт настройки OAuth1)Подключите этот GitHub-репозиторий в панели Vercel для автоматического развёртывания при пуше в
mainили запуститеvercel --prodвручную.Запомните URL развёртывания (проверьте Project → Settings → Domains, поскольку
fatsecret-mcp.vercel.appможет быть уже занят в общем пространстве имён Vercel).Добавьте исходящий IP этого развёртывания в список разрешённых в консоли разработчика FatSecret для запросов токена OAuth2 (см. шаг 1 раздела «Настройка») — это шаг, который с наибольшей вероятностью станет проблемой в продакшене, поскольку серверless-функции Vercel по умолчанию не имеют фиксированного IP.
Подключение к Claude
Пользовательские коннекторы можно только добавить через claude.ai (веб) или настольное приложение — не через мобильное приложение. После добавления они автоматически доступны на мобильных устройствах.
На claude.ai: Настройки → Коннекторы → Добавить пользовательский коннектор.
Название:
FatSecret. URL:https://<your-deployment>/api/mcp.Если в вашей учётной записи доступна бета-версия «Request headers»: добавьте туда
Authorization: Bearer <MCP_BEARER_TOKEN>и перейдите к шагу 5.В противном случае откройте расширенные настройки и заполните OAuth Client ID / OAuth Client Secret значениями
OAUTH_CLIENT_ID/OAUTH_CLIENT_SECRET, заданными в Vercel. Claude автоматически обнаружит конечные точки/authorizeи/tokenчерез метаданные.well-knownэтого сервера.Сохраните. Claude должен показать перечисленные выше 17 инструментов.
Попробуйте спросить: «バナナのカロリーを教えて» (скажи, сколько калорий в банане) или «今日の朝食にバナナを1本記録して» (запиши один банан на завтрак сегодня — после настройки и проверки этапов 3/4).
Благодарности
Дизайн трёхстороннего OAuth1-потока основывался на fcoury/fatsecret-mcp (MIT), который предоставляет OAuth-поток в виде самих MCP-инструментов; этот проект вместо этого запускает его один раз как отдельный скрипт настройки (scripts/fatsecret-oauth-setup.ts), поскольку он предназначен для одной личной учётной записи FatSecret, а не для
This server cannot be installed
Maintenance
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
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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