Skip to main content
Glama
a1dancole

MyFitnessPal MCP

by a1dancole

MyFitnessPal MCP — nutrition data for your Claude training coach

A remote MCP server, deployed on Cloudflare Workers, that exposes your MyFitnessPal diary — every food with portion and time, per-meal and daily totals for energy, macros and micros, water, logged exercise, steps and weight — to Claude. Add it once as a custom connector and it works on Claude web, desktop, and mobile. Pairs with the Strava, Google Health and Renpho connectors so your coach sees training load, recovery, body composition and fuelling.

How it talks to MFP: MyFitnessPal has no public API (the partner programme is closed). This server uses the mobile app's own OAuth identity flow and the same api.myfitnesspal.com/v2 API the app uses — the one the archived partner docs at myfitnesspalapi.com describe. No browser, no cookies, no scraping, no captcha. Credit for the identity flow: seonixx/myfitnesspal and jnelle/MyFitnesspal-API-Golang. Unofficial; MFP can change it at any time.

Tools

Tool

What it answers

get_daily_nutrition

"What did I eat today?" — per-meal and day totals (energy, protein, carbs, net carbs, fibre, sugar, fat subtypes, cholesterol, sodium, potassium, %DV micros), every food with portion and timestamp, water, exercise, steps, weight entries

get_food_log

Individual food entries over a range, filterable by meal or a text search — what was eaten around sessions, recurring foods

get_nutrition_trend

Daily totals over a window with means over logged days, min/max energy, protein/carb/fat energy split, weekly averages, water/exercise/steps

get_exercise_log

MFP-logged exercise (duration, calories, distance, HR) and daily steps

get_weight_log

Weight entries recorded in MFP

get_profile

Name, sex, birthdate/age, height, locale + token status

run_diagnostics

End-to-end probe: token refresh, profile, which diary types/fields the account accepts (with raw samples), measurements, candidate goal endpoints

query_endpoint

Escape hatch: call any api.myfitnesspal.com / identity endpoint with the connector's auth applied

refresh_data

Drop cached days + remembered request shape, refresh the token

delete_my_data

Delete everything cached for your account

Troubleshooting: if a tool errors or data looks missing, run run_diagnostics first. It reports the exact types/fields[] combination MFP accepts for your account and a raw sample per item type.


Related MCP server: MyFitnessPal MCP Server

How it works

