intervals-icu-mcp-server 0.1.4 → 0.1.6

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/dist/client.d.ts CHANGED
@@ -7,17 +7,17 @@ export declare const ActivitySchema: z.ZodObject<{
7
7
  id: z.ZodString;
8
8
  name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
9
9
  type: z.ZodOptional<z.ZodString>;
10
- startTime: z.ZodOptional<z.ZodString>;
10
+ start_date_local: z.ZodOptional<z.ZodString>;
11
11
  distance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
12
- duration: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
12
+ elapsed_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
13
13
  moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
14
- elevationGain: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
15
- avgPower: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
14
+ total_elevation_gain: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
15
+ icu_average_watts: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
16
16
  icu_weighted_avg_watts: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
17
- trainingLoad: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
17
+ icu_training_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
18
18
  icu_ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
19
19
  icu_intensity: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
20
- avgHr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
20
+ average_heartrate: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
21
21
  max_heartrate: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
22
22
  average_cadence: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
23
23
  calories: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
@@ -27,6 +27,8 @@ export declare const ActivitySchema: z.ZodObject<{
27
27
  trimp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
28
28
  average_temp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
29
29
  perceived_exertion: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
30
+ icu_rpe: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
31
+ session_rpe: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
30
32
  feel: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
31
33
  description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
32
34
  trainer: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
@@ -34,17 +36,17 @@ export declare const ActivitySchema: z.ZodObject<{
34
36
  id: z.ZodString;
35
37
  name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
36
38
  type: z.ZodOptional<z.ZodString>;
37
- startTime: z.ZodOptional<z.ZodString>;
39
+ start_date_local: z.ZodOptional<z.ZodString>;
38
40
  distance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
39
- duration: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
41
+ elapsed_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
40
42
  moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
41
- elevationGain: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
42
- avgPower: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
43
+ total_elevation_gain: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
44
+ icu_average_watts: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
43
45
  icu_weighted_avg_watts: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
44
- trainingLoad: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
46
+ icu_training_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
45
47
  icu_ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
46
48
  icu_intensity: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
47
- avgHr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
49
+ average_heartrate: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
48
50
  max_heartrate: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
49
51
  average_cadence: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
50
52
  calories: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
@@ -54,6 +56,8 @@ export declare const ActivitySchema: z.ZodObject<{
54
56
  trimp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
55
57
  average_temp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
56
58
  perceived_exertion: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
59
+ icu_rpe: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
60
+ session_rpe: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
57
61
  feel: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
58
62
  description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
59
63
  trainer: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
@@ -61,17 +65,17 @@ export declare const ActivitySchema: z.ZodObject<{
61
65
  id: z.ZodString;
62
66
  name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
63
67
  type: z.ZodOptional<z.ZodString>;
64
- startTime: z.ZodOptional<z.ZodString>;
68
+ start_date_local: z.ZodOptional<z.ZodString>;
65
69
  distance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
66
- duration: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
70
+ elapsed_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
67
71
  moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
68
- elevationGain: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
69
- avgPower: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
72
+ total_elevation_gain: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
73
+ icu_average_watts: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
70
74
  icu_weighted_avg_watts: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
71
- trainingLoad: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
75
+ icu_training_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
72
76
  icu_ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
73
77
  icu_intensity: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
74
- avgHr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
78
+ average_heartrate: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
75
79
  max_heartrate: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
76
80
  average_cadence: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
77
81
  calories: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
@@ -81,6 +85,8 @@ export declare const ActivitySchema: z.ZodObject<{
81
85
  trimp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
82
86
  average_temp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
83
87
  perceived_exertion: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
88
+ icu_rpe: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
89
+ session_rpe: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
84
90
  feel: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
85
91
  description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
86
92
  trainer: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
@@ -160,46 +166,52 @@ export type Wellness = z.infer<typeof WellnessSchema>;
160
166
  export declare const EventSchema: z.ZodObject<{
161
167
  id: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
162
168
  date: z.ZodOptional<z.ZodString>;
169
+ start_date_local: z.ZodOptional<z.ZodNullable<z.ZodString>>;
170
+ end_date_local: z.ZodOptional<z.ZodNullable<z.ZodString>>;
171
+ category: z.ZodOptional<z.ZodNullable<z.ZodString>>;
172
+ show_as_note: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
163
173
  name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
164
174
  description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
165
- race: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
166
- workout: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
167
- priority: z.ZodOptional<z.ZodNullable<z.ZodString>>;
175
+ color: z.ZodOptional<z.ZodNullable<z.ZodString>>;
168
176
  }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
169
177
  id: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
170
178
  date: z.ZodOptional<z.ZodString>;
179
+ start_date_local: z.ZodOptional<z.ZodNullable<z.ZodString>>;
180
+ end_date_local: z.ZodOptional<z.ZodNullable<z.ZodString>>;
181
+ category: z.ZodOptional<z.ZodNullable<z.ZodString>>;
182
+ show_as_note: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
171
183
  name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
172
184
  description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
173
- race: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
174
- workout: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
175
- priority: z.ZodOptional<z.ZodNullable<z.ZodString>>;
185
+ color: z.ZodOptional<z.ZodNullable<z.ZodString>>;
176
186
  }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
177
187
  id: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
178
188
  date: z.ZodOptional<z.ZodString>;
189
+ start_date_local: z.ZodOptional<z.ZodNullable<z.ZodString>>;
190
+ end_date_local: z.ZodOptional<z.ZodNullable<z.ZodString>>;
191
+ category: z.ZodOptional<z.ZodNullable<z.ZodString>>;
192
+ show_as_note: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
179
193
  name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
180
194
  description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
181
- race: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
182
- workout: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
183
- priority: z.ZodOptional<z.ZodNullable<z.ZodString>>;
195
+ color: z.ZodOptional<z.ZodNullable<z.ZodString>>;
184
196
  }, z.ZodTypeAny, "passthrough">>;
185
197
  export type Event = z.infer<typeof EventSchema>;
186
198
  export declare const IntervalSchema: z.ZodObject<{
187
- icu_intervals: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>;
188
- icu_groups: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>;
199
+ icu_intervals: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>>;
200
+ icu_groups: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>>;
189
201
  }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
190
- icu_intervals: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>;
191
- icu_groups: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>;
202
+ icu_intervals: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>>;
203
+ icu_groups: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>>;
192
204
  }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
193
- icu_intervals: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>;
194
- icu_groups: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>;
205
+ icu_intervals: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>>;
206
+ icu_groups: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>>;
195
207
  }, z.ZodTypeAny, "passthrough">>;
196
208
  export interface EventInput {
197
209
  name?: string;
198
210
  description?: string;
199
211
  start_date_local?: string;
212
+ end_date_local?: string;
200
213
  category?: string;
201
214
  type?: string;
202
- race?: boolean;
203
215
  distance?: number;
204
216
  sub_type?: string;
205
217
  workout_doc?: unknown;
@@ -210,99 +222,91 @@ export declare const AthleteSchema: z.ZodObject<{
210
222
  email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
211
223
  sex: z.ZodOptional<z.ZodNullable<z.ZodString>>;
212
224
  weight: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
213
- dob: z.ZodOptional<z.ZodNullable<z.ZodString>>;
225
+ icu_date_of_birth: z.ZodOptional<z.ZodNullable<z.ZodString>>;
214
226
  city: z.ZodOptional<z.ZodNullable<z.ZodString>>;
215
227
  country: z.ZodOptional<z.ZodNullable<z.ZodString>>;
216
- icu_ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
217
- icu_lthr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
218
228
  icu_resting_hr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
219
229
  icu_weight: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
220
- icu_vo2max: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
221
230
  }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
222
231
  id: z.ZodOptional<z.ZodString>;
223
232
  name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
224
233
  email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
225
234
  sex: z.ZodOptional<z.ZodNullable<z.ZodString>>;
226
235
  weight: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
227
- dob: z.ZodOptional<z.ZodNullable<z.ZodString>>;
236
+ icu_date_of_birth: z.ZodOptional<z.ZodNullable<z.ZodString>>;
228
237
  city: z.ZodOptional<z.ZodNullable<z.ZodString>>;
229
238
  country: z.ZodOptional<z.ZodNullable<z.ZodString>>;
230
- icu_ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
231
- icu_lthr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
232
239
  icu_resting_hr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
233
240
  icu_weight: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
234
- icu_vo2max: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
235
241
  }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
236
242
  id: z.ZodOptional<z.ZodString>;
237
243
  name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
238
244
  email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
239
245
  sex: z.ZodOptional<z.ZodNullable<z.ZodString>>;
240
246
  weight: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
241
- dob: z.ZodOptional<z.ZodNullable<z.ZodString>>;
247
+ icu_date_of_birth: z.ZodOptional<z.ZodNullable<z.ZodString>>;
242
248
  city: z.ZodOptional<z.ZodNullable<z.ZodString>>;
243
249
  country: z.ZodOptional<z.ZodNullable<z.ZodString>>;
244
- icu_ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
245
- icu_lthr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
246
250
  icu_resting_hr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
247
251
  icu_weight: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
248
- icu_vo2max: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
249
252
  }, z.ZodTypeAny, "passthrough">>;
250
253
  export type Athlete = z.infer<typeof AthleteSchema>;
251
- export declare const AthleteSummarySchema: z.ZodObject<{
252
- ctl: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
253
- atl: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
254
- tsb: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
255
- rampRate: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
256
- ctlLoad: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
257
- atlLoad: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
258
- }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
259
- ctl: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
260
- atl: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
261
- tsb: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
262
- rampRate: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
263
- ctlLoad: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
264
- atlLoad: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
265
- }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
266
- ctl: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
267
- atl: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
268
- tsb: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
269
- rampRate: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
270
- ctlLoad: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
271
- atlLoad: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
272
- }, z.ZodTypeAny, "passthrough">>;
273
- export type AthleteSummary = z.infer<typeof AthleteSummarySchema>;
274
- export declare const ZonesSchema: z.ZodObject<{
275
- power: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>;
276
- hr: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>;
277
- pace: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>;
254
+ export declare const SportSettingsSchema: z.ZodObject<{
255
+ types: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
256
+ ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
257
+ lthr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
258
+ max_hr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
259
+ threshold_pace: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
260
+ power_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
261
+ power_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
262
+ hr_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
263
+ hr_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
264
+ pace_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
265
+ pace_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
278
266
  }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
279
- power: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>;
280
- hr: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>;
281
- pace: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>;
267
+ types: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
268
+ ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
269
+ lthr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
270
+ max_hr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
271
+ threshold_pace: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
272
+ power_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
273
+ power_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
274
+ hr_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
275
+ hr_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
276
+ pace_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
277
+ pace_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
282
278
  }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
