MyFitnessPal MCP

io.github.Mason-Levyy由 GitHub 账号 Mason-Levyy 发布v0.5.0更新于 Nov 7, 2026

通过与你的AI对话来记录MyFitnessPal:搜索带宏量营养素的食物,记录餐食、体重、饮水等。

AI 翻译由 AI 模型根据下方的原文描述翻译,可能有误。

原文描述

Log MyFitnessPal by talking to your AI: search foods with macros, log meals, weight, water and more.

已验证STDIO仅桌面位置与生活数据与分析

概览

MyFitnessPal 的本地 MCP 服务;无需登录;STDIO;18 个工具。

暂无 AI 概览:以下信息来自注册中心条目和服务本身。

安装

在 SourceWeft 中

  1. 打开 控制台中的 MyFitnessPal MCP,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。

其他 MCP 客户端

参照 仓库 中的启动说明。

README

MyFitnessPal MCP is a free, open-source MCP server that connects MyFitnessPal to Claude, Cursor, VS Code, or any MCP client. Log meals by talking, search the food database with macros, track trends, and export your nutrition history, all against your real MyFitnessPal diary.

Published on PyPI as mfp-mcp and in the official MCP Registry as io.github.Mason-Levyy/mfp-mcp.

Unofficial. MyFitnessPal has no public API; this reverse-engineers the web app's own endpoints. It can break whenever MFP changes their site. Use at your own risk, with your own account.

Why this one?

MyFitnessPal moved behind Cloudflare + NextAuth, which broke the username/password login that most existing integrations rely on. This server:

  • Authenticates with your browser session cookie over a real Chrome TLS fingerprint (curl_cffi), which passes Cloudflare
  • Auto-refreshes the session (optional): a headless browser profile rotates the token when it expires, and failed calls retry automatically
  • Writes, not just reads: log, modify, and delete real diary entries
  • Search-then-log: get candidates with macros, then log the exact item

Quickstart

  1. Connect your account (one-time; prompts you to paste a cookie — see Authentication):

    bash
    uvx mfp-mcp auth
  2. Add the server to your client. The install buttons at the top do this in one click for Cursor and VS Code.

    Claude Code

    bash
    claude mcp add myfitnesspal -- uvx mfp-mcp

    Or install it as a plugin:

    /plugin install myfitnesspal-mcp --marketplace Mason-Levyy/myfitnesspal-mcp

    Claude Desktop (claude_desktop_config.json), Cursor (~/.cursor/mcp.json), Windsurf (~/.codeium/windsurf/mcp_config.json), and Cline (cline_mcp_settings.json) all take the same entry:

    json
    {  "mcpServers": {    "myfitnesspal": {      "command": "uvx",      "args": ["mfp-mcp"]    }  }}
    VS Code, Codex CLI, Gemini CLI

    VS Code (or use the button above):

    bash
    code --add-mcp '{"name":"myfitnesspal","command":"uvx","args":["mfp-mcp"]}'

    Codex CLI:

    bash
    codex mcp add myfitnesspal -- uvx mfp-mcp

    Gemini CLI:

    bash
    gemini mcp add myfitnesspal uvx mfp-mcp
  3. Talk to it: "log a banana as a snack", "what did I eat yesterday?", "chart my weight this month".

Requires uv. Any MCP client that speaks stdio or streamable HTTP works, not just Claude.

Finding this useful? A ⭐ on GitHub helps other MyFitnessPal users find it.

Authentication

This server signs in with your browser's MyFitnessPal session cookie:

  1. Log in at myfitnesspal.com
  2. Open DevTools (F12) → Application (Chrome) or Storage (Firefox) → Cookies → https://www.myfitnesspal.com
  3. Copy the value of __Secure-next-auth.session-token
  4. Paste it into the mfp-mcp auth prompt, or on macOS run mfp-mcp auth --clipboard and copy the cookie: it connects as soon as the token reaches the clipboard

Sessions last 30 days from their last renewal. The server renews the session whenever it builds a client and saves the cookies MyFitnessPal re-issues, so the saved session stays current as long as it's used at least once a month. mfp-mcp auth --check reports whether the saved session still works and whether auto-refresh is set up; it renews and saves the session as it checks and exits 1 when the session needs attention, so running it on a schedule (cron, launchd) keeps an idle session alive and warns before it lapses.

