@trainheroic-unofficial/athlete-mcp 2.1.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server.mjs +40 -5
- package/package.json +5 -5
package/dist/server.mjs
CHANGED
|
@@ -545,6 +545,34 @@ function confirmGate(ctx, message, confirmArg) {
|
|
|
545
545
|
*/
|
|
546
546
|
const SERVER_INSTRUCTIONS = "Speak to the user in plain, everyday language about their training. Describe what you are doing in the TrainHeroic app's own terms (for example, say you are creating a workout rather than naming a tool). Do not surface internal tool names (the snake_case identifiers such as athlete_session_create), raw parameter names, or numeric ids in your replies unless the user explicitly asks for them; they are implementation details. The tool descriptions cross-reference each other by name only so you can chain them correctly. Keep that wiring to yourself.";
|
|
547
547
|
//#endregion
|
|
548
|
+
//#region ../js/src/http-error.ts
|
|
549
|
+
/**
|
|
550
|
+
* A final non-2xx response from TrainHeroic. The error deliberately carries only request
|
|
551
|
+
* metadata that is safe to send to telemetry: never the path, query string, request body,
|
|
552
|
+
* response body, credentials, or session token.
|
|
553
|
+
*/
|
|
554
|
+
var TrainHeroicHttpError = class extends Error {
|
|
555
|
+
name = "TrainHeroicHttpError";
|
|
556
|
+
method;
|
|
557
|
+
status;
|
|
558
|
+
host;
|
|
559
|
+
constructor(method, url, status) {
|
|
560
|
+
const parsed = new URL(url);
|
|
561
|
+
const normalizedMethod = method.toUpperCase();
|
|
562
|
+
super(`TrainHeroic ${normalizedMethod} request failed with HTTP ${status}`);
|
|
563
|
+
this.method = normalizedMethod;
|
|
564
|
+
this.status = status;
|
|
565
|
+
this.host = parsed.host;
|
|
566
|
+
}
|
|
567
|
+
};
|
|
568
|
+
/** Call observability hooks without allowing them to change SDK behavior. */
|
|
569
|
+
function notifyHttpError(handler, method, url, status) {
|
|
570
|
+
if (!handler) return;
|
|
571
|
+
try {
|
|
572
|
+
Promise.resolve(handler(new TrainHeroicHttpError(method, url, status))).catch(() => {});
|
|
573
|
+
} catch {}
|
|
574
|
+
}
|
|
575
|
+
//#endregion
|
|
548
576
|
//#region ../js/src/auth.ts
|
|
549
577
|
const DEFAULT_AUTH_URL = "https://apis.trainheroic.com/auth";
|
|
550
578
|
/**
|
|
@@ -566,8 +594,9 @@ function authUrl() {
|
|
|
566
594
|
* the Phase 0 spike: no refresh_token, no api_token, no TTL). The 48-char session_id
|
|
567
595
|
* is sent as the `session-token` header and works against both API hosts.
|
|
568
596
|
*/
|
|
569
|
-
async function loginTrainHeroic(email, password) {
|
|
570
|
-
const
|
|
597
|
+
async function loginTrainHeroic(email, password, options = {}) {
|
|
598
|
+
const url = authUrl();
|
|
599
|
+
const res = await fetch(url, {
|
|
571
600
|
method: "POST",
|
|
572
601
|
headers: {
|
|
573
602
|
"content-type": "application/x-www-form-urlencoded",
|
|
@@ -578,7 +607,10 @@ async function loginTrainHeroic(email, password) {
|
|
|
578
607
|
password
|
|
579
608
|
}).toString()
|
|
580
609
|
});
|
|
581
|
-
if (!res.ok)
|
|
610
|
+
if (!res.ok) {
|
|
611
|
+
notifyHttpError(options.onHttpError, "POST", url, res.status);
|
|
612
|
+
return null;
|
|
613
|
+
}
|
|
582
614
|
const data = await res.json().catch(() => null);
|
|
583
615
|
if (!data || typeof data.id !== "number" || !data.session_id) return null;
|
|
584
616
|
return {
|
|
@@ -621,6 +653,7 @@ var TrainHeroicClient = class {
|
|
|
621
653
|
#email;
|
|
622
654
|
#password;
|
|
623
655
|
#onSession;
|
|
656
|
+
#onHttpError;
|
|
624
657
|
#sessionId;
|
|
625
658
|
#loginInFlight = null;
|
|
626
659
|
constructor(email, password, sessionId = null, options = {}) {
|
|
@@ -628,6 +661,7 @@ var TrainHeroicClient = class {
|
|
|
628
661
|
this.#password = password;
|
|
629
662
|
this.#sessionId = sessionId;
|
|
630
663
|
this.#onSession = options.onSession;
|
|
664
|
+
this.#onHttpError = options.onHttpError;
|
|
631
665
|
}
|
|
632
666
|
get sessionId() {
|
|
633
667
|
return this.#sessionId;
|
|
@@ -642,7 +676,7 @@ var TrainHeroicClient = class {
|
|
|
642
676
|
}
|
|
643
677
|
}
|
|
644
678
|
async #login() {
|
|
645
|
-
const session = await loginTrainHeroic(this.#email, this.#password);
|
|
679
|
+
const session = await loginTrainHeroic(this.#email, this.#password, this.#onHttpError ? { onHttpError: this.#onHttpError } : {});
|
|
646
680
|
if (!session) throw new TrainHeroicAuthError("TrainHeroic login failed");
|
|
647
681
|
this.#sessionId = session.sessionId;
|
|
648
682
|
try {
|
|
@@ -659,6 +693,7 @@ var TrainHeroicClient = class {
|
|
|
659
693
|
session = await this.#ensureSession();
|
|
660
694
|
res = await this.#send(method, url, session, options.body);
|
|
661
695
|
}
|
|
696
|
+
if (!res.ok) notifyHttpError(this.#onHttpError, method, url, res.status);
|
|
662
697
|
const text = await res.text();
|
|
663
698
|
let data = text;
|
|
664
699
|
if (text.length > 0) try {
|
|
@@ -2115,7 +2150,7 @@ function registerAthleteTrainingTools(server, ctx) {
|
|
|
2115
2150
|
}
|
|
2116
2151
|
//#endregion
|
|
2117
2152
|
//#region package.json
|
|
2118
|
-
var version = "2.1.
|
|
2153
|
+
var version = "2.1.1";
|
|
2119
2154
|
//#endregion
|
|
2120
2155
|
//#region src/server.ts
|
|
2121
2156
|
function main() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trainheroic-unofficial/athlete-mcp",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -21,13 +21,13 @@
|
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@modelcontextprotocol/server": "2.0.0",
|
|
23
23
|
"zod": "^4.4.3",
|
|
24
|
-
"@trainheroic-unofficial/
|
|
25
|
-
"@trainheroic-unofficial/
|
|
24
|
+
"@trainheroic-unofficial/js": "2.1.1",
|
|
25
|
+
"@trainheroic-unofficial/core": "2.1.1"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"@types/node": "^26.
|
|
28
|
+
"@types/node": "^26.2.0",
|
|
29
29
|
"tsdown": "^0.22.14",
|
|
30
|
-
"tsx": "^4.23.
|
|
30
|
+
"tsx": "^4.23.11",
|
|
31
31
|
"typescript": "^7.0.2",
|
|
32
32
|
"vitest": "^4.1.10"
|
|
33
33
|
},
|