intervals-icu-mcp-server 0.2.1 → 0.4.0
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 +146 -0
- package/dist/client.js +52 -0
- package/dist/format.js +36 -17
- package/dist/index.js +59 -2
- package/package.json +2 -2
package/dist/client.d.ts
CHANGED
|
@@ -85,6 +85,20 @@ export declare const ActivitySchema: z.ZodObject<{
|
|
|
85
85
|
power_meter: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
86
86
|
source: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
87
87
|
compliance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
88
|
+
icu_chat_id: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
89
|
+
coasting_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
90
|
+
ss_cp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
91
|
+
ss_w_prime: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
92
|
+
ss_p_max: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
93
|
+
icu_pm_ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
94
|
+
icu_w_prime: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
95
|
+
p_max: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
96
|
+
icu_max_wbal_depletion: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
97
|
+
icu_joules_above_ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
98
|
+
icu_weight: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
99
|
+
carbs_used: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
100
|
+
carbs_ingested: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
101
|
+
avg_lr_balance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
88
102
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
89
103
|
id: z.ZodString;
|
|
90
104
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
@@ -167,6 +181,20 @@ export declare const ActivitySchema: z.ZodObject<{
|
|
|
167
181
|
power_meter: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
168
182
|
source: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
169
183
|
compliance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
184
|
+
icu_chat_id: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
185
|
+
coasting_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
186
|
+
ss_cp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
187
|
+
ss_w_prime: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
188
|
+
ss_p_max: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
189
|
+
icu_pm_ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
190
|
+
icu_w_prime: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
191
|
+
p_max: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
192
|
+
icu_max_wbal_depletion: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
193
|
+
icu_joules_above_ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
194
|
+
icu_weight: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
195
|
+
carbs_used: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
196
|
+
carbs_ingested: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
197
|
+
avg_lr_balance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
170
198
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
171
199
|
id: z.ZodString;
|
|
172
200
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
@@ -249,6 +277,20 @@ export declare const ActivitySchema: z.ZodObject<{
|
|
|
249
277
|
power_meter: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
250
278
|
source: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
251
279
|
compliance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
280
|
+
icu_chat_id: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
281
|
+
coasting_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
282
|
+
ss_cp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
283
|
+
ss_w_prime: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
284
|
+
ss_p_max: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
285
|
+
icu_pm_ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
286
|
+
icu_w_prime: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
287
|
+
p_max: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
288
|
+
icu_max_wbal_depletion: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
289
|
+
icu_joules_above_ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
290
|
+
icu_weight: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
291
|
+
carbs_used: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
292
|
+
carbs_ingested: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
293
|
+
avg_lr_balance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
252
294
|
}, z.ZodTypeAny, "passthrough">>;
|
|
253
295
|
export type Activity = z.infer<typeof ActivitySchema>;
|
|
254
296
|
export declare const WellnessSchema: z.ZodObject<{
|
|
@@ -274,6 +316,24 @@ export declare const WellnessSchema: z.ZodObject<{
|
|
|
274
316
|
bodyFat: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
275
317
|
spO2: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
276
318
|
comments: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
319
|
+
rampRate: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
320
|
+
avgSleepingHR: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
321
|
+
sportInfo: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
322
|
+
type: z.ZodOptional<z.ZodString>;
|
|
323
|
+
eftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
324
|
+
wPrime: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
325
|
+
pMax: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
326
|
+
}, "strip", z.ZodTypeAny, {
|
|
327
|
+
type?: string | undefined;
|
|
328
|
+
eftp?: number | null | undefined;
|
|
329
|
+
wPrime?: number | null | undefined;
|
|
330
|
+
pMax?: number | null | undefined;
|
|
331
|
+
}, {
|
|
332
|
+
type?: string | undefined;
|
|
333
|
+
eftp?: number | null | undefined;
|
|
334
|
+
wPrime?: number | null | undefined;
|
|
335
|
+
pMax?: number | null | undefined;
|
|
336
|
+
}>, "many">>>;
|
|
277
337
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
278
338
|
id: z.ZodOptional<z.ZodString>;
|
|
279
339
|
ctl: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
@@ -297,6 +357,24 @@ export declare const WellnessSchema: z.ZodObject<{
|
|
|
297
357
|
bodyFat: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
298
358
|
spO2: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
299
359
|
comments: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
360
|
+
rampRate: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
361
|
+
avgSleepingHR: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
362
|
+
sportInfo: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
363
|
+
type: z.ZodOptional<z.ZodString>;
|
|
364
|
+
eftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
365
|
+
wPrime: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
366
|
+
pMax: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
367
|
+
}, "strip", z.ZodTypeAny, {
|
|
368
|
+
type?: string | undefined;
|
|
369
|
+
eftp?: number | null | undefined;
|
|
370
|
+
wPrime?: number | null | undefined;
|
|
371
|
+
pMax?: number | null | undefined;
|
|
372
|
+
}, {
|
|
373
|
+
type?: string | undefined;
|
|
374
|
+
eftp?: number | null | undefined;
|
|
375
|
+
wPrime?: number | null | undefined;
|
|
376
|
+
pMax?: number | null | undefined;
|
|
377
|
+
}>, "many">>>;
|
|
300
378
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
301
379
|
id: z.ZodOptional<z.ZodString>;
|
|
302
380
|
ctl: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
@@ -320,6 +398,24 @@ export declare const WellnessSchema: z.ZodObject<{
|
|
|
320
398
|
bodyFat: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
321
399
|
spO2: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
322
400
|
comments: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
401
|
+
rampRate: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
402
|
+
avgSleepingHR: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
403
|
+
sportInfo: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
404
|
+
type: z.ZodOptional<z.ZodString>;
|
|
405
|
+
eftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
406
|
+
wPrime: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
407
|
+
pMax: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
408
|
+
}, "strip", z.ZodTypeAny, {
|
|
409
|
+
type?: string | undefined;
|
|
410
|
+
eftp?: number | null | undefined;
|
|
411
|
+
wPrime?: number | null | undefined;
|
|
412
|
+
pMax?: number | null | undefined;
|
|
413
|
+
}, {
|
|
414
|
+
type?: string | undefined;
|
|
415
|
+
eftp?: number | null | undefined;
|
|
416
|
+
wPrime?: number | null | undefined;
|
|
417
|
+
pMax?: number | null | undefined;
|
|
418
|
+
}>, "many">>>;
|
|
323
419
|
}, z.ZodTypeAny, "passthrough">>;
|
|
324
420
|
export type Wellness = z.infer<typeof WellnessSchema>;
|
|
325
421
|
export declare const EventSchema: z.ZodObject<{
|
|
@@ -332,6 +428,11 @@ export declare const EventSchema: z.ZodObject<{
|
|
|
332
428
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
333
429
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
334
430
|
color: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
431
|
+
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
432
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
433
|
+
icu_training_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
434
|
+
icu_intensity: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
435
|
+
paired_activity_id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
335
436
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
336
437
|
id: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
|
|
337
438
|
date: z.ZodOptional<z.ZodString>;
|
|
@@ -342,6 +443,11 @@ export declare const EventSchema: z.ZodObject<{
|
|
|
342
443
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
343
444
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
344
445
|
color: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
446
|
+
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
447
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
448
|
+
icu_training_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
449
|
+
icu_intensity: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
450
|
+
paired_activity_id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
345
451
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
346
452
|
id: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
|
|
347
453
|
date: z.ZodOptional<z.ZodString>;
|
|
@@ -352,6 +458,11 @@ export declare const EventSchema: z.ZodObject<{
|
|
|
352
458
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
353
459
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
354
460
|
color: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
461
|
+
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
462
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
463
|
+
icu_training_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
464
|
+
icu_intensity: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
465
|
+
paired_activity_id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
355
466
|
}, z.ZodTypeAny, "passthrough">>;
|
|
356
467
|
export type Event = z.infer<typeof EventSchema>;
|
|
357
468
|
export declare const IntervalSchema: z.ZodObject<{
|
|
@@ -423,6 +534,10 @@ export declare const SportSettingsSchema: z.ZodObject<{
|
|
|
423
534
|
hr_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
424
535
|
pace_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
425
536
|
pace_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
537
|
+
w_prime: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
538
|
+
sweet_spot_min: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
539
|
+
sweet_spot_max: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
540
|
+
best_effort_distances: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
426
541
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
427
542
|
types: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
428
543
|
ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
@@ -435,6 +550,10 @@ export declare const SportSettingsSchema: z.ZodObject<{
|
|
|
435
550
|
hr_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
436
551
|
pace_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
437
552
|
pace_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
553
|
+
w_prime: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
554
|
+
sweet_spot_min: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
555
|
+
sweet_spot_max: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
556
|
+
best_effort_distances: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
438
557
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
439
558
|
types: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
440
559
|
ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
@@ -447,6 +566,10 @@ export declare const SportSettingsSchema: z.ZodObject<{
|
|
|
447
566
|
hr_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
448
567
|
pace_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
449
568
|
pace_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
569
|
+
w_prime: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
570
|
+
sweet_spot_min: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
571
|
+
sweet_spot_max: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
572
|
+
best_effort_distances: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
450
573
|
}, z.ZodTypeAny, "passthrough">>;
|
|
451
574
|
export type SportSettings = z.infer<typeof SportSettingsSchema>;
|
|
452
575
|
export declare const WorkoutSchema: z.ZodObject<{
|
|
@@ -455,18 +578,27 @@ export declare const WorkoutSchema: z.ZodObject<{
|
|
|
455
578
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
456
579
|
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
457
580
|
updated: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
581
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
582
|
+
icu_training_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
583
|
+
joules: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
458
584
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
459
585
|
id: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
|
|
460
586
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
461
587
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
462
588
|
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
463
589
|
updated: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
590
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
591
|
+
icu_training_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
592
|
+
joules: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
464
593
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
465
594
|
id: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
|
|
466
595
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
467
596
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
468
597
|
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
469
598
|
updated: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
599
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
600
|
+
icu_training_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
601
|
+
joules: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
470
602
|
}, z.ZodTypeAny, "passthrough">>;
|
|
471
603
|
export type Workout = z.infer<typeof WorkoutSchema>;
|
|
472
604
|
export interface WorkoutInput {
|
|
@@ -530,6 +662,8 @@ export declare const MessageSchema: z.ZodObject<{
|
|
|
530
662
|
export type Message = z.infer<typeof MessageSchema>;
|
|
531
663
|
export declare function getActivityMessages(config: ClientConfig, activityId: string): Promise<Message[]>;
|
|
532
664
|
export declare function addActivityMessage(config: ClientConfig, activityId: string, content: string): Promise<void>;
|
|
665
|
+
export declare function deleteActivityMessage(config: ClientConfig, activityId: string, messageId: number): Promise<void>;
|
|
666
|
+
export declare function updateActivityMessage(config: ClientConfig, activityId: string, messageId: number, content: string): Promise<void>;
|
|
533
667
|
export declare function getWellness(config: ClientConfig, params: {
|
|
534
668
|
startDate: string;
|
|
535
669
|
endDate: string;
|
|
@@ -564,6 +698,10 @@ export declare const AthleteFitnessSchema: z.ZodObject<{
|
|
|
564
698
|
eftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
565
699
|
eftpPerKg: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
566
700
|
weight: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
701
|
+
count: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
702
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
703
|
+
calories: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
704
|
+
distance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
567
705
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
568
706
|
date: z.ZodOptional<z.ZodString>;
|
|
569
707
|
fitness: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
@@ -574,6 +712,10 @@ export declare const AthleteFitnessSchema: z.ZodObject<{
|
|
|
574
712
|
eftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
575
713
|
eftpPerKg: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
576
714
|
weight: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
715
|
+
count: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
716
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
717
|
+
calories: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
718
|
+
distance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
577
719
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
578
720
|
date: z.ZodOptional<z.ZodString>;
|
|
579
721
|
fitness: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
@@ -584,6 +726,10 @@ export declare const AthleteFitnessSchema: z.ZodObject<{
|
|
|
584
726
|
eftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
585
727
|
eftpPerKg: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
586
728
|
weight: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
729
|
+
count: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
730
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
731
|
+
calories: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
732
|
+
distance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
587
733
|
}, z.ZodTypeAny, "passthrough">>;
|
|
588
734
|
export type AthleteFitness = z.infer<typeof AthleteFitnessSchema>;
|
|
589
735
|
export declare function getAthleteFitness(config: ClientConfig, params: {
|
package/dist/client.js
CHANGED
|
@@ -83,6 +83,20 @@ export const ActivitySchema = z.object({
|
|
|
83
83
|
power_meter: z.string().nullable().optional(),
|
|
84
84
|
source: z.string().nullable().optional(),
|
|
85
85
|
compliance: z.number().nullable().optional(),
|
|
86
|
+
icu_chat_id: z.number().nullable().optional(),
|
|
87
|
+
coasting_time: z.number().nullable().optional(),
|
|
88
|
+
ss_cp: z.number().nullable().optional(),
|
|
89
|
+
ss_w_prime: z.number().nullable().optional(),
|
|
90
|
+
ss_p_max: z.number().nullable().optional(),
|
|
91
|
+
icu_pm_ftp: z.number().nullable().optional(),
|
|
92
|
+
icu_w_prime: z.number().nullable().optional(),
|
|
93
|
+
p_max: z.number().nullable().optional(),
|
|
94
|
+
icu_max_wbal_depletion: z.number().nullable().optional(),
|
|
95
|
+
icu_joules_above_ftp: z.number().nullable().optional(),
|
|
96
|
+
icu_weight: z.number().nullable().optional(),
|
|
97
|
+
carbs_used: z.number().nullable().optional(),
|
|
98
|
+
carbs_ingested: z.number().nullable().optional(),
|
|
99
|
+
avg_lr_balance: z.number().nullable().optional(),
|
|
86
100
|
}).passthrough();
|
|
87
101
|
export const WellnessSchema = z.object({
|
|
88
102
|
id: z.string().optional(),
|
|
@@ -107,6 +121,14 @@ export const WellnessSchema = z.object({
|
|
|
107
121
|
bodyFat: z.number().nullable().optional(),
|
|
108
122
|
spO2: z.number().nullable().optional(),
|
|
109
123
|
comments: z.string().nullable().optional(),
|
|
124
|
+
rampRate: z.number().nullable().optional(),
|
|
125
|
+
avgSleepingHR: z.number().nullable().optional(),
|
|
126
|
+
sportInfo: z.array(z.object({
|
|
127
|
+
type: z.string().optional(),
|
|
128
|
+
eftp: z.number().nullable().optional(),
|
|
129
|
+
wPrime: z.number().nullable().optional(),
|
|
130
|
+
pMax: z.number().nullable().optional(),
|
|
131
|
+
})).nullable().optional(),
|
|
110
132
|
}).passthrough();
|
|
111
133
|
export const EventSchema = z.object({
|
|
112
134
|
id: z.union([z.string(), z.number()]),
|
|
@@ -118,6 +140,11 @@ export const EventSchema = z.object({
|
|
|
118
140
|
name: z.string().nullable().optional(),
|
|
119
141
|
description: z.string().nullable().optional(),
|
|
120
142
|
color: z.string().nullable().optional(),
|
|
143
|
+
type: z.string().nullable().optional(),
|
|
144
|
+
moving_time: z.number().nullable().optional(),
|
|
145
|
+
icu_training_load: z.number().nullable().optional(),
|
|
146
|
+
icu_intensity: z.number().nullable().optional(),
|
|
147
|
+
paired_activity_id: z.string().nullable().optional(),
|
|
121
148
|
}).passthrough();
|
|
122
149
|
export const IntervalSchema = z.object({
|
|
123
150
|
icu_intervals: z.array(z.record(z.unknown())).nullable().optional(),
|
|
@@ -147,6 +174,10 @@ export const SportSettingsSchema = z.object({
|
|
|
147
174
|
hr_zone_names: z.array(z.string()).nullable().optional(),
|
|
148
175
|
pace_zones: z.array(z.number()).nullable().optional(),
|
|
149
176
|
pace_zone_names: z.array(z.string()).nullable().optional(),
|
|
177
|
+
w_prime: z.number().nullable().optional(),
|
|
178
|
+
sweet_spot_min: z.number().nullable().optional(),
|
|
179
|
+
sweet_spot_max: z.number().nullable().optional(),
|
|
180
|
+
best_effort_distances: z.array(z.number()).nullable().optional(),
|
|
150
181
|
}).passthrough();
|
|
151
182
|
export const WorkoutSchema = z.object({
|
|
152
183
|
id: z.union([z.string(), z.number()]).optional(),
|
|
@@ -154,6 +185,9 @@ export const WorkoutSchema = z.object({
|
|
|
154
185
|
description: z.string().nullable().optional(),
|
|
155
186
|
type: z.string().nullable().optional(),
|
|
156
187
|
updated: z.string().nullable().optional(),
|
|
188
|
+
moving_time: z.number().nullable().optional(),
|
|
189
|
+
icu_training_load: z.number().nullable().optional(),
|
|
190
|
+
joules: z.number().nullable().optional(),
|
|
157
191
|
}).passthrough();
|
|
158
192
|
// ---- API methods ---- //
|
|
159
193
|
export async function getActivities(config, params) {
|
|
@@ -184,6 +218,20 @@ export async function getActivityMessages(config, activityId) {
|
|
|
184
218
|
export async function addActivityMessage(config, activityId, content) {
|
|
185
219
|
await mutate("POST", `/activity/${activityId}/messages`, config, { content });
|
|
186
220
|
}
|
|
221
|
+
// Intervals.icu has no endpoint to edit a message's content in place — only
|
|
222
|
+
// delete and re-add. Callers wanting an "edit" should use updateActivityMessage,
|
|
223
|
+
// which does both and leaves the old message showing as deleted.
|
|
224
|
+
export async function deleteActivityMessage(config, activityId, messageId) {
|
|
225
|
+
const activity = await getActivityDetails(config, activityId);
|
|
226
|
+
const chatId = activity.icu_chat_id;
|
|
227
|
+
if (chatId == null)
|
|
228
|
+
throw new Error(`Activity ${activityId} has no chat/messages.`);
|
|
229
|
+
await mutate("DELETE", `/chats/${chatId}/messages/${messageId}`, config);
|
|
230
|
+
}
|
|
231
|
+
export async function updateActivityMessage(config, activityId, messageId, content) {
|
|
232
|
+
await deleteActivityMessage(config, activityId, messageId);
|
|
233
|
+
await addActivityMessage(config, activityId, content);
|
|
234
|
+
}
|
|
187
235
|
export async function getWellness(config, params) {
|
|
188
236
|
const data = await request(`/athlete/${config.athleteId}/wellness`, config, { oldest: params.startDate, newest: params.endDate });
|
|
189
237
|
if (Array.isArray(data)) {
|
|
@@ -303,6 +351,10 @@ export const AthleteFitnessSchema = z.object({
|
|
|
303
351
|
eftp: z.number().nullable().optional(),
|
|
304
352
|
eftpPerKg: z.number().nullable().optional(),
|
|
305
353
|
weight: z.number().nullable().optional(),
|
|
354
|
+
count: z.number().nullable().optional(),
|
|
355
|
+
moving_time: z.number().nullable().optional(),
|
|
356
|
+
calories: z.number().nullable().optional(),
|
|
357
|
+
distance: z.number().nullable().optional(),
|
|
306
358
|
}).passthrough();
|
|
307
359
|
export async function getAthleteFitness(config, params) {
|
|
308
360
|
const data = await request(`/athlete/${config.athleteId}/athlete-summary.json`, config, { start: params.startDate, end: params.endDate });
|
package/dist/format.js
CHANGED
|
@@ -23,7 +23,9 @@ export function formatActivity(a) {
|
|
|
23
23
|
"Power:",
|
|
24
24
|
` Avg: ${n(a.icu_average_watts, " W")} | Weighted Avg: ${n(a.icu_weighted_avg_watts, " W")} | FTP: ${n(a.icu_ftp, " W")}`,
|
|
25
25
|
` Training Load: ${n(a.icu_training_load)} | Intensity: ${n(a.icu_intensity)} | VI: ${n(a.icu_variability_index)}`,
|
|
26
|
-
` Critical Power: ${n(a.icu_pm_cp, " W")} | Rolling FTP: ${n(a.icu_rolling_ftp, " W")} |
|
|
26
|
+
` Critical Power: ${n(a.icu_pm_cp, " W")} | Rolling FTP: ${n(a.icu_rolling_ftp, " W")} | Activity eFTP: ${n(a.icu_pm_ftp, " W")}`,
|
|
27
|
+
` Energy: ${a.icu_joules != null ? `${Math.round(a.icu_joules / 1000)} kJ` : "N/A"} | Above FTP: ${a.icu_joules_above_ftp != null ? `${Math.round(a.icu_joules_above_ftp / 1000)} kJ` : "N/A"}`,
|
|
28
|
+
` W': ${n(a.icu_w_prime, " J")} | Pmax: ${n(a.p_max, " W")} | W'bal Drop: ${a.icu_max_wbal_depletion != null ? `${(a.icu_max_wbal_depletion / 1000).toFixed(1)} kJ` : "N/A"}`,
|
|
27
29
|
"",
|
|
28
30
|
"Heart Rate:",
|
|
29
31
|
` Avg: ${n(a.average_heartrate, " bpm")} | Max: ${n(a.max_heartrate, " bpm")}`,
|
|
@@ -41,21 +43,21 @@ export function formatActivity(a) {
|
|
|
41
43
|
lines.push(` HR: ${a.icu_hr_zone_times.map((secs, i) => `Z${i + 1} ${fmtDuration(secs)}`).join(" | ")}`);
|
|
42
44
|
}
|
|
43
45
|
}
|
|
44
|
-
lines.push("", "Other:", ` Cadence: ${n(a.average_cadence, " rpm")} | Calories: ${n(a.calories)} | Speed: ${n(a.average_speed, " m/s")} (max ${n(a.max_speed, " m/s")})`, ` Temp: ${n(a.average_temp, "°C")} | Trainer: ${a.trainer ? "Yes" : "No"}`, ` RPE: ${n(a.icu_rpe ?? a.perceived_exertion)}/10 | Feel: ${n(a.feel)}/5`, "", "Fitness:", ` CTL: ${n(a.icu_ctl)} | ATL: ${n(a.icu_atl)} | TRIMP: ${n(a.trimp)} | Polarization Index: ${n(a.polarization_index)}`, ` Power Load: ${n(a.power_load)} | HR Load: ${n(a.hr_load)} | Strain: ${n(a.strain_score)}`, "", "Equipment:", ` Gear: ${n(a.gear?.name)} | Device: ${n(a.device_name)} | Power Meter: ${n(a.power_meter)}`, ` Source: ${n(a.source)} | Compliance: ${a.compliance != null ? `${a.compliance}%` : "N/A"}`);
|
|
46
|
+
lines.push("", "Other:", ` Cadence: ${n(a.average_cadence, " rpm")} | Calories: ${n(a.calories)} | Speed: ${n(a.average_speed, " m/s")} (max ${n(a.max_speed, " m/s")})`, ` Temp: ${n(a.average_temp, "°C")} | Trainer: ${a.trainer ? "Yes" : "No"} | Coasting: ${fmtDuration(a.coasting_time)}`, ` RPE: ${n(a.icu_rpe ?? a.perceived_exertion)}/10 | Feel: ${n(a.feel)}/5 | S-RPE: ${n(a.session_rpe)}`, ` L/R Balance: ${a.avg_lr_balance != null ? `${(100 - a.avg_lr_balance).toFixed(0)}/${a.avg_lr_balance.toFixed(0)}` : "N/A"}`, "", "Fitness:", ` CTL: ${n(a.icu_ctl)} | ATL: ${n(a.icu_atl)} | TRIMP: ${n(a.trimp)} | Polarization Index: ${n(a.polarization_index)}`, ` Power Load: ${n(a.power_load)} | HR Load: ${n(a.hr_load)} | Strain: ${n(a.strain_score)}`, ` SS CP: ${n(a.ss_cp, " W")} | SS W': ${n(a.ss_w_prime)} | SS Pmax: ${n(a.ss_p_max)}`, ` Weight: ${n(a.icu_weight, " kg")} | CHO Used: ${n(a.carbs_used, " g")} | CHO In: ${n(a.carbs_ingested, " g")}`, "", "Equipment:", ` Gear: ${n(a.gear?.name)} | Device: ${n(a.device_name)} | Power Meter: ${n(a.power_meter)}`, ` Source: ${n(a.source)} | Compliance: ${a.compliance != null ? `${a.compliance}%` : "N/A"}`);
|
|
45
47
|
if (a.description)
|
|
46
48
|
lines.push("", `Description: ${a.description}`);
|
|
47
49
|
return lines.join("\n");
|
|
48
50
|
}
|
|
49
51
|
export function formatWellness(date, w) {
|
|
50
52
|
const sleepHours = w.sleepSecs != null ? (w.sleepSecs / 3600).toFixed(1) + " h" : "N/A";
|
|
51
|
-
|
|
53
|
+
const lines = [
|
|
52
54
|
`**${date}**`,
|
|
53
55
|
"",
|
|
54
56
|
"Training:",
|
|
55
|
-
` CTL: ${n(w.ctl)} | ATL: ${n(w.atl)}`,
|
|
57
|
+
` CTL: ${n(w.ctl)} | ATL: ${n(w.atl)} | Ramp Rate: ${n(w.rampRate)}`,
|
|
56
58
|
"",
|
|
57
59
|
"Vitals:",
|
|
58
|
-
` Weight: ${n(w.weight, " kg")} | Resting HR: ${n(w.restingHR, " bpm")}`,
|
|
60
|
+
` Weight: ${n(w.weight, " kg")} | Resting HR: ${n(w.restingHR, " bpm")} | Avg Sleeping HR: ${n(w.avgSleepingHR, " bpm")}`,
|
|
59
61
|
` HRV: ${n(w.hrv)} | HRV SDNN: ${n(w.hrvSDNN)}`,
|
|
60
62
|
` SpO2: ${n(w.spO2, "%")} | VO2max: ${n(w.vo2max)} | Body Fat: ${n(w.bodyFat, "%")}`,
|
|
61
63
|
"",
|
|
@@ -69,11 +71,13 @@ export function formatWellness(date, w) {
|
|
|
69
71
|
"",
|
|
70
72
|
"Nutrition:",
|
|
71
73
|
` Calories: ${n(w.kcalConsumed, " kcal")} | Steps: ${n(w.steps)}`,
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
.
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
];
|
|
75
|
+
if (w.sportInfo?.length) {
|
|
76
|
+
lines.push("", "Sport Fitness (eFTP / W' / pMax):", ...w.sportInfo.map((s) => ` ${s.type ?? "Unknown"}: ${n(s.eftp, " W")} / ${n(s.wPrime, " J")} / ${n(s.pMax, " W")}`));
|
|
77
|
+
}
|
|
78
|
+
if (w.comments)
|
|
79
|
+
lines.push("", `Comments: ${w.comments}`);
|
|
80
|
+
return lines.join("\n").trimEnd();
|
|
77
81
|
}
|
|
78
82
|
export function formatEvent(e) {
|
|
79
83
|
const category = e.category ?? "";
|
|
@@ -88,14 +92,19 @@ export function formatEvent(e) {
|
|
|
88
92
|
const dateLabel = e.end_date_local && e.end_date_local !== e.start_date_local
|
|
89
93
|
? `${start} to ${e.end_date_local}`
|
|
90
94
|
: start;
|
|
91
|
-
|
|
95
|
+
const lines = [
|
|
92
96
|
`**${e.name ?? "Unnamed"}** (${e.id})`,
|
|
93
97
|
`Type: ${type} | Date: ${dateLabel}`,
|
|
94
98
|
e.category ? `Category: ${e.category}` : "",
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
.
|
|
98
|
-
|
|
99
|
+
];
|
|
100
|
+
if (e.type || e.moving_time != null || e.icu_training_load != null || e.icu_intensity != null) {
|
|
101
|
+
lines.push(`Sport: ${n(e.type)} | Planned Duration: ${e.moving_time != null ? fmtDuration(e.moving_time) : "N/A"} | Planned Load: ${n(e.icu_training_load)} | Intensity: ${n(e.icu_intensity)}`);
|
|
102
|
+
}
|
|
103
|
+
if (e.paired_activity_id)
|
|
104
|
+
lines.push(`Completed as: ${e.paired_activity_id}`);
|
|
105
|
+
if (e.description)
|
|
106
|
+
lines.push(`Description: ${e.description}`);
|
|
107
|
+
return lines.filter(Boolean).join("\n");
|
|
99
108
|
}
|
|
100
109
|
export function formatMessage(m) {
|
|
101
110
|
const when = m.created ? new Date(m.created).toLocaleString() : "Unknown time";
|
|
@@ -146,6 +155,13 @@ export function formatSportZones(s) {
|
|
|
146
155
|
const range = z.to != null ? `${z.from}-${z.to} m/s` : `${z.from}+ m/s`;
|
|
147
156
|
lines.push(` ${z.name}: ${range}`);
|
|
148
157
|
}
|
|
158
|
+
lines.push("");
|
|
159
|
+
}
|
|
160
|
+
if (s.w_prime != null || s.sweet_spot_min != null) {
|
|
161
|
+
lines.push(`Power Model: W' ${n(s.w_prime, " J")} | Sweet Spot ${n(s.sweet_spot_min, "%")}-${n(s.sweet_spot_max, "%")}`);
|
|
162
|
+
}
|
|
163
|
+
if (s.best_effort_distances?.length) {
|
|
164
|
+
lines.push(`Best Effort Distances: ${s.best_effort_distances.join(", ")} m`);
|
|
149
165
|
}
|
|
150
166
|
return lines.join("\n").trimEnd();
|
|
151
167
|
}
|
|
@@ -160,10 +176,13 @@ export function formatIntervalRow(interval, idx) {
|
|
|
160
176
|
const avgHr = interval["average_heartrate"] ?? 0;
|
|
161
177
|
const maxHr = interval["max_heartrate"] ?? 0;
|
|
162
178
|
const tl = interval["training_load"] ?? 0;
|
|
179
|
+
const intensity = interval["intensity"];
|
|
180
|
+
const vi = interval["w5s_variability"];
|
|
181
|
+
const decoupling = interval["decoupling"];
|
|
163
182
|
return [
|
|
164
183
|
`[${idx}] ${label} (${type})`,
|
|
165
184
|
` Duration: ${elapsed}s | Distance: ${distance}m`,
|
|
166
|
-
` Power: avg ${avgW}W, w.avg ${wAvg}W, max ${maxW}W | TL: ${tl}`,
|
|
167
|
-
` HR: avg ${avgHr}, max ${maxHr} bpm`,
|
|
185
|
+
` Power: avg ${avgW}W, w.avg ${wAvg}W, max ${maxW}W | TL: ${tl} | Intensity: ${n(intensity)} | VI: ${n(vi)}`,
|
|
186
|
+
` HR: avg ${avgHr}, max ${maxHr} bpm | Decoupling: ${n(decoupling, "%")}`,
|
|
168
187
|
].join("\n");
|
|
169
188
|
}
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
4
4
|
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
|
-
import { getActivities, getActivityDetails, getActivityIntervals, getWellness, getEvents, getEventById, getNotesByDate, createEvent, updateEvent, deleteEvent, getAthleteProfile, getAthleteZones, getAthleteSummary, getWellnessDay, updateWellness, getActivityStreams, getActivityPowerCurves, listWorkouts, createWorkout, bulkCreateEvents, bulkDeleteEvents, getAthleteFitness, getActivityMessages, addActivityMessage, } from "./client.js";
|
|
7
|
+
import { getActivities, getActivityDetails, getActivityIntervals, getWellness, getEvents, getEventById, getNotesByDate, createEvent, updateEvent, deleteEvent, getAthleteProfile, getAthleteZones, getAthleteSummary, getWellnessDay, updateWellness, getActivityStreams, getActivityPowerCurves, listWorkouts, createWorkout, bulkCreateEvents, bulkDeleteEvents, getAthleteFitness, getActivityMessages, addActivityMessage, deleteActivityMessage, updateActivityMessage, } from "./client.js";
|
|
8
8
|
import { formatActivity, formatWellness, formatEvent, formatIntervalRow, formatSportZones, formatMessage, } from "./format.js";
|
|
9
9
|
function getConfig(args) {
|
|
10
10
|
const apiKey = args["api_key"] ?? process.env.API_KEY ?? "";
|
|
@@ -309,6 +309,35 @@ const TOOLS = [
|
|
|
309
309
|
},
|
|
310
310
|
},
|
|
311
311
|
},
|
|
312
|
+
{
|
|
313
|
+
name: "update_activity_message",
|
|
314
|
+
description: "Edit a comment/note on an activity. Intervals.icu has no API to edit message content in place, so this deletes the old message and posts a new one with the updated text — the old message will show as \"(deleted)\" and the edited one will appear as a new message at the current time. Use get_activity_messages to find the message_id.",
|
|
315
|
+
inputSchema: {
|
|
316
|
+
type: "object",
|
|
317
|
+
required: ["activity_id", "message_id", "content"],
|
|
318
|
+
properties: {
|
|
319
|
+
activity_id: { type: "string", description: "The activity ID" },
|
|
320
|
+
message_id: { type: "number", description: "ID of the message to edit (from get_activity_messages)" },
|
|
321
|
+
content: { type: "string", description: "New comment text" },
|
|
322
|
+
athlete_id: { type: "string", description: "Athlete ID (defaults to ATHLETE_ID env var)" },
|
|
323
|
+
api_key: { type: "string", description: "API key (defaults to API_KEY env var)" },
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
name: "delete_activity_message",
|
|
329
|
+
description: "Delete a comment/note from an activity's chat thread. The message is soft-deleted (shows as \"(deleted)\") rather than removed entirely. Use get_activity_messages to find the message_id.",
|
|
330
|
+
inputSchema: {
|
|
331
|
+
type: "object",
|
|
332
|
+
required: ["activity_id", "message_id"],
|
|
333
|
+
properties: {
|
|
334
|
+
activity_id: { type: "string", description: "The activity ID" },
|
|
335
|
+
message_id: { type: "number", description: "ID of the message to delete (from get_activity_messages)" },
|
|
336
|
+
athlete_id: { type: "string", description: "Athlete ID (defaults to ATHLETE_ID env var)" },
|
|
337
|
+
api_key: { type: "string", description: "API key (defaults to API_KEY env var)" },
|
|
338
|
+
},
|
|
339
|
+
},
|
|
340
|
+
},
|
|
312
341
|
{
|
|
313
342
|
name: "list_workouts",
|
|
314
343
|
description: "List all workouts in the athlete's workout library.",
|
|
@@ -608,6 +637,11 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
608
637
|
`ATL (Fatigue): ${summary.fatigue ?? "N/A"}`,
|
|
609
638
|
`TSB (Form): ${summary.form ?? "N/A"}`,
|
|
610
639
|
`Ramp Rate: ${summary.rampRate ?? "N/A"}`,
|
|
640
|
+
"",
|
|
641
|
+
"## Last 7 Days",
|
|
642
|
+
"",
|
|
643
|
+
`Activities: ${summary.count ?? "N/A"} | Training Load: ${summary.training_load ?? "N/A"}`,
|
|
644
|
+
`Moving Time: ${summary.moving_time != null ? `${(summary.moving_time / 3600).toFixed(1)}h` : "N/A"} | Distance: ${summary.distance != null ? `${(summary.distance / 1000).toFixed(1)} km` : "N/A"} | Calories: ${summary.calories ?? "N/A"}`,
|
|
611
645
|
].join("\n");
|
|
612
646
|
return { content: [{ type: "text", text }] };
|
|
613
647
|
}
|
|
@@ -667,12 +701,35 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
667
701
|
await addActivityMessage(config, activityId, content);
|
|
668
702
|
return { content: [{ type: "text", text: `Comment added to activity ${activityId}.` }] };
|
|
669
703
|
}
|
|
704
|
+
case "update_activity_message": {
|
|
705
|
+
const activityId = z.string().parse(args["activity_id"]);
|
|
706
|
+
const messageId = z.number().parse(args["message_id"]);
|
|
707
|
+
const content = z.string().parse(args["content"]);
|
|
708
|
+
const config = getConfig(args);
|
|
709
|
+
await updateActivityMessage(config, activityId, messageId, content);
|
|
710
|
+
return { content: [{ type: "text", text: `Message ${messageId} on activity ${activityId} replaced with: "${content}"` }] };
|
|
711
|
+
}
|
|
712
|
+
case "delete_activity_message": {
|
|
713
|
+
const activityId = z.string().parse(args["activity_id"]);
|
|
714
|
+
const messageId = z.number().parse(args["message_id"]);
|
|
715
|
+
const config = getConfig(args);
|
|
716
|
+
await deleteActivityMessage(config, activityId, messageId);
|
|
717
|
+
return { content: [{ type: "text", text: `Message ${messageId} deleted from activity ${activityId}.` }] };
|
|
718
|
+
}
|
|
670
719
|
case "list_workouts": {
|
|
671
720
|
const config = getConfig(args);
|
|
672
721
|
const workouts = await listWorkouts(config);
|
|
673
722
|
if (!workouts.length)
|
|
674
723
|
return { content: [{ type: "text", text: "No workouts in library." }] };
|
|
675
|
-
const text = workouts.map(w =>
|
|
724
|
+
const text = workouts.map(w => {
|
|
725
|
+
const duration = w.moving_time != null ? `${Math.round(w.moving_time / 60)}min` : "N/A";
|
|
726
|
+
const kj = w.joules != null ? `${Math.round(w.joules / 1000)} kJ` : "N/A";
|
|
727
|
+
return [
|
|
728
|
+
`**${w.name ?? "Unnamed"}** (${w.id})`,
|
|
729
|
+
w.type ? `Type: ${w.type} | Duration: ${duration} | Load: ${w.icu_training_load ?? "N/A"} | Energy: ${kj}` : "",
|
|
730
|
+
w.description ? `${w.description}` : "",
|
|
731
|
+
].filter(Boolean).join("\n");
|
|
732
|
+
}).join("\n\n---\n\n");
|
|
676
733
|
return { content: [{ type: "text", text }] };
|
|
677
734
|
}
|
|
678
735
|
case "create_workout": {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "intervals-icu-mcp-server",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "MCP server for Intervals.icu —
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "MCP server for Intervals.icu — 26 tools for activities, wellness, calendar events, workouts and more",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"intervals-icu-mcp": "dist/index.js"
|