Auto-refresh (recommended)

With the autorefresh extra, auth also seeds a persistent headless browser profile. When MyFitnessPal rejects the session mid-call, the server tells your client it is retrying, boots the profile headlessly, lets MyFitnessPal rotate the session token, saves the fresh cookie, and retries the call.

bash
uvx --from 'mfp-mcp[autorefresh]' playwright install chromiumuvx --from 'mfp-mcp[autorefresh]' mfp-mcp auth

Then use the same --from 'mfp-mcp[autorefresh]' form in your client config (e.g. uvx --from 'mfp-mcp[autorefresh]' mfp-mcp).

Tools

ToolWhat it does
fitness_get_dayNutrition totals, diary entries, the MFP daily note, and feel note for a day
fitness_search_foodCandidate matches with brand, calories, macros, serving, and ids
fitness_draft_foodNumbered options with every serving size, filtered/ranked by optional calorie and macro targets
fitness_log_foodLog a draft option (and serving), a remembered food, or exact ids to the real diary
fitness_list_food_pinsRemembered query → food/serving choices (local)
fitness_clear_food_pinForget one remembered choice, or all of them
fitness_delete_foodRemove a diary entry by name match
fitness_modify_foodReplace an entry (or change its quantity), choosing the replacement like fitness_log_food
fitness_log_weightLog a weight measurement (updates the same day on re-log)
fitness_log_waterAdd water (cups, fl oz, mL, L) or set the day's total with replace
fitness_get_exerciseRead the exercise diary (cardio + strength)
fitness_get_exercise_entriesList cardio and strength entries with each section's columns
fitness_delete_exerciseRemove an exercise entry by name match (all_matches for multi-row sync cleanup)
fitness_get_noteRead the MyFitnessPal daily diary note (the "Notes" box) for a day
fitness_log_noteWrite that daily note to MFP (replace, or append a new line)
fitness_log_feelSave a subjective "how I feel" note (stored locally, never sent to MFP)
fitness_get_trendsOne metric over a date range: weight, calories_in, protein, carbs, fat
fitness_bulk_exportWhole date range in one call, for analysis

Logging flow

Food logging is draft-then-confirm, so what lands in your diary never depends on MyFitnessPal's search order:

  1. fitness_draft_food("greek yogurt", min_protein=15, max_calories=150) returns numbered options. Each lists every serving size with calories and macros for the whole entry (serving × quantity) plus a suggested serving; options that meet the targets come first, near misses follow. Call it again with different targets to refine.
  2. fitness_log_food(draft_id=..., option=2, serving=1) logs exactly that food and serving, and remembers the choice for that query.
  3. Next time, fitness_log_food(query="greek yogurt") logs the remembered food and serving without searching.

A bare fitness_log_food(query=...) with nothing remembered logs only when exactly one result matches the name exactly; otherwise it logs nothing and returns a draft to choose from. Remembered choices live in the local cache (fitness_list_food_pins, fitness_clear_food_pin). Drafts expire after 24 hours.

fitness_modify_food picks the replacement the same way, before deleting anything: a remembered food or a single exact-name match is used directly; otherwise the entry is left alone and a draft comes back — call fitness_modify_food again with the same query plus draft_id and option.

fitness_log_food, fitness_delete_food, and fitness_modify_food all take a meal argument the same way: breakfast/lunch/dinner/snacks, or the literal name of any meal section currently on your diary — including a renamed default meal or one of the up to two extra meals MyFitnessPal lets you add in Diary Settings. Matching is case-insensitive against your account's current meal labels. If you renamed a default meal, the keywords still work: breakfast/lunch/dinner/snacks fall back to your first through fourth meal, unless that slot now carries a different default name (e.g. lunch won't land in a second meal you renamed to "Dinner"). Any other unrecognized meal raises an error instead of silently logging into the wrong section.

Day summaries and trends read from a local SQLite cache that gap-fills from MyFitnessPal (first call on a fresh install fetches up to 30 days, one request per day).

