cronometer-api-mcp 0.1.0__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.
@@ -0,0 +1,24 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ lint:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+
14
+ - name: Install uv
15
+ uses: astral-sh/setup-uv@v4
16
+
17
+ - name: Install dependencies
18
+ run: uv sync
19
+
20
+ - name: Lint with ruff
21
+ run: uv run ruff check
22
+
23
+ - name: Check formatting with ruff
24
+ run: uv run ruff format --check
@@ -0,0 +1,25 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ publish:
9
+ runs-on: ubuntu-latest
10
+ environment: release
11
+ permissions:
12
+ # Required for PyPI trusted publishing via OIDC
13
+ id-token: write
14
+
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - name: Install uv
19
+ uses: astral-sh/setup-uv@v4
20
+
21
+ - name: Build package
22
+ run: uv build
23
+
24
+ - name: Publish to PyPI
25
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,8 @@
1
+ .env
2
+ __pycache__/
3
+ *.pyc
4
+ .venv/
5
+ *.egg-info/
6
+ dist/
7
+ build/
8
+ .ruff_cache/
@@ -0,0 +1 @@
1
+ 3.14
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Randy Westergren
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,225 @@
1
+ Metadata-Version: 2.4
2
+ Name: cronometer-api-mcp
3
+ Version: 0.1.0
4
+ Summary: MCP server for Cronometer nutrition data using the mobile REST API
5
+ Author: Randy
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Keywords: cronometer,health,mcp,model-context-protocol,nutrition
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.14
14
+ Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
15
+ Requires-Python: >=3.14
16
+ Requires-Dist: httpx>=0.27.0
17
+ Requires-Dist: mcp>=1.0.0
18
+ Requires-Dist: uvicorn>=0.30.0
19
+ Description-Content-Type: text/markdown
20
+
21
+ # cronometer-api-mcp
22
+
23
+ <!-- mcp-name: io.github.rwestergren/cronometer-api-mcp -->
24
+
25
+ An [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) server for [Cronometer](https://cronometer.com/) nutrition tracking, built on the reverse-engineered mobile REST API.
26
+
27
+ Unlike [cronometer-mcp](https://github.com/cphoskins/cronometer-mcp) which uses the fragile GWT-RPC web protocol (with magic hashes that break on every Cronometer deploy), this server uses the same JSON API that the Cronometer Android app uses -- clean payloads, stable endpoints, no permutation hashes.
28
+
29
+ ## Features
30
+
31
+ - **Food log** -- diary entries with food names, amounts, meal groups
32
+ - **Nutrition data** -- daily macro/micro totals and nutrition scores with per-nutrient confidence
33
+ - **Food search** -- search the Cronometer food database, get detailed nutrition info
34
+ - **Diary management** -- add/remove entries, copy days, mark days complete
35
+ - **Custom foods** -- create foods with custom nutrition data
36
+ - **Macro targets** -- read weekly schedule and saved templates
37
+ - **Fasting** -- view history and aggregate statistics
38
+
39
+ ## Quick Start
40
+
41
+ ### 1. Install [uv](https://docs.astral.sh/uv/)
42
+
43
+ ```bash
44
+ curl -LsSf https://astral.sh/uv/install.sh | sh
45
+ ```
46
+
47
+ ### 2. Set credentials
48
+
49
+ ```bash
50
+ export CRONOMETER_USERNAME="your@email.com"
51
+ export CRONOMETER_PASSWORD="your-password"
52
+ ```
53
+
54
+ ### 3. Configure your MCP client
55
+
56
+ `uvx` downloads and runs the server on demand -- no separate install step.
57
+
58
+ #### OpenCode (`opencode.json`)
59
+
60
+ ```json
61
+ {
62
+ "$schema": "https://opencode.ai/config.json",
63
+ "mcp": {
64
+ "cronometer": {
65
+ "type": "local",
66
+ "command": ["uvx", "cronometer-api-mcp"],
67
+ "environment": {
68
+ "CRONOMETER_USERNAME": "{env:CRONOMETER_USERNAME}",
69
+ "CRONOMETER_PASSWORD": "{env:CRONOMETER_PASSWORD}"
70
+ },
71
+ "enabled": true
72
+ }
73
+ }
74
+ }
75
+ ```
76
+
77
+ #### Claude Desktop (`claude_desktop_config.json`)
78
+
79
+ ```json
80
+ {
81
+ "mcpServers": {
82
+ "cronometer": {
83
+ "command": "uvx",
84
+ "args": ["cronometer-api-mcp"],
85
+ "env": {
86
+ "CRONOMETER_USERNAME": "your@email.com",
87
+ "CRONOMETER_PASSWORD": "your-password"
88
+ }
89
+ }
90
+ }
91
+ }
92
+ ```
93
+
94
+ ## Available Tools
95
+
96
+ ### Food Log & Nutrition
97
+
98
+ | Tool | Description |
99
+ |------|-------------|
100
+ | `get_food_log` | Diary entries for a date with food names, amounts, and meal groups |
101
+ | `get_daily_nutrition` | Daily macro and micronutrient totals |
102
+ | `get_nutrition_scores` | Category scores (Vitamins, Minerals, etc.) with per-nutrient consumed amounts and confidence levels |
103
+
104
+ ### Food Search & Details
105
+
106
+ | Tool | Description |
107
+ |------|-------------|
108
+ | `search_foods` | Search the Cronometer food database by name |
109
+ | `get_food_details` | Full nutrition profile and serving sizes for a food |
110
+
111
+ ### Diary Management
112
+
113
+ | Tool | Description |
114
+ |------|-------------|
115
+ | `add_food_entry` | Log a food serving to the diary |
116
+ | `remove_food_entry` | Remove one or more diary entries |
117
+ | `add_custom_food` | Create a custom food with specified nutrition |
118
+ | `copy_day` | Copy all entries from the previous day |
119
+ | `mark_day_complete` | Mark a diary day as complete or incomplete |
120
+
121
+ ### Targets & Tracking
122
+
123
+ | Tool | Description |
124
+ |------|-------------|
125
+ | `get_macro_targets` | Weekly macro schedule and saved target templates |
126
+ | `get_fasting_history` | Fasting history within a date range |
127
+ | `get_fasting_stats` | Aggregate fasting statistics |
128
+
129
+ All date parameters use `YYYY-MM-DD` format and default to today when omitted.
130
+
131
+ ## Remote Deployment
132
+
133
+ The server supports remote deployment with OAuth 2.1 authorization (PKCE) for use with Claude.ai and other remote MCP clients.
134
+
135
+ ### Environment Variables
136
+
137
+ | Variable | Required | Description |
138
+ |----------|----------|-------------|
139
+ | `CRONOMETER_USERNAME` | Yes | Cronometer account email |
140
+ | `CRONOMETER_PASSWORD` | Yes | Cronometer account password |
141
+ | `MCP_TRANSPORT` | No | Transport mode: `stdio` (default), `sse`, or `streamable-http` |
142
+ | `MCP_AUTH_TOKEN` | No | Bearer token for remote auth (enables OAuth flow) |
143
+ | `MCP_OAUTH_CLIENT_ID` | No | OAuth client ID for remote clients |
144
+ | `MCP_OAUTH_CLIENT_SECRET` | No | OAuth client secret for remote clients |
145
+ | `MCP_BASE_URL` | No | Public base URL for OAuth metadata endpoints |
146
+ | `PORT` | No | Listen port for remote transports (default 8000) |
147
+
148
+ ### Dokku / Heroku Deployment
149
+
150
+ The project includes a `Procfile` and `.python-version` for direct deployment with the Heroku Python buildpack:
151
+
152
+ ```bash
153
+ # Create app
154
+ dokku apps:create cronometer-api-mcp
155
+
156
+ # Set environment
157
+ dokku config:set cronometer-api-mcp \
158
+ MCP_TRANSPORT=streamable-http \
159
+ MCP_AUTH_TOKEN=$(openssl rand -hex 32) \
160
+ MCP_OAUTH_CLIENT_ID=my-client \
161
+ MCP_OAUTH_CLIENT_SECRET=$(openssl rand -hex 32) \
162
+ MCP_BASE_URL=https://your-domain.com \
163
+ CRONOMETER_USERNAME=your@email.com \
164
+ CRONOMETER_PASSWORD=your-password
165
+
166
+ # Deploy
167
+ git push dokku main
168
+ ```
169
+
170
+ ### Claude.ai Remote Connection
171
+
172
+ When deployed remotely with OAuth configured, connect from Claude.ai using:
173
+
174
+ - **Server URL**: `https://your-domain.com/mcp`
175
+ - **OAuth Client ID**: Value of `MCP_OAUTH_CLIENT_ID`
176
+ - **OAuth Client Secret**: Value of `MCP_OAUTH_CLIENT_SECRET`
177
+
178
+ Claude.ai will open a browser tab for authorization. Click **Authorize** to complete the connection.
179
+
180
+ ## How It Works
181
+
182
+ This server communicates with `mobile.cronometer.com` -- the same REST API used by the Cronometer Android/Flutter app. The API was reverse-engineered through:
183
+
184
+ 1. Static analysis of `libapp.so` (Dart AOT snapshot) from the APK to discover endpoint names
185
+ 2. Traffic interception via Frida + mitmproxy to capture exact request/response formats
186
+ 3. Trial-and-error against the live API to confirm payload shapes
187
+
188
+ The API uses two protocols:
189
+
190
+ - **v2 (`POST /api/v2/*`)** -- JSON-body auth, used for most operations (food search, diary read/write, nutrition, fasting, macros)
191
+ - **v3 (`DELETE /api/v3/user/{id}/*`)** -- Header-based auth (`x-crono-session`), used for diary entry deletion
192
+
193
+ ## Python API
194
+
195
+ You can use the client directly:
196
+
197
+ ```python
198
+ from cronometer_api_mcp.client import CronometerClient
199
+ from datetime import date
200
+
201
+ client = CronometerClient()
202
+
203
+ # Search for foods
204
+ results = client.search_food("chicken breast")
205
+
206
+ # Get food details
207
+ food = client.get_food(results[0]["id"])
208
+
209
+ # Log a serving
210
+ client.add_serving(
211
+ food_id=food["id"],
212
+ measure_id=food["defaultMeasureId"],
213
+ grams=200,
214
+ )
215
+
216
+ # Get today's diary
217
+ diary = client.get_diary()
218
+
219
+ # Get nutrition scores
220
+ scores = client.get_nutrition_scores()
221
+ ```
222
+
223
+ ## License
224
+
225
+ MIT
@@ -0,0 +1 @@
1
+ web: cronometer-api-mcp
@@ -0,0 +1,205 @@
1
+ # cronometer-api-mcp
2
+
3
+ <!-- mcp-name: io.github.rwestergren/cronometer-api-mcp -->
4
+
5
+ An [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) server for [Cronometer](https://cronometer.com/) nutrition tracking, built on the reverse-engineered mobile REST API.
6
+
7
+ Unlike [cronometer-mcp](https://github.com/cphoskins/cronometer-mcp) which uses the fragile GWT-RPC web protocol (with magic hashes that break on every Cronometer deploy), this server uses the same JSON API that the Cronometer Android app uses -- clean payloads, stable endpoints, no permutation hashes.
8
+
9
+ ## Features
10
+
11
+ - **Food log** -- diary entries with food names, amounts, meal groups
12
+ - **Nutrition data** -- daily macro/micro totals and nutrition scores with per-nutrient confidence
13
+ - **Food search** -- search the Cronometer food database, get detailed nutrition info
14
+ - **Diary management** -- add/remove entries, copy days, mark days complete
15
+ - **Custom foods** -- create foods with custom nutrition data
16
+ - **Macro targets** -- read weekly schedule and saved templates
17
+ - **Fasting** -- view history and aggregate statistics
18
+
19
+ ## Quick Start
20
+
21
+ ### 1. Install [uv](https://docs.astral.sh/uv/)
22
+
23
+ ```bash
24
+ curl -LsSf https://astral.sh/uv/install.sh | sh
25
+ ```
26
+
27
+ ### 2. Set credentials
28
+
29
+ ```bash
30
+ export CRONOMETER_USERNAME="your@email.com"
31
+ export CRONOMETER_PASSWORD="your-password"
32
+ ```
33
+
34
+ ### 3. Configure your MCP client
35
+
36
+ `uvx` downloads and runs the server on demand -- no separate install step.
37
+
38
+ #### OpenCode (`opencode.json`)
39
+
40
+ ```json
41
+ {
42
+ "$schema": "https://opencode.ai/config.json",
43
+ "mcp": {
44
+ "cronometer": {
45
+ "type": "local",
46
+ "command": ["uvx", "cronometer-api-mcp"],
47
+ "environment": {
48
+ "CRONOMETER_USERNAME": "{env:CRONOMETER_USERNAME}",
49
+ "CRONOMETER_PASSWORD": "{env:CRONOMETER_PASSWORD}"
50
+ },
51
+ "enabled": true
52
+ }
53
+ }
54
+ }
55
+ ```
56
+
57
+ #### Claude Desktop (`claude_desktop_config.json`)
58
+
59
+ ```json
60
+ {
61
+ "mcpServers": {
62
+ "cronometer": {
63
+ "command": "uvx",
64
+ "args": ["cronometer-api-mcp"],
65
+ "env": {
66
+ "CRONOMETER_USERNAME": "your@email.com",
67
+ "CRONOMETER_PASSWORD": "your-password"
68
+ }
69
+ }
70
+ }
71
+ }
72
+ ```
73
+
74
+ ## Available Tools
75
+
76
+ ### Food Log & Nutrition
77
+
78
+ | Tool | Description |
79
+ |------|-------------|
80
+ | `get_food_log` | Diary entries for a date with food names, amounts, and meal groups |
81
+ | `get_daily_nutrition` | Daily macro and micronutrient totals |
82
+ | `get_nutrition_scores` | Category scores (Vitamins, Minerals, etc.) with per-nutrient consumed amounts and confidence levels |
83
+
84
+ ### Food Search & Details
85
+
86
+ | Tool | Description |
87
+ |------|-------------|
88
+ | `search_foods` | Search the Cronometer food database by name |
89
+ | `get_food_details` | Full nutrition profile and serving sizes for a food |
90
+
91
+ ### Diary Management
92
+
93
+ | Tool | Description |
94
+ |------|-------------|
95
+ | `add_food_entry` | Log a food serving to the diary |
96
+ | `remove_food_entry` | Remove one or more diary entries |
97
+ | `add_custom_food` | Create a custom food with specified nutrition |
98
+ | `copy_day` | Copy all entries from the previous day |
99
+ | `mark_day_complete` | Mark a diary day as complete or incomplete |
100
+
101
+ ### Targets & Tracking
102
+
103
+ | Tool | Description |
104
+ |------|-------------|
105
+ | `get_macro_targets` | Weekly macro schedule and saved target templates |
106
+ | `get_fasting_history` | Fasting history within a date range |
107
+ | `get_fasting_stats` | Aggregate fasting statistics |
108
+
109
+ All date parameters use `YYYY-MM-DD` format and default to today when omitted.
110
+
111
+ ## Remote Deployment
112
+
113
+ The server supports remote deployment with OAuth 2.1 authorization (PKCE) for use with Claude.ai and other remote MCP clients.
114
+
115
+ ### Environment Variables
116
+
117
+ | Variable | Required | Description |
118
+ |----------|----------|-------------|
119
+ | `CRONOMETER_USERNAME` | Yes | Cronometer account email |
120
+ | `CRONOMETER_PASSWORD` | Yes | Cronometer account password |
121
+ | `MCP_TRANSPORT` | No | Transport mode: `stdio` (default), `sse`, or `streamable-http` |
122
+ | `MCP_AUTH_TOKEN` | No | Bearer token for remote auth (enables OAuth flow) |
123
+ | `MCP_OAUTH_CLIENT_ID` | No | OAuth client ID for remote clients |
124
+ | `MCP_OAUTH_CLIENT_SECRET` | No | OAuth client secret for remote clients |
125
+ | `MCP_BASE_URL` | No | Public base URL for OAuth metadata endpoints |
126
+ | `PORT` | No | Listen port for remote transports (default 8000) |
127
+
128
+ ### Dokku / Heroku Deployment
129
+
130
+ The project includes a `Procfile` and `.python-version` for direct deployment with the Heroku Python buildpack:
131
+
132
+ ```bash
133
+ # Create app
134
+ dokku apps:create cronometer-api-mcp
135
+
136
+ # Set environment
137
+ dokku config:set cronometer-api-mcp \
138
+ MCP_TRANSPORT=streamable-http \
139
+ MCP_AUTH_TOKEN=$(openssl rand -hex 32) \
140
+ MCP_OAUTH_CLIENT_ID=my-client \
141
+ MCP_OAUTH_CLIENT_SECRET=$(openssl rand -hex 32) \
142
+ MCP_BASE_URL=https://your-domain.com \
143
+ CRONOMETER_USERNAME=your@email.com \
144
+ CRONOMETER_PASSWORD=your-password
145
+
146
+ # Deploy
147
+ git push dokku main
148
+ ```
149
+
150
+ ### Claude.ai Remote Connection
151
+
152
+ When deployed remotely with OAuth configured, connect from Claude.ai using:
153
+
154
+ - **Server URL**: `https://your-domain.com/mcp`
155
+ - **OAuth Client ID**: Value of `MCP_OAUTH_CLIENT_ID`
156
+ - **OAuth Client Secret**: Value of `MCP_OAUTH_CLIENT_SECRET`
157
+
158
+ Claude.ai will open a browser tab for authorization. Click **Authorize** to complete the connection.
159
+
160
+ ## How It Works
161
+
162
+ This server communicates with `mobile.cronometer.com` -- the same REST API used by the Cronometer Android/Flutter app. The API was reverse-engineered through:
163
+
164
+ 1. Static analysis of `libapp.so` (Dart AOT snapshot) from the APK to discover endpoint names
165
+ 2. Traffic interception via Frida + mitmproxy to capture exact request/response formats
166
+ 3. Trial-and-error against the live API to confirm payload shapes
167
+
168
+ The API uses two protocols:
169
+
170
+ - **v2 (`POST /api/v2/*`)** -- JSON-body auth, used for most operations (food search, diary read/write, nutrition, fasting, macros)
171
+ - **v3 (`DELETE /api/v3/user/{id}/*`)** -- Header-based auth (`x-crono-session`), used for diary entry deletion
172
+
173
+ ## Python API
174
+
175
+ You can use the client directly:
176
+
177
+ ```python
178
+ from cronometer_api_mcp.client import CronometerClient
179
+ from datetime import date
180
+
181
+ client = CronometerClient()
182
+
183
+ # Search for foods
184
+ results = client.search_food("chicken breast")
185
+
186
+ # Get food details
187
+ food = client.get_food(results[0]["id"])
188
+
189
+ # Log a serving
190
+ client.add_serving(
191
+ food_id=food["id"],
192
+ measure_id=food["defaultMeasureId"],
193
+ grams=200,
194
+ )
195
+
196
+ # Get today's diary
197
+ diary = client.get_diary()
198
+
199
+ # Get nutrition scores
200
+ scores = client.get_nutrition_scores()
201
+ ```
202
+
203
+ ## License
204
+
205
+ MIT
@@ -0,0 +1,39 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "cronometer-api-mcp"
7
+ version = "0.1.0"
8
+ description = "MCP server for Cronometer nutrition data using the mobile REST API"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.14"
12
+ authors = [
13
+ { name = "Randy" },
14
+ ]
15
+ keywords = ["cronometer", "mcp", "nutrition", "health", "model-context-protocol"]
16
+ classifiers = [
17
+ "Development Status :: 3 - Alpha",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.14",
22
+ "Topic :: Scientific/Engineering :: Medical Science Apps.",
23
+ ]
24
+ dependencies = [
25
+ "mcp>=1.0.0",
26
+ "httpx>=0.27.0",
27
+ "uvicorn>=0.30.0",
28
+ ]
29
+
30
+ [project.scripts]
31
+ cronometer-api-mcp = "cronometer_api_mcp.server:main"
32
+
33
+ [dependency-groups]
34
+ dev = [
35
+ "ruff>=0.8.0",
36
+ ]
37
+
38
+ [tool.hatch.build.targets.wheel]
39
+ packages = ["src/cronometer_api_mcp"]
@@ -0,0 +1,34 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
+ "name": "io.github.rwestergren/cronometer-api-mcp",
4
+ "description": "MCP server for Cronometer nutrition tracking via the mobile REST API — food logs, nutrition scores, diary management, macros, fasting",
5
+ "repository": {
6
+ "url": "https://github.com/rwestergren/cronometer-api-mcp",
7
+ "source": "github"
8
+ },
9
+ "version": "0.1.0",
10
+ "packages": [
11
+ {
12
+ "registryType": "pypi",
13
+ "identifier": "cronometer-api-mcp",
14
+ "version": "0.1.0",
15
+ "transport": {
16
+ "type": "stdio"
17
+ },
18
+ "environmentVariables": [
19
+ {
20
+ "name": "CRONOMETER_USERNAME",
21
+ "description": "Your Cronometer account email",
22
+ "isRequired": true,
23
+ "isSecret": false
24
+ },
25
+ {
26
+ "name": "CRONOMETER_PASSWORD",
27
+ "description": "Your Cronometer account password",
28
+ "isRequired": true,
29
+ "isSecret": true
30
+ }
31
+ ]
32
+ }
33
+ ]
34
+ }
@@ -0,0 +1,5 @@
1
+ """Cronometer MCP server using the mobile REST API."""
2
+
3
+ from .client import CronometerClient, CronometerError
4
+
5
+ __all__ = ["CronometerClient", "CronometerError"]