MyFitnessPal MCP
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@MyFitnessPal MCPWhat were my macros for today?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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/v2API 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 |
| "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 |
| Individual food entries over a range, filterable by meal or a text search — what was eaten around sessions, recurring foods |
| Daily totals over a window with means over logged days, min/max energy, protein/carb/fat energy split, weekly averages, water/exercise/steps |
| MFP-logged exercise (duration, calories, distance, HR) and daily steps |
| Weight entries recorded in MFP |
| Name, sex, birthdate/age, height, locale + token status |
| End-to-end probe: token refresh, profile, which diary types/fields the account accepts (with raw samples), measurements, candidate goal endpoints |
| Escape hatch: call any |
| Drop cached days + remembered request shape, refresh the token |
| Delete everything cached for your account |
Troubleshooting: if a tool errors or data looks missing, run
run_diagnosticsfirst. It reports the exacttypes/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/v2Sign-in (once, on the connector's /authorize page)
POST identity-api.myfitnesspal.com/oauth/token— client-credentials token for the mobile app's OAuth client.GET identity-api…/clientKeys— the HS512 signing key MFP uses for password sign-ins.POST identity-api…/oauth/authorizewithcredentials=<JWT{username, password}>— returns a redirect tomfp://identity/callback?code=….POST …/oauth/token(authorization_code) — access + refresh + id tokens.GET identity-api…/users/{sub}— the MFP domain user id (mfp-user-idheader) 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.
Create two KV namespaces (
MFP_OAUTH_KV,MFP_CACHE) and put their ids inwrangler.jsonc.Add the two GitHub secrets and push.
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 theALLOWED_EMAILSvariable 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 deployConnect in Claude
Settings → Connectors → Add custom connector.
URL:
https://myfitnesspal-mcp.<subdomain>.workers.dev/mcpClick 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 iconNotes & 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_diagnosticssweeps candidates andquery_endpointcan 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
This server cannot be deployed
Maintenance
Related MCP Connectors
Connect Claude to your Intervals.icu watch data for fitness, workout review, and plan writing.
Garmin data in Claude & ChatGPT via the Garmin Health API. OAuth sign-in, no password sharing.
Connect your health, fitness, nutrition, sleep, and wearable data to your AI assistant.
WHOOP recovery, strain, sleep and workouts in Claude via official WHOOP OAuth. Free, open source.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to read and write MyFitnessPal data, including food diary, exercises, body measurements, nutrition goals, and water intake.MIT
- AlicenseAqualityDmaintenanceEnables AI assistants to read and log MyFitnessPal nutrition data, including tracking calories, macros, searching foods, and adding meals through natural conversation.713 npmMIT
- AlicenseAqualityCmaintenanceEnables AI assistants to interact with MyFitnessPal data including food diary, exercises, body measurements, nutrition goals, and water intake through natural language.2054MIT
- AlicenseNot gradedqualityAmaintenanceConnect MyFitnessPal to Claude or any MCP client. Log meals, search food database with macros, track trends, and export nutrition history against your real MyFitnessPal diary.136 PyPI12MIT