Water logging reads the day's current total from /food/water, adds the requested quantity, and posts the new total back to the same endpoint. Pass replace=True to set the day's total outright (e.g. to fix a mislogged amount); every call returns previous_ml, so a mistake can be reverted by passing it back as amount with unit="ml" and replace=True. The separate /stats request with a water_logged event is analytics telemetry; it does not persist the water total.

Remote / HTTP mode

The default transport is stdio. For network clients:

bash
mfp-mcp --http --host 127.0.0.1 --port 8484

This serves streamable HTTP at /mcp. A session idle for 30 minutes is closed, and the client has to reconnect; clients that keep the event stream open aren't affected. There is no built-in authentication — never expose it to the internet. Bind to localhost and front it with something that authenticates for you: a VPN/tailnet (e.g. tailscale serve), an authenticating reverse proxy, or an OAuth-aware MCP gateway.

Configuration

VariablePurposeDefault
MFP_COOKIESession cookie (full header or bare token); overrides the saved file–
MFP_USERNAMEYour MFP username (not email); only needed if profile lookup failsauto-detected
MFP_IMPERSONATEcurl_cffi browser fingerprint (try chrome124 on 403s)chrome
MFP_SYNC_DAYSGap-fill lookback window in days30
MFP_MCP_DATA_DIRWhere the SQLite cache + browser profile liveplatform data dir

Troubleshooting

  • 403 / Cloudflare blocked: try MFP_IMPERSONATE=chrome124 (or another curl_cffi target). Datacenter IPs get challenged far more than residential ones.
  • "Session expired": confirm with mfp-mcp auth --check, then re-run mfp-mcp auth, or set up auto-refresh.
  • "couldn't read your MyFitnessPal profile": MFP's profile endpoint 500s for some accounts. Set MFP_USERNAME to your username (not your email).
  • curl_cffi install issues: prebuilt wheels cover Linux/macOS/Windows; musl (Alpine) builds from source.

FAQ

How do I connect MyFitnessPal to Claude? Run uvx mfp-mcp auth once to save your MyFitnessPal session, then add the server: claude mcp add myfitnesspal -- uvx mfp-mcp in Claude Code, or the JSON entry from the Quickstart in Claude Desktop. Then ask Claude to log a meal or show yesterday's diary.

Is it free? Yes. It's open source under the MIT license, and it doesn't sell or collect anything.

Is there an official MyFitnessPal API? Not one you can use. MyFitnessPal's API is limited to approved partners and isn't open to new applications, so there's no API key to get. This server signs in with your own browser session cookie and makes the same requests the MyFitnessPal website makes (see How it works).

Which MCP clients does it work with? Any client that runs a stdio or streamable HTTP server, including Claude Desktop, Claude Code, Cursor, Windsurf, Cline, and VS Code. Use the uvx mfp-mcp command from the Quickstart. AI coding agents can follow llms-install.md.

Can it log meals as well as read them? Yes. It logs, replaces, and deletes diary entries, logs weight and water, and writes the daily note. See Tools.

Where does my data go? The server talks only to MyFitnessPal. The session cookie stays in your local config directory, and day summaries, feel notes, and remembered foods stay in a local SQLite file. Tool results go to whichever MCP client and model you connect it to.

How it works

  • Every request runs over a curl_cffi session that impersonates Chrome's TLS fingerprint, so Cloudflare lets it through with just the NextAuth session cookie. The diary, exercise, and measurements pages are parsed with lxml.
  • Writes replicate the web app's own XHR calls: the legacy food-search page supplies the food_id/weight_id that /food/add accepts, deletes go through /food/remove, water reads/writes via /food/water, and the daily note reads/writes via /food/note — each with the page CSRF token.
  • Day summaries, trends, and exports read a local SQLite cache that gap-fills missing days. The MyFitnessPal daily note syncs both ways; feel notes are local-only.

Development

bash
git clone https://github.com/Mason-Levyy/myfitnesspal-mcpcd myfitnesspal-mcpuv sync --extra autorefreshuv run pytest

Tests run against synthetic MyFitnessPal HTML/JSON fixtures — no account needed. Lint and formatting are enforced with ruff (uv run ruff check ., uv run ruff format .).

Contributing