283
- power: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>;
284
- hr: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>;
285
- pace: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>, "many">>;
279
+ types: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
280
+ ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
281
+ lthr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
282
+ max_hr: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
283
+ threshold_pace: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
284
+ power_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
285
+ power_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
286
+ hr_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
287
+ hr_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
288
+ pace_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
289
+ pace_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
286
290
  }, z.ZodTypeAny, "passthrough">>;
287
- export type Zones = z.infer<typeof ZonesSchema>;
291
+ export type SportSettings = z.infer<typeof SportSettingsSchema>;
288
292
  export declare const WorkoutSchema: z.ZodObject<{
289
293
  id: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
290
294
  name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
291
295
  description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
292
296
  type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
293
- created: z.ZodOptional<z.ZodNullable<z.ZodString>>;
297
+ updated: z.ZodOptional<z.ZodNullable<z.ZodString>>;
294
298
  }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
295
299
  id: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
296
300
  name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
297
301
  description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
298
302
  type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
299
- created: z.ZodOptional<z.ZodNullable<z.ZodString>>;
303
+ updated: z.ZodOptional<z.ZodNullable<z.ZodString>>;
300
304
  }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
301
305
  id: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
302
306
  name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
303
307
  description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
304
308
  type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
305
- created: z.ZodOptional<z.ZodNullable<z.ZodString>>;
309
+ updated: z.ZodOptional<z.ZodNullable<z.ZodString>>;
306
310
  }, z.ZodTypeAny, "passthrough">>;
