intervals-icu-mcp-server 0.1.9 → 0.2.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 CHANGED
@@ -343,6 +343,34 @@ export declare function getActivities(config: ClientConfig, params: {
343
343
  }): Promise<Activity[]>;
344
344
  export declare function getActivityDetails(config: ClientConfig, activityId: string): Promise<Activity>;
345
345
  export declare function getActivityIntervals(config: ClientConfig, activityId: string): Promise<z.infer<typeof IntervalSchema>>;
346
+ export declare const MessageSchema: z.ZodObject<{
347
+ id: z.ZodOptional<z.ZodNumber>;
348
+ athlete_id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
349
+ name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
350
+ created: z.ZodOptional<z.ZodNullable<z.ZodString>>;
351
+ type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
352
+ content: z.ZodOptional<z.ZodNullable<z.ZodString>>;
353
+ attachment_url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
354
+ }, "strip", z.ZodTypeAny, {
355
+ id?: number | undefined;
356
+ name?: string | null | undefined;
357
+ type?: string | null | undefined;
358
+ athlete_id?: string | null | undefined;
359
+ created?: string | null | undefined;
360
+ content?: string | null | undefined;
361
+ attachment_url?: string | null | undefined;
362
+ }, {
363
+ id?: number | undefined;
364
+ name?: string | null | undefined;
365
+ type?: string | null | undefined;
366
+ athlete_id?: string | null | undefined;
367
+ created?: string | null | undefined;
368
+ content?: string | null | undefined;
369
+ attachment_url?: string | null | undefined;
370
+ }>;
371
+ export type Message = z.infer<typeof MessageSchema>;
372
+ export declare function getActivityMessages(config: ClientConfig, activityId: string): Promise<Message[]>;
373
+ export declare function addActivityMessage(config: ClientConfig, activityId: string, content: string): Promise<void>;
346
374
  export declare function getWellness(config: ClientConfig, params: {
347
375
  startDate: string;
348
376
  endDate: string;
package/dist/client.js CHANGED
@@ -138,6 +138,22 @@ export async function getActivityIntervals(config, activityId) {
138
138
  const data = await request(`/activity/${activityId}/intervals`, config);
139
139
  return IntervalSchema.parse(data);
140
140
  }
141
+ export const MessageSchema = z.object({
142
+ id: z.number().optional(),
143
+ athlete_id: z.string().nullable().optional(),
144
+ name: z.string().nullable().optional(),
145
+ created: z.string().nullable().optional(),
146
+ type: z.string().nullable().optional(),
147
+ content: z.string().nullable().optional(),
148
+ attachment_url: z.string().nullable().optional(),
149
+ });
150
+ export async function getActivityMessages(config, activityId) {
151
+ const data = await request(`/activity/${activityId}/messages`, config);
152
+ return z.array(MessageSchema).parse(data);
153
+ }
154
+ export async function addActivityMessage(config, activityId, content) {
155
+ await mutate("POST", `/activity/${activityId}/messages`, config, { content });
156
+ }
141
157
  export async function getWellness(config, params) {
142
158
  const data = await request(`/athlete/${config.athleteId}/wellness`, config, { oldest: params.startDate, newest: params.endDate });
143
159
  if (Array.isArray(data)) {
package/dist/format.d.ts CHANGED
@@ -1,6 +1,7 @@
1
- import type { Activity, Wellness, Event, SportSettings } from "./client.js";
1
+ import type { Activity, Wellness, Event, SportSettings, Message } 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 formatMessage(m: Message): string;
5
6
  export declare function formatSportZones(s: SportSettings): string;
6
7
  export declare function formatIntervalRow(interval: Record<string, unknown>, idx: number): string;
package/dist/format.js CHANGED
@@ -83,6 +83,10 @@ export function formatEvent(e) {
83
83
  .filter(Boolean)
84
84
  .join("\n");
85
85
  }
86
+ export function formatMessage(m) {
87
+ const when = m.created ? new Date(m.created).toLocaleString() : "Unknown time";
88
+ return `**${m.name ?? "Unknown"}** (${when}): ${m.content ?? ""}`;
89
+ }
86
90
  function zoneRanges(breakpoints, names) {
87
91
  const count = names?.length ?? (breakpoints?.length ?? 0) + 1;
88
92
  const ranges = [];
package/dist/index.js CHANGED
@@ -4,8 +4,8 @@ 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, } from "./client.js";
8
- import { formatActivity, formatWellness, formatEvent, formatIntervalRow, formatSportZones, } from "./format.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, } from "./client.js";
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 ?? "";
11
11
  const athleteId = args["athlete_id"] ??
@@ -282,6 +282,33 @@ const TOOLS = [
282
282
  },
283
283
  },
284
284
  },
285
+ {
286
+ name: "get_activity_messages",
287
+ description: "Get the comments/notes left on a specific activity (the chat thread shown under an activity in Intervals.icu, e.g. coach feedback).",
288
+ inputSchema: {
289
+ type: "object",
290
+ required: ["activity_id"],
291
+ properties: {
292
+ activity_id: { type: "string", description: "The activity ID" },
293
+ athlete_id: { type: "string", description: "Athlete ID (defaults to ATHLETE_ID env var)" },
294
+ api_key: { type: "string", description: "API key (defaults to API_KEY env var)" },
295
+ },
296
+ },
297
+ },
298
+ {
299
+ name: "add_activity_message",
300
+ description: "Post a comment/note on a specific activity (adds to the activity's chat thread in Intervals.icu).",
301
+ inputSchema: {
302
+ type: "object",
303
+ required: ["activity_id", "content"],
304
+ properties: {
305
+ activity_id: { type: "string", description: "The activity ID" },
306
+ content: { type: "string", description: "Comment text to post" },
307
+ athlete_id: { type: "string", description: "Athlete ID (defaults to ATHLETE_ID env var)" },
308
+ api_key: { type: "string", description: "API key (defaults to API_KEY env var)" },
309
+ },
310
+ },
311
+ },
285
312
  {
286
313
  name: "list_workouts",
287
314
  description: "List all workouts in the athlete's workout library.",
@@ -624,6 +651,22 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
624
651
  const curves = await getActivityPowerCurves(config, activityId);
625
652
  return { content: [{ type: "text", text: `Power curves for activity ${activityId}:\n\n${JSON.stringify(curves, null, 2)}` }] };
626
653
  }
654
+ case "get_activity_messages": {
655
+ const activityId = z.string().parse(args["activity_id"]);
656
+ const config = getConfig(args);
657
+ const messages = await getActivityMessages(config, activityId);
658
+ if (!messages.length)
659
+ return { content: [{ type: "text", text: "No comments on this activity." }] };
660
+ const text = messages.map(formatMessage).join("\n");
661
+ return { content: [{ type: "text", text }] };
662
+ }
663
+ case "add_activity_message": {
664
+ const activityId = z.string().parse(args["activity_id"]);
665
+ const content = z.string().parse(args["content"]);
666
+ const config = getConfig(args);
667
+ await addActivityMessage(config, activityId, content);
668
+ return { content: [{ type: "text", text: `Comment added to activity ${activityId}.` }] };
669
+ }
627
670
  case "list_workouts": {
628
671
  const config = getConfig(args);
629
672
  const workouts = await listWorkouts(config);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "intervals-icu-mcp-server",
3
- "version": "0.1.9",
4
- "description": "MCP server for Intervals.icu — 20 tools for activities, wellness, calendar events, workouts and more",
3
+ "version": "0.2.0",
4
+ "description": "MCP server for Intervals.icu — 24 tools for activities, wellness, calendar events, workouts and more",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "intervals-icu-mcp": "dist/index.js"