Issues and pull requests are welcome, especially endpoint captures when MyFitnessPal changes something. See CONTRIBUTING.md for setup, style, and the PR checklist, and SECURITY.md for how to report vulnerabilities privately. Release history is in CHANGELOG.md.

Support the project

If this server saves you time, please star the repo. Stars are how other MyFitnessPal users find it in GitHub search and MCP directories. Bug reports and endpoint captures are just as welcome in issues.

Credits

The sign-in and the diary, exercise, weight, and food-detail parsing started as python-myfitnesspal by Adam Coddington, which this project used as a dependency through 0.4.x. That code now lives in this repo, trimmed to what the server uses and adapted to its curl_cffi session, under python-myfitnesspal's MIT license (see NOTICE). Thanks to Adam and its contributors for years of keeping up with MyFitnessPal's site.

License

MIT. Code adapted from python-myfitnesspal keeps its own MIT license notice in NOTICE.

来源:README.md,提交 1a35efd

工具

18

fitness_get_day

Get day summary

Nutrition summary, diary entries, the MyFitnessPal daily note, and the local feel note for a day. date: YYYY-MM-DD (default: today).

输入参数date

fitness_search_food

Search foods

Search MyFitnessPal's food database and return candidate matches. Each candidate has name, brand, calories, macros, serving, and the food_id + weight_id to pass to fitness_log_food to log exactly that item.

输入参数limitquery必填with_macros

fitness_draft_food

Draft food entry

Draft a food entry: numbered options to choose from before logging. Each option lists every serving size with its calories/protein/carbs/fat for the whole entry (serving × quantity) and a suggested_serving. The min_/max_ targets (grams; calories in kcal) also apply to the whole entry: options that fit come first, near misses follow, flagged fits_targets=false. A food you've confirmed before for this query is pinned to the top. The order is fixed once drafted. Log a choice with fitness_log_food(draft_id=..., option=N, serving=M); call this again with different targets to refine. Drafts last 24 hours. date: YYYY-MM-DD (default: today).

输入参数datemeallimitquery必填max_fatmin_fatquantitymax_carbsmin_carbsmax_proteinmin_proteinmax_calories另有 1 个

fitness_log_food

Log food

