ergzone-mcp 1.3.0 → 1.3.1

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.
package/README.md CHANGED
@@ -57,6 +57,7 @@ Prefer not to store your password? Use `ERGZONE_SESSION_TOKEN` instead (copied f
57
57
  | Tool | What it does |
58
58
  |------|------|
59
59
  | `auth_check` | who am I |
60
+ | `update_profile` | set max HR, resting HR, weight, weight unit |
60
61
  | `list_workouts` / `get_workout` | browse workouts |
61
62
  | `create_workout` / `update_workout` / `delete_workout` | manage workouts |
62
63
  | `build_intervals` | preview intervals before saving |
@@ -73,6 +74,7 @@ Just talk to Claude in plain language:
73
74
  - **Create** — *"Create a workout 'Tuesday tempo' with 3 × 2 min at 22 spm, 1 min rest."*
74
75
  - **Progressive intensity** — *"Build a workout: 2 blocks of 1-2-1-3-1-4 minutes, each interval 0.1s/500m faster than the previous, 4 min rest between blocks."*
75
76
  - **Results** — *"Show my last few ErgZone results."*
77
+ - **Profile** — *"Set my max heart rate to 186."*
76
78
  - **Analysis** — *"Analyze my last result: pace, SPI and HR zone per interval."*
77
79
  - **Stats** — *"How many meters did I row this month?"*
78
80
  - **Tidy up** — *"Delete the workout 'Tuesday tempo'."*
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ergzone-mcp",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "Unofficial MCP server for ErgZone (Concept2 rowing). Zero runtime dependencies.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/client.mjs CHANGED
@@ -109,12 +109,20 @@ export function todayISO() {
109
109
  return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}`;
110
110
  }
111
111
 
112
+ // A real ErgZone track id is a UUID. This guards against an unresolved MCPB
113
+ // placeholder (e.g. the literal "${user_config.track_id}" when the user leaves
114
+ // the field blank), which is truthy and would otherwise poison resolution and
115
+ // disable the auto-detect fallback.
116
+ const isValidTrackId = (v) =>
117
+ typeof v === 'string' && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v.trim());
118
+
112
119
  // Resolve the track to use, in order: explicit arg -> ERGZONE_TRACK_ID -> auto-discover
113
- // the user's personal "My Workouts" track. Discovery result is cached in memory.
120
+ // the user's personal "My Workouts" track. Invalid/placeholder values are ignored
121
+ // so the auto-detect path still runs. Discovery result is cached in memory.
114
122
  let trackIdCache = null;
115
123
  export async function resolveTrackId(explicit) {
116
- if (explicit) return explicit;
117
- if (process.env.ERGZONE_TRACK_ID) return process.env.ERGZONE_TRACK_ID;
124
+ if (isValidTrackId(explicit)) return explicit.trim();
125
+ if (isValidTrackId(process.env.ERGZONE_TRACK_ID)) return process.env.ERGZONE_TRACK_ID.trim();
118
126
  if (trackIdCache) return trackIdCache;
119
127
 
120
128
  const data = await gql('query{ tracks(onlyAdmin:true){ id name trackMode type isOwner } }');