{
  "markdown": "# myfitnesspal-mcp\n\nConnect MyFitnessPal to Claude or any MCP client. Log meals by talking, search\nthe food database with macros, track trends, and export your nutrition history, all against your real MyFitnessPal diary.\n\nPublished on PyPI as [`mfp-mcp`](https://pypi.org/project/mfp-mcp/).\n\n<!-- mcp-name: io.github.Mason-Levyy/mfp-mcp -->\n\n> **Unofficial.** MyFitnessPal has no public API; this reverse-engineers the\n> web app's own endpoints. It can break whenever MFP changes their site. Use at\n> your own risk, with your own account.\n\n![quick demo](demo.gif)\n\n## Why this one?\n\nMyFitnessPal moved behind Cloudflare + NextAuth, which broke the\nusername/password login that most existing integrations rely on. This server:\n\n- **Authenticates with your browser session cookie** over a real Chrome TLS\n  fingerprint ([curl_cffi](https://github.com/lexiforest/curl_cffi)), which\n  passes Cloudflare.\n- **Auto-refreshes the session** (optional): a headless browser profile rotates\n  the token when it expires, and failed calls retry automatically.\n- **Writes, not just reads**: log, modify, and delete real diary entries.\n- **Search-then-log**: get candidates with macros, then log the exact item.\n\n## Quickstart\n\n1. Connect your account (one-time; prompts you to paste a cookie — see\n   [Authentication](#authentication)):\n\n   ```bash\n   uvx mfp-mcp auth\n   ```\n\n2. Add the server to your client.\n\n   **Claude Code**\n\n   ```bash\n   claude mcp add myfitnesspal -- uvx mfp-mcp\n   ```\n\n   **Claude Desktop** (`claude_desktop_config.json`)\n\n   ```json\n   {\n     \"mcpServers\": {\n       \"myfitnesspal\": {\n         \"command\": \"uvx\",\n         \"args\": [\"mfp-mcp\"]\n       }\n     }\n   }\n   ```\n\n3. Talk to it: *\"log a banana as a snack\"*, *\"what did I eat yesterday?\"*,\n   *\"chart my weight this month\"*.\n\nRequires [uv](https://docs.astral.sh/uv/). Any MCP client that speaks stdio or\nstreamable HTTP works, not just Claude.\n\n## Authentication\n\nMyFitnessPal killed headless password login, so this uses your browser's\nsession cookie:\n\n1. Log in at [myfitnesspal.com](https://www.myfitnesspal.com).\n2. Open DevTools (F12) → **Application** (Chrome) or **Storage** (Firefox) →\n   **Cookies** → `https://www.myfitnesspal.com`.\n3. Copy the value of `__Secure-next-auth.session-token`.\n4. Paste it into the `mfp-mcp auth` prompt (input is hidden).\n\nPasting the entire `Cookie:` header from any request in the Network tab also\nworks. Cookies are stored with owner-only permissions in your platform config\ndir, or supply them via the `MFP_COOKIE` environment variable instead.\n\nSessions last around 30 days. When one expires, either re-run `auth` — or\nenable auto-refresh so you never have to.\n\n### Auto-refresh (recommended)\n\nWith the `autorefresh` extra, `auth` also seeds a persistent headless browser\nprofile. When MyFitnessPal rejects the session mid-call, the server tells your\nclient it is retrying, boots the profile headlessly, lets MyFitnessPal rotate\nthe session token, saves the fresh cookie, and retries the call.\n\n```bash\nuvx --from 'mfp-mcp[autorefresh]' playwright install chromium\nuvx --from 'mfp-mcp[autorefresh]' mfp-mcp auth\n```\n\nThen use the same `--from 'mfp-mcp[autorefresh]'` form in your client config\n(e.g. `uvx --from 'mfp-mcp[autorefresh]' mfp-mcp`).\n\n## Tools\n\n| Tool | What it does |\n| --- | --- |\n| `fitness_get_day` | Nutrition totals, diary entries, the MFP daily note, and feel note for a day |\n| `fitness_search_food` | Candidate matches with brand, calories, macros, serving, and ids |\n| `fitness_log_food` | Log a food to the real diary (top match, or an exact search candidate) |\n| `fitness_delete_food` | Remove a diary entry by name match |\n| `fitness_modify_food` | Replace an entry (or change its quantity) |\n| `fitness_log_weight` | Log a weight measurement (updates the same day on re-log) |\n| `fitness_get_exercise` | Read the exercise diary (cardio + strength) |\n| `fitness_get_note` | Read the MyFitnessPal daily diary note (the \"Notes\" box) for a day |\n| `fitness_log_note` | Write that daily note to MFP (replace, or `append` a new line) |\n| `fitness_log_feel` | Save a subjective \"how I feel\" note (stored locally, never sent to MFP) |\n| `fitness_get_trends` | One metric over a date range: weight, calories_in, protein, carbs, fat |\n| `fitness_bulk_export` | Whole date range in one call, for analysis |\n\nThe high-accuracy logging flow: `fitness_search_food(\"greek yogurt\")` returns\ncandidates with macros and a `food_id`/`weight_id`; pass those to\n`fitness_log_food` to log exactly that item instead of trusting the top match.\n\nDay summaries and trends read from a local SQLite cache that gap-fills from\nMyFitnessPal (first call on a fresh install fetches up to 30 days, one request\nper day — subsequent calls are fast).\n\nWater intake is read-only (it appears in day summaries): MyFitnessPal's water\n*write* isn't exposed on any endpoint we've found — `/food/water` accepts POSTs\nbut ignores them. If you capture the real call in your browser, a PR is very\nwelcome.\n\n## Remote / HTTP mode\n\nThe default transport is stdio. For network clients:\n\n```bash\nmfp-mcp --http --host 127.0.0.1 --port 8484\n```\n\nThis serves streamable HTTP at `/mcp`. **There is no built-in authentication —\nnever expose it to the internet.** Bind to localhost and front it with\nsomething that authenticates for you: a VPN/tailnet (e.g. `tailscale serve`),\nan authenticating reverse proxy, or an OAuth-aware MCP gateway.\n\n## Configuration\n\n| Variable | Purpose | Default |\n| --- | --- | --- |\n| `MFP_COOKIE` | Session cookie (full header or bare token); overrides the saved file | – |\n| `MFP_USERNAME` | Your MFP username (not email); only needed if profile lookup fails | auto-detected |\n| `MFP_IMPERSONATE` | curl_cffi browser fingerprint (try `chrome124` on 403s) | `chrome` |\n| `MFP_SYNC_DAYS` | Gap-fill lookback window in days | `30` |\n| `MFP_MCP_DATA_DIR` | Where the SQLite cache + browser profile live | platform data dir |\n\n## Troubleshooting\n\n- **403 / Cloudflare blocked**: try `MFP_IMPERSONATE=chrome124` (or another\n  [curl_cffi target](https://github.com/lexiforest/curl_cffi#supported-browsers)).\n  Datacenter IPs get challenged far more than residential ones.\n- **\"Session expired\"**: re-run `mfp-mcp auth`, or set up\n  [auto-refresh](#auto-refresh-recommended).\n- **\"couldn't read your MyFitnessPal profile\"**: MFP's profile endpoint 500s\n  for some accounts. Set `MFP_USERNAME` to your username (not your email).\n- **curl_cffi install issues**: prebuilt wheels cover Linux/macOS/Windows;\n  musl (Alpine) builds from source.\n\n## How it works\n\n- [python-myfitnesspal](https://github.com/coddingtonbear/python-myfitnesspal)\n  parses the diary, measurements, and exercise pages — run over a `curl_cffi`\n  session that impersonates Chrome's TLS fingerprint so Cloudflare lets it\n  through with just the NextAuth session cookie.\n- Writes replicate the web app's own XHR calls: the legacy food-search page\n  supplies the `food_id`/`weight_id` that `/food/add` accepts, deletes go\n  through `/food/remove`, and the daily note reads/writes via `/food/note` —\n  each with the page CSRF token.\n- Day summaries, trends, and exports read a local SQLite cache that gap-fills\n  missing days. The MyFitnessPal daily note syncs both ways; feel notes are\n  local-only.\n\n## Development\n\n```bash\ngit clone https://github.com/Mason-Levyy/myfitnesspal-mcp\ncd myfitnesspal-mcp\nuv sync --extra autorefresh\nuv run pytest\n```\n\nTests run against synthetic MyFitnessPal HTML/JSON fixtures — no account\nneeded.\n\n## License\n\n[MIT](LICENSE)\n",
  "bytes": 7535,
  "sha": "517c2de1194ffaccfe09dfaf872b00b05eb5525cc24b65ba2f670ffe4a8bd8bf",
  "repo_slug": "mason-levyy/myfitnesspal-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_mason_levyy_mfp_mcp_64341847/readme"
}