Log a food to the real MyFitnessPal diary. Preferred: pick from a fitness_draft_food draft with draft_id + option (+ serving, default the option's suggested_serving). meal, quantity, and date default to the draft's. pin=True remembers the choice so logging the same query later reuses this food and serving. With only `query`: logs a pinned food, or the single exact-name match; otherwise nothing is logged and a draft is returned (needs_choice=true) to pick from. With food_id + weight_id (from fitness_search_food): logs exactly that item, `query` being its display name. meal: breakfast|lunch|dinner|snacks (default breakfast) or any meal name on the account. quantity: number of servings (default 1). date: YYYY-MM-DD (default today).

输入参数pindatemealqueryoptionfood_idservingdraft_idquantityweight_id

fitness_list_food_pins

List remembered foods

List remembered food choices (query → food and serving) that fitness_log_food reuses. Stored locally only.

无需输入参数。

fitness_clear_food_pin

Forget remembered food

Forget a remembered food choice for `query`, or every choice with clear_all=True, so the next log of that query drafts options again.

输入参数queryclear_all

fitness_delete_food

Delete food entry

Remove a food from the MyFitnessPal diary by name match. query: text matched against logged entry names (e.g. "banana"). If this matches nothing, the error lists what's actually logged that day/meal — use that to retry with a better query. If it matches more than one entry (and none is an exact name match), the error lists the candidates; narrow `query` to pick one. Identical duplicates (same name, including its quantity, in the same meal) are interchangeable, so one of them is removed; call again to remove another. meal: optional breakfast|lunch|dinner|snacks or any meal name on the account, to disambiguate duplicates. date: YYYY-MM-DD (default: today).

输入参数datemealquery必填

fitness_modify_food

Replace food entry

Replace a MyFitnessPal diary entry: deletes the match, then adds a food. query: the existing entry to replace (name match) within `meal`. If this matches nothing, the error lists what's actually logged that day/meal — use that to retry with a better query. If it matches more than one entry (and none is an exact name match), the error lists the candidates; narrow `query` to pick one. Of several identical duplicates, one is replaced. new_query: the food to add instead; omit to re-add `query` (e.g. to change quantity). The replacement is chosen like fitness_log_food's: a pinned food or a single exact-name match is used directly; otherwise nothing is changed and a draft comes back (needs_choice=true) — call again with the same query plus draft_id + option (and optionally serving). meal: breakfast|lunch|dinner|snacks or any meal name on the account, used for both the delete and the add. quantity: servings (default 1, or the draft's). date: YYYY-MM-DD (default: today).

输入参数datemealquery必填optionservingdraft_idquantitynew_query

fitness_log_weight

Log weight

Log a weight measurement to MyFitnessPal. weight: in your MyFitnessPal account's display unit (kg or lbs). Logging twice for the same date updates that day's measurement. date: YYYY-MM-DD (default: today).

输入参数dateweight必填

fitness_log_water

Log water

Log water to the real MyFitnessPal water tracker. amount: quantity to add to the day's total. unit: cup | fl_oz | ml | l (common spellings like "cups", "oz", "fl oz", "milliliters", "litres" are accepted). replace: set the day's total to `amount` instead of adding — use it to correct a mislogged total (amount=0 clears the day). Returns previous_ml; to undo a mistake, call again with amount=previous_ml, unit="ml", replace=True. date: YYYY-MM-DD (default: today).

输入参数dateunitamount必填replace

fitness_get_exercise

Get exercise diary

Read the MyFitnessPal exercise diary (cardio + strength) for a day. date: YYYY-MM-DD (default: today).

输入参数date

fitness_get_exercise_entries

List exercise entries

List a day's cardio and strength exercise-diary entries. Each entry has its section, name, and that section's columns (cardio: minutes, calories_burned; strength: sets, reps_set, weight_set). entry_id is informational only — fitness_delete_exercise deletes by name match. date: YYYY-MM-DD (default: today).

输入参数date

fitness_delete_exercise

Delete exercise entry

Remove exercise-diary entries by name match (case-insensitive). query: text matched against logged exercise names. By default deletes exactly one entry, like fitness_delete_food: an exact name match wins; otherwise several matches raise an error listing the candidates, and no match raises an error listing what's actually logged. Of several identical rows (same name and columns), one is removed. all_matches: delete every entry whose name contains `query` — for cleaning up syncs that log one workout as several same-named rows (e.g. Garmin's "Aerobics, general"). Check fitness_get_exercise_entries first; a short query can match many entries. date: YYYY-MM-DD (default: today).

输入参数datequery必填all_matches

fitness_get_note

Get daily note

Read the MyFitnessPal daily diary note (the free-text 'Notes' box at the bottom of the day) straight from your account. date: YYYY-MM-DD (default: today).

输入参数date

fitness_log_note

Write daily note

Write the MyFitnessPal daily diary note (the free-text 'Notes' box at the bottom of the day). This is your real MFP note, synced to your account — distinct from the local-only fitness_log_feel. text: the note body. append: add to the existing note on a new line instead of replacing it. date: YYYY-MM-DD (default: today).

输入参数datetext必填append

fitness_log_feel

Save feel note

Save a 'how I feel today' note. Stored locally only — never sent to MyFitnessPal. rating: optional 1-5. date: YYYY-MM-DD (default: today).

输入参数datenoterating

fitness_bulk_export

Export date range

Export a whole date range at once for analysis: per-day nutrition totals, food entries with macros, the MyFitnessPal daily note, and local feel notes. Read-only. start/end: YYYY-MM-DD (default: last 30 days ending today). sync_first: gap-fill from MyFitnessPal before exporting. Off by default so large historical exports stay fast on cached data.

输入参数endstartsync_first

版本历史

6
  1. v0.5.0最新Nov 3, 2026
  2. v0.4.3Oct 23, 2026
  3. v0.4.2Oct 21, 2026
  4. v0.4.1Sep 30, 2026
  5. v0.4.0Sep 29, 2026
  6. v0.3.0Sep 16, 2026

评分

已满足适用检查项的 90%

该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。

  • 近 30 天内可连通25 分
  • 已声明认证方式10 分

    请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。

  • 已列出工具必需15 分
  • 描述必需15 分
  • 图标10 分
  • 文档15 分
  • 许可证10 分