Claude (web/desktop/mobile)
  └─ custom connector → /mcp
       └─ workers-oauth-provider  (this Worker IS Claude's OAuth server)
            └─ AuthHandler        (MFP sign-in page: one-time credential → token exchange)
                 └─ MyFitnessPalMCP (Durable Object) → MfpClient → api.myfitnesspal.com/v2

Sign-in (once, on the connector's /authorize page)

  1. POST identity-api.myfitnesspal.com/oauth/token — client-credentials token for the mobile app's OAuth client.

  2. GET identity-api…/clientKeys — the HS512 signing key MFP uses for password sign-ins.

  3. POST identity-api…/oauth/authorize with credentials=<JWT{username, password}> — returns a redirect to mfp://identity/callback?code=….

  4. POST …/oauth/token (authorization_code) — access + refresh + id tokens.

  5. GET identity-api…/users/{sub} — the MFP domain user id (mfp-user-id header) and profile.

Only the refresh token (and the first access token) is kept, encrypted inside the OAuth grant's props; the password is never stored. Thereafter the Worker refreshes silently; the newest rotated refresh token lives sealed in KV.

Reading the diary

GET api.myfitnesspal.com/v2/diary?entry_date=YYYY-MM-DD&types=…&fields[]=… with Authorization: Bearer, mfp-user-id, mfp-client-id and the app's api-version/user-agent headers. Item types: food_entry, diary_meal, exercise_entry, water, steps_aggregate. Pagination follows the Link: rel=next header.

The exact types/fields[] the mobile token accepts aren't documented, so the client discovers them: it tries the richest request, then a smaller field set, then no fields, then one type at a time — and remembers the winning combination for a day. Anything rejected is reported on the tool result. Completed days are immutable and cached (sealed) for 30 days; today is always live. Each day is one upstream call, so windows are capped at 92 days.

Field mapping

nutritional_contents → unit-suffixed keys: energy_kcal (kJ converted), protein_g, carbohydrates_g, net_carbs_g, fiber_g, sugar_g, fat_g, saturated_fat_g, monounsaturated_fat_g, polyunsaturated_fat_g, trans_fat_g, cholesterol_mg, sodium_mg, potassium_mg, and calcium/iron/vitamin_a/vitamin_c/vitamin_d_pct_dv (MFP stores those as percent of daily value). Unknown nutrients are kept under extra.

Day totals come from MFP's own diary_meal summaries when present (totals_source: "diary_meal"), otherwise from summing food_entry rows.

Caching & encryption

Everything written to the MFP_CACHE KV namespace — tokens, the discovered request shape, diary days — is AES-256-GCM sealed with a key derived from SESSION_ENCRYPTION_KEY, keyed per user. Without the secret, caching is disabled. Cache failures never break a request.


Where the client credentials come from

The identity flow needs the OAuth client id/secret embedded in the MyFitnessPal Android app. They are not reproduced here; the Go client linked above ships them in its .env.sample. Set them as Worker secrets MFP_CLIENT_ID and MFP_CLIENT_SECRET. If MFP rotates them, sign-in stops working until they are updated.

Deploy

Option A — GitHub Actions

.github/workflows/deploy.yml deploys on every push to master. Secrets live in Cloudflare; GitHub only holds CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID.

  1. Create two KV namespaces (MFP_OAUTH_KV, MFP_CACHE) and put their ids in wrangler.jsonc.

  2. Add the two GitHub secrets and push.

  3. In Cloudflare (Workers & Pages → myfitnesspal-mcp → Settings → Variables and Secrets) add secrets SESSION_ENCRYPTION_KEY (any long random string), MFP_CLIENT_ID, MFP_CLIENT_SECRET. Optionally set the ALLOWED_EMAILS variable to your MFP email so nobody else can connect to your deployment.

Option B — local wrangler

npm install
npx wrangler kv namespace create MFP_OAUTH_KV   # paste the id into wrangler.jsonc
npx wrangler kv namespace create MFP_CACHE      # paste the id into wrangler.jsonc
npx wrangler secret put SESSION_ENCRYPTION_KEY
npx wrangler secret put MFP_CLIENT_ID
npx wrangler secret put MFP_CLIENT_SECRET
npx wrangler deploy

Connect in Claude

  1. Settings → Connectors → Add custom connector.

  2. URL: https://myfitnesspal-mcp.<subdomain>.workers.dev/mcp

  3. Click Connect → sign in with your MyFitnessPal email/username and password → done.

Then: "Run diagnostics on MyFitnessPal, then show me yesterday's nutrition."

Connector icon

The Worker advertises PUBLIC_URL/icon.png in its MCP serverInfo.icons (and websiteUrl), so clients that render server branding show it in the connector list. The default is a generated plate-and-cutlery icon (npm run icon). To use the official MyFitnessPal app icon instead, save the PNG from the App Store / Play Store listing and embed it:

npm run icon:embed -- ~/Downloads/myfitnesspal-icon.png   # writes src/icon.ts + assets/icon.png
npm run deploy

(The official mark is MyFitnessPal's trademark — fine for a personal deployment, not for redistribution, which is why it isn't in this repo.)

Local development

cp .dev.vars.example .dev.vars   # set the secrets
npm run dev                      # http://localhost:8787
npm test                         # vitest (fake identity + API backend)
npm run typecheck
npm run icon

Notes & limits

  • Unofficial. The app's private client is used with your own credentials for personal use; MFP may rotate the client or change the API.

  • Health Connect already syncs MFP meal summaries to Google Health; what this adds is the per-food log with timestamps, micros, water, MFP exercise and weight.

  • Nutrient goals have no confirmed endpoint yet — run_diagnostics sweeps candidates and query_endpoint can explore.

  • Subrequest limits. Every diary day is one upstream call; on the Workers free plan (50 subrequests/request) keep uncached windows short. Cached days are cheap.

  • Password changes invalidate the refresh token — disconnect and reconnect the connector.

Privacy

  • Your password is exchanged once for tokens and never stored; the refresh token lives encrypted inside the OAuth grant.

  • Diary data is cached only in your own KV namespace, sealed, and deletable with delete_my_data; nothing is sent to any third party.

License

MIT

A
license - permissive license
Not graded
quality - not tested
B
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 Servers

View all related MCP servers

Related MCP Connectors

  • Garmin data in Claude & ChatGPT via the Garmin Health API. OAuth sign-in, no password sharing.

  • WHOOP recovery, strain, sleep and workouts in Claude via official WHOOP OAuth. Free, open source.

  • Connect Claude to Fathom meeting recordings, transcripts, and summaries

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/a1dancole/myfitnesspal-mcp'

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