intervals-mcp-server 1.0.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/LICENSE +21 -0
- package/README.md +151 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2345 -0
- package/dist/index.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/utils/dates.ts","../src/utils/validation.ts","../src/auth.ts","../src/api/client.ts","../src/openUrl.ts","../src/server.ts","../src/tools/activities.ts","../src/utils/formatting.ts","../src/tools/gear.ts","../src/tools/shared.ts","../src/tools/customItems.ts","../src/tools/events.ts","../src/utils/types.ts","../src/tools/powerCurves.ts","../src/tools/wellness.ts"],"sourcesContent":["/**\n * intervals-mcp-server — MCP server for the Intervals.icu API.\n *\n * Default (no args): serve over stdio, running the onboarding wizard first\n * when no credentials are configured yet (interactive terminal only).\n * `auth`: (re)run the credential setup wizard.\n * `serve`: start the server, skipping the onboarding check.\n */\n\nimport { Command } from \"commander\";\nimport { hasCredentials, readPackageVersion } from \"./config.js\";\nimport { runOnboarding } from \"./auth.js\";\nimport { serveStdio, serveStreamableHttp } from \"./server.js\";\n\ninterface ServeOptions {\n transport: string;\n host: string;\n port: string;\n}\n\nconst NO_CREDENTIALS_HINT = `No Intervals.icu credentials found.\n\n Run the interactive setup once in your terminal:\n\n npx intervals-mcp-server auth\n\n It opens https://intervals.icu/settings where you can copy your API Key\n and Athlete ID, verifies them, and saves them for future runs.\n\n Alternatively set the API_KEY and ATHLETE_ID environment variables in your\n MCP client configuration.`;\n\nfunction isInteractive(): boolean {\n return Boolean(process.stdin.isTTY && process.stdout.isTTY);\n}\n\nasync function startServer(opts: ServeOptions): Promise<void> {\n const transport = opts.transport.toLowerCase();\n if (transport === \"stdio\") {\n await serveStdio();\n return;\n }\n if (transport === \"streamable-http\" || transport === \"http\") {\n const port = Number.parseInt(opts.port, 10);\n if (!Number.isInteger(port) || port <= 0 || port > 65535) {\n console.error(`Invalid port: ${opts.port}`);\n process.exit(1);\n }\n await serveStreamableHttp(opts.host, port);\n return;\n }\n console.error(`Unsupported transport \"${opts.transport}\". Use \"stdio\" or \"streamable-http\".`);\n process.exit(1);\n}\n\nconst program = new Command();\n\nprogram\n .name(\"intervals-mcp-server\")\n .description(\"Model Context Protocol server for the Intervals.icu API\")\n .version(readPackageVersion())\n .option(\"--transport <type>\", \"transport: stdio or streamable-http\", \"stdio\")\n .option(\"--host <host>\", \"HTTP host when using streamable-http\", \"127.0.0.1\")\n .option(\"--port <port>\", \"HTTP port when using streamable-http\", \"8765\")\n .action(async (opts: ServeOptions) => {\n if (!hasCredentials()) {\n if (!isInteractive()) {\n console.error(NO_CREDENTIALS_HINT);\n process.exit(1);\n }\n // Interactive first run: configure, show client snippets, then exit so\n // the MCP client spawns a clean process (no prompt noise on stdio).\n const ok = await runOnboarding();\n process.exit(ok ? 0 : 1);\n }\n await startServer(opts);\n });\n\nprogram\n .command(\"auth\")\n .description(\"Run (or re-run) the interactive credential setup wizard\")\n .action(async () => {\n if (!isInteractive()) {\n console.error(\"The auth wizard needs an interactive terminal. Run it directly in your shell:\\n\\n npx intervals-mcp-server auth\\n\");\n process.exit(1);\n }\n const ok = await runOnboarding();\n process.exit(ok ? 0 : 1);\n });\n\nprogram\n .command(\"serve\")\n .description(\"Start the MCP server (skips the onboarding check)\")\n .option(\"--transport <type>\", \"transport: stdio or streamable-http\", \"stdio\")\n .option(\"--host <host>\", \"HTTP host when using streamable-http\", \"127.0.0.1\")\n .option(\"--port <port>\", \"HTTP port when using streamable-http\", \"8765\")\n .action(async (opts: ServeOptions) => {\n await startServer(opts);\n });\n\nprogram.parseAsync(process.argv).catch((err: unknown) => {\n console.error(\"[intervals-mcp-server] fatal:\", err);\n process.exit(1);\n});\n","/**\n * Configuration: credentials resolve from environment variables first, then\n * from the config file written by `intervals-mcp-server auth`.\n */\n\nimport { readFileSync, writeFileSync, mkdirSync, chmodSync, existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport { validateAthleteId } from \"./utils/validation.js\";\n\nexport const DEFAULT_API_BASE_URL = \"https://intervals.icu/api/v1\";\n\nexport interface Config {\n apiKey: string;\n athleteId: string;\n apiBaseUrl: string;\n userAgent: string;\n}\n\nexport interface StoredCredentials {\n apiKey: string;\n athleteId: string;\n}\n\n/** Package version (read from package.json, with a safe fallback). */\nexport function readPackageVersion(): string {\n try {\n const pkgUrl = new URL(\"../package.json\", import.meta.url);\n const pkg = JSON.parse(readFileSync(pkgUrl, \"utf8\")) as { version?: string };\n return pkg.version ?? \"1.0.0\";\n } catch {\n return \"1.0.0\";\n }\n}\n\n/** Directory holding the config file (XDG-aware, defaults to ~/.config). */\nexport function configDir(): string {\n const xdg = process.env.XDG_CONFIG_HOME;\n const base = xdg && path.isAbsolute(xdg) ? xdg : path.join(homedir(), \".config\");\n return path.join(base, \"intervals-mcp-server\");\n}\n\n/** Absolute path of the on-disk credentials file. */\nexport function configFilePath(): string {\n return path.join(configDir(), \"config.json\");\n}\n\n/** Read credentials from the config file. Returns null when absent/invalid. */\nexport function readStoredCredentials(): StoredCredentials | null {\n const file = configFilePath();\n if (!existsSync(file)) return null;\n try {\n const raw = JSON.parse(readFileSync(file, \"utf8\")) as Partial<StoredCredentials>;\n if (typeof raw.apiKey === \"string\" && typeof raw.athleteId === \"string\") {\n return { apiKey: raw.apiKey, athleteId: raw.athleteId };\n }\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Persist credentials to the config file (created with 0600 permissions).\n * Throws on invalid athlete ID.\n */\nexport function saveStoredCredentials(creds: StoredCredentials): void {\n validateAthleteId(creds.athleteId);\n mkdirSync(configDir(), { recursive: true });\n const file = configFilePath();\n writeFileSync(file, JSON.stringify(creds, null, 2) + \"\\n\", { mode: 0o600 });\n try {\n chmodSync(file, 0o600);\n } catch {\n // chmod can fail on exotic filesystems; the file is still private-ish\n }\n}\n\n/**\n * Resolve the effective configuration.\n * Environment variables win over the config file so MCP clients can override\n * per-server (`env` in the client config) and CI stays possible.\n */\nexport function getConfig(): Config {\n const stored = readStoredCredentials();\n const apiKey = process.env.API_KEY || stored?.apiKey || \"\";\n const athleteId = process.env.ATHLETE_ID || stored?.athleteId || \"\";\n\n if (athleteId) validateAthleteId(athleteId);\n\n return {\n apiKey,\n athleteId,\n apiBaseUrl: process.env.INTERVALS_API_BASE_URL || DEFAULT_API_BASE_URL,\n userAgent: `intervalsicu-mcp-server-ts/${readPackageVersion()}`,\n };\n}\n\n/** Whether both API key and athlete ID are available from any source. */\nexport function hasCredentials(): boolean {\n const cfg = getConfig();\n return Boolean(cfg.apiKey && cfg.athleteId);\n}\n","/**\n * Date utility functions.\n *\n * Helpers for local-time date strings (YYYY-MM-DD) and default date ranges.\n */\n\n/** Format a Date as a local YYYY-MM-DD string (no UTC conversion). */\nexport function toLocalDateString(date: Date): string {\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, \"0\");\n const day = String(date.getDate()).padStart(2, \"0\");\n return `${year}-${month}-${day}`;\n}\n\n/** Today's date as YYYY-MM-DD (local time). */\nexport function getDefaultEndDate(): string {\n return toLocalDateString(new Date());\n}\n\n/** Date string `daysAgo` days before today, as YYYY-MM-DD (local time). */\nexport function getDefaultStartDate(daysAgo = 30): string {\n const d = new Date();\n d.setDate(d.getDate() - daysAgo);\n return toLocalDateString(d);\n}\n\n/** Date string `daysAhead` days after today, as YYYY-MM-DD (local time). */\nexport function getDefaultFutureEndDate(daysAhead = 30): string {\n const d = new Date();\n d.setDate(d.getDate() + daysAhead);\n return toLocalDateString(d);\n}\n\n/** Resolve a date range with defaults: start = 30 days ago, end = today. */\nexport function parseDateRange(\n startDate?: string | null,\n endDate?: string | null,\n defaultStartDaysAgo = 30,\n): [string, string] {\n const start = startDate || getDefaultStartDate(defaultStartDaysAgo);\n const end = endDate || getDefaultEndDate();\n return [start, end];\n}\n\n/** Format \"YYYY-MM-DDTHH:MM:SS...\" (ISO) as \"YYYY-MM-DD HH:MM:SS\", keeping the\n * recorded wall-clock time (no timezone conversion). Falls back to the input. */\nexport function formatIsoDateTime(value: string): string {\n const match = /^(\\d{4}-\\d{2}-\\d{2})[T ](\\d{2}:\\d{2}:\\d{2})/.exec(value);\n return match ? `${match[1]} ${match[2]}` : value;\n}\n","/**\n * Validation utilities for tool input parameters.\n */\n\nimport { parseDateRange } from \"./dates.js\";\n\nconst ATHLETE_ID_PATTERN = /^i?\\d+$/;\n\n/**\n * Validate that an athlete ID is well formed.\n * Empty strings are allowed (meaning no default athlete ID is set).\n * Non-empty IDs must be all digits or 'i' followed by digits.\n */\nexport function validateAthleteId(athleteId: string): void {\n if (athleteId && !ATHLETE_ID_PATTERN.test(athleteId)) {\n throw new Error(\n \"ATHLETE_ID must be all digits (e.g. 123456) or start with 'i' followed by digits (e.g. i123456)\",\n );\n }\n}\n\n/**\n * Validate that a date string is a real date in YYYY-MM-DD format.\n * Returns the validated string, or throws.\n */\nexport function validateDate(dateStr: string): string {\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(dateStr)) {\n const [y, m, d] = dateStr.split(\"-\").map(Number) as [number, number, number];\n const parsed = new Date(y, m - 1, d);\n if (\n parsed.getFullYear() === y &&\n parsed.getMonth() === m - 1 &&\n parsed.getDate() === d\n ) {\n return dateStr;\n }\n }\n throw new Error(\"Invalid date format. Please use YYYY-MM-DD.\");\n}\n\nexport interface ResolvedAthleteId {\n athleteId: string;\n error: string | null;\n}\n\n/**\n * Resolve the athlete ID from an explicit parameter or the configured default.\n * Returns the ID plus an error message when neither is available.\n */\nexport function resolveAthleteId(\n athleteId: string | undefined | null,\n defaultAthleteId: string,\n): ResolvedAthleteId {\n const idToUse = athleteId ?? defaultAthleteId;\n if (!idToUse) {\n return {\n athleteId: \"\",\n error:\n \"Error: No athlete ID provided and no default ATHLETE_ID found. Run `npx intervals-mcp-server auth` to configure your credentials.\",\n };\n }\n return { athleteId: idToUse, error: null };\n}\n\n/**\n * Determine the activity type from an explicit value or by inferring it from\n * the event/workout name. Defaults to \"Ride\".\n */\nexport function resolveActivityType(\n name: string | undefined | null,\n activityType?: string | null,\n): string {\n if (activityType) return activityType;\n const nameLower = name?.toLowerCase() ?? \"\";\n const mapping: Array<[string, string[]]> = [\n [\"Ride\", [\"bike\", \"cycle\", \"cycling\", \"ride\"]],\n [\"Run\", [\"run\", \"running\", \"jog\", \"jogging\"]],\n [\"Swim\", [\"swim\", \"swimming\", \"pool\"]],\n [\"Walk\", [\"walk\", \"walking\", \"hike\", \"hiking\"]],\n [\"Row\", [\"row\", \"rowing\"]],\n ];\n for (const [workout, keywords] of mapping) {\n if (keywords.some((keyword) => nameLower.includes(keyword))) {\n return workout;\n }\n }\n return \"Ride\";\n}\n\n/** Resolve start/end date parameters with defaults (start 30 days ago, end today). */\nexport function resolveDateParams(\n startDate?: string | null,\n endDate?: string | null,\n defaultStartDaysAgo = 30,\n): [string, string] {\n return parseDateRange(startDate, endDate, defaultStartDaysAgo);\n}\n","/**\n * First-run onboarding wizard.\n *\n * Guides the user through getting their API key and athlete ID from\n * https://intervals.icu/settings, validates them against the live API, and\n * persists them to the config file.\n */\n\nimport * as p from \"@clack/prompts\";\nimport { makeIntervalsRequest, isApiError } from \"./api/client.js\";\nimport {\n configFilePath,\n hasCredentials,\n readStoredCredentials,\n saveStoredCredentials,\n} from \"./config.js\";\nimport { openUrl, terminalLink } from \"./openUrl.js\";\nimport { getDefaultEndDate } from \"./utils/dates.js\";\nimport { validateAthleteId } from \"./utils/validation.js\";\n\nexport const SETTINGS_URL = \"https://intervals.icu/settings\";\n\nconst CLIENT_SNIPPETS = `\nAdd the server to your MCP client (pick one):\n\n Claude Code\n claude mcp add intervals -s user -- npx intervals-mcp-server\n\n Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json)\n {\n \"mcpServers\": {\n \"intervals\": { \"command\": \"npx\", \"args\": [\"intervals-mcp-server\"] }\n }\n }\n\n Cursor (~/.cursor/mcp.json)\n {\n \"mcpServers\": {\n \"intervals\": { \"command\": \"npx\", \"args\": [\"intervals-mcp-server\"] }\n }\n }`;\n\nfunction cancel(): never {\n p.cancel(\"Setup cancelled — nothing was saved.\");\n process.exit(0);\n}\n\n/** Verify credentials against the live API. Returns null on success or an error message. */\nexport async function verifyCredentials(\n apiKey: string,\n athleteId: string,\n): Promise<string | null> {\n const today = getDefaultEndDate();\n const result = await makeIntervalsRequest(`/athlete/${athleteId}/wellness`, {\n apiKey,\n params: { oldest: today, newest: today },\n });\n if (isApiError(result)) {\n if (result.status_code === 401) return \"The API key was rejected (401). Please re-check it.\";\n if (result.status_code === 404) return `Athlete ID \"${athleteId}\" was not found (404).`;\n return result.message;\n }\n return null;\n}\n\n/** Run the interactive setup wizard. Returns true when credentials were saved. */\nexport async function runOnboarding(): Promise<boolean> {\n const existing = readStoredCredentials();\n\n console.log(\"\");\n p.intro(\"Intervals.icu MCP server — first-time setup\");\n\n p.log.message(\n `This server needs your Intervals.icu ${terminalLink(\"API Key\", SETTINGS_URL)} and Athlete ID.`,\n );\n\n p.log.step(\"Step 1 — opening the Intervals.icu settings page in your browser\");\n const opened = openUrl(SETTINGS_URL);\n if (!opened) {\n p.log.warn(\"Could not open a browser automatically — open this URL manually:\");\n console.log(` ${SETTINGS_URL}`);\n } else {\n console.log(` ${SETTINGS_URL}`);\n }\n\n p.log.step(\"Step 2 — copy your credentials from that page\");\n console.log(\n [\n \" • API Key: find the “API Key” row and click Show, then copy the value\",\n \" • Athlete ID: shown on the same settings page (all digits, e.g. 123456,\",\n \" sometimes prefixed with “i”, e.g. i12345)\",\n ].join(\"\\n\"),\n );\n\n let apiKey = existing?.apiKey ?? \"\";\n let athleteId = existing?.athleteId ?? \"\";\n let verified = false;\n\n for (let attempt = 1; attempt <= 3 && !verified; attempt++) {\n p.log.step(`Step 3 — enter your credentials (attempt ${attempt}/3)`);\n\n const keyAnswer = await p.password({\n message: \"Paste your Intervals.icu API Key:\",\n validate: (value) => {\n if (!value || value.trim().length < 8) return \"The API key looks too short — please re-paste it.\";\n },\n });\n if (p.isCancel(keyAnswer)) cancel();\n apiKey = keyAnswer.trim();\n\n const idAnswer = await p.text({\n message: \"Enter your Athlete ID:\",\n placeholder: \"e.g. 123456 or i12345\",\n initialValue: athleteId,\n validate: (value) => {\n if (!value) return \"Athlete ID is required.\";\n try {\n validateAthleteId(value.trim());\n } catch {\n return \"Athlete ID must be all digits or “i” followed by digits.\";\n }\n },\n });\n if (p.isCancel(idAnswer)) cancel();\n athleteId = idAnswer.trim();\n\n const spinner = p.spinner();\n spinner.start(\"Verifying credentials against intervals.icu…\");\n const problem = await verifyCredentials(apiKey, athleteId);\n if (problem == null) {\n spinner.stop(\"Credentials verified ✓\");\n verified = true;\n } else {\n spinner.stop(\"Verification failed\");\n p.log.error(problem);\n }\n }\n\n if (!verified) {\n p.log.warn(\"Saving the credentials without live verification.\");\n const saveAnyway = await p.confirm({\n message: \"Save them anyway?\",\n initialValue: false,\n });\n if (p.isCancel(saveAnyway) || !saveAnyway) cancel();\n }\n\n try {\n saveStoredCredentials({ apiKey, athleteId });\n } catch (e) {\n p.log.error(`Could not save the config file: ${(e as Error).message}`);\n p.outro(\"Setup failed. Try again with `npx intervals-mcp-server auth`.\");\n return false;\n }\n\n p.log.success(`Credentials saved to ${configFilePath()} (readable only by you)`);\n\n if (hasCredentials()) {\n p.log.success(\"Configuration complete — the server is ready.\");\n }\n\n console.log(CLIENT_SNIPPETS);\n p.outro(\"Done! Re-run `npx intervals-mcp-server auth` any time to change credentials.\");\n return true;\n}\n","/**\n * HTTP client for the Intervals.icu API.\n *\n * Uses the platform fetch (Node >= 18) with Basic authentication\n * (username \"API_KEY\", the key as password). Failures are returned as\n * `{ error: true, message, status_code? }` dictionaries instead of thrown,\n * matching the original server's error contract.\n */\n\nimport { getConfig } from \"../config.js\";\nimport type { Dict } from \"../utils/formatting.js\";\n\nexport interface ApiError {\n error: true;\n message: string;\n status_code?: number;\n}\n\nexport type ApiResult = Dict | Dict[] | ApiError;\n\nexport function isApiError(result: unknown): result is ApiError {\n return (\n typeof result === \"object\" &&\n result !== null &&\n !Array.isArray(result) &&\n (result as Dict)[\"error\"] === true\n );\n}\n\n/** True when the result is an empty object or empty array. */\nexport function isEmptyResult(result: ApiResult): boolean {\n if (result == null) return true;\n if (Array.isArray(result)) return result.length === 0;\n return Object.keys(result).length === 0;\n}\n\nexport type QueryValue = string | number | boolean | Array<string | number>;\n\nexport interface RequestOptions {\n apiKey?: string;\n params?: Record<string, QueryValue>;\n method?: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\";\n data?: unknown;\n timeoutMs?: number;\n}\n\nfunction buildSearchString(params: Record<string, QueryValue> | undefined): string {\n if (!params) return \"\";\n const search = new URLSearchParams();\n for (const [key, value] of Object.entries(params)) {\n if (Array.isArray(value)) {\n for (const item of value) search.append(key, String(item));\n } else {\n search.append(key, String(value));\n }\n }\n const s = search.toString();\n return s ? `?${s}` : \"\";\n}\n\nfunction basicAuthHeader(apiKey: string): string {\n return `Basic ${Buffer.from(`API_KEY:${apiKey}`).toString(\"base64\")}`;\n}\n\nfunction statusErrorMessage(status: number): string | null {\n switch (status) {\n case 401:\n return \"401 Unauthorized: Please check your API key.\";\n case 403:\n return \"403 Forbidden: You may not have permission to access this resource.\";\n case 404:\n return \"404 Not Found: The requested endpoint or ID doesn't exist.\";\n case 422:\n return \"422 Unprocessable Entity: The server couldn't process the request (invalid parameters or unsupported operation).\";\n case 429:\n return \"429 Too Many Requests: Too many requests in a short time period.\";\n case 500:\n return \"500 Internal Server Error: The Intervals.icu server encountered an internal error.\";\n case 503:\n return \"503 Service Unavailable: The Intervals.icu server might be down or undergoing maintenance.\";\n default:\n return null;\n }\n}\n\n/**\n * Make a request to the Intervals.icu API with error handling.\n *\n * @param url API path, e.g. \"/athlete/{id}/activities\"\n */\nexport async function makeIntervalsRequest(\n url: string,\n options: RequestOptions = {},\n): Promise<ApiResult> {\n const { apiKey, params, method = \"GET\", data, timeoutMs = 30_000 } = options;\n const config = getConfig();\n\n const keyToUse = apiKey ?? config.apiKey;\n if (!keyToUse) {\n return {\n error: true,\n message:\n \"API key is required. Run `npx intervals-mcp-server auth` or set the API_KEY environment variable.\",\n };\n }\n\n const headers: Record<string, string> = {\n \"User-Agent\": config.userAgent,\n Accept: \"application/json\",\n Authorization: basicAuthHeader(keyToUse),\n };\n if (method === \"POST\" || method === \"PUT\") {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n const fullUrl = `${config.apiBaseUrl}${url}${buildSearchString(params)}`;\n\n try {\n const response = await fetch(fullUrl, {\n method,\n headers,\n body: method === \"POST\" || method === \"PUT\" ? JSON.stringify(data ?? null) : undefined,\n signal: AbortSignal.timeout(timeoutMs),\n });\n\n const text = await response.text();\n\n if (!response.ok) {\n const friendly = statusErrorMessage(response.status);\n return {\n error: true,\n status_code: response.status,\n message: friendly ?? (text || `HTTP ${response.status}`),\n };\n }\n\n let responseData: unknown;\n try {\n responseData = text ? JSON.parse(text) : {};\n } catch {\n return { error: true, message: \"Invalid JSON in response\" };\n }\n\n return responseData as ApiResult;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { error: true, message: `Request error: ${message}` };\n }\n}\n","/** Cross-platform \"open this URL in the default browser\". */\n\nimport { spawn } from \"node:child_process\";\n\nexport function openUrl(url: string): boolean {\n try {\n let command: string;\n let args: string[];\n switch (process.platform) {\n case \"darwin\":\n command = \"open\";\n args = [url];\n break;\n case \"win32\":\n command = \"cmd\";\n args = [\"/c\", \"start\", \"\", url];\n break;\n default:\n command = \"xdg-open\";\n args = [url];\n }\n const child = spawn(command, args, { detached: true, stdio: \"ignore\" });\n child.unref();\n return true;\n } catch {\n return false;\n }\n}\n\n/** Render a clickable terminal hyperlink (OSC 8) with plain-text fallback. */\nexport function terminalLink(url: string, label = url): string {\n // ESC ]8;;URL ESC \\ label ESC ]8;; ESC \\\n const esc = \"\\u001B\";\n return `${esc}]8;;${url}${esc}\\\\${label}${esc}]8;;${esc}\\\\`;\n}\n","/**\n * MCP server assembly and transports.\n */\n\nimport http from \"node:http\";\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { readPackageVersion } from \"./config.js\";\nimport { registerActivityTools } from \"./tools/activities.js\";\nimport { registerCustomItemTools } from \"./tools/customItems.js\";\nimport { registerEventTools } from \"./tools/events.js\";\nimport { registerGearTools } from \"./tools/gear.js\";\nimport { registerPowerCurveTools } from \"./tools/powerCurves.js\";\nimport { registerWellnessTools } from \"./tools/wellness.js\";\n\nexport const MCP_PATH = \"/mcp\";\n\n/** Create the MCP server instance with all tools registered. */\nexport function createServer(): McpServer {\n const server = new McpServer({\n name: \"intervals-icu\",\n version: readPackageVersion(),\n });\n\n registerActivityTools(server);\n registerEventTools(server);\n registerWellnessTools(server);\n registerGearTools(server);\n registerPowerCurveTools(server);\n registerCustomItemTools(server);\n\n return server;\n}\n\n/** Run the MCP server over stdio (the transport used by MCP clients). */\nexport async function serveStdio(): Promise<void> {\n const server = createServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\n/**\n * Run the MCP server over Streamable HTTP (stateless) at http://host:port/mcp.\n * Useful for remote setups (e.g. behind a tunnel for ChatGPT connectors).\n */\nexport async function serveStreamableHttp(host: string, port: number): Promise<void> {\n const httpServer = http.createServer(async (req, res) => {\n const url = req.url ?? \"/\";\n const isMcpPath = url === MCP_PATH || url.startsWith(`${MCP_PATH}/`);\n if (!isMcpPath) {\n res.writeHead(404).end(\"Not found\");\n return;\n }\n\n if (req.method !== \"POST\") {\n // Stateless servers only accept POST requests\n res.writeHead(405, { Allow: \"POST\" }).end(\"Method Not Allowed\");\n return;\n }\n\n try {\n // Fresh server + transport per request (stateless pattern)\n const server = createServer();\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: undefined,\n enableJsonResponse: true,\n });\n res.on(\"close\", () => {\n transport.close();\n void server.close();\n });\n await server.connect(transport);\n await transport.handleRequest(req, res);\n } catch (err) {\n console.error(\"[intervals-mcp-server] error handling MCP request:\", err);\n if (!res.headersSent) {\n res.writeHead(500).end(\"Internal Server Error\");\n }\n }\n });\n\n await new Promise<void>((resolve) => {\n httpServer.listen(port, host, () => resolve());\n });\n console.error(\n `[intervals-mcp-server] Streamable HTTP transport listening at http://${host}:${port}${MCP_PATH}`,\n );\n}\n","/**\n * Activity tools: retrieval, detailed analysis, streams, messages.\n */\n\nimport { z } from \"zod\";\nimport { makeIntervalsRequest, isApiError, isEmptyResult } from \"../api/client.js\";\nimport { getConfig } from \"../config.js\";\nimport { toLocalDateString } from \"../utils/dates.js\";\nimport {\n formatActivityMessage,\n formatActivitySummary,\n formatIntervals,\n type Dict,\n} from \"../utils/formatting.js\";\nimport { resolveAthleteId, resolveDateParams } from \"../utils/validation.js\";\nimport { resolveGearForActivities, resolveGearForActivity } from \"./gear.js\";\nimport { textResult, apiErrorMessage, type ToolRegistrar } from \"./shared.js\";\n\n/** Extract a list of activity dictionaries from the API result. */\nfunction parseActivitiesFromResult(result: unknown): Dict[] {\n if (Array.isArray(result)) {\n return result.filter((item): item is Dict => typeof item === \"object\" && item !== null);\n }\n if (typeof result === \"object\" && result !== null) {\n const obj = result as Dict;\n // Result is a container — pull the first list value\n for (const value of Object.values(obj)) {\n if (Array.isArray(value)) {\n return value.filter((item): item is Dict => typeof item === \"object\" && item !== null);\n }\n }\n // If no list was found but the dict has typical activity fields, treat as single\n if ([\"name\", \"startTime\", \"distance\"].some((key) => key in obj)) return [obj];\n }\n return [];\n}\n\n/** Filter out unnamed activities from the list. */\nfunction filterNamedActivities(activities: Dict[]): Dict[] {\n return activities.filter(\n (activity) => activity[\"name\"] && activity[\"name\"] !== \"Unnamed\",\n );\n}\n\n/** Fetch additional activities from an earlier date range. */\nasync function fetchMoreActivities(\n athleteId: string,\n startDate: string,\n apiKey: string | undefined,\n apiLimit: number,\n): Promise<Dict[]> {\n const oldest = new Date(`${startDate}T00:00:00`);\n const olderStart = new Date(oldest);\n olderStart.setDate(olderStart.getDate() - 60);\n const olderEnd = new Date(oldest);\n olderEnd.setDate(olderEnd.getDate() - 1);\n\n const olderStartDate = toLocalDateString(olderStart);\n const olderEndDate = toLocalDateString(olderEnd);\n if (olderStartDate >= olderEndDate) return [];\n\n const moreResult = await makeIntervalsRequest(`/athlete/${athleteId}/activities`, {\n apiKey,\n params: { oldest: olderStartDate, newest: olderEndDate, limit: apiLimit },\n });\n\n if (Array.isArray(moreResult)) return filterNamedActivities(moreResult as Dict[]);\n return [];\n}\n\nfunction formatActivitiesResponse(\n activities: Dict[],\n athleteId: string,\n includeUnnamed: boolean,\n): string {\n if (!activities.length) {\n if (includeUnnamed) {\n return `No valid activities found for athlete ${athleteId} in the specified date range.`;\n }\n return `No named activities found for athlete ${athleteId} in the specified date range. Try with include_unnamed=true to see all activities.`;\n }\n\n let summary = \"Activities:\\n\\n\";\n for (const activity of activities) {\n summary += `${formatActivitySummary(activity)}\\n`;\n }\n return summary;\n}\n\nconst DEFAULT_STREAM_TYPES =\n \"time,watts,heartrate,cadence,altitude,distance,velocity_smooth\";\n\nexport const registerActivityTools: ToolRegistrar = (server) => {\n server.registerTool(\n \"get_activities\",\n {\n title: \"Get Activities\",\n description:\n \"Get a list of activities for an athlete from Intervals.icu.\\n\\n\" +\n \"Args:\\n\" +\n \" athlete_id: The Intervals.icu athlete ID (optional, uses the configured default)\\n\" +\n \" api_key: The Intervals.icu API key (optional, uses the configured default)\\n\" +\n \" start_date: Start date in YYYY-MM-DD format (optional, defaults to 30 days ago)\\n\" +\n \" end_date: End date in YYYY-MM-DD format (optional, defaults to today)\\n\" +\n \" limit: Maximum number of activities to return (optional, defaults to 10)\\n\" +\n \" include_unnamed: Whether to include unnamed activities (optional, defaults to false)\",\n inputSchema: {\n athlete_id: z.string().optional(),\n api_key: z.string().optional(),\n start_date: z.string().optional(),\n end_date: z.string().optional(),\n limit: z.number().int().positive().default(10),\n include_unnamed: z.boolean().default(false),\n },\n },\n async ({ athlete_id, api_key, start_date, end_date, limit, include_unnamed }) => {\n const config = getConfig();\n const { athleteId, error } = resolveAthleteId(athlete_id, config.athleteId);\n if (error) return textResult(error);\n\n const [startDate, endDate] = resolveDateParams(start_date, end_date);\n\n // Fetch more activities if we need to filter out unnamed ones\n const apiLimit = !include_unnamed ? limit * 3 : limit;\n\n const result = await makeIntervalsRequest(`/athlete/${athleteId}/activities`, {\n apiKey: api_key,\n params: { oldest: startDate, newest: endDate, limit: apiLimit },\n });\n\n if (isApiError(result)) {\n return textResult(`Error fetching activities: ${apiErrorMessage(result)}`);\n }\n if (isEmptyResult(result)) {\n return textResult(\n `No activities found for athlete ${athleteId} in the specified date range.`,\n );\n }\n\n let activities = parseActivitiesFromResult(result);\n if (!activities.length) {\n return textResult(\n `No valid activities found for athlete ${athleteId} in the specified date range.`,\n );\n }\n\n if (!include_unnamed) {\n activities = filterNamedActivities(activities);\n if (activities.length < limit) {\n const more = await fetchMoreActivities(athleteId, startDate, api_key, apiLimit);\n activities.push(...more);\n }\n }\n\n activities = activities.slice(0, limit);\n\n await resolveGearForActivities(activities, { athleteId, apiKey: api_key });\n\n return textResult(formatActivitiesResponse(activities, athleteId, include_unnamed));\n },\n );\n\n server.registerTool(\n \"get_activity_details\",\n {\n title: \"Get Activity Details\",\n description: \"Get detailed information for a specific activity from Intervals.icu.\",\n inputSchema: {\n activity_id: z.string().describe(\"The Intervals.icu activity ID\"),\n api_key: z.string().optional(),\n },\n },\n async ({ activity_id, api_key }) => {\n const result = await makeIntervalsRequest(`/activity/${activity_id}`, {\n apiKey: api_key,\n });\n\n if (isApiError(result)) {\n return textResult(`Error fetching activity details: ${apiErrorMessage(result)}`);\n }\n if (isEmptyResult(result)) {\n return textResult(`No details found for activity ${activity_id}.`);\n }\n\n const activityData = Array.isArray(result) ? result[0] : result;\n if (typeof activityData !== \"object\" || activityData === null) {\n return textResult(`Invalid activity format for activity ${activity_id}.`);\n }\n\n await resolveGearForActivity(activityData as Dict, { apiKey: api_key });\n\n let detailedView = formatActivitySummary(activityData as Dict);\n\n const zones = (activityData as Dict)[\"zones\"];\n if (typeof zones === \"object\" && zones !== null) {\n detailedView += \"\\nPower Zones:\\n\";\n for (const zone of (zones as Dict)[\"power\"] ?? []) {\n detailedView += `Zone ${zone[\"number\"]}: ${zone[\"secondsInZone\"]} seconds\\n`;\n }\n detailedView += \"\\nHeart Rate Zones:\\n\";\n for (const zone of (zones as Dict)[\"hr\"] ?? []) {\n detailedView += `Zone ${zone[\"number\"]}: ${zone[\"secondsInZone\"]} seconds\\n`;\n }\n }\n\n return textResult(detailedView);\n },\n );\n\n server.registerTool(\n \"get_activity_intervals\",\n {\n title: \"Get Activity Intervals\",\n description:\n \"Get interval data for a specific activity from Intervals.icu.\\n\\n\" +\n \"This endpoint returns detailed metrics for each interval in an activity, including power, heart rate,\\n\" +\n \"cadence, speed, and environmental data. It also includes grouped intervals if applicable.\",\n inputSchema: {\n activity_id: z.string().describe(\"The Intervals.icu activity ID\"),\n api_key: z.string().optional(),\n },\n },\n async ({ activity_id, api_key }) => {\n const result = await makeIntervalsRequest(`/activity/${activity_id}/intervals`, {\n apiKey: api_key,\n });\n\n if (isApiError(result)) {\n return textResult(`Error fetching intervals: ${apiErrorMessage(result)}`);\n }\n if (isEmptyResult(result)) {\n return textResult(`No interval data found for activity ${activity_id}.`);\n }\n if (\n typeof result !== \"object\" ||\n Array.isArray(result) ||\n !(\"icu_intervals\" in result || \"icu_groups\" in (result as Dict))\n ) {\n return textResult(`No interval data or unrecognized format for activity ${activity_id}.`);\n }\n\n return textResult(formatIntervals(result as Dict));\n },\n );\n\n server.registerTool(\n \"get_activity_streams\",\n {\n title: \"Get Activity Streams\",\n description:\n \"Get stream data for a specific activity from Intervals.icu.\\n\\n\" +\n \"This endpoint returns time-series data for an activity, including metrics like power, heart rate,\\n\" +\n \"cadence, altitude, distance, temperature, and velocity data.\\n\\n\" +\n \"Available stream types: time, watts, heartrate, cadence, altitude, distance,\\n\" +\n \"core_temperature, skin_temperature, velocity_smooth\",\n inputSchema: {\n activity_id: z.string().describe(\"The Intervals.icu activity ID\"),\n api_key: z.string().optional(),\n stream_types: z\n .string()\n .optional()\n .describe(\n \"Comma-separated list of stream types to retrieve (optional, defaults to common types)\",\n ),\n },\n },\n async ({ activity_id, api_key, stream_types }) => {\n const result = await makeIntervalsRequest(`/activity/${activity_id}/streams`, {\n apiKey: api_key,\n params: { types: stream_types || DEFAULT_STREAM_TYPES },\n });\n\n if (isApiError(result)) {\n return textResult(`Error fetching activity streams: ${apiErrorMessage(result)}`);\n }\n\n const streams = Array.isArray(result) ? (result as Dict[]) : [];\n if (!streams.length) {\n return textResult(`No stream data found for activity ${activity_id}.`);\n }\n\n let summary = `Activity Streams for ${activity_id}:\\n\\n`;\n for (const stream of streams) {\n const streamType = stream[\"type\"] ?? \"unknown\";\n const streamName = stream[\"name\"] ?? streamType;\n const data = (stream[\"data\"] ?? []) as unknown[];\n const valueType = stream[\"valueType\"] ?? \"\";\n\n summary += `Stream: ${streamName} (${streamType})\\n`;\n summary += ` Value Type: ${valueType}\\n`;\n summary += ` Data Points: ${data.length}\\n`;\n\n if (data.length > 0) {\n if (data.length <= 10) {\n summary += ` Values: ${JSON.stringify(data)}\\n`;\n } else {\n summary += ` First 5 values: ${JSON.stringify(data.slice(0, 5))}\\n`;\n summary += ` Last 5 values: ${JSON.stringify(data.slice(-5))}\\n`;\n }\n }\n summary += \"\\n\";\n }\n\n return textResult(summary);\n },\n );\n\n server.registerTool(\n \"get_activity_messages\",\n {\n title: \"Get Activity Messages\",\n description: \"Get messages (notes/comments) for a specific activity from Intervals.icu.\",\n inputSchema: {\n activity_id: z.string().describe(\"The Intervals.icu activity ID\"),\n api_key: z.string().optional(),\n },\n },\n async ({ activity_id, api_key }) => {\n const result = await makeIntervalsRequest(`/activity/${activity_id}/messages`, {\n apiKey: api_key,\n });\n\n if (isApiError(result)) {\n return textResult(`Error fetching activity messages: ${apiErrorMessage(result)}`);\n }\n\n const messages = Array.isArray(result) ? (result as Dict[]) : [];\n if (!messages.length) {\n return textResult(`No messages found for activity ${activity_id}.`);\n }\n\n let output = `Messages for activity ${activity_id}:\\n\\n`;\n for (const msg of messages) {\n output += `${formatActivityMessage(msg)}\\n\\n`;\n }\n return textResult(output);\n },\n );\n\n server.registerTool(\n \"add_activity_message\",\n {\n title: \"Add Activity Message\",\n description: \"Add a message (note/comment) to an activity on Intervals.icu.\",\n inputSchema: {\n activity_id: z.string().describe(\"The Intervals.icu activity ID\"),\n content: z.string().describe(\"The message text to add\"),\n api_key: z.string().optional(),\n },\n },\n async ({ activity_id, content, api_key }) => {\n const result = await makeIntervalsRequest(`/activity/${activity_id}/messages`, {\n apiKey: api_key,\n method: \"POST\",\n data: { content },\n });\n\n if (isApiError(result)) {\n return textResult(`Error adding message to activity: ${apiErrorMessage(result)}`);\n }\n if (typeof result !== \"object\" || result === null || Array.isArray(result)) {\n return textResult(\"Error: Unexpected response when adding message.\");\n }\n\n const msgId = (result as Dict)[\"id\"];\n if (msgId != null) {\n return textResult(\n `Successfully added message (ID: ${msgId}) to activity ${activity_id}.`,\n );\n }\n return textResult(\n `Message appears to have been added to activity ${activity_id}, but no ID was returned. Please verify manually.`,\n );\n },\n );\n};\n","/**\n * Formatting utilities for Intervals.icu API payloads.\n *\n * All formatters take loosely-typed API dictionaries and render readable text.\n */\n\nimport { formatIsoDateTime } from \"./dates.js\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type Dict = Record<string, any>;\n\n// ---------------------------------------------------------------------------\n// Activities\n// ---------------------------------------------------------------------------\n\nexport function formatActivitySummary(activity: Dict): string {\n let startTime = activity[\"startTime\"] ?? activity[\"start_date\"] ?? \"Unknown\";\n if (typeof startTime === \"string\" && startTime.length > 10) {\n startTime = formatIsoDateTime(startTime);\n }\n\n let rpe: unknown = activity[\"perceived_exertion\"] ?? activity[\"icu_rpe\"] ?? \"N/A\";\n if (typeof rpe === \"number\") rpe = `${rpe}/10`;\n\n let feel: unknown = activity[\"feel\"] ?? \"N/A\";\n if (typeof feel === \"number\") feel = `${feel}/5`;\n\n // Gear (bike, shoes). Activity payloads include the gear ID but not the\n // name; tools/gear.ts resolves it and injects `_resolved_gear_name` before\n // this formatter runs.\n const resolvedName = activity[\"_resolved_gear_name\"];\n const gearRaw = activity[\"gear\"];\n let gearName: string;\n let gearId: unknown;\n if (resolvedName) {\n gearName = resolvedName;\n gearId =\n typeof gearRaw === \"object\" && gearRaw !== null\n ? (gearRaw[\"id\"] ?? activity[\"gear_id\"] ?? \"N/A\")\n : (activity[\"gear_id\"] ?? \"N/A\");\n } else if (typeof gearRaw === \"object\" && gearRaw !== null) {\n gearName = gearRaw[\"name\"] || gearRaw[\"display_name\"] || \"N/A\";\n gearId = gearRaw[\"id\"] ?? \"N/A\";\n } else {\n gearName = activity[\"gear_name\"] ?? \"N/A\";\n gearId = activity[\"gear_id\"] ?? \"N/A\";\n }\n\n return `Activity: ${activity[\"name\"] ?? \"Unnamed\"}\nID: ${activity[\"id\"] ?? \"N/A\"}\nType: ${activity[\"type\"] ?? \"Unknown\"}\nDate: ${startTime}\nDescription: ${activity[\"description\"] ?? \"N/A\"}\nDistance: ${activity[\"distance\"] ?? 0} meters\nDuration: ${activity[\"duration\"] ?? activity[\"elapsed_time\"] ?? 0} seconds\nMoving Time: ${activity[\"moving_time\"] ?? \"N/A\"} seconds\nElevation Gain: ${activity[\"elevationGain\"] ?? activity[\"total_elevation_gain\"] ?? 0} meters\nElevation Loss: ${activity[\"total_elevation_loss\"] ?? \"N/A\"} meters\n\nPower Data:\nAverage Power: ${activity[\"avgPower\"] ?? activity[\"icu_average_watts\"] ?? activity[\"average_watts\"] ?? \"N/A\"} watts\nWeighted Avg Power: ${activity[\"icu_weighted_avg_watts\"] ?? \"N/A\"} watts\nTraining Load: ${activity[\"trainingLoad\"] ?? activity[\"icu_training_load\"] ?? \"N/A\"}\nFTP: ${activity[\"icu_ftp\"] ?? \"N/A\"} watts\nKilojoules: ${activity[\"icu_joules\"] ?? \"N/A\"}\nIntensity: ${activity[\"icu_intensity\"] ?? \"N/A\"}\nPower:HR Ratio: ${activity[\"icu_power_hr\"] ?? \"N/A\"}\nVariability Index: ${activity[\"icu_variability_index\"] ?? \"N/A\"}\n\nHeart Rate Data:\nAverage Heart Rate: ${activity[\"avgHr\"] ?? activity[\"average_heartrate\"] ?? \"N/A\"} bpm\nMax Heart Rate: ${activity[\"max_heartrate\"] ?? \"N/A\"} bpm\nLTHR: ${activity[\"lthr\"] ?? \"N/A\"} bpm\nResting HR: ${activity[\"icu_resting_hr\"] ?? \"N/A\"} bpm\nDecoupling: ${activity[\"decoupling\"] ?? \"N/A\"}\n\nOther Metrics:\nCadence: ${activity[\"average_cadence\"] ?? \"N/A\"} rpm\nCalories burned: ${activity[\"calories\"] ?? \"N/A\"} kcal\nAverage Speed: ${activity[\"average_speed\"] ?? \"N/A\"} m/s\nMax Speed: ${activity[\"max_speed\"] ?? \"N/A\"} m/s\nAverage Stride: ${activity[\"average_stride\"] ?? \"N/A\"}\nL/R Balance: ${activity[\"avg_lr_balance\"] ?? \"N/A\"}\nWeight: ${activity[\"icu_weight\"] ?? \"N/A\"} kg\nRPE: ${rpe}\nSession RPE: ${activity[\"session_rpe\"] ?? \"N/A\"}\nFeel: ${feel}\n\nEnvironment:\nTrainer: ${activity[\"trainer\"] ?? \"N/A\"}\nAverage Temp: ${activity[\"average_temp\"] ?? \"N/A\"}°C\nMin Temp: ${activity[\"min_temp\"] ?? \"N/A\"}°C\nMax Temp: ${activity[\"max_temp\"] ?? \"N/A\"}°C\nAvg Wind Speed: ${activity[\"average_wind_speed\"] ?? \"N/A\"} km/h\nHeadwind %: ${activity[\"headwind_percent\"] ?? \"N/A\"}%\nTailwind %: ${activity[\"tailwind_percent\"] ?? \"N/A\"}%\n\nTraining Metrics:\nFitness (CTL): ${activity[\"icu_ctl\"] ?? \"N/A\"}\nFatigue (ATL): ${activity[\"icu_atl\"] ?? \"N/A\"}\nTRIMP: ${activity[\"trimp\"] ?? \"N/A\"}\nPolarization Index: ${activity[\"polarization_index\"] ?? \"N/A\"}\nPower Load: ${activity[\"power_load\"] ?? \"N/A\"}\nHR Load: ${activity[\"hr_load\"] ?? \"N/A\"}\nPace Load: ${activity[\"pace_load\"] ?? \"N/A\"}\nEfficiency Factor: ${activity[\"icu_efficiency_factor\"] ?? \"N/A\"}\n\nDevice Info:\nDevice: ${activity[\"device_name\"] ?? \"N/A\"}\nPower Meter: ${activity[\"power_meter\"] ?? \"N/A\"}\nFile Type: ${activity[\"file_type\"] ?? \"N/A\"}\n\nGear:\nName: ${gearName}\nID: ${gearId}`;\n}\n\nexport function formatWorkout(workout: Dict): string {\n return `Workout: ${workout[\"name\"] ?? \"Unnamed\"}\nDescription: ${workout[\"description\"] ?? \"No description\"}\nSport: ${workout[\"sport\"] ?? \"Unknown\"}\nDuration: ${workout[\"duration\"] ?? 0} seconds\nTSS: ${workout[\"tss\"] ?? \"N/A\"}\nIntervals: ${(workout[\"intervals\"] ?? []).length}`;\n}\n\nexport function formatActivityMessage(message: Dict): string {\n let created = message[\"created\"] ?? \"Unknown\";\n if (typeof created === \"string\" && created.length > 10) {\n created = formatIsoDateTime(created);\n }\n return `Author: ${message[\"name\"] ?? \"Unknown\"}\nDate: ${created}\nType: ${message[\"type\"] ?? \"TEXT\"}\nContent: ${message[\"content\"] ?? \"\"}`;\n}\n\n// ---------------------------------------------------------------------------\n// Wellness\n// ---------------------------------------------------------------------------\n\nfunction formatTrainingMetrics(get: (k: string) => unknown): string[] {\n const rows: Array<[string, string]> = [\n [\"ctl\", \"Fitness (CTL)\"],\n [\"atl\", \"Fatigue (ATL)\"],\n [\"rampRate\", \"Ramp Rate\"],\n [\"ctlLoad\", \"CTL Load\"],\n [\"atlLoad\", \"ATL Load\"],\n ];\n const lines: string[] = [];\n for (const [k, label] of rows) {\n if (get(k) != null) lines.push(`- ${label}: ${get(k)}`);\n }\n return lines;\n}\n\nfunction formatSportInfo(get: (k: string) => unknown): string[] {\n const lines: string[] = [];\n const sportInfo = get(\"sportInfo\");\n if (Array.isArray(sportInfo)) {\n for (const sport of sportInfo) {\n if (typeof sport === \"object\" && sport !== null && sport[\"eftp\"] != null) {\n lines.push(`- ${sport[\"type\"]}: eFTP = ${sport[\"eftp\"]}`);\n }\n }\n }\n return lines;\n}\n\nfunction formatVitalSigns(get: (k: string) => unknown): string[] {\n const rows: Array<[string, string, string]> = [\n [\"weight\", \"Weight\", \"kg\"],\n [\"restingHR\", \"Resting HR\", \"bpm\"],\n [\"hrv\", \"HRV\", \"\"],\n [\"hrvSDNN\", \"HRV SDNN\", \"\"],\n [\"avgSleepingHR\", \"Average Sleeping HR\", \"bpm\"],\n [\"spO2\", \"SpO2\", \"%\"],\n [\"systolic\", \"Systolic BP\", \"\"],\n [\"diastolic\", \"Diastolic BP\", \"\"],\n [\"respiration\", \"Respiration\", \"breaths/min\"],\n [\"bloodGlucose\", \"Blood Glucose\", \"mmol/L\"],\n [\"lactate\", \"Lactate\", \"mmol/L\"],\n [\"vo2max\", \"VO2 Max\", \"ml/kg/min\"],\n [\"bodyFat\", \"Body Fat\", \"%\"],\n [\"abdomen\", \"Abdomen\", \"cm\"],\n [\"baevskySI\", \"Baevsky Stress Index\", \"\"],\n ];\n const lines: string[] = [];\n for (const [k, label, unit] of rows) {\n if (get(k) == null) continue;\n if (k === \"systolic\" && get(\"diastolic\") != null) {\n lines.push(`- Blood Pressure: ${get(\"systolic\")}/${get(\"diastolic\")} mmHg`);\n } else if (k !== \"systolic\" && k !== \"diastolic\") {\n lines.push(`- ${label}: ${get(k)}${unit ? ` ${unit}` : \"\"}`);\n }\n }\n return lines;\n}\n\nconst SLEEP_QUALITY_LABELS: Record<number, string> = {\n 1: \"Great\",\n 2: \"Good\",\n 3: \"Average\",\n 4: \"Poor\",\n};\n\nfunction formatSleepRecovery(get: (k: string) => unknown): string[] {\n const lines: string[] = [];\n let sleepHours: string | null = null;\n if (get(\"sleepSecs\") != null) {\n const secs = get(\"sleepSecs\") as number;\n sleepHours = (secs / 3600).toFixed(2);\n } else if (get(\"sleepHours\") != null) {\n sleepHours = `${get(\"sleepHours\")}`;\n }\n if (sleepHours !== null) lines.push(` Sleep: ${sleepHours} hours`);\n\n if (get(\"sleepQuality\") != null) {\n const quality = get(\"sleepQuality\") as number;\n lines.push(` Sleep Quality: ${quality} (${SLEEP_QUALITY_LABELS[quality] ?? String(quality)})`);\n }\n if (get(\"sleepScore\") != null) lines.push(` Device Sleep Score: ${get(\"sleepScore\")}/100`);\n if (get(\"readiness\") != null) lines.push(` Readiness: ${get(\"readiness\")}/10`);\n return lines;\n}\n\nfunction formatMenstrualTracking(get: (k: string) => unknown): string[] {\n const lines: string[] = [];\n if (get(\"menstrualPhase\") != null) {\n const phase = String(get(\"menstrualPhase\"));\n lines.push(` Menstrual Phase: ${phase.charAt(0).toUpperCase()}${phase.slice(1)}`);\n }\n if (get(\"menstrualPhasePredicted\") != null) {\n const phase = String(get(\"menstrualPhasePredicted\"));\n lines.push(` Predicted Phase: ${phase.charAt(0).toUpperCase()}${phase.slice(1)}`);\n }\n return lines;\n}\n\nfunction formatSubjectiveFeelings(get: (k: string) => unknown): string[] {\n const rows: Array<[string, string]> = [\n [\"soreness\", \"Soreness\"],\n [\"fatigue\", \"Fatigue\"],\n [\"stress\", \"Stress\"],\n [\"mood\", \"Mood\"],\n [\"motivation\", \"Motivation\"],\n [\"injury\", \"Injury Level\"],\n ];\n const lines: string[] = [];\n for (const [k, label] of rows) {\n if (get(k) != null) lines.push(` ${label}: ${get(k)}/10`);\n }\n return lines;\n}\n\nfunction formatNutritionHydration(get: (k: string) => unknown): string[] {\n const rows: Array<[string, string, string]> = [\n [\"kcalConsumed\", \"Calories Consumed\", \"\"],\n [\"carbohydrates\", \"Carbohydrates\", \"g\"],\n [\"protein\", \"Protein\", \"g\"],\n [\"fatTotal\", \"Fat\", \"g\"],\n [\"hydrationVolume\", \"Hydration Volume\", \"\"],\n ];\n const lines: string[] = [];\n for (const [k, label, unit] of rows) {\n if (get(k) != null) lines.push(`- ${label}: ${get(k)}${unit ? ` ${unit}` : \"\"}`);\n }\n if (get(\"hydration\") != null) lines.push(` Hydration Score: ${get(\"hydration\")}/10`);\n return lines;\n}\n\n/**\n * Format a wellness entry into a readable string.\n *\n * When `includeAllFields` is true, any field not covered by the standard\n * sections is appended under \"Other Fields\" (mirroring the Python KeyTracker).\n */\nexport function formatWellnessEntry(entries: Dict, includeAllFields = false): string {\n const accessed = new Set<string>();\n const get = (k: string): unknown => {\n accessed.add(k);\n return entries[k];\n };\n\n if (includeAllFields) {\n // Mark metadata/internal keys so they don't appear in \"Other Fields\"\n for (const k of [\"date\", \"updated\", \"tempWeight\", \"tempRestingHR\"]) accessed.add(k);\n }\n\n const lines: string[] = [\"Wellness Data:\"];\n lines.push(`Date: ${get(\"id\") ?? \"N/A\"}`);\n lines.push(\"\");\n\n const trainingMetrics = formatTrainingMetrics(get);\n if (trainingMetrics.length) {\n lines.push(\"Training Metrics:\");\n lines.push(...trainingMetrics);\n lines.push(\"\");\n }\n\n const sportInfo = formatSportInfo(get);\n if (sportInfo.length) {\n lines.push(\"Sport-Specific Info:\");\n lines.push(...sportInfo);\n lines.push(\"\");\n }\n\n const vitalSigns = formatVitalSigns(get);\n if (vitalSigns.length) {\n lines.push(\"Vital Signs:\");\n lines.push(...vitalSigns);\n lines.push(\"\");\n }\n\n const sleepLines = formatSleepRecovery(get);\n if (sleepLines.length) {\n lines.push(\"Sleep & Recovery:\");\n lines.push(...sleepLines);\n lines.push(\"\");\n }\n\n const menstrualLines = formatMenstrualTracking(get);\n if (menstrualLines.length) {\n lines.push(\"Menstrual Tracking:\");\n lines.push(...menstrualLines);\n lines.push(\"\");\n }\n\n const subjectiveLines = formatSubjectiveFeelings(get);\n if (subjectiveLines.length) {\n lines.push(\"Subjective Feelings:\");\n lines.push(...subjectiveLines);\n lines.push(\"\");\n }\n\n const nutritionLines = formatNutritionHydration(get);\n if (nutritionLines.length) {\n lines.push(\"Nutrition & Hydration:\");\n lines.push(...nutritionLines);\n lines.push(\"\");\n }\n\n if (get(\"steps\") != null) {\n lines.push(\"Activity:\");\n lines.push(`- Steps: ${get(\"steps\")}`);\n lines.push(\"\");\n }\n\n if (get(\"comments\")) lines.push(`Comments: ${get(\"comments\")}`);\n if (accessed.has(\"locked\")) {\n lines.push(`Status: ${get(\"locked\") ? \"Locked\" : \"Unlocked\"}`);\n }\n\n if (includeAllFields) {\n const otherLines: string[] = [];\n for (const [key, value] of Object.entries(entries)) {\n if (!accessed.has(key) && value != null) {\n otherLines.push(\n `- ${key}: ${typeof value === \"object\" ? JSON.stringify(value) : value}`,\n );\n }\n }\n if (otherLines.length) {\n lines.push(\"\");\n lines.push(\"Other Fields:\");\n lines.push(...otherLines);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n// ---------------------------------------------------------------------------\n// Events\n// ---------------------------------------------------------------------------\n\nexport function formatEventSummary(event: Dict): string {\n const eventDate = event[\"start_date_local\"] ?? event[\"date\"] ?? \"Unknown\";\n const eventType = event[\"workout\"] ? \"Workout\" : event[\"race\"] ? \"Race\" : \"Other\";\n return `Date: ${eventDate}\nID: ${event[\"id\"] ?? \"N/A\"}\nType: ${eventType}\nName: ${event[\"name\"] ?? \"Unnamed\"}\nDescription: ${event[\"description\"] ?? \"No description\"}`;\n}\n\nexport function formatEventDetails(event: Dict): string {\n let details = `Event Details:\n\nID: ${event[\"id\"] ?? \"N/A\"}\nDate: ${event[\"date\"] ?? \"Unknown\"}\nName: ${event[\"name\"] ?? \"Unnamed\"}\nDescription: ${event[\"description\"] ?? \"No description\"}`;\n\n const workout = event[\"workout\"];\n if (typeof workout === \"object\" && workout !== null) {\n details += `\n\nWorkout Information:\nWorkout ID: ${workout[\"id\"] ?? \"N/A\"}\nSport: ${workout[\"sport\"] ?? \"Unknown\"}\nDuration: ${workout[\"duration\"] ?? 0} seconds\nTSS: ${workout[\"tss\"] ?? \"N/A\"}`;\n if (Array.isArray(workout[\"intervals\"])) {\n details += `\nIntervals: ${workout[\"intervals\"].length}`;\n }\n }\n\n if (event[\"race\"]) {\n details += `\n\nRace Information:\nPriority: ${event[\"priority\"] ?? \"N/A\"}\nResult: ${event[\"result\"] ?? \"N/A\"}`;\n }\n\n const cal = event[\"calendar\"];\n if (typeof cal === \"object\" && cal !== null) {\n details += `\n\nCalendar: ${cal[\"name\"] ?? \"N/A\"}`;\n }\n\n return details;\n}\n\n// ---------------------------------------------------------------------------\n// Custom items\n// ---------------------------------------------------------------------------\n\nexport function formatCustomItemDetails(item: Dict): string {\n const lines = [\"Custom Item Details:\", \"\"];\n lines.push(`ID: ${item[\"id\"] ?? \"N/A\"}`);\n lines.push(`Name: ${item[\"name\"] ?? \"N/A\"}`);\n lines.push(`Type: ${item[\"type\"] ?? \"N/A\"}`);\n if (item[\"description\"]) lines.push(`Description: ${item[\"description\"]}`);\n if (item[\"visibility\"]) lines.push(`Visibility: ${item[\"visibility\"]}`);\n if (item[\"index\"] != null) lines.push(`Index: ${item[\"index\"]}`);\n if (item[\"hide_script\"] != null) lines.push(`Hide Script: ${item[\"hide_script\"]}`);\n if (item[\"content\"]) lines.push(`Content: ${JSON.stringify(item[\"content\"], null, 2)}`);\n return lines.join(\"\\n\");\n}\n\n// ---------------------------------------------------------------------------\n// Intervals\n// ---------------------------------------------------------------------------\n\nexport function formatIntervals(intervalsData: Dict): string {\n let result = `Intervals Analysis:\n\nID: ${intervalsData[\"id\"] ?? \"N/A\"}\nAnalyzed: ${intervalsData[\"analyzed\"] ?? \"N/A\"}\n\n`;\n\n const intervals = intervalsData[\"icu_intervals\"];\n if (Array.isArray(intervals) && intervals.length > 0) {\n result += \"Individual Intervals:\\n\\n\";\n intervals.forEach((interval: Dict, i: number) => {\n result += `[${i + 1}] ${interval[\"label\"] ?? `Interval ${i + 1}`} (${interval[\"type\"] ?? \"Unknown\"})\nDuration: ${interval[\"elapsed_time\"] ?? 0} seconds (moving: ${interval[\"moving_time\"] ?? 0} seconds)\nDistance: ${interval[\"distance\"] ?? 0} meters\nStart-End Indices: ${interval[\"start_index\"] ?? 0}-${interval[\"end_index\"] ?? 0}\n\nPower Metrics:\n Average Power: ${interval[\"average_watts\"] ?? 0} watts (${interval[\"average_watts_kg\"] ?? 0} W/kg)\n Max Power: ${interval[\"max_watts\"] ?? 0} watts (${interval[\"max_watts_kg\"] ?? 0} W/kg)\n Weighted Avg Power: ${interval[\"weighted_average_watts\"] ?? 0} watts\n Intensity: ${interval[\"intensity\"] ?? 0}\n Training Load: ${interval[\"training_load\"] ?? 0}\n Joules: ${interval[\"joules\"] ?? 0}\n Joules > FTP: ${interval[\"joules_above_ftp\"] ?? 0}\n Power Zone: ${interval[\"zone\"] ?? \"N/A\"} (${interval[\"zone_min_watts\"] ?? 0}-${interval[\"zone_max_watts\"] ?? 0} watts)\n W' Balance: Start ${interval[\"wbal_start\"] ?? 0}, End ${interval[\"wbal_end\"] ?? 0}\n L/R Balance: ${interval[\"avg_lr_balance\"] ?? 0}\n Variability: ${interval[\"w5s_variability\"] ?? 0}\n Torque: Avg ${interval[\"average_torque\"] ?? 0}, Min ${interval[\"min_torque\"] ?? 0}, Max ${interval[\"max_torque\"] ?? 0}\n\nHeart Rate & Metabolic:\n Heart Rate: Avg ${interval[\"average_heartrate\"] ?? 0}, Min ${interval[\"min_heartrate\"] ?? 0}, Max ${interval[\"max_heartrate\"] ?? 0} bpm\n Decoupling: ${interval[\"decoupling\"] ?? 0}\n DFA α1: ${interval[\"average_dfa_a1\"] ?? 0}\n Respiration: ${interval[\"average_respiration\"] ?? 0} breaths/min\n EPOC: ${interval[\"average_epoc\"] ?? 0}\n SmO2: ${interval[\"average_smo2\"] ?? 0}% / ${interval[\"average_smo2_2\"] ?? 0}%\n THb: ${interval[\"average_thb\"] ?? 0} / ${interval[\"average_thb_2\"] ?? 0}\n\nSpeed & Cadence:\n Speed: Avg ${interval[\"average_speed\"] ?? 0}, Min ${interval[\"min_speed\"] ?? 0}, Max ${interval[\"max_speed\"] ?? 0} m/s\n GAP: ${interval[\"gap\"] ?? 0} m/s\n Cadence: Avg ${interval[\"average_cadence\"] ?? 0}, Min ${interval[\"min_cadence\"] ?? 0}, Max ${interval[\"max_cadence\"] ?? 0} rpm\n Stride: ${interval[\"average_stride\"] ?? 0}\n\nElevation & Environment:\n Elevation Gain: ${interval[\"total_elevation_gain\"] ?? 0} meters\n Altitude: Min ${interval[\"min_altitude\"] ?? 0}, Max ${interval[\"max_altitude\"] ?? 0} meters\n Gradient: ${interval[\"average_gradient\"] ?? 0}%\n Temperature: ${interval[\"average_temp\"] ?? 0}°C (Weather: ${interval[\"average_weather_temp\"] ?? 0}°C, Feels like: ${interval[\"average_feels_like\"] ?? 0}°C)\n Wind: Speed ${interval[\"average_wind_speed\"] ?? 0} km/h, Gust ${interval[\"average_wind_gust\"] ?? 0} km/h, Direction ${interval[\"prevailing_wind_deg\"] ?? 0}°\n Headwind: ${interval[\"headwind_percent\"] ?? 0}%, Tailwind: ${interval[\"tailwind_percent\"] ?? 0}%\n\n`;\n });\n }\n\n const groups = intervalsData[\"icu_groups\"];\n if (Array.isArray(groups) && groups.length > 0) {\n result += \"Interval Groups:\\n\\n\";\n groups.forEach((group: Dict, i: number) => {\n result += `Group: ${group[\"id\"] ?? `Group ${i + 1}`} (Contains ${group[\"count\"] ?? 0} intervals)\nDuration: ${group[\"elapsed_time\"] ?? 0} seconds (moving: ${group[\"moving_time\"] ?? 0} seconds)\nDistance: ${group[\"distance\"] ?? 0} meters\nStart-End Indices: ${group[\"start_index\"] ?? 0}-N/A\n\nPower: Avg ${group[\"average_watts\"] ?? 0} watts (${group[\"average_watts_kg\"] ?? 0} W/kg), Max ${group[\"max_watts\"] ?? 0} watts\nW. Avg Power: ${group[\"weighted_average_watts\"] ?? 0} watts, Intensity: ${group[\"intensity\"] ?? 0}\nHeart Rate: Avg ${group[\"average_heartrate\"] ?? 0}, Max ${group[\"max_heartrate\"] ?? 0} bpm\nSpeed: Avg ${group[\"average_speed\"] ?? 0}, Max ${group[\"max_speed\"] ?? 0} m/s\nCadence: Avg ${group[\"average_cadence\"] ?? 0}, Max ${group[\"max_cadence\"] ?? 0} rpm\n\n`;\n });\n }\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Power curves\n// ---------------------------------------------------------------------------\n\n/** Format seconds into a concise human-readable label (e.g. 5s, 2m, 1h). */\nexport function formatDurationLabel(secs: number): string {\n if (secs < 60) return `${secs}s`;\n if (secs < 3600) {\n const mins = Math.floor(secs / 60);\n const remainder = secs % 60;\n return remainder ? `${mins}m${remainder}s` : `${mins}m`;\n }\n const hours = Math.floor(secs / 3600);\n const remainder = Math.floor((secs % 3600) / 60);\n return remainder ? `${hours}h${remainder}m` : `${hours}h`;\n}\n\nexport interface CurveDataPoint {\n secs: number;\n watts: number | null;\n activity_id: string;\n watts_per_kg?: number;\n wkg_activity_id?: string;\n}\n\nexport interface ExtractedCurve {\n id: string;\n label: string;\n start: string;\n end: string;\n data_points: CurveDataPoint[];\n}\n\nexport function formatPowerCurves(\n curves: ExtractedCurve[],\n activityType: string,\n includeNormalised: boolean,\n): string {\n const lines: string[] = [`Power Curves (${activityType}):`, \"\"];\n\n for (const curve of curves) {\n const label = curve.label || curve.id || \"Unknown\";\n let dateRange = \"\";\n if (curve.start && curve.end) {\n const startShort = curve.start.length > 10 ? curve.start.slice(0, 10) : curve.start;\n const endShort = curve.end.length > 10 ? curve.end.slice(0, 10) : curve.end;\n dateRange = ` (${startShort} to ${endShort})`;\n }\n lines.push(`${label}${dateRange}:`);\n\n const dataPoints = curve.data_points ?? [];\n if (!dataPoints.length) {\n lines.push(\" No data available for requested durations.\");\n lines.push(\"\");\n continue;\n }\n\n for (const point of dataPoints) {\n const durLabel = formatDurationLabel(point.secs);\n const aid = point.activity_id ?? \"\";\n const parts = [` ${durLabel}: ${point.watts ?? \"N/A\"}W`];\n if (includeNormalised && point.watts_per_kg != null) {\n parts.push(`${point.watts_per_kg.toFixed(2)}W/kg`);\n const wkgAid = point.wkg_activity_id ?? \"\";\n if (wkgAid && wkgAid !== aid) parts.push(`[${aid}|wkg:${wkgAid}]`);\n else parts.push(`[${aid}]`);\n } else {\n parts.push(`[${aid}]`);\n }\n lines.push(parts.join(\" \"));\n }\n lines.push(\"\");\n }\n\n return lines.join(\"\\n\");\n}\n","/**\n * Gear tools and gear-name resolution.\n *\n * Intervals.icu activity payloads include only the gear ID, not the name. The\n * gear catalog lives at /athlete/{id}/gear; we cache it per athlete for the\n * process lifetime and inject the resolved name into activities as\n * `_resolved_gear_name` before formatting.\n */\n\nimport { z } from \"zod\";\nimport { makeIntervalsRequest } from \"../api/client.js\";\nimport { getConfig } from \"../config.js\";\nimport { resolveAthleteId } from \"../utils/validation.js\";\nimport type { Dict } from \"../utils/formatting.js\";\nimport { textResult, type ToolRegistrar } from \"./shared.js\";\n\n// Module-level cache of the raw gear catalog per athlete. Single source of\n// truth: the id->name map and the rich listing are both derived from it.\nconst gearRawCache = new Map<string, Dict[]>();\n\n/** Pull the gear ID out of an activity dict, handling the two known shapes. */\nexport function extractGearId(activity: Dict): string | null {\n const gearRaw = activity[\"gear\"];\n if (typeof gearRaw === \"object\" && gearRaw !== null) {\n const id = gearRaw[\"id\"];\n if (id) return String(id);\n }\n const gearId = activity[\"gear_id\"];\n if (gearId) return String(gearId);\n return null;\n}\n\n/** Normalize the /athlete/{id}/gear response into a list of gear dicts. */\nfunction itemsFromResponse(result: unknown): Dict[] {\n if (Array.isArray(result)) return result.filter((i) => typeof i === \"object\" && i !== null);\n if (typeof result === \"object\" && result !== null) {\n for (const value of Object.values(result as Dict)) {\n if (Array.isArray(value)) {\n return value.filter((i) => typeof i === \"object\" && i !== null) as Dict[];\n }\n }\n }\n return [];\n}\n\n/** Convert a raw gear list into a { gearId: gearName } lookup. */\nfunction deriveGearMap(items: Dict[]): Map<string, string> {\n const map = new Map<string, string>();\n for (const item of items) {\n const gid = item[\"id\"];\n const name = item[\"name\"] || item[\"display_name\"];\n if (gid && name) map.set(String(gid), String(name));\n }\n return map;\n}\n\n/** Return (and cache) the raw gear list for an athlete. */\nexport async function getGearRaw(\n opts: { athleteId?: string; apiKey?: string; refresh?: boolean } = {},\n): Promise<Dict[]> {\n const config = getConfig();\n const { athleteId, error } = resolveAthleteId(opts.athleteId, config.athleteId);\n if (error || !athleteId) return [];\n\n if (!opts.refresh && gearRawCache.has(athleteId)) {\n return gearRawCache.get(athleteId) as Dict[];\n }\n\n const result = await makeIntervalsRequest(`/athlete/${athleteId}/gear`, {\n apiKey: opts.apiKey,\n });\n const items = itemsFromResponse(result);\n gearRawCache.set(athleteId, items);\n return items;\n}\n\n/** Return the { gearId: gearName } lookup for an athlete (derived from cache). */\nexport async function getGearMap(\n opts: { athleteId?: string; apiKey?: string; refresh?: boolean } = {},\n): Promise<Map<string, string>> {\n const items = await getGearRaw(opts);\n return deriveGearMap(items);\n}\n\n/** Inject `_resolved_gear_name` into an activity dict if gear is present. */\nexport async function resolveGearForActivity(\n activity: Dict,\n opts: { athleteId?: string; apiKey?: string } = {},\n): Promise<void> {\n const gearId = extractGearId(activity);\n if (!gearId) return;\n const gearMap = await getGearMap(opts);\n const name = gearMap.get(gearId);\n if (name) activity[\"_resolved_gear_name\"] = name;\n}\n\n/** Inject `_resolved_gear_name` into each activity in a list. In-place. */\nexport async function resolveGearForActivities(\n activities: Dict[],\n opts: { athleteId?: string; apiKey?: string } = {},\n): Promise<void> {\n if (!activities.length) return;\n // Pre-warm the cache once, then iterate.\n await getGearMap(opts);\n for (const activity of activities) {\n if (typeof activity === \"object\" && activity !== null) {\n await resolveGearForActivity(activity, opts);\n }\n }\n}\n\nexport const registerGearTools: ToolRegistrar = (server) => {\n server.registerTool(\n \"get_gear_list\",\n {\n title: \"Get Gear List\",\n description:\n \"Get the gear catalog (bikes, shoes, etc.) for an athlete from Intervals.icu.\\n\\n\" +\n \"Returns one line per gear item with id, type, name, and basic stats.\\n\" +\n \"The result is cached for the MCP process lifetime; pass refresh=true to re-fetch.\",\n inputSchema: {\n athlete_id: z.string().optional().describe(\"Intervals.icu athlete ID (defaults to configured ATHLETE_ID)\"),\n api_key: z.string().optional().describe(\"Intervals.icu API key (defaults to configured API_KEY)\"),\n refresh: z.boolean().default(false).describe(\"Bypass the cache and re-fetch from the API\"),\n },\n },\n async ({ athlete_id, api_key, refresh }) => {\n const config = getConfig();\n const { athleteId, error } = resolveAthleteId(athlete_id, config.athleteId);\n if (error) return textResult(error);\n if (!athleteId) {\n return textResult(\n \"Error: athlete_id is required (either as argument or via ATHLETE_ID).\",\n );\n }\n\n const items = await getGearRaw({ athleteId, apiKey: api_key, refresh });\n\n if (!items.length) return textResult(`No gear found for athlete ${athleteId}.`);\n\n let output = `Gear catalog for athlete ${athleteId}:\\n\\n`;\n output += `${\"ID\".padEnd(14)} ${\"Type\".padEnd(8)} ${\"Name\".padEnd(32)} ${\"Default\".padEnd(8)} ${\"Acts\".padEnd(6)} ${\"Dist (km)\".padEnd(10)} ${\"Retired\".padEnd(8)}\\n`;\n output += `${\"-\".repeat(14)} ${\"-\".repeat(8)} ${\"-\".repeat(32)} ${\"-\".repeat(8)} ${\"-\".repeat(6)} ${\"-\".repeat(10)} ${\"-\".repeat(8)}\\n`;\n for (const it of items) {\n const gid = String(it[\"id\"] ?? \"?\");\n const gtype = String(it[\"component_type\"] ?? it[\"type\"] ?? \"?\");\n const name = String(it[\"name\"] ?? \"?\").slice(0, 32);\n const defaultFor = String(it[\"default_for_type\"] || it[\"default_for\"] || \"\");\n const acts = String(it[\"activities\"] ?? it[\"activity_count\"] ?? \"?\");\n const distM = it[\"distance\"] ?? 0;\n const distKm =\n typeof distM === \"number\" ? (distM / 1000).toFixed(1) : \"?\";\n const retired = it[\"retired\"] ? \"yes\" : \"\";\n output += `${gid.padEnd(14)} ${gtype.padEnd(8)} ${name.padEnd(32)} ${defaultFor.padEnd(8)} ${acts.padEnd(6)} ${distKm.padEnd(10)} ${retired.padEnd(8)}\\n`;\n }\n\n return textResult(output);\n },\n );\n};\n","/** Shared helpers for tool registration. */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { Dict } from \"../utils/formatting.js\";\n\n/** A module's tool registration entry point. */\nexport type ToolRegistrar = (server: McpServer) => void;\n\n/** Wrap a plain string as MCP tool content. */\nexport function textResult(text: string): { content: Array<{ type: \"text\"; text: string }> } {\n return { content: [{ type: \"text\", text }] };\n}\n\n/** Extract the error message from an API error result. */\nexport function apiErrorMessage(result: Dict): string {\n return typeof result[\"message\"] === \"string\" ? result[\"message\"] : \"Unknown error\";\n}\n","/**\n * Custom item tools: management of charts, custom fields, zones, etc.\n */\n\nimport { z } from \"zod\";\nimport { makeIntervalsRequest, isApiError } from \"../api/client.js\";\nimport { getConfig } from \"../config.js\";\nimport { formatCustomItemDetails, type Dict } from \"../utils/formatting.js\";\nimport { resolveAthleteId } from \"../utils/validation.js\";\nimport { textResult, apiErrorMessage, type ToolRegistrar } from \"./shared.js\";\n\n/** Accept content as an object, or as a JSON string (parsed leniently). */\nconst ContentSchema = z\n .union([z.record(z.unknown()), z.string()])\n .optional()\n .transform((val, ctx): Record<string, unknown> | null => {\n if (val == null) return null;\n if (typeof val !== \"string\") return val;\n try {\n return JSON.parse(val) as Record<string, unknown>;\n } catch {\n ctx.addIssue({ code: z.ZodIssueCode.custom, message: \"content must be valid JSON when passed as a string.\" });\n return z.NEVER;\n }\n });\n\nconst ITEM_TYPE_DESCRIPTION =\n \"Type of custom item (e.g. FITNESS_CHART, TRACE_CHART, INPUT_FIELD, ACTIVITY_FIELD, INTERVAL_FIELD, ACTIVITY_STREAM, ACTIVITY_CHART, ACTIVITY_HISTOGRAM, ACTIVITY_HEATMAP, ACTIVITY_MAP, ACTIVITY_PANEL, ZONES)\";\nconst CONTENT_DESCRIPTION =\n 'Configuration content for the custom item as an object (optional). Important enum values:\\n' +\n '- \"type\" field for INPUT_FIELD/ACTIVITY_FIELD: must be \"numeric\", \"text\", or \"select\" (NOT \"number\")\\n' +\n '- \"aggregate\" field: must be \"MIN\", \"SUM\", \"MAX\", or \"AVERAGE\" (NOT \"AVG\")';\n\nexport const registerCustomItemTools: ToolRegistrar = (server) => {\n server.registerTool(\n \"get_custom_items\",\n {\n title: \"Get Custom Items\",\n description:\n \"Get custom items (charts, custom fields, zones, etc.) for an athlete from Intervals.icu.\",\n inputSchema: {\n athlete_id: z.string().optional(),\n api_key: z.string().optional(),\n },\n },\n async ({ athlete_id, api_key }) => {\n const config = getConfig();\n const { athleteId, error } = resolveAthleteId(athlete_id, config.athleteId);\n if (error) return textResult(error);\n\n const result = await makeIntervalsRequest(`/athlete/${athleteId}/custom-item`, {\n apiKey: api_key,\n });\n\n if (isApiError(result)) {\n return textResult(`Error fetching custom items: ${apiErrorMessage(result)}`);\n }\n if (result == null || (Array.isArray(result) && result.length === 0)) {\n return textResult(`No custom items found for athlete ${athleteId}.`);\n }\n\n let output = \"Custom Items:\\n\\n\";\n for (const item of result as Dict[]) {\n if (typeof item !== \"object\" || item === null) continue;\n output += `- ID: ${item[\"id\"]}\\n`;\n output += ` Name: ${item[\"name\"] ?? \"N/A\"}\\n`;\n output += ` Type: ${item[\"type\"] ?? \"N/A\"}\\n`;\n if (item[\"description\"]) output += ` Description: ${item[\"description\"]}\\n`;\n output += \"\\n\";\n }\n return textResult(output);\n },\n );\n\n server.registerTool(\n \"get_custom_item_by_id\",\n {\n title: \"Get Custom Item By ID\",\n description: \"Get detailed information for a specific custom item from Intervals.icu.\",\n inputSchema: {\n item_id: z.number().int().describe(\"The custom item ID\"),\n athlete_id: z.string().optional(),\n api_key: z.string().optional(),\n },\n },\n async ({ item_id, athlete_id, api_key }) => {\n const config = getConfig();\n const { athleteId, error } = resolveAthleteId(athlete_id, config.athleteId);\n if (error) return textResult(error);\n\n const result = await makeIntervalsRequest(`/athlete/${athleteId}/custom-item/${item_id}`, {\n apiKey: api_key,\n });\n\n if (isApiError(result)) {\n return textResult(`Error fetching custom item: ${apiErrorMessage(result)}`);\n }\n if (typeof result !== \"object\" || result === null || Array.isArray(result)) {\n return textResult(`No custom item found with ID ${item_id}.`);\n }\n return textResult(formatCustomItemDetails(result as Dict));\n },\n );\n\n server.registerTool(\n \"create_custom_item\",\n {\n title: \"Create Custom Item\",\n description: \"Create a new custom item for an athlete on Intervals.icu.\",\n inputSchema: {\n name: z.string().describe(\"Name of the custom item\"),\n item_type: z.string().describe(ITEM_TYPE_DESCRIPTION),\n athlete_id: z.string().optional(),\n api_key: z.string().optional(),\n description: z.string().optional().describe(\"Description of the custom item (optional)\"),\n content: ContentSchema.describe(CONTENT_DESCRIPTION),\n visibility: z\n .string()\n .optional()\n .describe(\"Visibility setting: PRIVATE, FOLLOWERS, or PUBLIC (optional)\"),\n },\n },\n async ({ name, item_type, athlete_id, api_key, description, content, visibility }) => {\n const config = getConfig();\n const { athleteId, error } = resolveAthleteId(athlete_id, config.athleteId);\n if (error) return textResult(error);\n\n const data: Dict = { name, type: item_type };\n if (description != null) data[\"description\"] = description;\n if (content != null) data[\"content\"] = content;\n if (visibility != null) data[\"visibility\"] = visibility;\n\n const result = await makeIntervalsRequest(`/athlete/${athleteId}/custom-item`, {\n apiKey: api_key,\n data,\n method: \"POST\",\n });\n\n if (isApiError(result)) {\n return textResult(`Error creating custom item: ${apiErrorMessage(result)}`);\n }\n if (typeof result !== \"object\" || result === null || Array.isArray(result)) {\n return textResult(\"Error: Unexpected response when creating custom item.\");\n }\n return textResult(\n `Successfully created custom item:\\n\\n${formatCustomItemDetails(result as Dict)}`,\n );\n },\n );\n\n server.registerTool(\n \"update_custom_item\",\n {\n title: \"Update Custom Item\",\n description: \"Update an existing custom item for an athlete on Intervals.icu.\",\n inputSchema: {\n item_id: z.number().int().describe(\"The custom item ID to update\"),\n athlete_id: z.string().optional(),\n api_key: z.string().optional(),\n name: z.string().optional().describe(\"New name for the custom item (optional)\"),\n item_type: z.string().optional().describe(\"New type for the custom item (optional)\"),\n description: z.string().optional().describe(\"New description for the custom item (optional)\"),\n content: ContentSchema.describe(CONTENT_DESCRIPTION),\n visibility: z\n .string()\n .optional()\n .describe(\"New visibility setting: PRIVATE, FOLLOWERS, or PUBLIC (optional)\"),\n },\n },\n async ({ item_id, athlete_id, api_key, name, item_type, description, content, visibility }) => {\n const config = getConfig();\n const { athleteId, error } = resolveAthleteId(athlete_id, config.athleteId);\n if (error) return textResult(error);\n\n const data: Dict = {};\n if (name != null) data[\"name\"] = name;\n if (item_type != null) data[\"type\"] = item_type;\n if (description != null) data[\"description\"] = description;\n if (content != null) data[\"content\"] = content;\n if (visibility != null) data[\"visibility\"] = visibility;\n\n const result = await makeIntervalsRequest(`/athlete/${athleteId}/custom-item/${item_id}`, {\n apiKey: api_key,\n data,\n method: \"PUT\",\n });\n\n if (isApiError(result)) {\n return textResult(`Error updating custom item: ${apiErrorMessage(result)}`);\n }\n if (typeof result !== \"object\" || result === null || Array.isArray(result)) {\n return textResult(\"Error: Unexpected response when updating custom item.\");\n }\n return textResult(\n `Successfully updated custom item:\\n\\n${formatCustomItemDetails(result as Dict)}`,\n );\n },\n );\n\n server.registerTool(\n \"delete_custom_item\",\n {\n title: \"Delete Custom Item\",\n description: \"Delete a custom item for an athlete from Intervals.icu.\",\n inputSchema: {\n item_id: z.number().int().describe(\"The custom item ID to delete\"),\n athlete_id: z.string().optional(),\n api_key: z.string().optional(),\n },\n },\n async ({ item_id, athlete_id, api_key }) => {\n const config = getConfig();\n const { athleteId, error } = resolveAthleteId(athlete_id, config.athleteId);\n if (error) return textResult(error);\n\n const result = await makeIntervalsRequest(`/athlete/${athleteId}/custom-item/${item_id}`, {\n apiKey: api_key,\n method: \"DELETE\",\n });\n\n if (isApiError(result)) {\n return textResult(`Error deleting custom item: ${apiErrorMessage(result)}`);\n }\n return textResult(`Successfully deleted custom item ${item_id}.`);\n },\n );\n};\n","/**\n * Event tools: retrieval, creation, update, and deletion of calendar events.\n */\n\nimport { z } from \"zod\";\nimport { makeIntervalsRequest, isApiError } from \"../api/client.js\";\nimport { getConfig } from \"../config.js\";\nimport { getDefaultEndDate, getDefaultFutureEndDate } from \"../utils/dates.js\";\nimport { formatEventDetails, formatEventSummary, type Dict } from \"../utils/formatting.js\";\nimport { formatWorkoutDoc, WorkoutDocSchema } from \"../utils/types.js\";\nimport {\n resolveActivityType,\n resolveAthleteId,\n validateDate,\n} from \"../utils/validation.js\";\nimport { textResult, apiErrorMessage, type ToolRegistrar } from \"./shared.js\";\n\nconst WORKOUT_DOC_HELP = `Post event for an athlete to Intervals.icu. If event_id is provided, the event will be updated instead of created.\n\nExample:\n \"workout_doc\": {\n \"description\": \"High-intensity workout for increasing VO2 max\",\n \"steps\": [\n {\"power\": {\"value\": 80, \"units\": \"%ftp\"}, \"duration\": 900, \"warmup\": true},\n {\"reps\": 2, \"text\": \"High-intensity intervals\", \"steps\": [\n {\"power\": {\"value\": 110, \"units\": \"%ftp\"}, \"distance\": 500, \"text\": \"High-intensity\"},\n {\"power\": {\"value\": 80, \"units\": \"%ftp\"}, \"duration\": 90, \"text\": \"Recovery\"}\n ]},\n {\"power\": {\"value\": 80, \"units\": \"%ftp\"}, \"duration\": 600, \"cooldown\": true},\n {\"text\": \"\"}\n ]\n }\n\nStep properties:\n distance: Distance of step in meters\n {\"distance\": 5000}\n duration: Duration of step in seconds\n {\"duration\": 1800}\n power/hr/pace/cadence: Define step intensity\n Percentage of FTP: {\"power\": {\"value\": 80, \"units\": \"%ftp\"}}\n Absolute power: {\"power\": {\"value\": 200, \"units\": \"w\"}}\n Heart rate: {\"hr\": {\"value\": 75, \"units\": \"%hr\"}}\n Heart rate (LTHR): {\"hr\": {\"value\": 85, \"units\": \"%lthr\"}}\n Cadence: {\"cadence\": {\"value\": 90, \"units\": \"cadence\"}}\n Pace by ftp: {\"pace\": {\"value\": 80, \"units\": \"%pace\"}}\n Pace by zone: {\"pace\": {\"value\": 2, \"units\": \"pace_zone\"}}\n Zone by power: {\"power\": {\"value\": 2, \"units\": \"power_zone\"}}\n Zone by heart rate: {\"hr\": {\"value\": 2, \"units\": \"hr_zone\"}}\n Ranges: Specify ranges for power, heart rate, or cadence:\n {\"power\": {\"start\": 80, \"end\": 90, \"units\": \"%ftp\"}}\n Ramps: Instead of a range, indicate a gradual change in intensity (useful for ERG workouts):\n {\"ramp\": true, \"power\": {\"start\": 80, \"end\": 90, \"units\": \"%ftp\"}}\n Repeats: include the reps property and add nested steps\n {\"reps\": 3,\n \"steps\": [\n {\"power\": {\"value\": 110, \"units\": \"%ftp\"}, \"distance\": 500, \"text\": \"High-intensity\"},\n {\"power\": {\"value\": 80, \"units\": \"%ftp\"}, \"duration\": 90, \"text\": \"Recovery\"}\n ]}\n Free Ride: Include freeride to indicate a segment without ERG control, optionally with a suggested power range:\n {\"freeride\": true, \"power\": {\"value\": 80, \"units\": \"%ftp\"}}\n Comments and Labels: Add descriptive text to label steps:\n {\"text\": \"Warmup\"}\n\nHow to use steps:\n- Set distance or duration as appropriate for step\n- Use \"reps\" with nested steps to define repeat intervals (as in example above)\n- Define one of \"power\", \"hr\" or \"pace\" to define step intensity`;\n\nfunction prepareEventData(\n name: string,\n workoutType: string,\n startDate: string,\n workoutDoc: z.infer<typeof WorkoutDocSchema> | undefined,\n movingTime: number | null,\n distance: number | null,\n): Dict {\n const resolvedWorkoutType = resolveActivityType(name, workoutType);\n return {\n start_date_local: `${startDate}T00:00:00`,\n category: \"WORKOUT\",\n name,\n description: workoutDoc ? formatWorkoutDoc(workoutDoc) : null,\n type: resolvedWorkoutType,\n moving_time: movingTime,\n distance,\n };\n}\n\nasync function handleEventResponse(\n result: unknown,\n action: string,\n athleteId: string,\n startDate: string,\n): Promise<string> {\n if (isApiError(result)) {\n return `Error ${action} event: ${apiErrorMessage(result)}`;\n }\n if (\n result == null ||\n (typeof result === \"object\" && !Array.isArray(result) && Object.keys(result).length === 0)\n ) {\n return `No events ${action} for athlete ${athleteId}.`;\n }\n if (typeof result === \"object\" && !Array.isArray(result)) {\n return `Successfully ${action} event id: ${(result as Dict)[\"id\"]}`;\n }\n return `Event ${action} successfully at ${startDate}`;\n}\n\nasync function createOrUpdateEventRequest(\n athleteId: string,\n apiKey: string | undefined,\n eventData: Dict,\n startDate: string,\n eventId: string | undefined,\n): Promise<string> {\n let url = `/athlete/${athleteId}/events`;\n if (eventId) url += `/${eventId}`;\n const result = await makeIntervalsRequest(url, {\n apiKey,\n data: eventData,\n method: eventId ? \"PUT\" : \"POST\",\n });\n const action = eventId ? \"updated\" : \"created\";\n return handleEventResponse(result, action, athleteId, startDate);\n}\n\nexport const registerEventTools: ToolRegistrar = (server) => {\n server.registerTool(\n \"get_events\",\n {\n title: \"Get Events\",\n description:\n \"Get events for an athlete from Intervals.icu.\\n\\n\" +\n \"Args:\\n\" +\n \" athlete_id: The Intervals.icu athlete ID (optional, uses the configured default)\\n\" +\n \" api_key: The Intervals.icu API key (optional, uses the configured default)\\n\" +\n \" start_date: Start date in YYYY-MM-DD format (optional, defaults to today)\\n\" +\n \" end_date: End date in YYYY-MM-DD format (optional, defaults to 30 days from today)\",\n inputSchema: {\n athlete_id: z.string().optional(),\n api_key: z.string().optional(),\n start_date: z.string().optional(),\n end_date: z.string().optional(),\n },\n },\n async ({ athlete_id, api_key, start_date, end_date }) => {\n const config = getConfig();\n const { athleteId, error } = resolveAthleteId(athlete_id, config.athleteId);\n if (error) return textResult(error);\n\n const oldest = start_date || getDefaultEndDate();\n const newest = end_date || getDefaultFutureEndDate();\n\n const result = await makeIntervalsRequest(`/athlete/${athleteId}/events`, {\n apiKey: api_key,\n params: { oldest, newest },\n });\n\n if (isApiError(result)) {\n return textResult(`Error fetching events: ${apiErrorMessage(result)}`);\n }\n\n const events = Array.isArray(result) ? (result as Dict[]) : [];\n if (!events.length) {\n return textResult(\n `No events found for athlete ${athleteId} in the specified date range.`,\n );\n }\n\n let summary = \"Events:\\n\\n\";\n for (const event of events) {\n if (typeof event !== \"object\" || event === null) continue;\n summary += `${formatEventSummary(event)}\\n\\n`;\n }\n return textResult(summary);\n },\n );\n\n server.registerTool(\n \"get_event_by_id\",\n {\n title: \"Get Event By ID\",\n description: \"Get detailed information for a specific event from Intervals.icu.\",\n inputSchema: {\n event_id: z.string().describe(\"The Intervals.icu event ID\"),\n athlete_id: z.string().optional(),\n api_key: z.string().optional(),\n },\n },\n async ({ event_id, athlete_id, api_key }) => {\n const config = getConfig();\n const { athleteId, error } = resolveAthleteId(athlete_id, config.athleteId);\n if (error) return textResult(error);\n\n const result = await makeIntervalsRequest(`/athlete/${athleteId}/event/${event_id}`, {\n apiKey: api_key,\n });\n\n if (isApiError(result)) {\n return textResult(`Error fetching event details: ${apiErrorMessage(result)}`);\n }\n if (\n result == null ||\n Array.isArray(result) ||\n Object.keys(result as Dict).length === 0\n ) {\n return textResult(`No details found for event ${event_id}.`);\n }\n\n return textResult(formatEventDetails(result as Dict));\n },\n );\n\n server.registerTool(\n \"delete_event\",\n {\n title: \"Delete Event\",\n description: \"Delete an event for an athlete from Intervals.icu.\",\n inputSchema: {\n event_id: z.string().describe(\"The Intervals.icu event ID\"),\n athlete_id: z.string().optional(),\n api_key: z.string().optional(),\n },\n },\n async ({ event_id, athlete_id, api_key }) => {\n const config = getConfig();\n const { athleteId, error } = resolveAthleteId(athlete_id, config.athleteId);\n if (error) return textResult(error);\n if (!event_id) return textResult(\"Error: No event ID provided.\");\n\n const result = await makeIntervalsRequest(`/athlete/${athleteId}/events/${event_id}`, {\n apiKey: api_key,\n method: \"DELETE\",\n });\n\n if (isApiError(result)) {\n return textResult(`Error deleting event: ${apiErrorMessage(result)}`);\n }\n return textResult(JSON.stringify(result, null, 2));\n },\n );\n\n server.registerTool(\n \"delete_events_by_date_range\",\n {\n title: \"Delete Events By Date Range\",\n description:\n \"Delete events for an athlete from Intervals.icu in the specified date range.\",\n inputSchema: {\n start_date: z.string().describe(\"Start date in YYYY-MM-DD format\"),\n end_date: z.string().describe(\"End date in YYYY-MM-DD format\"),\n athlete_id: z.string().optional(),\n api_key: z.string().optional(),\n },\n },\n async ({ start_date, end_date, athlete_id, api_key }) => {\n const config = getConfig();\n const { athleteId, error } = resolveAthleteId(athlete_id, config.athleteId);\n if (error) return textResult(error);\n\n let oldest: string, newest: string;\n try {\n oldest = validateDate(start_date);\n newest = validateDate(end_date);\n } catch (e) {\n return textResult(`Error deleting events: ${(e as Error).message}`);\n }\n\n const fetchResult = await makeIntervalsRequest(`/athlete/${athleteId}/events`, {\n apiKey: api_key,\n params: { oldest, newest },\n });\n if (isApiError(fetchResult)) {\n return textResult(`Error deleting events: ${apiErrorMessage(fetchResult)}`);\n }\n const events = Array.isArray(fetchResult) ? (fetchResult as Dict[]) : [];\n\n const failedEvents: unknown[] = [];\n for (const event of events) {\n const deleteResult = await makeIntervalsRequest(\n `/athlete/${athleteId}/events/${event[\"id\"]}`,\n { apiKey: api_key, method: \"DELETE\" },\n );\n if (isApiError(deleteResult)) failedEvents.push(event[\"id\"]);\n }\n\n const deletedCount = events.length - failedEvents.length;\n return textResult(\n `Deleted ${deletedCount} events. Failed to delete ${failedEvents.length} events: ${JSON.stringify(failedEvents)}`,\n );\n },\n );\n\n server.registerTool(\n \"add_or_update_event\",\n {\n title: \"Add Or Update Event\",\n description: WORKOUT_DOC_HELP,\n inputSchema: {\n workout_type: z\n .string()\n .describe(\"Workout type (e.g. Ride, Run, Swim, Walk, Row)\"),\n name: z.string().describe(\"Name of the activity\"),\n athlete_id: z.string().optional(),\n api_key: z.string().optional(),\n event_id: z\n .string()\n .optional()\n .describe(\"The Intervals.icu event ID (optional; if set the event is updated)\"),\n start_date: z\n .string()\n .optional()\n .describe(\"Start date in YYYY-MM-DD format (optional, defaults to today)\"),\n workout_doc: WorkoutDocSchema.optional().describe(\n \"Steps as a list of step objects (optional, needed to define workout steps)\",\n ),\n moving_time: z\n .number()\n .nullable()\n .optional()\n .describe(\"Total expected moving time of the workout in seconds (optional)\"),\n distance: z\n .number()\n .nullable()\n .optional()\n .describe(\"Total expected distance of the workout in meters (optional)\"),\n },\n },\n async ({\n workout_type,\n name,\n athlete_id,\n api_key,\n event_id,\n start_date,\n workout_doc,\n moving_time,\n distance,\n }) => {\n const config = getConfig();\n const { athleteId, error } = resolveAthleteId(athlete_id, config.athleteId);\n if (error) return textResult(error);\n\n const startDate = start_date || getDefaultEndDate();\n try {\n const validatedDate = validateDate(startDate);\n const eventData = prepareEventData(\n name,\n workout_type,\n validatedDate,\n workout_doc,\n moving_time ?? null,\n distance ?? null,\n );\n return textResult(\n await createOrUpdateEventRequest(\n athleteId,\n api_key,\n eventData,\n validatedDate,\n event_id,\n ),\n );\n } catch (e) {\n return textResult(`Error: ${(e as Error).message}`);\n }\n },\n );\n\n server.registerTool(\n \"add_or_update_note\",\n {\n title: \"Add Or Update Note\",\n description:\n \"Add or update a plain text note (category NOTE) on the Intervals.icu calendar.\",\n inputSchema: {\n name: z.string().describe(\"Title of the note\"),\n description: z.string().describe(\"Plain text content of the note\"),\n start_date: z\n .string()\n .optional()\n .describe(\"Date in YYYY-MM-DD format (optional, defaults to today)\"),\n color: z.string().optional().describe(\"Color of the note (e.g. green, orange, red, blue)\"),\n athlete_id: z.string().optional(),\n api_key: z.string().optional(),\n event_id: z\n .string()\n .optional()\n .describe(\"The Intervals.icu event ID (optional, for updates)\"),\n },\n },\n async ({ name, description, start_date, color, athlete_id, api_key, event_id }) => {\n const config = getConfig();\n const { athleteId, error } = resolveAthleteId(athlete_id, config.athleteId);\n if (error) return textResult(error);\n\n const startDate = start_date || getDefaultEndDate();\n try {\n const validatedDate = validateDate(startDate);\n const eventData: Dict = {\n category: \"NOTE\",\n name,\n description,\n start_date_local: `${validatedDate}T00:00:00`,\n color: color ?? \"green\",\n };\n return textResult(\n await createOrUpdateEventRequest(\n athleteId,\n api_key,\n eventData,\n validatedDate,\n event_id,\n ),\n );\n } catch (e) {\n return textResult(`Error: ${(e as Error).message}`);\n }\n },\n );\n};\n","/**\n * Workout data structures for the Intervals.icu API.\n *\n * Zod schemas mirror the Python dataclasses (Value / Step / WorkoutDoc) so the\n * MCP tool input schema stays identical, plus formatting helpers that render a\n * WorkoutDoc into the human-readable description attached to calendar events.\n */\n\nimport { z } from \"zod\";\n\n// ---------------------------------------------------------------------------\n// Enums\n// ---------------------------------------------------------------------------\n\nexport const WorkoutTargetSchema = z.enum([\"AUTO\", \"POWER\", \"HR\", \"PACE\"]);\nexport const HrTargetSchema = z.enum([\"lap\", \"1s\", \"3s\", \"10s\", \"30s\"]);\nexport const IntensitySchema = z.enum([\n \"active\",\n \"rest\",\n \"warmup\",\n \"cooldown\",\n \"recovery\",\n \"interval\",\n \"other\",\n]);\nexport const PaceUnitsSchema = z.enum([\n \"SECS_100M\",\n \"SECS_100Y\",\n \"MINS_KM\",\n \"MINS_MILE\",\n \"SECS_500M\",\n]);\nexport const ValueUnitsSchema = z.enum([\n \"%mmp\",\n \"%hr\",\n \"%lthr\",\n \"%pace\",\n \"power_zone\",\n \"hr_zone\",\n \"pace_zone\",\n \"w\",\n \"%ftp\",\n \"cadence\",\n \"MINS_KM\",\n \"MINS_MILE\",\n \"SECS_100M\",\n \"SECS_500M\",\n]);\n\n// ---------------------------------------------------------------------------\n// Value / Step / WorkoutDoc\n// ---------------------------------------------------------------------------\n\nexport const ValueSchema = z.object({\n value: z.number().optional(),\n start: z.number().optional(),\n end: z.number().optional(),\n units: ValueUnitsSchema.optional(),\n target: HrTargetSchema.optional(),\n});\n\nexport interface Step {\n text?: string;\n text_locale?: Record<string, string>;\n duration?: number;\n distance?: number;\n until_lap_press?: boolean;\n reps?: number;\n warmup?: boolean;\n cooldown?: boolean;\n intensity?: z.infer<typeof IntensitySchema>;\n steps?: Step[];\n ramp?: boolean;\n freeride?: boolean;\n maxeffort?: boolean;\n power?: Value;\n hr?: Value;\n pace?: Value;\n cadence?: Value;\n hidepower?: boolean;\n // Filled in with actual watts/bpm etc. when resolve=true is supplied by the API\n _power?: Value;\n _hr?: Value;\n _pace?: Value;\n _distance?: number;\n}\n\nexport type Value = z.infer<typeof ValueSchema>;\n\nexport const StepSchema: z.ZodType<Step> = z.lazy(() =>\n z.object({\n text: z.string().optional(),\n text_locale: z.record(z.string()).optional(),\n duration: z.number().optional(),\n distance: z.number().optional(),\n until_lap_press: z.boolean().optional(),\n reps: z.number().optional(),\n warmup: z.boolean().optional(),\n cooldown: z.boolean().optional(),\n intensity: IntensitySchema.optional(),\n steps: z.array(StepSchema).optional(),\n ramp: z.boolean().optional(),\n freeride: z.boolean().optional(),\n maxeffort: z.boolean().optional(),\n power: ValueSchema.optional(),\n hr: ValueSchema.optional(),\n pace: ValueSchema.optional(),\n cadence: ValueSchema.optional(),\n hidepower: z.boolean().optional(),\n _power: ValueSchema.optional(),\n _hr: ValueSchema.optional(),\n _pace: ValueSchema.optional(),\n _distance: z.number().optional(),\n }),\n);\n\nexport const WorkoutDocSchema = z.object({\n description: z.string().optional(),\n description_locale: z.record(z.string()).optional(),\n duration: z.number().optional(),\n distance: z.number().optional(),\n ftp: z.number().optional(),\n lthr: z.number().optional(),\n threshold_pace: z.number().optional(), // meters/sec\n pace_units: PaceUnitsSchema.optional(),\n sport_settings: z.record(z.unknown()).optional(),\n category: z.string().optional(),\n target: WorkoutTargetSchema.optional(),\n steps: z.array(StepSchema).optional(),\n zone_times: z.array(z.union([z.number(), z.unknown()])).optional(),\n options: z.record(z.string()).optional(),\n locales: z.array(z.string()).optional(),\n});\n\nexport type WorkoutDoc = z.infer<typeof WorkoutDocSchema>;\n\n// ---------------------------------------------------------------------------\n// Formatting (ports of the Python dataclass __str__ implementations)\n// ---------------------------------------------------------------------------\n\n/** Format a number without decimals when it is a whole number. */\nexport function floatToStr(value: number): string {\n return Number.isInteger(value) ? String(value) : String(value);\n}\n\nconst PERCENT_UNITS = new Set([\"%hr\", \"%mmp\", \"%lthr\", \"%pace\", \"%ftp\"]);\nconst ZONE_UNITS = new Set([\"power_zone\", \"hr_zone\", \"pace_zone\"]);\n\nconst UNITS_LABEL: Partial<Record<NonNullable<Value[\"units\"]>, string>> = {\n \"%hr\": \"HR\",\n hr_zone: \"HR\",\n \"%mmp\": \"MMP\",\n \"%lthr\": \"LTHR\",\n \"%pace\": \"Pace\",\n pace_zone: \"Pace\",\n \"%ftp\": \"ftp\",\n power_zone: \"W\",\n cadence: \"Cadence\",\n};\n\nfunction formatScalar(value: number, units: Value[\"units\"]): string {\n if (units && PERCENT_UNITS.has(units)) return `${floatToStr(value)}%`;\n if (units && ZONE_UNITS.has(units)) return `Z${floatToStr(value)}`;\n if (units === \"w\") return `${floatToStr(value)}W`;\n if (units === \"cadence\") return `${floatToStr(value)}rpm`;\n return floatToStr(value);\n}\n\n/** Render a Value (single, range or ramp) like the Python `Value.__str__`. */\nexport function formatValue(v: Value): string {\n let val = \"\";\n if (v.start != null && v.end != null) {\n val += `${formatScalar(v.start, v.units)}-${formatScalar(v.end, v.units)} `;\n }\n if (v.value != null) {\n val += `${formatScalar(v.value, v.units)} `;\n }\n if (v.units != null) {\n const label = UNITS_LABEL[v.units] ?? \"\";\n if (label) val += `${label} `;\n }\n if (v.target != null) {\n val += `hr=${v.target} `;\n }\n return val.trim();\n}\n\nfunction formatDuration(durationSecs: number): string {\n let remaining = durationSecs;\n let val = \"\";\n if (remaining >= 3600) {\n val += `${Math.floor(remaining / 3600)}h`;\n remaining %= 3600;\n }\n if (remaining > 100 || remaining === 60) {\n val += `${Math.floor(remaining / 60)}m`;\n remaining %= 60;\n }\n if (remaining > 0) {\n val += `${remaining}s`;\n }\n return val;\n}\n\nfunction formatDistance(distance: number): string {\n if (distance < 1000) return `${floatToStr(distance)}mtr`;\n return `${floatToStr(distance / 1000)}km`;\n}\n\n/** Render a single Step (or nested repeat step) like the Python `Step._to_str`. */\nexport function formatStep(step: Step, nested = false): string {\n let val = \"\";\n if (step.reps != null) {\n val += `\\n${step.reps}x `;\n } else {\n if (!nested && step.warmup) val += \"\\nWarmup\\n\";\n if (!nested && step.cooldown) val += \"\\nCooldown\\n\";\n\n if (step.duration != null) {\n val += `- ${formatDuration(step.duration)} `;\n } else if (step.distance != null) {\n val += `- ${formatDistance(step.distance)} `;\n }\n\n if (step.freeride) val += \"freeride \";\n if (step.maxeffort) val += \"maxeffort \";\n if (step.ramp) val += \"ramp \";\n if (step.hidepower) val += \"hidepower \";\n if (step.intensity != null) val += `intensity=${step.intensity} `;\n\n if (step.power) val += `${formatValue(step.power)} `;\n if (step.hr) val += `${formatValue(step.hr)} `;\n if (step.pace) val += `${formatValue(step.pace)} `;\n if (step.cadence) val += `${formatValue(step.cadence)} `;\n }\n if (step.text != null) {\n val += `${step.text} `;\n }\n if (step.reps != null && step.steps != null) {\n for (const child of step.steps) {\n val += `\\n${formatStep(child, true)}`;\n }\n val += \"\\n\";\n } else if (!nested && (step.warmup || step.cooldown)) {\n val += \"\\n\";\n }\n return val;\n}\n\n/** Render a WorkoutDoc into the description text attached to calendar events. */\nexport function formatWorkoutDoc(doc: WorkoutDoc): string {\n let val = \"\";\n if (doc.description != null) {\n val += `${doc.description}\\n`;\n }\n if (doc.steps != null) {\n for (const step of doc.steps) {\n val += `${formatStep(step)}\\n`;\n }\n }\n return val;\n}\n","/**\n * Power curve tools: best power for selected durations across time periods.\n */\n\nimport { z } from \"zod\";\nimport { makeIntervalsRequest, isApiError } from \"../api/client.js\";\nimport { getConfig } from \"../config.js\";\nimport {\n formatPowerCurves,\n type CurveDataPoint,\n type ExtractedCurve,\n type Dict,\n} from \"../utils/formatting.js\";\nimport { resolveAthleteId } from \"../utils/validation.js\";\nimport { textResult, apiErrorMessage, type ToolRegistrar } from \"./shared.js\";\n\n// 5s, 15s, 30s, 1min, 2min, 5min, 10min, 20min, 60min\nexport const DEFAULT_DURATIONS = [5, 15, 30, 60, 120, 300, 600, 1200, 3600];\n\n/** Build the curves query parameter list based on user selections. */\nfunction buildCurvesParam(\n thisSeason: boolean,\n lastSeason: boolean,\n startDate?: string,\n endDate?: string,\n): string[] {\n const curves: string[] = [];\n if (thisSeason) curves.push(\"s0\");\n if (lastSeason) curves.push(\"s1\");\n if (startDate && endDate) curves.push(`r.${startDate}.${endDate}`);\n return curves;\n}\n\n/** Validate that start/end dates are both present or both absent, and ordered. */\nfunction validateDates(startDate?: string, endDate?: string): string | null {\n if (!startDate !== !endDate) {\n return \"Error: Both start_date and end_date must be provided together for a custom date range.\";\n }\n if (startDate && endDate) {\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(startDate) || !/^\\d{4}-\\d{2}-\\d{2}$/.test(endDate)) {\n return \"Error: Dates must be in YYYY-MM-DD format.\";\n }\n if (startDate >= endDate) return \"Error: start_date must be before end_date.\";\n }\n return null;\n}\n\n/** Extract power data for requested durations from a single curve. */\nfunction extractCurveData(\n curve: Dict,\n durations: number[],\n includeNormalised: boolean,\n): ExtractedCurve {\n const secs = (curve[\"secs\"] ?? []) as number[];\n const values = (curve[\"values\"] ?? []) as Array<number | null>;\n const activityIds = (curve[\"activity_id\"] ?? []) as Array<string | null>;\n const wattsPerKg = (curve[\"watts_per_kg\"] ?? []) as Array<number | null>;\n const wkgActivityIds = (curve[\"wkg_activity_id\"] ?? []) as Array<string | null>;\n\n const secToIdx = new Map<number, number>();\n secs.forEach((s, i) => secToIdx.set(s, i));\n\n const dataPoints: CurveDataPoint[] = [];\n for (const dur of durations) {\n const idx = secToIdx.get(dur);\n if (idx === undefined || idx >= values.length) continue;\n const point: CurveDataPoint = {\n secs: dur,\n watts: values[idx] ?? null,\n activity_id: idx < activityIds.length && activityIds[idx] != null ? (activityIds[idx] as string) : \"\",\n };\n if (includeNormalised && idx < wattsPerKg.length) {\n point.watts_per_kg =\n wattsPerKg[idx] != null ? Math.round((wattsPerKg[idx] as number) * 100) / 100 : undefined;\n point.wkg_activity_id =\n idx < wkgActivityIds.length && wkgActivityIds[idx] != null\n ? (wkgActivityIds[idx] as string)\n : \"\";\n }\n dataPoints.push(point);\n }\n\n return {\n id: String(curve[\"id\"] ?? \"\"),\n label: String(curve[\"label\"] ?? curve[\"id\"] ?? \"\"),\n start: String(curve[\"start_date_local\"] ?? \"\"),\n end: String(curve[\"end_date_local\"] ?? \"\"),\n data_points: dataPoints,\n };\n}\n\nexport const registerPowerCurveTools: ToolRegistrar = (server) => {\n server.registerTool(\n \"get_athlete_power_curves\",\n {\n title: \"Get Athlete Power Curves\",\n description:\n \"Get power curves for an athlete from Intervals.icu.\\n\\n\" +\n \"Returns best power output for selected durations across specified time periods.\\n\" +\n \"Uses FFT power computation. Power values are in watts.\",\n inputSchema: {\n activity_type: z.string().default(\"Ride\").describe('Activity type (e.g. \"Ride\", \"Run\", \"VirtualRide\")'),\n durations: z\n .array(z.number().int())\n .optional()\n .describe(\"Durations in seconds to include (defaults to [5, 15, 30, 60, 120, 300, 600, 1200, 3600])\"),\n indoor_outdoor: z\n .string()\n .optional()\n .describe('Filter by location — \"indoor\" or \"outdoor\". Omit for no filtering.'),\n start_date: z\n .string()\n .optional()\n .describe(\"Start date (YYYY-MM-DD) for custom date range curve. Must be used with end_date.\"),\n end_date: z\n .string()\n .optional()\n .describe(\"End date (YYYY-MM-DD) for custom date range curve. Must be used with start_date.\"),\n this_season: z.boolean().default(true).describe(\"Include this season's curve\"),\n last_season: z.boolean().default(true).describe(\"Include last season's curve\"),\n include_normalised: z.boolean().default(true).describe(\"Include weight-normalised W/kg values\"),\n athlete_id: z.string().optional(),\n api_key: z.string().optional(),\n },\n },\n async ({\n activity_type,\n durations,\n indoor_outdoor,\n start_date,\n end_date,\n this_season,\n last_season,\n include_normalised,\n athlete_id,\n api_key,\n }) => {\n const config = getConfig();\n const { athleteId, error } = resolveAthleteId(athlete_id, config.athleteId);\n if (error) return textResult(error);\n\n const durs = durations ?? DEFAULT_DURATIONS;\n\n if (indoor_outdoor && ![\"indoor\", \"outdoor\"].includes(indoor_outdoor)) {\n return textResult(\"Error: indoor_outdoor must be 'indoor', 'outdoor', or omitted.\");\n }\n\n const dateError = validateDates(start_date, end_date);\n if (dateError) return textResult(dateError);\n\n const curves = buildCurvesParam(this_season, last_season, start_date, end_date);\n if (!curves.length) {\n return textResult(\n \"Error: At least one curve must be selected (this_season, last_season, or a date range).\",\n );\n }\n\n const params: Record<string, unknown> = {\n curves,\n type: activity_type,\n includeRanks: false,\n };\n if (indoor_outdoor) {\n params[\"filters\"] = JSON.stringify([\n { field_id: \"indoor\", value: indoor_outdoor, id: 1 },\n ]);\n }\n\n const result = await makeIntervalsRequest(`/athlete/${athleteId}/power-curves`, {\n apiKey: api_key,\n params: params as Record<string, import(\"../api/client.js\").QueryValue>,\n });\n\n if (isApiError(result)) {\n return textResult(`Error fetching power curves: ${apiErrorMessage(result)}`);\n }\n\n let curveList: Dict[] = [];\n if (typeof result === \"object\" && result !== null && !Array.isArray(result)) {\n curveList = ((result as Dict)[\"list\"] ?? []) as Dict[];\n } else if (Array.isArray(result)) {\n curveList = result as Dict[];\n }\n\n if (!curveList.length) {\n return textResult(`No power curve data found for athlete ${athleteId} (${activity_type}).`);\n }\n\n const extracted = curveList\n .filter((c) => typeof c === \"object\" && c !== null)\n .map((c) => extractCurveData(c, durs, include_normalised));\n\n if (!extracted.length) {\n return textResult(`No power curve data found for athlete ${athleteId} (${activity_type}).`);\n }\n\n return textResult(formatPowerCurves(extracted, activity_type, include_normalised));\n },\n );\n};\n","/**\n * Wellness tools: retrieval of athlete wellness data.\n */\n\nimport { z } from \"zod\";\nimport { makeIntervalsRequest, isApiError } from \"../api/client.js\";\nimport { getConfig } from \"../config.js\";\nimport { formatWellnessEntry, type Dict } from \"../utils/formatting.js\";\nimport { resolveAthleteId, resolveDateParams } from \"../utils/validation.js\";\nimport { textResult, apiErrorMessage, type ToolRegistrar } from \"./shared.js\";\n\nexport const registerWellnessTools: ToolRegistrar = (server) => {\n server.registerTool(\n \"get_wellness_data\",\n {\n title: \"Get Wellness Data\",\n description:\n \"Get wellness data for an athlete from Intervals.icu.\\n\\n\" +\n \"By default returns standard wellness fields (training metrics, vitals, sleep,\\n\" +\n \"subjective scores, etc.). Set include_all_fields=true to also include any\\n\" +\n \"additional or custom fields configured by the user in Intervals.icu.\",\n inputSchema: {\n athlete_id: z.string().optional(),\n api_key: z.string().optional(),\n start_date: z.string().optional().describe(\"Start date in YYYY-MM-DD format (defaults to 30 days ago)\"),\n end_date: z.string().optional().describe(\"End date in YYYY-MM-DD format (defaults to today)\"),\n include_all_fields: z\n .boolean()\n .default(false)\n .describe(\"Include additional and custom fields beyond the standard set\"),\n },\n },\n async ({ athlete_id, api_key, start_date, end_date, include_all_fields }) => {\n const config = getConfig();\n const { athleteId, error } = resolveAthleteId(athlete_id, config.athleteId);\n if (error) return textResult(error);\n\n const [oldest, newest] = resolveDateParams(start_date, end_date);\n\n const result = await makeIntervalsRequest(`/athlete/${athleteId}/wellness`, {\n apiKey: api_key,\n params: { oldest, newest },\n });\n\n if (isApiError(result)) {\n return textResult(`Error fetching wellness data: ${apiErrorMessage(result)}`);\n }\n if (\n result == null ||\n (typeof result === \"object\" && !Array.isArray(result) && Object.keys(result).length === 0)\n ) {\n return textResult(\n `No wellness data found for athlete ${athleteId} in the specified date range.`,\n );\n }\n\n let summary = \"Wellness Data:\\n\\n\";\n\n if (typeof result === \"object\" && !Array.isArray(result)) {\n // Result is a dict keyed by date\n for (const [dateStr, data] of Object.entries(result as Dict)) {\n if (typeof data === \"object\" && data !== null && !(\"date\" in data)) {\n data[\"date\"] = dateStr;\n }\n summary += `${formatWellnessEntry(data as Dict, include_all_fields)}\\n\\n`;\n }\n } else if (Array.isArray(result)) {\n for (const entry of result as Dict[]) {\n if (typeof entry === \"object\" && entry !== null) {\n summary += `${formatWellnessEntry(entry, include_all_fields)}\\n\\n`;\n }\n }\n }\n\n return textResult(summary);\n },\n );\n};\n"],"mappings":"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","names":["text","cancel","spinner","z","remainder","text","z","z","z","z","z","z","z","z","z","z"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "intervals-mcp-server",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Model Context Protocol (MCP) server for the Intervals.icu API — TypeScript edition",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/HduSy/intervals-mcp-server.git"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"intervals",
|
|
13
|
+
"intervals.icu",
|
|
14
|
+
"mcp",
|
|
15
|
+
"model-context-protocol",
|
|
16
|
+
"claude",
|
|
17
|
+
"cycling",
|
|
18
|
+
"running",
|
|
19
|
+
"training"
|
|
20
|
+
],
|
|
21
|
+
"bin": {
|
|
22
|
+
"intervals-mcp-server": "dist/index.js"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"README.md",
|
|
27
|
+
"LICENSE"
|
|
28
|
+
],
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=18.19"
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"build": "tsup",
|
|
34
|
+
"test": "vitest run",
|
|
35
|
+
"test:watch": "vitest",
|
|
36
|
+
"typecheck": "tsc --noEmit",
|
|
37
|
+
"smoke": "node scripts/smoke.mjs"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@clack/prompts": "^1.7.0",
|
|
41
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
42
|
+
"commander": "^15.0.0",
|
|
43
|
+
"zod": "^3.25.76"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/node": "^22.10.0",
|
|
47
|
+
"tsup": "^8.3.0",
|
|
48
|
+
"typescript": "^5.7.0",
|
|
49
|
+
"vitest": "^3.0.0"
|
|
50
|
+
},
|
|
51
|
+
"prepublishOnly": "pnpm build && pnpm test"
|
|
52
|
+
}
|