mfp-mcp
A Model Context Protocol (MCP) server that connects AI assistants to your MyFitnessPal data. Lets Claude read your food diary, nutrition goals, weight measurements, and more.
MFP has no official API - this uses the myfitnesspal Python library which scrapes the website using browser cookies.
Quick start
# Install
git clone https://github.com/jevy/myfitnesspal-mcp.git
cd myfitnesspal-mcp
uv sync --extra browser
# Authenticate (must be logged into MFP in your browser first)
mfp-mcp auth --from-browser chrome
# Verify
mfp-mcp auth-status
# Start the server
mfp-mcp serve
Adding to Claude Code
Run mfp-mcp config to get the JSON snippet, or add this to your Claude Code project settings (.claude/settings.json):
{
"mcpServers": {
"myfitnesspal": {
"command": "/path/to/your/.venv/bin/mfp-mcp",
"args": ["serve"]
}
}
}
Replace the path with the output of which mfp-mcp after installing.
Tools
| Tool | Description | Inputs | |------|-------------|--------| | mfp_get_diary | Get food diary for a single date | date (YYYY-MM-DD) | | mfp_get_nutrition_summary | Get nutrition totals across a date range (max 31 days) | start_date, end_date | | mfp_get_goals | Get calorie and macro goals | none | | mfp_get_measurements | Get body measurements (weight, body fat, etc.) over time | measurement?, start_date?, end_date? | | mfp_get_profile | Get user profile and preferences | none | | mfp_search_food | Search the MFP food database | query | | mfp_get_food_details | Get full nutrition for a food item | mfp_id | | mfp_auth_status | Check whether authentication is valid | none | | mfp_refresh_auth | Re-extract cookies from browser | browser? (auto/chrome/firefox/safari/edge) |
CLI reference
mfp-mcp auth --from-browser <browser> Authenticate (extract + store cookies)
mfp-mcp auth-status Check stored credential validity
mfp-mcp auth-clear Remove stored credentials
mfp-mcp config Output Claude Code MCP config JSON
mfp-mcp serve Start stdio MCP server
mfp-mcp help Show help
Authentication
MFP requires browser cookies for access. The auth command extracts cookies from your browser and stores them securely.
# Auto-detect browser
mfp-mcp auth --from-browser auto
# Specific browser
mfp-mcp auth --from-browser chrome
mfp-mcp auth --from-browser firefox
mfp-mcp auth --from-browser safari
You must be logged into myfitnesspal.com in the browser first.
How authentication works
Credentials are stored using a layered system (checked in order):
- Environment variable (
MFP_COOKIES) - for CI/testing - System keyring - macOS Keychain, GNOME Keyring, etc.
- Encrypted file -
~/.config/myfitnesspal-mcp/credentials.enc
The encrypted file uses AES-256-GCM with a key derived via PBKDF2-HMAC-SHA256 (600,000 iterations) bound to machine-specific identifiers. File permissions are set to 600 (owner-only).
Cookie values are never logged, never included in error messages, and never returned to Claude. Multiple layers of defence prevent accidental leakage:
repr=Falseon all cookie fields- Custom
__repr__implementations that mask values - Result sanitisation before returning tool responses
Architecture
src/mfp_mcp/
├── cli.py # CLI entry point
├── server.py # stdio MCP server, tool registration
├── auth/
│ ├── storage.py # Unified credential storage (env → keyring → file)
│ ├── keyring.py # System keyring backend
│ ├── encrypted.py # AES-256-GCM file backend
│ ├── browser.py # Browser cookie extraction
│ └── validator.py # Cookie validation via NextAuth session
├── client/
│ ├── mfp.py # Async wrapper around myfitnesspal library
│ └── models.py # Pydantic response models
└── tools/
├── _validation.py # Pydantic input validation
├── diary.py # mfp_get_diary
├── nutrition.py # mfp_get_nutrition_summary
├── goals.py # mfp_get_goals
├── measurements.py # mfp_get_measurements
├── food.py # mfp_search_food, mfp_get_food_details
├── profile.py # mfp_get_profile
├── auth_status.py # mfp_auth_status
└── refresh_auth.py # mfp_refresh_auth
Technical notes
MFP WAF workaround
The upstream myfitnesspal library's __init__ hits /user/auth_token which MFP's WAF now blocks (HTTP 403). This server works around the issue by:
- Creating the library's
Clientobject without calling__init__(viaobject.__new__()) - Setting up the HTTP session manually with plain
requests(cloudscraper also gets blocked) - Getting the username from MFP's NextAuth session endpoint (
/api/auth/session) - The HTML scraping methods (
get_date,get_measurements) continue to work normally
Rate limiting
Requests to MFP are throttled to one every 500ms with a lock to prevent concurrent requests. This is conservative to avoid triggering MFP's rate limits.
Development
# Install with dev dependencies
uv sync --extra dev --extra browser
# Run tests
pytest
# Lint
ruff check src/ tests/
Requirements
- Python 3.12+
- A MyFitnessPal account with an active browser session
- uv for dependency management












