@trainheroic-unofficial/athlete-mcp 3.7.1 → 4.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.
Files changed (2) hide show
  1. package/dist/server.mjs +29 -7
  2. package/package.json +3 -3
package/dist/server.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { McpServer, acceptedContent, inputRequired, inputResponse } from "@modelcontextprotocol/server";
1
+ import { CLIENT_CAPABILITIES_META_KEY, McpServer, acceptedContent, inputRequired, inputResponse } from "@modelcontextprotocol/server";
2
2
  import { serveStdio } from "@modelcontextprotocol/server/stdio";
3
3
  import process from "node:process";
4
4
  import { z } from "zod";
@@ -733,14 +733,26 @@ const exerciseSpecSchema = z.object({
733
733
  z.number(),
734
734
  z.string(),
735
735
  z.array(z.union([z.number(), z.string()]))
736
- ]).optional(),
736
+ ]).optional().describe("Primary slot values; may be reps, distance, or time. State primaryUnit."),
737
737
  sets: z.number().optional(),
738
- weight: z.union([z.number(), z.array(z.number())]).optional(),
738
+ weight: z.union([z.number(), z.array(z.number())]).optional().describe("Secondary slot values; may be weight or time. State secondaryUnit."),
739
+ primaryUnit: z.string().trim().min(1).optional().describe("Intended primary unit from exercise_resolve, such as reps, m, mi, or sec."),
740
+ secondaryUnit: z.string().trim().min(1).optional().describe("Intended secondary unit from exercise_resolve, such as lb or sec."),
739
741
  rpe: z.union([z.number(), z.string()]).optional(),
740
742
  instr: z.string().optional(),
741
743
  param_1_type: z.number().optional(),
742
744
  param_2_type: z.number().optional()
743
745
  }).superRefine((exercise, ctx) => {
746
+ if (exercise.reps !== void 0 && exercise.primaryUnit === void 0) ctx.addIssue({
747
+ code: "custom",
748
+ message: "primaryUnit is required when reps contains primary slot values.",
749
+ path: ["primaryUnit"]
750
+ });
751
+ if (exercise.weight !== void 0 && exercise.secondaryUnit === void 0) ctx.addIssue({
752
+ code: "custom",
753
+ message: "secondaryUnit is required when weight contains secondary slot values.",
754
+ path: ["secondaryUnit"]
755
+ });
744
756
  if (Array.isArray(exercise.reps) && Array.isArray(exercise.weight) && exercise.reps.length !== exercise.weight.length) ctx.addIssue({
745
757
  code: "custom",
746
758
  message: `Per-set reps and weight arrays must have the same length; received ${exercise.reps.length} reps and ${exercise.weight.length} weights.`,
@@ -976,6 +988,15 @@ function errorResult(message) {
976
988
  const NOT_CONFIRMED = "Not confirmed — the user declined. Nothing was changed.";
977
989
  /** Appended to the prompt so the fallback survives whichever way a client surfaces the request. */
978
990
  const FALLBACK_HINT = " (If you cannot show this prompt, re-run the tool with confirm:true once the user has agreed.)";
991
+ const CONFIRMATION_REQUIRED = "Ask the user to approve this action, then retry the tool with confirm:true only after they agree. Nothing was changed.";
992
+ /** `undefined` means a legacy request, whose capability check belongs to the SDK's shim. */
993
+ function modernClientSupportsFormElicitation(ctx) {
994
+ const envelope = ctx.mcpReq.envelope;
995
+ if (envelope === void 0) return void 0;
996
+ const elicitation = envelope[CLIENT_CAPABILITIES_META_KEY]?.elicitation;
997
+ if (elicitation === void 0) return false;
998
+ return elicitation.form !== void 0 || elicitation.url === void 0;
999
+ }
979
1000
  /**
980
1001
  * Confirm a destructive/athlete-facing action.
981
1002
  *
@@ -991,14 +1012,15 @@ const FALLBACK_HINT = " (If you cannot show this prompt, re-run the tool with co
991
1012
  * confirmation message ever needs data fetched first, that fetch must be idempotent.
992
1013
  *
993
1014
  * Written once in the 2026 `inputRequired` style: modern clients retry with `inputResponses`.
994
- * A client that cannot elicit at all never reaches the denial below — the SDK rejects the
995
- * request before the retry so it must pass `confirm: true`, which is why the hint rides inside
996
- * the prompt text itself.
1015
+ * MCP correctly rejects unsupported embedded requests with `-32021`. This application has an
1016
+ * alternate `confirm: true` flow, so a modern client that does not declare form elicitation gets
1017
+ * a model-readable tool error that tells it how to recover while the gate remains closed.
997
1018
  */
998
1019
  function confirmGate(ctx, message, confirmArg) {
999
1020
  if (confirmArg === true) return void 0;
1000
1021
  if (acceptedContent(ctx.mcpReq.inputResponses, "confirm")?.confirm === true) return void 0;
1001
1022
  if (inputResponse(ctx.mcpReq.inputResponses, "confirm").kind !== "missing") return errorResult(NOT_CONFIRMED);
1023
+ if (modernClientSupportsFormElicitation(ctx) === false) return errorResult(`${message} ${CONFIRMATION_REQUIRED}`);
1002
1024
  const prompt = message + FALLBACK_HINT;
1003
1025
  return inputRequired({ inputRequests: { confirm: inputRequired.elicit({
1004
1026
  message: prompt,
@@ -3203,7 +3225,7 @@ function registerAthleteTrainingTools(server, ctx) {
3203
3225
  }
3204
3226
  //#endregion
3205
3227
  //#region package.json
3206
- var version = "3.7.1";
3228
+ var version = "4.0.0";
3207
3229
  //#endregion
3208
3230
  //#region src/server.ts
3209
3231
  function main() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trainheroic-unofficial/athlete-mcp",
3
- "version": "3.7.1",
3
+ "version": "4.0.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -21,8 +21,8 @@
21
21
  "dependencies": {
22
22
  "@modelcontextprotocol/server": "2.0.0",
23
23
  "zod": "^4.6.3",
24
- "@trainheroic-unofficial/core": "3.7.1",
25
- "@trainheroic-unofficial/js": "3.7.1"
24
+ "@trainheroic-unofficial/core": "4.0.0",
25
+ "@trainheroic-unofficial/js": "4.0.0"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/node": "^26.5.1",