Cronometer MCP server
Click on "Install 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., "@Cronometer MCP serverHow many calories did I eat yesterday?"
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.
Cronometer MCP server
Read and write your Cronometer food diary from Claude.ai and Claude Code. It talks to mobile.cronometer.com, the same API the Cronometer Android app uses, and puts an OAuth 2.1 login in front so you can add it to Claude.ai as a custom connector. Claude Code can use a plain token instead. You do not need a Gold subscription, and there is no limit of ten exports a day like there is with CSV export.
Why not the other options
Terra API sends your Cronometer data to a webhook, but it can only read, and your food log passes through someone else's servers
gocronometerand similar export tools can only read, and they are rate limitedTools that scrape the Cronometer website can write, but they rely on codes that change every time Cronometer ships an update, and they need Gold
Related MCP server: cronometer-api-mcp
Tools
Reading
Tool | What you get |
| Everything in the diary for one day. Each food comes with its name, where it came from, the serving size, how many servings, and what that food added to your nutrients. You also get calories (target, eaten, left) and totals for every nutrient you track |
| Nutrient totals for one day |
| Cronometer's nutrition scores |
| Search the food database |
| Full nutrients and serving sizes for one food |
| The nutrient goals shown next to your daily totals |
| Your protein, carb and fat goals |
| What you can measure, and the units each one accepts |
| One measurement over time |
| Fasts between two dates |
| Fasting totals and averages |
| Every nutrient you can set on a custom food, with units |
Writing
Tool | What it does |
| Add a food to a meal |
| Change how much you ate, or when |
| Delete food entries |
| Create your own food, with up to all 94 nutrients |
| Retire a custom food, or bring one back |
| Write a note on a day |
| Rewrite a note |
| Record a measurement such as weight or body fat |
| Fix a measurement you got wrong |
| Add an exercise |
| Change how long an exercise lasted, or how much it burned |
| Record a fast, finished or still running |
| Change a fast's times or goal, including ending one that is still running |
| Delete a fast |
| Copy one day's diary onto another day |
| Mark a day done, or not done |
Custom foods
add_custom_food takes a dict of nutrient name to amount, so you can give it
anything from one nutrient to the whole catalog in a single call:
{
"name": "Vaasan Ruispalat",
"serving_name": "1 slice",
"serving_grams": 33,
"nutrients": {
"energy": 79, "protein": 3.1, "carbs": 12.5, "fiber": 3.4,
"fat": 0.8, "saturated": 0.2, "salt_g": 0.36,
"iron": 0.9, "magnesium": 26, "b1_thiamine": 0.09, "folate": 11
}
}Amounts are for one whole serving, each in that nutrient's own unit. Call
list_nutrients for the accepted names, which come from your account's own
catalog rather than a table baked in here.
A nutrient you leave out stays blank in Cronometer. Passing 0 instead states
that the food contains none of it, and the app treats the two differently, so
only pass what you actually know. An unrecognised name is an error rather than
being quietly dropped, because a food that silently lost a nutrient still looks
complete.
Two conveniences the food label has and the catalog does not: energy_kj is
converted to calories, and salt_g to sodium. Pass one or the other, not both.
How it fits together
Claude.ai / Claude Code
| HTTPS
Cloudflare Tunnel, or any proxy that gives you HTTPS
|
nginx 127.0.0.1:8431
|
auth-server.js :8432 handles the login and the tokens
|
cronometer-mcp :8430 the server itself, local only
|
mobile.cronometer.comThe server itself has no login of its own, and it refuses to listen on anything but the local machine. So anything that reaches it has already got past the login. That login accepts either an OAuth token, which is what Claude.ai sets up for you, or a fixed token, which is quicker for Claude Code.
Install
git clone https://github.com/rollecode/cronometer-mcp.git
cd cronometer-mcp
./install.shThe installer sets up Python and Node, asks for your Cronometer login and a password for the connector's login page, makes a token, and writes the service files and the nginx site with your own hostname and username filled in.
You need Node 18 or newer, Python 3.12 or newer, and uv.
Putting the server online is left to you, because this is where setups differ the most, and a wrong guess here would put your food diary on the public internet. Point a tunnel or a proxy at 127.0.0.1:8431. With Cloudflare Tunnel:
ingress:
- hostname: cronometer-mcp.example.com
service: http://localhost:8431It has to be HTTPS. OAuth will not work over plain HTTP.
Self-hosting it by hand
If you would rather see every step than run the installer, this is all of it. The end state is two services on your own machine, reachable over HTTPS.
1. Get the code and its dependencies
git clone https://github.com/rollecode/cronometer-mcp.git
cd cronometer-mcp
npm install --omit=dev
uv venv && uv pip install -e .2. Store your Cronometer login
./set-credentials.shIt prompts for your email, password and time zone, and writes them to
~/.config/cronometer-mcp/env with mode 0600. The password is never echoed and
never reaches your shell history. Do it by hand if you prefer:
mkdir -p ~/.config/cronometer-mcp && chmod 700 ~/.config/cronometer-mcp
cat > ~/.config/cronometer-mcp/env <<'EOF'
CRONOMETER_USERNAME=you@example.com
CRONOMETER_PASSWORD=your-password
CRONOMETER_ACCOUNT_TZ=Europe/Helsinki
EOF
chmod 600 ~/.config/cronometer-mcp/envCheck it works before going further. This logs in and prints your diary:
set -a && . ~/.config/cronometer-mcp/env && set +a
.venv/bin/python -c "from cronometer_mcp import CronometerClient; c=CronometerClient(); print(c.get_diary()['summary'])"3. Set the connector password and a token
The password is what you type on the sign-in page when adding the connector in Claude.ai. Only its scrypt hash is stored.
CONFIG_DIR=~/.config/cronometer-mcp node set-password.js 'your-password-here'The token is the shortcut for Claude Code, which sends a header and skips the browser entirely.
openssl rand -hex 32 > ~/.config/cronometer-mcp/token
chmod 600 ~/.config/cronometer-mcp/token4. Install the two services
systemd/ holds both unit files. Replace YOUR_USER with your username and
cronometer-mcp.example.com with your hostname, then:
mkdir -p ~/.cache/cronometer-mcp
sudo cp systemd/cronometer-mcp.service systemd/cronometer-mcp-auth.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now cronometer-mcp cronometer-mcp-auth
systemctl status cronometer-mcp cronometer-mcp-authcronometer-mcp is the server itself on :8430, reachable only from the machine
it runs on. cronometer-mcp-auth is the login layer on :8432, and it is the
only thing that talks to :8430.
One trap worth naming, because the symptom is confusing: do not add
IPAddressDeny=any to cronometer-mcp.service. It is a sensible hardening line
for a server that only reads local files, but this one has to reach
mobile.cronometer.com, and with it set every tool call hangs until it times
out while systemd still reports the service as active. Nothing is gained by it
either, since the server already refuses to listen beyond the local machine.
5. Put nginx in front
sudo cp nginx/cronometer-mcp.conf /etc/nginx/sites-enabled/cronometer-mcp
sudo nginx -t && sudo systemctl reload nginxIt listens on 127.0.0.1:8431 and passes everything to the login layer. The
long read timeout and proxy_buffering off matter: the MCP holds the connection
open and sends as it goes, and buffering would stall it.
6. Give it an HTTPS address
A Cloudflare Tunnel avoids opening a router port. Any HTTPS reverse proxy works just as well.
ingress:
- hostname: cronometer-mcp.example.com
service: http://localhost:8431cloudflared tunnel route dns YOUR_TUNNEL cronometer-mcp.example.com
sudo systemctl restart cloudflared7. Check it from outside
curl https://cronometer-mcp.example.com/.well-known/oauth-authorization-server
curl -o /dev/null -w '%{http_code}\n' -X POST https://cronometer-mcp.example.com/mcpThe first returns the login details. The second must return 401: anything else
means the login layer is being bypassed and your diary is exposed.
Then connect a client as described under Connecting.
Updating
git pull
uv pip install -e . && npm install --omit=dev
sudo systemctl restart cronometer-mcp cronometer-mcp-authAfter adding or renaming a tool, press Reconnect on the connector in Claude.ai.
That refreshes the tool list inside a conversation you already have open, and
your sign-in survives it, because tokens live in oauth.db on disk rather than
in memory.
When something is wrong
journalctl -u cronometer-mcp -n 50 --no-pager
journalctl -u cronometer-mcp-auth -n 50 --no-pagerWhat you see | What it usually is |
Tool calls hang, service says active |
|
| Token mismatch, compare the header against |
Sign-in page rejects the password | No hash stored yet, run step 3 |
Login fails asking for a 2FA code | |
| The login layer is down, |
Connecting
Claude.ai. Go to Settings, Connectors, Add custom connector, and give it https://your-host/mcp. Leave the client ID and secret empty. Sign in with the password the installer set. Doing this once covers web, desktop and mobile, because connectors belong to your account rather than one device.
Claude Code, through the browser:
claude mcp add --transport http cronometer https://your-host/mcp --scope userThen run /mcp to sign in.
Claude Code, with a token, no browser:
claude mcp add --transport http cronometer https://your-host/mcp \
--header "Authorization: Bearer $(cat ~/.config/cronometer-mcp/token)" \
--scope userUsing it without a server at all
If Claude runs on the same machine, skip the web server and the login entirely and let it start the MCP directly:
claude mcp add cronometer -- /path/to/cronometer-mcp/.venv/bin/cronometer-mcpIt reads your login from ~/.config/cronometer-mcp/env or from a .env file.
Settings
Variable | What it is for |
| Your Cronometer email |
| Your Cronometer password |
| The time zone your diary days are counted in |
| Your two-factor secret, only if you have two-factor on. Needs the |
| The public address of the server |
| Login server port, 8432 by default |
| Where the MCP server is, |
| Where the password, token and database are kept |
| How long a call may go quiet before it is cut off, 120000 by default |
| MCP server port, 8430 by default |
| Public address, used to advertise the icon to clients |
Everything secret lives in ~/.config/cronometer-mcp/, readable only by you: env holds your Cronometer login, password-hash the password for the connector's login page, token the fixed token, and oauth.db the apps and tokens the login server has handed out. Tokens are stored scrambled, so a stolen copy of the database gives nobody a working key.
Your Cronometer session is saved in ~/.cache/cronometer-mcp/session.json, so restarting the server does not log in again and again and hit Cronometer's limit.
If you use two-factor
A server left running on its own cannot type a code, so it needs the secret behind the code instead:
uv pip install -e '.[totp]'Then set CRONOMETER_TOTP_SECRET to the secret from your authenticator app. Without it, an account with two-factor turned on will fail to log in and tell you exactly this.
Working on the code
uv venv && uv pip install -e . && uv pip install pytest ruff
.venv/bin/python -m pytest tests -q
.venv/bin/python -m ruff check src/ tests/Credits
The Cronometer client started as a copy of rwestergren/cronometer-api-mcp. The login layer comes from rollecode/obsidian-remote-mcp.
This server cannot be installed
Maintenance
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
- Alicense-qualityDmaintenanceEnables AI assistants to read and write MyFitnessPal data, including food diary, exercises, body measurements, nutrition goals, and water intake.MIT
- AlicenseAqualityBmaintenanceEnables nutrition tracking with Cronometer, including food logging, food search, diary management, and nutrition data retrieval via natural language.13MIT
- Alicense-qualityAmaintenanceConnect 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.6MIT
- Alicense-qualityCmaintenanceEnables Claude.ai to read your MacroFactor nutrition data and log food back into MacroFactor.MIT
Related MCP Connectors
WHOOP recovery, strain, sleep and workouts in Claude via official WHOOP OAuth. Free, open source.
Garmin data in Claude & ChatGPT via the Garmin Health API. OAuth sign-in, no password sharing.
Connect Claude to Fathom meeting recordings, transcripts, and summaries
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/rollecode/cronometer-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server