intervals-icu-mcp-server 0.2.1 → 0.3.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 +107 -0
- package/dist/client.js +39 -0
- package/dist/format.js +32 -15
- package/dist/index.js +59 -2
- package/package.json +2 -2
package/dist/client.d.ts
CHANGED
|
@@ -85,6 +85,7 @@ 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>>;
|
|
88
89
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
89
90
|
id: z.ZodString;
|
|
90
91
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
@@ -167,6 +168,7 @@ export declare const ActivitySchema: z.ZodObject<{
|
|
|
167
168
|
power_meter: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
168
169
|
source: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
169
170
|
compliance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
171
|
+
icu_chat_id: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
170
172
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
171
173
|
id: z.ZodString;
|
|
172
174
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
@@ -249,6 +251,7 @@ export declare const ActivitySchema: z.ZodObject<{
|
|
|
249
251
|
power_meter: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
250
252
|
source: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
251
253
|
compliance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
254
|
+
icu_chat_id: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
252
255
|
}, z.ZodTypeAny, "passthrough">>;
|
|
253
256
|
export type Activity = z.infer<typeof ActivitySchema>;
|
|
254
257
|
export declare const WellnessSchema: z.ZodObject<{
|
|
@@ -274,6 +277,24 @@ export declare const WellnessSchema: z.ZodObject<{
|
|
|
274
277
|
bodyFat: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
275
278
|
spO2: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
276
279
|
comments: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
280
|
+
rampRate: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
281
|
+
avgSleepingHR: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
282
|
+
sportInfo: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
283
|
+
type: z.ZodOptional<z.ZodString>;
|
|
284
|
+
eftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
285
|
+
wPrime: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
286
|
+
pMax: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
287
|
+
}, "strip", z.ZodTypeAny, {
|
|
288
|
+
type?: string | undefined;
|
|
289
|
+
eftp?: number | null | undefined;
|
|
290
|
+
wPrime?: number | null | undefined;
|
|
291
|
+
pMax?: number | null | undefined;
|
|
292
|
+
}, {
|
|
293
|
+
type?: string | undefined;
|
|
294
|
+
eftp?: number | null | undefined;
|
|
295
|
+
wPrime?: number | null | undefined;
|
|
296
|
+
pMax?: number | null | undefined;
|
|
297
|
+
}>, "many">>>;
|
|
277
298
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
278
299
|
id: z.ZodOptional<z.ZodString>;
|
|
279
300
|
ctl: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
@@ -297,6 +318,24 @@ export declare const WellnessSchema: z.ZodObject<{
|
|
|
297
318
|
bodyFat: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
298
319
|
spO2: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
299
320
|
comments: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
321
|
+
rampRate: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
322
|
+
avgSleepingHR: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
323
|
+
sportInfo: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
324
|
+
type: z.ZodOptional<z.ZodString>;
|
|
325
|
+
eftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
326
|
+
wPrime: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
327
|
+
pMax: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
328
|
+
}, "strip", z.ZodTypeAny, {
|
|
329
|
+
type?: string | undefined;
|
|
330
|
+
eftp?: number | null | undefined;
|
|
331
|
+
wPrime?: number | null | undefined;
|
|
332
|
+
pMax?: number | null | undefined;
|
|
333
|
+
}, {
|
|
334
|
+
type?: string | undefined;
|
|
335
|
+
eftp?: number | null | undefined;
|
|
336
|
+
wPrime?: number | null | undefined;
|
|
337
|
+
pMax?: number | null | undefined;
|
|
338
|
+
}>, "many">>>;
|
|
300
339
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
301
340
|
id: z.ZodOptional<z.ZodString>;
|
|
302
341
|
ctl: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
@@ -320,6 +359,24 @@ export declare const WellnessSchema: z.ZodObject<{
|
|
|
320
359
|
bodyFat: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
321
360
|
spO2: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
322
361
|
comments: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
362
|
+
rampRate: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
363
|
+
avgSleepingHR: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
364
|
+
sportInfo: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
365
|
+
type: z.ZodOptional<z.ZodString>;
|
|
366
|
+
eftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
367
|
+
wPrime: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
368
|
+
pMax: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
369
|
+
}, "strip", z.ZodTypeAny, {
|
|
370
|
+
type?: string | undefined;
|
|
371
|
+
eftp?: number | null | undefined;
|
|
372
|
+
wPrime?: number | null | undefined;
|
|
373
|
+
pMax?: number | null | undefined;
|
|
374
|
+
}, {
|
|
375
|
+
type?: string | undefined;
|
|
376
|
+
eftp?: number | null | undefined;
|
|
377
|
+
wPrime?: number | null | undefined;
|
|
378
|
+
pMax?: number | null | undefined;
|
|
379
|
+
}>, "many">>>;
|
|
323
380
|
}, z.ZodTypeAny, "passthrough">>;
|
|
324
381
|
export type Wellness = z.infer<typeof WellnessSchema>;
|
|
325
382
|
export declare const EventSchema: z.ZodObject<{
|
|
@@ -332,6 +389,11 @@ export declare const EventSchema: z.ZodObject<{
|
|
|
332
389
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
333
390
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
334
391
|
color: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
392
|
+
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
393
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
394
|
+
icu_training_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
395
|
+
icu_intensity: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
396
|
+
paired_activity_id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
335
397
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
336
398
|
id: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
|
|
337
399
|
date: z.ZodOptional<z.ZodString>;
|
|
@@ -342,6 +404,11 @@ export declare const EventSchema: z.ZodObject<{
|
|
|
342
404
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
343
405
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
344
406
|
color: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
407
|
+
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
408
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
409
|
+
icu_training_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
410
|
+
icu_intensity: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
411
|
+
paired_activity_id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
345
412
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
346
413
|
id: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
|
|
347
414
|
date: z.ZodOptional<z.ZodString>;
|
|
@@ -352,6 +419,11 @@ export declare const EventSchema: z.ZodObject<{
|
|
|
352
419
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
353
420
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
354
421
|
color: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
422
|
+
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
423
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
424
|
+
icu_training_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
425
|
+
icu_intensity: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
426
|
+
paired_activity_id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
355
427
|
}, z.ZodTypeAny, "passthrough">>;
|
|
356
428
|
export type Event = z.infer<typeof EventSchema>;
|
|
357
429
|
export declare const IntervalSchema: z.ZodObject<{
|
|
@@ -423,6 +495,10 @@ export declare const SportSettingsSchema: z.ZodObject<{
|
|
|
423
495
|
hr_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
424
496
|
pace_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
425
497
|
pace_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
498
|
+
w_prime: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
499
|
+
sweet_spot_min: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
500
|
+
sweet_spot_max: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
501
|
+
best_effort_distances: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
426
502
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
427
503
|
types: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
428
504
|
ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
@@ -435,6 +511,10 @@ export declare const SportSettingsSchema: z.ZodObject<{
|
|
|
435
511
|
hr_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
436
512
|
pace_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
437
513
|
pace_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
514
|
+
w_prime: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
515
|
+
sweet_spot_min: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
516
|
+
sweet_spot_max: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
517
|
+
best_effort_distances: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
438
518
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
439
519
|
types: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
440
520
|
ftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
@@ -447,6 +527,10 @@ export declare const SportSettingsSchema: z.ZodObject<{
|
|
|
447
527
|
hr_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
448
528
|
pace_zones: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
449
529
|
pace_zone_names: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
530
|
+
w_prime: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
531
|
+
sweet_spot_min: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
532
|
+
sweet_spot_max: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
533
|
+
best_effort_distances: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodNumber, "many">>>;
|
|
450
534
|
}, z.ZodTypeAny, "passthrough">>;
|
|
451
535
|
export type SportSettings = z.infer<typeof SportSettingsSchema>;
|
|
452
536
|
export declare const WorkoutSchema: z.ZodObject<{
|
|
@@ -455,18 +539,27 @@ export declare const WorkoutSchema: z.ZodObject<{
|
|
|
455
539
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
456
540
|
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
457
541
|
updated: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
542
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
543
|
+
icu_training_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
544
|
+
joules: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
458
545
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
459
546
|
id: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
|
|
460
547
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
461
548
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
462
549
|
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
463
550
|
updated: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
551
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
552
|
+
icu_training_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
553
|
+
joules: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
464
554
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
465
555
|
id: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
|
|
466
556
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
467
557
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
468
558
|
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
469
559
|
updated: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
560
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
561
|
+
icu_training_load: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
562
|
+
joules: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
470
563
|
}, z.ZodTypeAny, "passthrough">>;
|
|
471
564
|
export type Workout = z.infer<typeof WorkoutSchema>;
|
|
472
565
|
export interface WorkoutInput {
|
|
@@ -530,6 +623,8 @@ export declare const MessageSchema: z.ZodObject<{
|
|
|
530
623
|
export type Message = z.infer<typeof MessageSchema>;
|
|
531
624
|
export declare function getActivityMessages(config: ClientConfig, activityId: string): Promise<Message[]>;
|
|
532
625
|
export declare function addActivityMessage(config: ClientConfig, activityId: string, content: string): Promise<void>;
|
|
626
|
+
export declare function deleteActivityMessage(config: ClientConfig, activityId: string, messageId: number): Promise<void>;
|
|
627
|
+
export declare function updateActivityMessage(config: ClientConfig, activityId: string, messageId: number, content: string): Promise<void>;
|
|
533
628
|
export declare function getWellness(config: ClientConfig, params: {
|
|
534
629
|
startDate: string;
|
|
535
630
|
endDate: string;
|
|
@@ -564,6 +659,10 @@ export declare const AthleteFitnessSchema: z.ZodObject<{
|
|
|
564
659
|
eftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
565
660
|
eftpPerKg: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
566
661
|
weight: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
662
|
+
count: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
663
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
664
|
+
calories: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
665
|
+
distance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
567
666
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
568
667
|
date: z.ZodOptional<z.ZodString>;
|
|
569
668
|
fitness: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
@@ -574,6 +673,10 @@ export declare const AthleteFitnessSchema: z.ZodObject<{
|
|
|
574
673
|
eftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
575
674
|
eftpPerKg: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
576
675
|
weight: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
676
|
+
count: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
677
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
678
|
+
calories: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
679
|
+
distance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
577
680
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
578
681
|
date: z.ZodOptional<z.ZodString>;
|
|
579
682
|
fitness: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
@@ -584,6 +687,10 @@ export declare const AthleteFitnessSchema: z.ZodObject<{
|
|
|
584
687
|
eftp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
585
688
|
eftpPerKg: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
586
689
|
weight: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
690
|
+
count: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
691
|
+
moving_time: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
692
|
+
calories: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
693
|
+
distance: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
587
694
|
}, z.ZodTypeAny, "passthrough">>;
|
|
588
695
|
export type AthleteFitness = z.infer<typeof AthleteFitnessSchema>;
|
|
589
696
|
export declare function getAthleteFitness(config: ClientConfig, params: {
|
package/dist/client.js
CHANGED
|
@@ -83,6 +83,7 @@ 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(),
|
|
86
87
|
}).passthrough();
|
|
87
88
|
export const WellnessSchema = z.object({
|
|
88
89
|
id: z.string().optional(),
|
|
@@ -107,6 +108,14 @@ export const WellnessSchema = z.object({
|
|
|
107
108
|
bodyFat: z.number().nullable().optional(),
|
|
108
109
|
spO2: z.number().nullable().optional(),
|
|
109
110
|
comments: z.string().nullable().optional(),
|
|
111
|
+
rampRate: z.number().nullable().optional(),
|
|
112
|
+
avgSleepingHR: z.number().nullable().optional(),
|
|
113
|
+
sportInfo: z.array(z.object({
|
|
114
|
+
type: z.string().optional(),
|
|
115
|
+
eftp: z.number().nullable().optional(),
|
|
116
|
+
wPrime: z.number().nullable().optional(),
|
|
117
|
+
pMax: z.number().nullable().optional(),
|
|
118
|
+
})).nullable().optional(),
|
|
110
119
|
}).passthrough();
|
|
111
120
|
export const EventSchema = z.object({
|
|
112
121
|
id: z.union([z.string(), z.number()]),
|
|
@@ -118,6 +127,11 @@ export const EventSchema = z.object({
|
|
|
118
127
|
name: z.string().nullable().optional(),
|
|
119
128
|
description: z.string().nullable().optional(),
|
|
120
129
|
color: z.string().nullable().optional(),
|
|
130
|
+
type: z.string().nullable().optional(),
|
|
131
|
+
moving_time: z.number().nullable().optional(),
|
|
132
|
+
icu_training_load: z.number().nullable().optional(),
|
|
133
|
+
icu_intensity: z.number().nullable().optional(),
|
|
134
|
+
paired_activity_id: z.string().nullable().optional(),
|
|
121
135
|
}).passthrough();
|
|
122
136
|
export const IntervalSchema = z.object({
|
|
123
137
|
icu_intervals: z.array(z.record(z.unknown())).nullable().optional(),
|
|
@@ -147,6 +161,10 @@ export const SportSettingsSchema = z.object({
|
|
|
147
161
|
hr_zone_names: z.array(z.string()).nullable().optional(),
|
|
148
162
|
pace_zones: z.array(z.number()).nullable().optional(),
|
|
149
163
|
pace_zone_names: z.array(z.string()).nullable().optional(),
|
|
164
|
+
w_prime: z.number().nullable().optional(),
|
|
165
|
+
sweet_spot_min: z.number().nullable().optional(),
|
|
166
|
+
sweet_spot_max: z.number().nullable().optional(),
|
|
167
|
+
best_effort_distances: z.array(z.number()).nullable().optional(),
|
|
150
168
|
}).passthrough();
|
|
151
169
|
export const WorkoutSchema = z.object({
|
|
152
170
|
id: z.union([z.string(), z.number()]).optional(),
|
|
@@ -154,6 +172,9 @@ export const WorkoutSchema = z.object({
|
|
|
154
172
|
description: z.string().nullable().optional(),
|
|
155
173
|
type: z.string().nullable().optional(),
|
|
156
174
|
updated: z.string().nullable().optional(),
|
|
175
|
+
moving_time: z.number().nullable().optional(),
|
|
176
|
+
icu_training_load: z.number().nullable().optional(),
|
|
177
|
+
joules: z.number().nullable().optional(),
|
|
157
178
|
}).passthrough();
|
|
158
179
|
// ---- API methods ---- //
|
|
159
180
|
export async function getActivities(config, params) {
|
|
@@ -184,6 +205,20 @@ export async function getActivityMessages(config, activityId) {
|
|
|
184
205
|
export async function addActivityMessage(config, activityId, content) {
|
|
185
206
|
await mutate("POST", `/activity/${activityId}/messages`, config, { content });
|
|
186
207
|
}
|
|
208
|
+
// Intervals.icu has no endpoint to edit a message's content in place — only
|
|
209
|
+
// delete and re-add. Callers wanting an "edit" should use updateActivityMessage,
|
|
210
|
+
// which does both and leaves the old message showing as deleted.
|
|
211
|
+
export async function deleteActivityMessage(config, activityId, messageId) {
|
|
212
|
+
const activity = await getActivityDetails(config, activityId);
|
|
213
|
+
const chatId = activity.icu_chat_id;
|
|
214
|
+
if (chatId == null)
|
|
215
|
+
throw new Error(`Activity ${activityId} has no chat/messages.`);
|
|
216
|
+
await mutate("DELETE", `/chats/${chatId}/messages/${messageId}`, config);
|
|
217
|
+
}
|
|
218
|
+
export async function updateActivityMessage(config, activityId, messageId, content) {
|
|
219
|
+
await deleteActivityMessage(config, activityId, messageId);
|
|
220
|
+
await addActivityMessage(config, activityId, content);
|
|
221
|
+
}
|
|
187
222
|
export async function getWellness(config, params) {
|
|
188
223
|
const data = await request(`/athlete/${config.athleteId}/wellness`, config, { oldest: params.startDate, newest: params.endDate });
|
|
189
224
|
if (Array.isArray(data)) {
|
|
@@ -303,6 +338,10 @@ export const AthleteFitnessSchema = z.object({
|
|
|
303
338
|
eftp: z.number().nullable().optional(),
|
|
304
339
|
eftpPerKg: z.number().nullable().optional(),
|
|
305
340
|
weight: z.number().nullable().optional(),
|
|
341
|
+
count: z.number().nullable().optional(),
|
|
342
|
+
moving_time: z.number().nullable().optional(),
|
|
343
|
+
calories: z.number().nullable().optional(),
|
|
344
|
+
distance: z.number().nullable().optional(),
|
|
306
345
|
}).passthrough();
|
|
307
346
|
export async function getAthleteFitness(config, params) {
|
|
308
347
|
const data = await request(`/athlete/${config.athleteId}/athlete-summary.json`, config, { start: params.startDate, end: params.endDate });
|
package/dist/format.js
CHANGED
|
@@ -48,14 +48,14 @@ export function formatActivity(a) {
|
|
|
48
48
|
}
|
|
49
49
|
export function formatWellness(date, w) {
|
|
50
50
|
const sleepHours = w.sleepSecs != null ? (w.sleepSecs / 3600).toFixed(1) + " h" : "N/A";
|
|
51
|
-
|
|
51
|
+
const lines = [
|
|
52
52
|
`**${date}**`,
|
|
53
53
|
"",
|
|
54
54
|
"Training:",
|
|
55
|
-
` CTL: ${n(w.ctl)} | ATL: ${n(w.atl)}`,
|
|
55
|
+
` CTL: ${n(w.ctl)} | ATL: ${n(w.atl)} | Ramp Rate: ${n(w.rampRate)}`,
|
|
56
56
|
"",
|
|
57
57
|
"Vitals:",
|
|
58
|
-
` Weight: ${n(w.weight, " kg")} | Resting HR: ${n(w.restingHR, " bpm")}`,
|
|
58
|
+
` Weight: ${n(w.weight, " kg")} | Resting HR: ${n(w.restingHR, " bpm")} | Avg Sleeping HR: ${n(w.avgSleepingHR, " bpm")}`,
|
|
59
59
|
` HRV: ${n(w.hrv)} | HRV SDNN: ${n(w.hrvSDNN)}`,
|
|
60
60
|
` SpO2: ${n(w.spO2, "%")} | VO2max: ${n(w.vo2max)} | Body Fat: ${n(w.bodyFat, "%")}`,
|
|
61
61
|
"",
|
|
@@ -69,11 +69,13 @@ export function formatWellness(date, w) {
|
|
|
69
69
|
"",
|
|
70
70
|
"Nutrition:",
|
|
71
71
|
` Calories: ${n(w.kcalConsumed, " kcal")} | Steps: ${n(w.steps)}`,
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
.
|
|
75
|
-
|
|
76
|
-
|
|
72
|
+
];
|
|
73
|
+
if (w.sportInfo?.length) {
|
|
74
|
+
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")}`));
|
|
75
|
+
}
|
|
76
|
+
if (w.comments)
|
|
77
|
+
lines.push("", `Comments: ${w.comments}`);
|
|
78
|
+
return lines.join("\n").trimEnd();
|
|
77
79
|
}
|
|
78
80
|
export function formatEvent(e) {
|
|
79
81
|
const category = e.category ?? "";
|
|
@@ -88,14 +90,19 @@ export function formatEvent(e) {
|
|
|
88
90
|
const dateLabel = e.end_date_local && e.end_date_local !== e.start_date_local
|
|
89
91
|
? `${start} to ${e.end_date_local}`
|
|
90
92
|
: start;
|
|
91
|
-
|
|
93
|
+
const lines = [
|
|
92
94
|
`**${e.name ?? "Unnamed"}** (${e.id})`,
|
|
93
95
|
`Type: ${type} | Date: ${dateLabel}`,
|
|
94
96
|
e.category ? `Category: ${e.category}` : "",
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
.
|
|
98
|
-
|
|
97
|
+
];
|
|
98
|
+
if (e.type || e.moving_time != null || e.icu_training_load != null || e.icu_intensity != null) {
|
|
99
|
+
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)}`);
|
|
100
|
+
}
|
|
101
|
+
if (e.paired_activity_id)
|
|
102
|
+
lines.push(`Completed as: ${e.paired_activity_id}`);
|
|
103
|
+
if (e.description)
|
|
104
|
+
lines.push(`Description: ${e.description}`);
|
|
105
|
+
return lines.filter(Boolean).join("\n");
|
|
99
106
|
}
|
|
100
107
|
export function formatMessage(m) {
|
|
101
108
|
const when = m.created ? new Date(m.created).toLocaleString() : "Unknown time";
|
|
@@ -146,6 +153,13 @@ export function formatSportZones(s) {
|
|
|
146
153
|
const range = z.to != null ? `${z.from}-${z.to} m/s` : `${z.from}+ m/s`;
|
|
147
154
|
lines.push(` ${z.name}: ${range}`);
|
|
148
155
|
}
|
|
156
|
+
lines.push("");
|
|
157
|
+
}
|
|
158
|
+
if (s.w_prime != null || s.sweet_spot_min != null) {
|
|
159
|
+
lines.push(`Power Model: W' ${n(s.w_prime, " J")} | Sweet Spot ${n(s.sweet_spot_min, "%")}-${n(s.sweet_spot_max, "%")}`);
|
|
160
|
+
}
|
|
161
|
+
if (s.best_effort_distances?.length) {
|
|
162
|
+
lines.push(`Best Effort Distances: ${s.best_effort_distances.join(", ")} m`);
|
|
149
163
|
}
|
|
150
164
|
return lines.join("\n").trimEnd();
|
|
151
165
|
}
|
|
@@ -160,10 +174,13 @@ export function formatIntervalRow(interval, idx) {
|
|
|
160
174
|
const avgHr = interval["average_heartrate"] ?? 0;
|
|
161
175
|
const maxHr = interval["max_heartrate"] ?? 0;
|
|
162
176
|
const tl = interval["training_load"] ?? 0;
|
|
177
|
+
const intensity = interval["intensity"];
|
|
178
|
+
const vi = interval["w5s_variability"];
|
|
179
|
+
const decoupling = interval["decoupling"];
|
|
163
180
|
return [
|
|
164
181
|
`[${idx}] ${label} (${type})`,
|
|
165
182
|
` 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`,
|
|
183
|
+
` Power: avg ${avgW}W, w.avg ${wAvg}W, max ${maxW}W | TL: ${tl} | Intensity: ${n(intensity)} | VI: ${n(vi)}`,
|
|
184
|
+
` HR: avg ${avgHr}, max ${maxHr} bpm | Decoupling: ${n(decoupling, "%")}`,
|
|
168
185
|
].join("\n");
|
|
169
186
|
}
|
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.3.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"
|