307
311
  export type Workout = z.infer<typeof WorkoutSchema>;
308
312
  export interface WorkoutInput {
@@ -352,8 +356,8 @@ export declare function createEvent(config: ClientConfig, input: EventInput): Pr
352
356
  export declare function updateEvent(config: ClientConfig, eventId: string, input: EventInput): Promise<Event>;
353
357
  export declare function deleteEvent(config: ClientConfig, eventId: string): Promise<void>;
354
358
  export declare function getAthleteProfile(config: ClientConfig): Promise<Athlete>;
355
- export declare function getAthleteZones(config: ClientConfig): Promise<Zones>;
356
- export declare function getAthleteSummary(config: ClientConfig): Promise<AthleteSummary>;
359
+ export declare function getAthleteZones(config: ClientConfig): Promise<SportSettings[]>;
360
+ export declare function getAthleteSummary(config: ClientConfig): Promise<AthleteFitness | undefined>;
357
361
  export declare function getWellnessDay(config: ClientConfig, date: string): Promise<Wellness>;
358
362
  export declare function updateWellness(config: ClientConfig, date: string, input: WellnessInput): Promise<Wellness>;
359
363
  export declare function getActivityStreams(config: ClientConfig, activityId: string, types?: string[]): Promise<Record<string, unknown[]>>;
package/dist/client.js CHANGED
@@ -28,17 +28,17 @@ export const ActivitySchema = z.object({
28
28
  id: z.string(),
29
29
  name: z.string().nullable().optional(),
30
30
  type: z.string().optional(),
31
- startTime: z.string().optional(),
31
+ start_date_local: z.string().optional(),
32
32
  distance: z.number().nullable().optional(),
33
- duration: z.number().nullable().optional(),
33
+ elapsed_time: z.number().nullable().optional(),
34
34
  moving_time: z.number().nullable().optional(),
35
- elevationGain: z.number().nullable().optional(),
36
- avgPower: z.number().nullable().optional(),
35
+ total_elevation_gain: z.number().nullable().optional(),
36
+ icu_average_watts: z.number().nullable().optional(),
37
37
  icu_weighted_avg_watts: z.number().nullable().optional(),
38
- trainingLoad: z.number().nullable().optional(),
38
+ icu_training_load: z.number().nullable().optional(),
39
39
  icu_ftp: z.number().nullable().optional(),
40
40
  icu_intensity: z.number().nullable().optional(),
41
- avgHr: z.number().nullable().optional(),
41
+ average_heartrate: z.number().nullable().optional(),
42
42
  max_heartrate: z.number().nullable().optional(),
43
43
  average_cadence: z.number().nullable().optional(),
44
44
  calories: z.number().nullable().optional(),
@@ -48,6 +48,8 @@ export const ActivitySchema = z.object({
48
48
  trimp: z.number().nullable().optional(),
49
49
  average_temp: z.number().nullable().optional(),
50
50
  perceived_exertion: z.number().nullable().optional(),
51
+ icu_rpe: z.number().nullable().optional(),
52
+ session_rpe: z.number().nullable().optional(),
51
53
  feel: z.number().nullable().optional(),
52
54
  description: z.string().nullable().optional(),
53
55
  trainer: z.boolean().nullable().optional(),
@@ -79,15 +81,17 @@ export const WellnessSchema = z.object({
79
81
  export const EventSchema = z.object({
80
82
  id: z.union([z.string(), z.number()]),
81
83
  date: z.string().optional(),
84
+ start_date_local: z.string().nullable().optional(),
85
+ end_date_local: z.string().nullable().optional(),
86
+ category: z.string().nullable().optional(),
87
+ show_as_note: z.boolean().nullable().optional(),
82
88
  name: z.string().nullable().optional(),
83
89
  description: z.string().nullable().optional(),
84
- race: z.boolean().nullable().optional(),
85
- workout: z.unknown().nullable().optional(),
86
- priority: z.string().nullable().optional(),
90
+ color: z.string().nullable().optional(),
87
91
  }).passthrough();
88
92
  export const IntervalSchema = z.object({
89
- icu_intervals: z.array(z.record(z.unknown())).optional(),
90
- icu_groups: z.array(z.record(z.unknown())).optional(),
93
+ icu_intervals: z.array(z.record(z.unknown())).nullable().optional(),
94
+ icu_groups: z.array(z.record(z.unknown())).nullable().optional(),
91
95
  }).passthrough();
92
96
  export const AthleteSchema = z.object({
93
97
  id: z.string().optional(),
@@ -95,34 +99,31 @@ export const AthleteSchema = z.object({
95
99
  email: z.string().nullable().optional(),
96
100
  sex: z.string().nullable().optional(),
97
101
  weight: z.number().nullable().optional(),
98
- dob: z.string().nullable().optional(),
102
+ icu_date_of_birth: z.string().nullable().optional(),
99
103
  city: z.string().nullable().optional(),
100
104
  country: z.string().nullable().optional(),
101
- icu_ftp: z.number().nullable().optional(),
102
- icu_lthr: z.number().nullable().optional(),
103
105
  icu_resting_hr: z.number().nullable().optional(),
104
106
  icu_weight: z.number().nullable().optional(),
105
- icu_vo2max: z.number().nullable().optional(),
106
107
  }).passthrough();
107
- export const AthleteSummarySchema = z.object({
108
- ctl: z.number().nullable().optional(),
109
- atl: z.number().nullable().optional(),
110
- tsb: z.number().nullable().optional(),
111
- rampRate: z.number().nullable().optional(),
112
- ctlLoad: z.number().nullable().optional(),
113
- atlLoad: z.number().nullable().optional(),
114
- }).passthrough();
115
- export const ZonesSchema = z.object({
116
- power: z.array(z.record(z.unknown())).optional(),
117
- hr: z.array(z.record(z.unknown())).optional(),
118
- pace: z.array(z.record(z.unknown())).optional(),
108
+ export const SportSettingsSchema = z.object({
109
+ types: z.array(z.string()).nullable().optional(),
110
+ ftp: z.number().nullable().optional(),
111
+ lthr: z.number().nullable().optional(),
112
+ max_hr: z.number().nullable().optional(),
113
+ threshold_pace: z.number().nullable().optional(),
114
+ power_zones: z.array(z.number()).nullable().optional(),
115
+ power_zone_names: z.array(z.string()).nullable().optional(),
116
+ hr_zones: z.array(z.number()).nullable().optional(),
117
+ hr_zone_names: z.array(z.string()).nullable().optional(),
118
+ pace_zones: z.array(z.number()).nullable().optional(),
119
+ pace_zone_names: z.array(z.string()).nullable().optional(),
119
120
  }).passthrough();
120
121
  export const WorkoutSchema = z.object({
121
122
  id: z.union([z.string(), z.number()]).optional(),
122
123
  name: z.string().nullable().optional(),
123
124
  description: z.string().nullable().optional(),
124
125
  type: z.string().nullable().optional(),
125
- created: z.string().nullable().optional(),
126
+ updated: z.string().nullable().optional(),
126
127
  }).passthrough();
127
128
  // ---- API methods ---- //
128
129
  export async function getActivities(config, params) {
@@ -161,10 +162,7 @@ export async function getEventById(config, eventId) {
161
162
  export async function getNotesByDate(config, date) {
162
163
  const data = await request(`/athlete/${config.athleteId}/events`, config, { oldest: date, newest: date });
163
164
  const events = z.array(EventSchema).parse(data);
164
- return events.filter((e) => {
165
- const raw = e;
166
- return raw["category"] === "NOTE" || (!e.race && !e.workout);
167
- });
165
+ return events.filter((e) => e.category === "NOTE" || e.show_as_note === true);
168
166
  }
169
167
  async function mutate(method, path, config, body) {
170
168
  const url = `${BASE_URL}${path}`;
@@ -202,12 +200,14 @@ export async function getAthleteProfile(config) {
202
200
  return AthleteSchema.parse(data);
203
201
  }
204
202
  export async function getAthleteZones(config) {
205
- const data = await request(`/athlete/${config.athleteId}/zones`, config);
206
- return ZonesSchema.parse(data);
203
+ const data = await request(`/athlete/${config.athleteId}/sport-settings`, config);
204
+ return z.array(SportSettingsSchema).parse(data);
207
205
  }
208
206
  export async function getAthleteSummary(config) {
209
- const data = await request(`/athlete/${config.athleteId}/summary`, config);
210
- return AthleteSummarySchema.parse(data);
207
+ const today = new Date().toISOString().slice(0, 10);
208
+ const weekAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString().slice(0, 10);
209
+ const entries = await getAthleteFitness(config, { startDate: weekAgo, endDate: today });
210
+ return entries.at(-1);
211
211
  }
212
212
  export async function getWellnessDay(config, date) {
213
213
  const data = await request(`/athlete/${config.athleteId}/wellness/${date}`, config);
@@ -222,7 +222,12 @@ export async function getActivityStreams(config, activityId, types) {
222
222
  if (types?.length)
223
223
  params["types"] = types.join(",");
224
224
  const data = await request(`/activity/${activityId}/streams.json`, config, params);
225
- return data;
225
+ const result = {};
226
+ for (const stream of data) {
227
+ if (stream.type)
228
+ result[stream.type] = stream.data ?? [];
229
+ }
230
+ return result;
226
231
  }
227
232
  export async function getActivityPowerCurves(config, activityId) {
228
233
  return request(`/activity/${activityId}/power-curves`, config);
@@ -240,7 +245,7 @@ export async function bulkCreateEvents(config, events) {
240
245
  return z.array(EventSchema).parse(data);
241
246
  }
242
247
  export async function bulkDeleteEvents(config, eventIds) {
243
- await mutate("POST", `/athlete/${config.athleteId}/events/bulk-delete`, config, eventIds);
248
+ await mutate("PUT", `/athlete/${config.athleteId}/events/bulk-delete`, config, eventIds.map((id) => ({ id: Number(id) })));
244
249
  }
245
250
  export const AthleteFitnessSchema = z.object({
246
251
  date: z.string().optional(),
@@ -254,7 +259,7 @@ export const AthleteFitnessSchema = z.object({
254
259
  weight: z.number().nullable().optional(),
255
260
  }).passthrough();
256
261
  export async function getAthleteFitness(config, params) {
257
- const data = await request(`/athlete/${config.athleteId}/athlete-summary.json`, config, { oldest: params.startDate, newest: params.endDate, athleteId: config.athleteId });
262
+ const data = await request(`/athlete/${config.athleteId}/athlete-summary.json`, config, { start: params.startDate, end: params.endDate });
258
263
  const all = z.array(AthleteFitnessSchema).parse(data);
259
264
  return all.filter((e) => e["athlete_id"] === config.athleteId);
260
265
  }
package/dist/format.d.ts CHANGED
@@ -1,5 +1,6 @@
1
- import type { Activity, Wellness, Event } from "./client.js";
1
+ import type { Activity, Wellness, Event, SportSettings } from "./client.js";
2
2
  export declare function formatActivity(a: Activity): string;
3
3
  export declare function formatWellness(date: string, w: Wellness): string;
4
4
  export declare function formatEvent(e: Event): string;
5
+ export declare function formatSportZones(s: SportSettings): string;
5
6
  export declare function formatIntervalRow(interval: Record<string, unknown>, idx: number): string;
package/dist/format.js CHANGED
@@ -4,26 +4,26 @@ function n(v, unit = "") {
4
4
  return `${v}${unit}`;
5
5
  }
6
6
  export function formatActivity(a) {
7
- const startTime = a.startTime
8
- ? new Date(a.startTime).toLocaleString()
7
+ const startTime = a.start_date_local
8
+ ? new Date(a.start_date_local).toLocaleString()
9
9
  : "Unknown";
10
10
  const lines = [
11
11
  `**${a.name ?? "Unnamed"}** (${a.id})`,
12
12
  `Type: ${n(a.type)} | Date: ${startTime}`,
13
- `Distance: ${n(a.distance, " m")} | Duration: ${n(a.duration, " s")} | Moving: ${n(a.moving_time, " s")}`,
14
- `Elevation: ${n(a.elevationGain, " m")}`,
13
+ `Distance: ${n(a.distance, " m")} | Duration: ${n(a.elapsed_time, " s")} | Moving: ${n(a.moving_time, " s")}`,
14
+ `Elevation: ${n(a.total_elevation_gain, " m")}`,
15
15
  "",
16
16
  "Power:",
17
- ` Avg: ${n(a.avgPower, " W")} | Weighted Avg: ${n(a.icu_weighted_avg_watts, " W")} | FTP: ${n(a.icu_ftp, " W")}`,
18
- ` Training Load: ${n(a.trainingLoad)} | Intensity: ${n(a.icu_intensity)}`,
17
+ ` Avg: ${n(a.icu_average_watts, " W")} | Weighted Avg: ${n(a.icu_weighted_avg_watts, " W")} | FTP: ${n(a.icu_ftp, " W")}`,
18
+ ` Training Load: ${n(a.icu_training_load)} | Intensity: ${n(a.icu_intensity)}`,
19
19
  "",
20
20
  "Heart Rate:",
21
- ` Avg: ${n(a.avgHr, " bpm")} | Max: ${n(a.max_heartrate, " bpm")}`,
21
+ ` Avg: ${n(a.average_heartrate, " bpm")} | Max: ${n(a.max_heartrate, " bpm")}`,
22
22
  "",
23
23
  "Other:",
24
24
  ` Cadence: ${n(a.average_cadence, " rpm")} | Calories: ${n(a.calories)} | Speed: ${n(a.average_speed, " m/s")}`,
25
25
  ` Temp: ${n(a.average_temp, "°C")} | Trainer: ${a.trainer ? "Yes" : "No"}`,
26
- ` RPE: ${n(a.perceived_exertion)}/10 | Feel: ${n(a.feel)}/10`,
26
+ ` RPE: ${n(a.icu_rpe ?? a.perceived_exertion)}/10 | Feel: ${n(a.feel)}/10`,
27
27
  "",
28
28
  "Fitness:",
29
29
  ` CTL: ${n(a.icu_ctl)} | ATL: ${n(a.icu_atl)} | TRIMP: ${n(a.trimp)}`,
@@ -62,16 +62,71 @@ export function formatWellness(date, w) {
62
62
  .trimEnd();
63
63
  }
64
64
  export function formatEvent(e) {
65
- const type = e.race ? "Race" : e.workout ? "Workout" : "Event";
65
+ const category = e.category ?? "";
66
+ const type = category.startsWith("RACE")
67
+ ? "Race"
68
+ : category === "WORKOUT"
69
+ ? "Workout"
70
+ : category === "NOTE" || e.show_as_note
71
+ ? "Note"
72
+ : "Event";
73
+ const start = e.start_date_local ?? e.date ?? "Unknown";
74
+ const dateLabel = e.end_date_local && e.end_date_local !== e.start_date_local
75
+ ? `${start} to ${e.end_date_local}`
76
+ : start;
66
77
  return [
67
78
  `**${e.name ?? "Unnamed"}** (${e.id})`,
68
- `Type: ${type} | Date: ${e.date ?? "Unknown"}`,
79
+ `Type: ${type} | Date: ${dateLabel}`,
80
+ e.category ? `Category: ${e.category}` : "",
69
81
  e.description ? `Description: ${e.description}` : "",
70
- e.priority ? `Priority: ${e.priority}` : "",
71
82
  ]
72
83
  .filter(Boolean)
73
84
  .join("\n");
74
85
  }
86
+ function zoneRanges(breakpoints, names) {
87
+ const count = names?.length ?? (breakpoints?.length ?? 0) + 1;
88
+ const ranges = [];
89
+ let from = 0;
90
+ for (let i = 0; i < count; i++) {
91
+ const raw = breakpoints && i < breakpoints.length ? breakpoints[i] : null;
92
+ // Intervals.icu caps the top zone with a 999 sentinel meaning "no upper bound".
93
+ const to = raw != null && raw < 900 ? raw : null;
94
+ ranges.push({ name: names?.[i] ?? `Z${i + 1}`, from, to });
95
+ if (to != null)
96
+ from = to;
97
+ }
98
+ return ranges;
99
+ }
100
+ export function formatSportZones(s) {
101
+ const title = s.types?.length ? s.types.join(", ") : "Default";
102
+ const lines = [`## ${title}`, ""];
103
+ if (s.power_zones?.length) {
104
+ lines.push(`Power Zones${s.ftp != null ? ` (FTP: ${s.ftp}W)` : ""}:`);
105
+ for (const z of zoneRanges(s.power_zones, s.power_zone_names)) {
106
+ const abs = s.ftp != null ? ` (${Math.round((s.ftp * z.from) / 100)}-${z.to != null ? Math.round((s.ftp * z.to) / 100) + "W" : "W+"})` : "";
107
+ const pct = z.to != null ? `${z.from}-${z.to}%` : `${z.from}%+`;
108
+ lines.push(` ${z.name}: ${pct}${abs}`);
109
+ }
110
+ lines.push("");
111
+ }
112
+ if (s.hr_zones?.length) {
113
+ lines.push(`HR Zones${s.lthr != null ? ` (LTHR: ${s.lthr}bpm)` : ""}:`);
114
+ for (const z of zoneRanges(s.hr_zones, s.hr_zone_names)) {
115
+ const abs = s.lthr != null ? ` (${Math.round((s.lthr * z.from) / 100)}-${z.to != null ? Math.round((s.lthr * z.to) / 100) + "bpm" : "bpm+"})` : "";
116
+ const pct = z.to != null ? `${z.from}-${z.to}%` : `${z.from}%+`;
117
+ lines.push(` ${z.name}: ${pct}${abs}`);
118
+ }
119
+ lines.push("");
120
+ }
121
+ if (s.pace_zones?.length) {
122
+ lines.push("Pace Zones (% of threshold pace):");
123
+ for (const z of zoneRanges(s.pace_zones, s.pace_zone_names)) {
124
+ const pct = z.to != null ? `${z.from}-${z.to}%` : `${z.from}%+`;
125
+ lines.push(` ${z.name}: ${pct}`);
126
+ }
127
+ }
128
+ return lines.join("\n").trimEnd();
129
+ }
75
130
  export function formatIntervalRow(interval, idx) {
76
131
  const label = interval["label"] ?? `Interval ${idx}`;
77
132
  const type = interval["type"] ?? "Unknown";
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
5
5
  import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
6
6
  import { z } from "zod";
7
7
  import { getActivities, getActivityDetails, getActivityIntervals, getWellness, getEvents, getEventById, getNotesByDate, createEvent, updateEvent, deleteEvent, getAthleteProfile, getAthleteZones, getAthleteSummary, getWellnessDay, updateWellness, getActivityStreams, getActivityPowerCurves, listWorkouts, createWorkout, bulkCreateEvents, bulkDeleteEvents, getAthleteFitness, } from "./client.js";
8
- import { formatActivity, formatWellness, formatEvent, formatIntervalRow, } from "./format.js";
8
+ import { formatActivity, formatWellness, formatEvent, formatIntervalRow, formatSportZones, } from "./format.js";
9
9
  function getConfig(args) {
10
10
  const apiKey = args["api_key"] ?? process.env.API_KEY ?? "";
11
11
  const athleteId = args["athlete_id"] ??
@@ -119,11 +119,11 @@ const TOOLS = [
119
119
  required: ["start_date_local"],
120
120
  properties: {
121
121
  start_date_local: { type: "string", description: "Date/time in ISO 8601 format, e.g. 2024-06-01T08:00:00" },
122
+ end_date_local: { type: "string", description: "End date in ISO 8601 format for a multi-day event (e.g. a NOTE, HOLIDAY, SICK, or INJURED entry spanning several days), e.g. 2024-06-05" },
122
123
  name: { type: "string", description: "Event name" },
123
124
  description: { type: "string", description: "Event description. To create a structured workout, write it in Intervals.icu's Workout Builder plain-text syntax — Intervals.icu parses this into the workout structure (steps, duration, zones) automatically. Syntax: each step is a line starting with '-', e.g. '-10m 50-60%' (duration as h/m/s combos like '1h20m', '3m30s', '20s'; intensity as a %FTP value/range, or a zone like 'z1'/'z4'). Append 'power=Ns' to set the power-smoothing window (power=10s for steady efforts, power=3s or power=1s for short hard efforts/sprints/kicks). HR-based targets: 'z4 90% hr'. Optional cadence suffix: '85-95rpm'. Repeats: put 'Nx' on its own line, then the repeated step lines, then a blank line before the next block. Example: \"- Warmup 10m 50%\\n\\n4x\\n- Hard 4m 105% power=10s\\n- Easy 2m 50%\\n\\n- Cooldown 5m 50%\\n\"" },
124
- category: { type: "string", description: "Event category: WORKOUT, NOTE, RACE_A, RACE_B, RACE_C (race priority A/B/C)" },
125
+ category: { type: "string", description: "Event category: WORKOUT, NOTE, RACE_A, RACE_B, RACE_C (race priority A/B/C — this is what makes it a race, there is no separate race flag), PLAN, HOLIDAY, SICK, INJURED, TARGET, and others" },
125
126
  type: { type: "string", description: "Activity type: Ride, Run, Swim, WeightTraining, etc." },
126
- race: { type: "boolean", description: "Mark as a race event (default: false)" },
127
127
  distance: { type: "number", description: "Distance in meters (e.g. 100000 for 100km)" },
128
128
  sub_type: { type: "string", description: "Race category/sub-type (e.g. A, B, C)" },
129
129
  workout_doc: { type: "object", description: "Pre-computed Intervals.icu workout_doc (as returned by get_event_by_id/list_workouts on an existing structured workout) to copy verbatim onto this event. Hand-written partial docs won't render correctly — prefer setting `description` with the Workout Builder syntax and omitting this field so Intervals.icu computes it." },
@@ -141,11 +141,11 @@ const TOOLS = [
141
141
  properties: {
142
142
  event_id: { type: "string", description: "The event ID to update" },
143
143
  start_date_local: { type: "string", description: "New date/time (moves the event), e.g. 2024-06-05T08:00:00" },
144
+ end_date_local: { type: "string", description: "New end date for a multi-day event (e.g. a NOTE, HOLIDAY, SICK, or INJURED entry spanning several days), e.g. 2024-06-08" },
144
145
  name: { type: "string", description: "New event name" },
145
146
  description: { type: "string", description: "New description. Use Intervals.icu's Workout Builder plain-text syntax to have Intervals.icu recompute the workout structure — steps as '-<duration> <intensity>' lines (duration as h/m/s combos, intensity as %FTP or a zone like 'z1'), optional 'power=Ns' smoothing suffix, 'Nx' repeat blocks, HR targets ('z4 90% hr'), cadence suffix ('85-95rpm'). Example: \"- Warmup 10m 50%\\n\\n4x\\n- Hard 4m 105% power=10s\\n- Easy 2m 50%\\n\\n- Cooldown 5m 50%\\n\"" },
146
147
  category: { type: "string", description: "New category" },
147
148
  type: { type: "string", description: "New activity type" },
148
- race: { type: "boolean", description: "Toggle race flag" },
149
149
  distance: { type: "number", description: "Distance in meters (e.g. 100000 for 100km)" },
150
150
  sub_type: { type: "string", description: "Race category/sub-type (e.g. A, B, C)" },
151
151
  workout_doc: { type: "object", description: "Pre-computed Intervals.icu workout_doc to copy verbatim. Hand-written partial docs won't render correctly — prefer updating `description` with Workout Builder syntax instead." },
@@ -169,7 +169,7 @@ const TOOLS = [
169
169
  },
170
170
  {
171
171
  name: "get_athlete_profile",
172
- description: "Get athlete profile including FTP, LTHR, weight, VO2max and other settings.",
172
+ description: "Get athlete profile: name, sex, DOB, weight, resting HR, city/country. For FTP/LTHR/zones use get_athlete_zones.",
173
173
  inputSchema: {
174
174
  type: "object",
175
175
  properties: {
@@ -345,7 +345,6 @@ const TOOLS = [
345
345
  description: { type: "string", description: "Use Workout Builder plain-text syntax for a structured workout — '-<duration> <intensity>' step lines, 'Nx' repeat blocks, optional 'power=Ns' smoothing suffix, HR targets ('z4 90% hr'), cadence suffix ('85-95rpm'). Example: \"- Warmup 10m 50%\\n\\n4x\\n- Hard 4m 105% power=10s\\n- Easy 2m 50%\\n\\n- Cooldown 5m 50%\\n\"" },
346
346
  category: { type: "string" },
347
347
  type: { type: "string" },
348
- race: { type: "boolean" },
349
348
  workout_doc: { type: "object", description: "Pre-computed workout_doc to copy verbatim; prefer `description` with Workout Builder syntax instead" },
350
349
  },
351
350
  },
@@ -511,9 +510,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
511
510
  name: args["name"],
512
511
  description: args["description"],
513
512
  start_date_local: z.string().parse(args["start_date_local"]),
513
+ end_date_local: args["end_date_local"],
514
514
  category: args["category"],
515
515
  type: args["type"],
516
- race: args["race"],
517
516
  distance: args["distance"],
518
517
  sub_type: args["sub_type"],
519
518
  workout_doc: args["workout_doc"],
@@ -524,7 +523,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
524
523
  const eventId = z.string().parse(args["event_id"]);
525
524
  const config = getConfig(args);
526
525
  const input = {};
527
- for (const key of ["name", "description", "start_date_local", "category", "type", "race", "distance", "sub_type", "workout_doc"]) {
526
+ for (const key of ["name", "description", "start_date_local", "end_date_local", "category", "type", "distance", "sub_type", "workout_doc"]) {
528
527
  if (args[key] !== undefined)
529
528
  input[key] = args[key];
530
529
  }
@@ -543,47 +542,34 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
543
542
  const lines = [
544
543
  `**${athlete.name ?? "Athlete"}** (${athlete.id ?? config.athleteId})`,
545
544
  athlete.email ? `Email: ${athlete.email}` : "",
546
- `Sex: ${athlete.sex ?? "N/A"} | DOB: ${athlete.dob ?? "N/A"} | City: ${athlete.city ?? "N/A"}, ${athlete.country ?? "N/A"}`,
545
+ `Sex: ${athlete.sex ?? "N/A"} | DOB: ${athlete.icu_date_of_birth ?? "N/A"} | City: ${athlete.city ?? "N/A"}, ${athlete.country ?? "N/A"}`,
547
546
  "",
548
- "Performance:",
549
- ` FTP: ${athlete.icu_ftp ?? "N/A"} W | LTHR: ${athlete.icu_lthr ?? "N/A"} bpm`,
550
- ` Weight: ${athlete.icu_weight ?? athlete.weight ?? "N/A"} kg | VO2max: ${athlete.icu_vo2max ?? "N/A"}`,
551
- ` Resting HR: ${athlete.icu_resting_hr ?? "N/A"} bpm`,
547
+ `Weight: ${athlete.icu_weight ?? athlete.weight ?? "N/A"} kg | Resting HR: ${athlete.icu_resting_hr ?? "N/A"} bpm`,
548
+ "(FTP/LTHR/zones are per-sport use get_athlete_zones for those)",
552
549
  ].filter(Boolean).join("\n");
553
550
  return { content: [{ type: "text", text: lines }] };
554
551
  }
555
552
  case "get_athlete_zones": {
556
553
  const config = getConfig(args);
557
- const zones = await getAthleteZones(config);
558
- const lines = [];
559
- const formatZones = (label, zoneList) => {
560
- if (!zoneList?.length)
561
- return;
562
- lines.push(`## ${label} Zones`, "");
563
- zoneList.forEach((z, i) => {
564
- const name = z["name"] ?? `Zone ${i + 1}`;
565
- const min = z["min"] ?? z["from"] ?? "";
566
- const max = z["max"] ?? z["to"] ?? "";
567
- lines.push(` Z${i + 1} ${name}: ${min}–${max}`);
568
- });
569
- lines.push("");
570
- };
571
- formatZones("Power", zones.power);
572
- formatZones("Heart Rate", zones.hr);
573
- formatZones("Pace", zones.pace);
574
- if (!lines.length)
575
- lines.push("No zone data available.");
576
- return { content: [{ type: "text", text: lines.join("\n") }] };
554
+ const sportSettings = await getAthleteZones(config);
555
+ if (!sportSettings.length) {
556
+ return { content: [{ type: "text", text: "No zone data available." }] };
557
+ }
558
+ const text = sportSettings.map(formatSportZones).join("\n\n---\n\n");
559
+ return { content: [{ type: "text", text }] };
577
560
  }
578
561
  case "get_athlete_summary": {
579
562
  const config = getConfig(args);
580
563
  const summary = await getAthleteSummary(config);
564
+ if (!summary) {
565
+ return { content: [{ type: "text", text: "No fitness data available." }] };
566
+ }
581
567
  const text = [
582
568
  "## Current Fitness Snapshot",
583
569
  "",
584
- `CTL (Fitness): ${summary.ctl ?? "N/A"}`,
585
- `ATL (Fatigue): ${summary.atl ?? "N/A"}`,
586
- `TSB (Form): ${summary.tsb ?? "N/A"}`,
570
+ `CTL (Fitness): ${summary.fitness ?? "N/A"}`,
571
+ `ATL (Fatigue): ${summary.fatigue ?? "N/A"}`,
572
+ `TSB (Form): ${summary.form ?? "N/A"}`,
587
573
  `Ramp Rate: ${summary.rampRate ?? "N/A"}`,
588
574
  ].join("\n");
589
575
  return { content: [{ type: "text", text }] };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "intervals-icu-mcp-server",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "MCP server for Intervals.icu — 20 tools for activities, wellness, calendar events, workouts and more",
5
5
  "type": "module",
6
6
  "bin": {