cronometer-api-mcp 0.1.3__tar.gz → 0.1.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cronometer_api_mcp-0.1.4/.env.example +2 -0
- {cronometer_api_mcp-0.1.3 → cronometer_api_mcp-0.1.4}/PKG-INFO +15 -2
- {cronometer_api_mcp-0.1.3 → cronometer_api_mcp-0.1.4}/README.md +13 -1
- {cronometer_api_mcp-0.1.3 → cronometer_api_mcp-0.1.4}/pyproject.toml +2 -1
- {cronometer_api_mcp-0.1.3 → cronometer_api_mcp-0.1.4}/server.json +2 -2
- {cronometer_api_mcp-0.1.3 → cronometer_api_mcp-0.1.4}/src/cronometer_api_mcp/client.py +4 -1
- {cronometer_api_mcp-0.1.3 → cronometer_api_mcp-0.1.4}/src/cronometer_api_mcp/server.py +34 -0
- {cronometer_api_mcp-0.1.3 → cronometer_api_mcp-0.1.4}/uv.lock +2 -0
- {cronometer_api_mcp-0.1.3 → cronometer_api_mcp-0.1.4}/.dockerignore +0 -0
- {cronometer_api_mcp-0.1.3 → cronometer_api_mcp-0.1.4}/.github/workflows/ci.yml +0 -0
- {cronometer_api_mcp-0.1.3 → cronometer_api_mcp-0.1.4}/.github/workflows/docker.yml +0 -0
- {cronometer_api_mcp-0.1.3 → cronometer_api_mcp-0.1.4}/.github/workflows/publish.yml +0 -0
- {cronometer_api_mcp-0.1.3 → cronometer_api_mcp-0.1.4}/.gitignore +0 -0
- {cronometer_api_mcp-0.1.3 → cronometer_api_mcp-0.1.4}/.python-version +0 -0
- {cronometer_api_mcp-0.1.3 → cronometer_api_mcp-0.1.4}/Dockerfile +0 -0
- {cronometer_api_mcp-0.1.3 → cronometer_api_mcp-0.1.4}/LICENSE +0 -0
- {cronometer_api_mcp-0.1.3 → cronometer_api_mcp-0.1.4}/Procfile +0 -0
- {cronometer_api_mcp-0.1.3 → cronometer_api_mcp-0.1.4}/src/cronometer_api_mcp/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cronometer-api-mcp
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: MCP server for Cronometer nutrition data using the mobile REST API
|
|
5
5
|
Author: Randy
|
|
6
6
|
License-Expression: MIT
|
|
@@ -15,6 +15,7 @@ Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
|
|
|
15
15
|
Requires-Python: >=3.14
|
|
16
16
|
Requires-Dist: httpx>=0.27.0
|
|
17
17
|
Requires-Dist: mcp>=1.0.0
|
|
18
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
18
19
|
Requires-Dist: uvicorn>=0.30.0
|
|
19
20
|
Description-Content-Type: text/markdown
|
|
20
21
|
|
|
@@ -97,7 +98,7 @@ export CRONOMETER_PASSWORD="your-password"
|
|
|
97
98
|
|
|
98
99
|
| Tool | Description |
|
|
99
100
|
|------|-------------|
|
|
100
|
-
| `get_food_log` | Diary entries for a date with food names, amounts, and meal groups |
|
|
101
|
+
| `get_food_log` | Diary entries for a date with food names, amounts, and meal groups, plus an energy_summary (target/consumed/remaining kcal) |
|
|
101
102
|
| `get_daily_nutrition` | Daily macro and micronutrient totals |
|
|
102
103
|
| `get_nutrition_scores` | Category scores (Vitamins, Minerals, etc.) with per-nutrient consumed amounts and confidence levels |
|
|
103
104
|
|
|
@@ -177,6 +178,18 @@ When deployed remotely with OAuth configured, connect from Claude.ai using:
|
|
|
177
178
|
|
|
178
179
|
Claude.ai will open a browser tab for authorization. Click **Authorize** to complete the connection.
|
|
179
180
|
|
|
181
|
+
## Development
|
|
182
|
+
|
|
183
|
+
For local development, copy `.env.example` to `.env` and fill in your credentials:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
cp .env.example .env
|
|
187
|
+
# edit .env
|
|
188
|
+
uv run cronometer-api-mcp
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
The CLI auto-loads `.env` on startup (dev convenience only). Real environment variables always win over `.env`, so production deployments and MCP client `env` blocks are unaffected.
|
|
192
|
+
|
|
180
193
|
## How It Works
|
|
181
194
|
|
|
182
195
|
This server communicates with `mobile.cronometer.com` -- the same REST API used by the Cronometer Android/Flutter app. The API was reverse-engineered through:
|
|
@@ -77,7 +77,7 @@ export CRONOMETER_PASSWORD="your-password"
|
|
|
77
77
|
|
|
78
78
|
| Tool | Description |
|
|
79
79
|
|------|-------------|
|
|
80
|
-
| `get_food_log` | Diary entries for a date with food names, amounts, and meal groups |
|
|
80
|
+
| `get_food_log` | Diary entries for a date with food names, amounts, and meal groups, plus an energy_summary (target/consumed/remaining kcal) |
|
|
81
81
|
| `get_daily_nutrition` | Daily macro and micronutrient totals |
|
|
82
82
|
| `get_nutrition_scores` | Category scores (Vitamins, Minerals, etc.) with per-nutrient consumed amounts and confidence levels |
|
|
83
83
|
|
|
@@ -157,6 +157,18 @@ When deployed remotely with OAuth configured, connect from Claude.ai using:
|
|
|
157
157
|
|
|
158
158
|
Claude.ai will open a browser tab for authorization. Click **Authorize** to complete the connection.
|
|
159
159
|
|
|
160
|
+
## Development
|
|
161
|
+
|
|
162
|
+
For local development, copy `.env.example` to `.env` and fill in your credentials:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
cp .env.example .env
|
|
166
|
+
# edit .env
|
|
167
|
+
uv run cronometer-api-mcp
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
The CLI auto-loads `.env` on startup (dev convenience only). Real environment variables always win over `.env`, so production deployments and MCP client `env` blocks are unaffected.
|
|
171
|
+
|
|
160
172
|
## How It Works
|
|
161
173
|
|
|
162
174
|
This server communicates with `mobile.cronometer.com` -- the same REST API used by the Cronometer Android/Flutter app. The API was reverse-engineered through:
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "cronometer-api-mcp"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.4"
|
|
8
8
|
description = "MCP server for Cronometer nutrition data using the mobile REST API"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -25,6 +25,7 @@ dependencies = [
|
|
|
25
25
|
"mcp>=1.0.0",
|
|
26
26
|
"httpx>=0.27.0",
|
|
27
27
|
"uvicorn>=0.30.0",
|
|
28
|
+
"python-dotenv>=1.0.0",
|
|
28
29
|
]
|
|
29
30
|
|
|
30
31
|
[project.scripts]
|
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
"url": "https://github.com/rwestergren/cronometer-api-mcp",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "0.1.
|
|
9
|
+
"version": "0.1.4",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "pypi",
|
|
13
13
|
"identifier": "cronometer-api-mcp",
|
|
14
|
-
"version": "0.1.
|
|
14
|
+
"version": "0.1.4",
|
|
15
15
|
"transport": {
|
|
16
16
|
"type": "stdio"
|
|
17
17
|
},
|
|
@@ -371,7 +371,10 @@ class CronometerClient:
|
|
|
371
371
|
|
|
372
372
|
Args:
|
|
373
373
|
food_id: Cronometer food ID.
|
|
374
|
-
measure_id: Measure/unit ID
|
|
374
|
+
measure_id: Measure/unit ID. Get this from search_food() results
|
|
375
|
+
(measureId field) or get_food() (defaultMeasureId or measures[].id).
|
|
376
|
+
0 is only valid for user-created custom foods; database-sourced
|
|
377
|
+
foods (CRDB/NCCDB/FDC) require a real measure ID.
|
|
375
378
|
grams: Weight in grams.
|
|
376
379
|
translation_id: Translation ID (from search results, usually 0).
|
|
377
380
|
day: Date to log to. Defaults to today.
|
|
@@ -88,6 +88,18 @@ def get_food_log(date: str | None = None) -> str:
|
|
|
88
88
|
Returns every food entry logged for the day, including food names,
|
|
89
89
|
amounts, meal groups, and nutrient data.
|
|
90
90
|
|
|
91
|
+
Also returns a top-level energy_summary field with pre-computed
|
|
92
|
+
values most relevant to the user:
|
|
93
|
+
|
|
94
|
+
- total_target_kcal: daily calorie target dynamically adjusted
|
|
95
|
+
for expenditure and weight goal (equivalent to Cronometer's
|
|
96
|
+
"Total Target" in the Energy Summary screen)
|
|
97
|
+
- consumed_kcal: total calories consumed
|
|
98
|
+
- remaining_kcal: calories remaining to stay on target
|
|
99
|
+
(total_target_kcal - consumed_kcal). Always report this
|
|
100
|
+
when summarizing the user's day. Prefer this over manually
|
|
101
|
+
deriving values from the burn breakdown fields.
|
|
102
|
+
|
|
91
103
|
Args:
|
|
92
104
|
date: Date as YYYY-MM-DD (defaults to today).
|
|
93
105
|
"""
|
|
@@ -95,9 +107,22 @@ def get_food_log(date: str | None = None) -> str:
|
|
|
95
107
|
client = _get_client()
|
|
96
108
|
day = _parse_date(date)
|
|
97
109
|
data = client.get_diary(day)
|
|
110
|
+
|
|
111
|
+
summary = (data or {}).get("summary") or {}
|
|
112
|
+
target = (summary.get("macros") or {}).get("energy")
|
|
113
|
+
consumed = (summary.get("consumed") or {}).get("total")
|
|
114
|
+
energy_summary: dict | None = None
|
|
115
|
+
if target is not None and consumed is not None:
|
|
116
|
+
energy_summary = {
|
|
117
|
+
"total_target_kcal": target,
|
|
118
|
+
"consumed_kcal": consumed,
|
|
119
|
+
"remaining_kcal": int(round(target - consumed)),
|
|
120
|
+
}
|
|
121
|
+
|
|
98
122
|
return _ok(
|
|
99
123
|
{
|
|
100
124
|
"date": date or str(date_module_today()),
|
|
125
|
+
"energy_summary": energy_summary,
|
|
101
126
|
"diary": data,
|
|
102
127
|
}
|
|
103
128
|
)
|
|
@@ -977,6 +1002,15 @@ class OAuthAuthorizationMiddleware:
|
|
|
977
1002
|
|
|
978
1003
|
|
|
979
1004
|
def main():
|
|
1005
|
+
# Load .env for local development. No-op if the file is missing.
|
|
1006
|
+
# override=False keeps real environment variables (Docker, systemd,
|
|
1007
|
+
# MCP client `env` blocks, etc.) authoritative over .env.
|
|
1008
|
+
from dotenv import find_dotenv, load_dotenv
|
|
1009
|
+
|
|
1010
|
+
dotenv_path = find_dotenv(usecwd=True)
|
|
1011
|
+
if dotenv_path and load_dotenv(dotenv_path, override=False):
|
|
1012
|
+
logger.info("Loaded .env from %s", dotenv_path)
|
|
1013
|
+
|
|
980
1014
|
transport = os.getenv("MCP_TRANSPORT", "stdio")
|
|
981
1015
|
|
|
982
1016
|
if transport == "stdio":
|
|
@@ -102,6 +102,7 @@ source = { editable = "." }
|
|
|
102
102
|
dependencies = [
|
|
103
103
|
{ name = "httpx" },
|
|
104
104
|
{ name = "mcp" },
|
|
105
|
+
{ name = "python-dotenv" },
|
|
105
106
|
{ name = "uvicorn" },
|
|
106
107
|
]
|
|
107
108
|
|
|
@@ -114,6 +115,7 @@ dev = [
|
|
|
114
115
|
requires-dist = [
|
|
115
116
|
{ name = "httpx", specifier = ">=0.27.0" },
|
|
116
117
|
{ name = "mcp", specifier = ">=1.0.0" },
|
|
118
|
+
{ name = "python-dotenv", specifier = ">=1.0.0" },
|
|
117
119
|
{ name = "uvicorn", specifier = ">=0.30.0" },
|
|
118
120
|
]
|
|
119
121
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|