hevy-coach 0.1.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 +142 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +16 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/coaching.d.ts +4 -0
- package/dist/tools/coaching.d.ts.map +1 -0
- package/dist/tools/coaching.js +306 -0
- package/dist/tools/coaching.js.map +1 -0
- package/dist/tools/exercises.d.ts +4 -0
- package/dist/tools/exercises.d.ts.map +1 -0
- package/dist/tools/exercises.js +87 -0
- package/dist/tools/exercises.js.map +1 -0
- package/dist/tools/routines.d.ts +4 -0
- package/dist/tools/routines.d.ts.map +1 -0
- package/dist/tools/routines.js +126 -0
- package/dist/tools/routines.js.map +1 -0
- package/dist/tools/workouts.d.ts +4 -0
- package/dist/tools/workouts.d.ts.map +1 -0
- package/dist/tools/workouts.js +66 -0
- package/dist/tools/workouts.js.map +1 -0
- package/dist/utils/hevy-client.d.ts +136 -0
- package/dist/utils/hevy-client.d.ts.map +1 -0
- package/dist/utils/hevy-client.js +88 -0
- package/dist/utils/hevy-client.js.map +1 -0
- package/dist/utils/response.d.ts +21 -0
- package/dist/utils/response.d.ts.map +1 -0
- package/dist/utils/response.js +22 -0
- package/dist/utils/response.js.map +1 -0
- package/package.json +54 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Furkan Tanyol
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# HevyCoach
|
|
2
|
+
|
|
3
|
+
AI personal training system that connects to [Hevy](https://hevyapp.com) via MCP (Model Context Protocol). Not just another API wrapper — HevyCoach adds coaching intelligence on top of workout data.
|
|
4
|
+
|
|
5
|
+
**What makes this different from existing Hevy MCP servers:** Other servers give you CRUD operations. HevyCoach adds the brain — workout analysis, progression tracking with Epley 1RM estimation, training summaries, and exercise search. Combined with the CLAUDE.md coaching prompt, it turns Claude into a full athletic coach covering strength, hypertrophy, VO2max, mobility, flexibility, and longevity.
|
|
6
|
+
|
|
7
|
+
## What You Get
|
|
8
|
+
|
|
9
|
+
- **Complete athletic programming** — strength, hypertrophy, VO2max, mobility, flexibility, stamina, longevity
|
|
10
|
+
- **Coaching intelligence** — workout analysis, progression tracking, automatic adaptation recommendations
|
|
11
|
+
- **Auto-pushed to Hevy** — routines appear in your app, ready to log
|
|
12
|
+
- **Daily briefings** — morning message with today's workout + conditioning + mobility
|
|
13
|
+
- **Adaptive coaching** — reads your completed workouts and adjusts programming
|
|
14
|
+
- **Weekly reviews** — volume tracking, PR highlights, conditioning adherence, program adjustments
|
|
15
|
+
|
|
16
|
+
## Setup
|
|
17
|
+
|
|
18
|
+
### Prerequisites
|
|
19
|
+
|
|
20
|
+
- [Hevy Pro](https://hevyapp.com) subscription (required for API access)
|
|
21
|
+
- API key from Hevy Settings → API
|
|
22
|
+
- Node.js 18+
|
|
23
|
+
- [Claude Desktop](https://claude.ai/download) (or any MCP-compatible client)
|
|
24
|
+
|
|
25
|
+
### Install
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
git clone https://github.com/AugmentedMind/hevy-coach.git
|
|
29
|
+
cd hevy-coach
|
|
30
|
+
npm install
|
|
31
|
+
npm run build
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Configure Claude Desktop
|
|
35
|
+
|
|
36
|
+
Add to your MCP config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"mcpServers": {
|
|
41
|
+
"hevy-coach": {
|
|
42
|
+
"command": "node",
|
|
43
|
+
"args": ["/absolute/path/to/hevy-coach/dist/cli.js"],
|
|
44
|
+
"env": {
|
|
45
|
+
"HEVY_API_KEY": "your-hevy-api-key"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Restart Claude Desktop. The tools appear in the MCP tools list.
|
|
53
|
+
|
|
54
|
+
### Add the Coaching Brain
|
|
55
|
+
|
|
56
|
+
Create a Claude Project called **"HevyCoach"**:
|
|
57
|
+
|
|
58
|
+
1. Open Claude Desktop → Projects → New Project
|
|
59
|
+
2. Name it "HevyCoach"
|
|
60
|
+
3. In Project Instructions, paste the contents of `CLAUDE.md`
|
|
61
|
+
4. Add `training-history.md` as a project file
|
|
62
|
+
|
|
63
|
+
### Start Training
|
|
64
|
+
|
|
65
|
+
Open the HevyCoach project and say:
|
|
66
|
+
|
|
67
|
+
> "I want to start training with you. Let's do the onboarding."
|
|
68
|
+
|
|
69
|
+
Claude will ask about your body, training history, goals, and preferences. Then it generates your full program (strength + conditioning + mobility) and pushes routines to Hevy.
|
|
70
|
+
|
|
71
|
+
### Daily Automation (Optional)
|
|
72
|
+
|
|
73
|
+
Create two Claude Desktop scheduled tasks:
|
|
74
|
+
|
|
75
|
+
**Morning briefing (7 AM):**
|
|
76
|
+
> Read my HevyCoach program. Tell me today's workout with warmup, exercises, sets/reps/weights, conditioning if scheduled, and daily mobility drills.
|
|
77
|
+
|
|
78
|
+
**Evening sync (11:59 PM):**
|
|
79
|
+
> Fetch my latest Hevy workout. Analyze it against today's plan. Summarize performance, note progressions or missed targets, and adjust upcoming sessions if needed.
|
|
80
|
+
|
|
81
|
+
## Tools
|
|
82
|
+
|
|
83
|
+
### Data Tools
|
|
84
|
+
| Tool | Description |
|
|
85
|
+
|------|-------------|
|
|
86
|
+
| `get-workouts` | List recent workouts (paginated) |
|
|
87
|
+
| `get-workout` | Get specific workout by ID |
|
|
88
|
+
| `get-workout-count` | Total logged workouts |
|
|
89
|
+
| `get-workout-events` | Track changes since a date |
|
|
90
|
+
| `get-routines` | List saved routines |
|
|
91
|
+
| `get-routine` | Get routine details |
|
|
92
|
+
| `create-routine` | Push routine to Hevy |
|
|
93
|
+
| `update-routine` | Modify existing routine |
|
|
94
|
+
| `get-routine-folders` | List routine folders |
|
|
95
|
+
| `create-routine-folder` | Create folder |
|
|
96
|
+
| `get-exercise-templates` | Browse exercise library |
|
|
97
|
+
| `get-exercise-template` | Get exercise details |
|
|
98
|
+
| `get-exercise-history` | Past performance data |
|
|
99
|
+
| `create-exercise-template` | Create custom exercise |
|
|
100
|
+
|
|
101
|
+
### Coaching Tools
|
|
102
|
+
| Tool | Description |
|
|
103
|
+
|------|-------------|
|
|
104
|
+
| `analyze-workout` | Compare completed vs planned workout. Returns per-exercise analysis with progression recommendations. |
|
|
105
|
+
| `get-training-summary` | Aggregate last N workouts: volume, frequency, consistency, duration trends. |
|
|
106
|
+
| `get-exercise-progression` | Track exercise over time: weight/rep trends, estimated 1RM (Epley), plateau detection. |
|
|
107
|
+
| `find-exercise` | Search exercises by name or muscle group. |
|
|
108
|
+
|
|
109
|
+
## Architecture
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
hevy-coach/
|
|
113
|
+
├── src/
|
|
114
|
+
│ ├── index.ts # Server factory
|
|
115
|
+
│ ├── cli.ts # CLI entry point (stdio transport)
|
|
116
|
+
│ ├── tools/
|
|
117
|
+
│ │ ├── workouts.ts # Workout CRUD
|
|
118
|
+
│ │ ├── routines.ts # Routine CRUD
|
|
119
|
+
│ │ ├── exercises.ts # Exercise templates
|
|
120
|
+
│ │ └── coaching.ts # Coaching intelligence (the differentiator)
|
|
121
|
+
│ └── utils/
|
|
122
|
+
│ ├── hevy-client.ts # Hevy API client
|
|
123
|
+
│ └── response.ts # MCP response helpers
|
|
124
|
+
├── CLAUDE.md # Coaching brain + user profile + program
|
|
125
|
+
├── training-history.md # Long-term tracking template
|
|
126
|
+
└── package.json
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Development
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
npm run build # Compile TypeScript
|
|
133
|
+
npm run dev # Watch mode
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Credits
|
|
137
|
+
|
|
138
|
+
Inspired by [chrisdoc/hevy-mcp](https://github.com/chrisdoc/hevy-mcp) and [tomtorggler/hevy-mcp-server](https://github.com/tomtorggler/hevy-mcp-server). Built from scratch with coaching intelligence as the core focus.
|
|
139
|
+
|
|
140
|
+
## License
|
|
141
|
+
|
|
142
|
+
MIT — Furkan Tanyol
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { createServer } from "./index.js";
|
|
4
|
+
const apiKey = process.env.HEVY_API_KEY;
|
|
5
|
+
if (!apiKey) {
|
|
6
|
+
console.error("HEVY_API_KEY environment variable is required.");
|
|
7
|
+
console.error("Get your API key from Hevy Settings → API (requires Pro subscription).");
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
const server = createServer(apiKey);
|
|
11
|
+
const transport = new StdioServerTransport();
|
|
12
|
+
server.connect(transport).catch((err) => {
|
|
13
|
+
console.error("Failed to start hevy-coach:", err);
|
|
14
|
+
process.exit(1);
|
|
15
|
+
});
|
|
16
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;AAExC,IAAI,CAAC,MAAM,EAAE,CAAC;IACZ,OAAO,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;IAChE,OAAO,CAAC,KAAK,CAAC,wEAAwE,CAAC,CAAC;IACxF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;AACpC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAE7C,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACtC,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;IAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAOpE,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CActD"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { HevyClient } from "./utils/hevy-client.js";
|
|
3
|
+
import { registerWorkoutTools } from "./tools/workouts.js";
|
|
4
|
+
import { registerRoutineTools } from "./tools/routines.js";
|
|
5
|
+
import { registerExerciseTools } from "./tools/exercises.js";
|
|
6
|
+
import { registerCoachingTools } from "./tools/coaching.js";
|
|
7
|
+
export function createServer(apiKey) {
|
|
8
|
+
const server = new McpServer({
|
|
9
|
+
name: "hevy-coach",
|
|
10
|
+
version: "0.1.0",
|
|
11
|
+
});
|
|
12
|
+
const client = new HevyClient(apiKey);
|
|
13
|
+
registerWorkoutTools(server, client);
|
|
14
|
+
registerRoutineTools(server, client);
|
|
15
|
+
registerExerciseTools(server, client);
|
|
16
|
+
registerCoachingTools(server, client);
|
|
17
|
+
return server;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IAEtC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEtC,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coaching.d.ts","sourceRoot":"","sources":["../../src/tools/coaching.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,UAAU,EAAyC,MAAM,yBAAyB,CAAC;AAGjG,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,QAiL1E"}
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { jsonResponse, textResponse, errorResponse, getErrorMessage } from "../utils/response.js";
|
|
3
|
+
export function registerCoachingTools(server, client) {
|
|
4
|
+
// ─── ANALYZE WORKOUT ──────────────────────────────────────────────
|
|
5
|
+
// The brain: compares a completed workout against the planned session
|
|
6
|
+
// and generates coaching feedback + adaptation recommendations.
|
|
7
|
+
server.registerTool("analyze-workout", {
|
|
8
|
+
description: `Analyze a completed workout against a planned session. Compares actual vs planned performance
|
|
9
|
+
and generates coaching feedback with adaptation recommendations.
|
|
10
|
+
|
|
11
|
+
Provide the workout ID to analyze and the planned session details (exercises with target sets/reps/weight/RPE).
|
|
12
|
+
Returns: performance summary, progression recommendations, volume analysis, and suggested changes for next session.
|
|
13
|
+
|
|
14
|
+
This is the core coaching tool — call it after each workout to drive adaptive programming.`,
|
|
15
|
+
inputSchema: {
|
|
16
|
+
workoutId: z.string().min(1).describe("ID of the completed workout to analyze"),
|
|
17
|
+
plannedExercises: z.array(z.object({
|
|
18
|
+
name: z.string().describe("Exercise name as it appears in Hevy"),
|
|
19
|
+
targetSets: z.number().int().describe("Planned number of sets"),
|
|
20
|
+
targetReps: z.number().int().describe("Planned reps per set"),
|
|
21
|
+
targetWeightKg: z.number().nullable().describe("Planned weight in kg (null for bodyweight)"),
|
|
22
|
+
targetRpe: z.number().nullable().describe("Target RPE (1-10, null if not specified)"),
|
|
23
|
+
})).describe("The planned exercises for this session"),
|
|
24
|
+
},
|
|
25
|
+
}, async ({ workoutId, plannedExercises }) => {
|
|
26
|
+
try {
|
|
27
|
+
const workout = await client.getWorkout(workoutId);
|
|
28
|
+
if (!workout)
|
|
29
|
+
return textResponse("Workout not found.");
|
|
30
|
+
const analysis = analyzeWorkoutPerformance(workout, plannedExercises);
|
|
31
|
+
return jsonResponse(analysis);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
return errorResponse(getErrorMessage(error));
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
// ─── GET RECENT SUMMARY ───────────────────────────────────────────
|
|
38
|
+
// Fetches the last N workouts and produces a structured training summary
|
|
39
|
+
// for the coaching brain to reason about.
|
|
40
|
+
server.registerTool("get-training-summary", {
|
|
41
|
+
description: `Get a structured summary of recent training. Fetches the last N workouts and produces:
|
|
42
|
+
- Total sessions and training days
|
|
43
|
+
- Volume per muscle group (total sets)
|
|
44
|
+
- Exercise frequency (which exercises, how often)
|
|
45
|
+
- Weight progression trends
|
|
46
|
+
- Average session duration
|
|
47
|
+
- Training consistency (days between sessions)
|
|
48
|
+
|
|
49
|
+
Use this for weekly reviews, program adjustments, and trend analysis.`,
|
|
50
|
+
inputSchema: {
|
|
51
|
+
workoutCount: z.coerce.number().int().gte(1).lte(50).default(10)
|
|
52
|
+
.describe("Number of recent workouts to analyze (default 10)"),
|
|
53
|
+
},
|
|
54
|
+
}, async ({ workoutCount }) => {
|
|
55
|
+
try {
|
|
56
|
+
// Fetch workouts in pages of 10
|
|
57
|
+
const allWorkouts = [];
|
|
58
|
+
let page = 1;
|
|
59
|
+
const pageSize = Math.min(workoutCount, 10);
|
|
60
|
+
while (allWorkouts.length < workoutCount) {
|
|
61
|
+
const result = await client.getWorkouts(page, pageSize);
|
|
62
|
+
if (!result.workouts.length)
|
|
63
|
+
break;
|
|
64
|
+
allWorkouts.push(...result.workouts);
|
|
65
|
+
if (result.workouts.length < pageSize)
|
|
66
|
+
break;
|
|
67
|
+
page++;
|
|
68
|
+
}
|
|
69
|
+
const workouts = allWorkouts.slice(0, workoutCount);
|
|
70
|
+
if (!workouts.length)
|
|
71
|
+
return textResponse("No workouts found.");
|
|
72
|
+
const summary = generateTrainingSummary(workouts);
|
|
73
|
+
return jsonResponse(summary);
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
return errorResponse(getErrorMessage(error));
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
// ─── GET EXERCISE PROGRESSION ─────────────────────────────────────
|
|
80
|
+
// Shows how a specific exercise has progressed over time — weights, reps, estimated 1RM.
|
|
81
|
+
server.registerTool("get-exercise-progression", {
|
|
82
|
+
description: `Track progression for a specific exercise over time. Shows:
|
|
83
|
+
- Weight progression (session by session)
|
|
84
|
+
- Rep progression
|
|
85
|
+
- Estimated 1RM trend (Epley formula)
|
|
86
|
+
- Best set (highest estimated 1RM)
|
|
87
|
+
- Volume trend (total sets × reps × weight per session)
|
|
88
|
+
|
|
89
|
+
Use this to identify plateaus, track PRs, and inform programming decisions.`,
|
|
90
|
+
inputSchema: {
|
|
91
|
+
exerciseTemplateId: z.string().min(1).describe("Hevy exercise template ID"),
|
|
92
|
+
sessions: z.coerce.number().int().gte(1).lte(20).default(10)
|
|
93
|
+
.describe("Number of recent sessions to analyze (default 10)"),
|
|
94
|
+
},
|
|
95
|
+
}, async ({ exerciseTemplateId, sessions }) => {
|
|
96
|
+
try {
|
|
97
|
+
const history = await client.getExerciseHistory(exerciseTemplateId, 1, sessions);
|
|
98
|
+
if (!history.exercise_history?.length) {
|
|
99
|
+
return textResponse("No history found for this exercise.");
|
|
100
|
+
}
|
|
101
|
+
const progression = analyzeExerciseProgression(history.exercise_history);
|
|
102
|
+
return jsonResponse(progression);
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
return errorResponse(getErrorMessage(error));
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
// ─── FIND EXERCISE ────────────────────────────────────────────────
|
|
109
|
+
// Search for exercises by name or muscle group — easier than browsing paginated templates.
|
|
110
|
+
server.registerTool("find-exercise", {
|
|
111
|
+
description: `Search for exercises by name or muscle group. Returns matching exercise template IDs
|
|
112
|
+
that can be used in routines. Searches across all pages of the exercise library.`,
|
|
113
|
+
inputSchema: {
|
|
114
|
+
query: z.string().min(1).describe("Exercise name or muscle group to search for"),
|
|
115
|
+
},
|
|
116
|
+
}, async ({ query }) => {
|
|
117
|
+
try {
|
|
118
|
+
const allTemplates = [];
|
|
119
|
+
let page = 1;
|
|
120
|
+
const queryLower = query.toLowerCase();
|
|
121
|
+
// Search through pages until we have enough or run out
|
|
122
|
+
while (page <= 5) {
|
|
123
|
+
const result = await client.getExerciseTemplates(page, 100);
|
|
124
|
+
if (!result.exercise_templates.length)
|
|
125
|
+
break;
|
|
126
|
+
const matches = result.exercise_templates.filter((t) => t.title.toLowerCase().includes(queryLower) ||
|
|
127
|
+
t.primary_muscle_group.toLowerCase().includes(queryLower) ||
|
|
128
|
+
t.secondary_muscle_groups?.some((m) => m.toLowerCase().includes(queryLower)));
|
|
129
|
+
allTemplates.push(...matches);
|
|
130
|
+
if (result.exercise_templates.length < 100)
|
|
131
|
+
break;
|
|
132
|
+
page++;
|
|
133
|
+
}
|
|
134
|
+
if (!allTemplates.length) {
|
|
135
|
+
return textResponse(`No exercises found matching "${query}".`);
|
|
136
|
+
}
|
|
137
|
+
return jsonResponse({
|
|
138
|
+
query,
|
|
139
|
+
matches: allTemplates.length,
|
|
140
|
+
exercises: allTemplates.map((t) => ({
|
|
141
|
+
id: t.id,
|
|
142
|
+
title: t.title,
|
|
143
|
+
primaryMuscle: t.primary_muscle_group,
|
|
144
|
+
secondaryMuscles: t.secondary_muscle_groups,
|
|
145
|
+
equipment: t.equipment,
|
|
146
|
+
isCustom: t.is_custom,
|
|
147
|
+
})),
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
return errorResponse(getErrorMessage(error));
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
function analyzeWorkoutPerformance(workout, planned) {
|
|
156
|
+
const duration = workout.start_time && workout.end_time
|
|
157
|
+
? Math.round((new Date(workout.end_time).getTime() - new Date(workout.start_time).getTime()) / 60000)
|
|
158
|
+
: null;
|
|
159
|
+
const exerciseResults = workout.exercises.map((actual) => {
|
|
160
|
+
const plan = planned.find((p) => p.name.toLowerCase() === actual.title.toLowerCase());
|
|
161
|
+
const workingSets = actual.sets.filter((s) => s.type === "normal" || s.type === "failure" || s.type === "dropset");
|
|
162
|
+
const totalReps = workingSets.reduce((sum, s) => sum + (s.reps || 0), 0);
|
|
163
|
+
const maxWeight = Math.max(...workingSets.map((s) => s.weight_kg || 0));
|
|
164
|
+
const avgRpe = workingSets.filter((s) => s.rpe).length > 0
|
|
165
|
+
? workingSets.reduce((sum, s) => sum + (s.rpe || 0), 0) / workingSets.filter((s) => s.rpe).length
|
|
166
|
+
: null;
|
|
167
|
+
const setsCompleted = workingSets.length;
|
|
168
|
+
const repsPerSet = setsCompleted > 0 ? totalReps / setsCompleted : 0;
|
|
169
|
+
let recommendation = "maintain";
|
|
170
|
+
if (plan) {
|
|
171
|
+
const hitsReps = repsPerSet >= plan.targetReps;
|
|
172
|
+
const hitsTarget = setsCompleted >= plan.targetSets;
|
|
173
|
+
if (hitsReps && hitsTarget && avgRpe !== null && avgRpe <= 7) {
|
|
174
|
+
recommendation = "increase_weight";
|
|
175
|
+
}
|
|
176
|
+
else if (hitsReps && hitsTarget && avgRpe !== null && avgRpe <= 8) {
|
|
177
|
+
recommendation = "maintain_then_increase";
|
|
178
|
+
}
|
|
179
|
+
else if (!hitsReps && avgRpe !== null && avgRpe >= 9.5) {
|
|
180
|
+
recommendation = "decrease_weight";
|
|
181
|
+
}
|
|
182
|
+
else if (!hitsReps) {
|
|
183
|
+
recommendation = "hold_weight";
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
exercise: actual.title,
|
|
188
|
+
planned: plan
|
|
189
|
+
? { sets: plan.targetSets, reps: plan.targetReps, weightKg: plan.targetWeightKg, rpe: plan.targetRpe }
|
|
190
|
+
: null,
|
|
191
|
+
actual: {
|
|
192
|
+
setsCompleted,
|
|
193
|
+
avgRepsPerSet: Math.round(repsPerSet * 10) / 10,
|
|
194
|
+
totalReps,
|
|
195
|
+
maxWeightKg: maxWeight,
|
|
196
|
+
avgRpe: avgRpe ? Math.round(avgRpe * 10) / 10 : null,
|
|
197
|
+
},
|
|
198
|
+
recommendation,
|
|
199
|
+
notes: actual.notes,
|
|
200
|
+
};
|
|
201
|
+
});
|
|
202
|
+
// Check for planned exercises that weren't done
|
|
203
|
+
const skippedExercises = planned.filter((p) => !workout.exercises.some((a) => a.title.toLowerCase() === p.name.toLowerCase()));
|
|
204
|
+
const totalSets = workout.exercises.reduce((sum, ex) => sum + ex.sets.filter((s) => s.type !== "warmup").length, 0);
|
|
205
|
+
return {
|
|
206
|
+
workoutId: workout.id,
|
|
207
|
+
title: workout.title,
|
|
208
|
+
date: workout.start_time,
|
|
209
|
+
durationMinutes: duration,
|
|
210
|
+
totalWorkingSets: totalSets,
|
|
211
|
+
exerciseResults,
|
|
212
|
+
skippedExercises: skippedExercises.map((e) => e.name),
|
|
213
|
+
overallAdherence: planned.length > 0
|
|
214
|
+
? Math.round(((planned.length - skippedExercises.length) / planned.length) * 100)
|
|
215
|
+
: 100,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
function generateTrainingSummary(workouts) {
|
|
219
|
+
const totalSessions = workouts.length;
|
|
220
|
+
// Date range
|
|
221
|
+
const dates = workouts.map((w) => new Date(w.start_time)).sort((a, b) => a.getTime() - b.getTime());
|
|
222
|
+
const dateRange = {
|
|
223
|
+
from: dates[0]?.toISOString().split("T")[0],
|
|
224
|
+
to: dates[dates.length - 1]?.toISOString().split("T")[0],
|
|
225
|
+
};
|
|
226
|
+
// Training frequency
|
|
227
|
+
const daysBetween = [];
|
|
228
|
+
for (let i = 1; i < dates.length; i++) {
|
|
229
|
+
daysBetween.push(Math.round((dates[i].getTime() - dates[i - 1].getTime()) / 86400000));
|
|
230
|
+
}
|
|
231
|
+
const avgDaysBetween = daysBetween.length
|
|
232
|
+
? Math.round((daysBetween.reduce((a, b) => a + b, 0) / daysBetween.length) * 10) / 10
|
|
233
|
+
: 0;
|
|
234
|
+
// Duration
|
|
235
|
+
const durations = workouts
|
|
236
|
+
.filter((w) => w.start_time && w.end_time)
|
|
237
|
+
.map((w) => (new Date(w.end_time).getTime() - new Date(w.start_time).getTime()) / 60000);
|
|
238
|
+
const avgDuration = durations.length
|
|
239
|
+
? Math.round(durations.reduce((a, b) => a + b, 0) / durations.length)
|
|
240
|
+
: 0;
|
|
241
|
+
// Exercise frequency
|
|
242
|
+
const exerciseCounts = {};
|
|
243
|
+
const muscleGroupSets = {};
|
|
244
|
+
for (const workout of workouts) {
|
|
245
|
+
for (const exercise of workout.exercises) {
|
|
246
|
+
exerciseCounts[exercise.title] = (exerciseCounts[exercise.title] || 0) + 1;
|
|
247
|
+
const workingSets = exercise.sets.filter((s) => s.type !== "warmup").length;
|
|
248
|
+
muscleGroupSets[exercise.title] = (muscleGroupSets[exercise.title] || 0) + workingSets;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
// Sort by frequency
|
|
252
|
+
const topExercises = Object.entries(exerciseCounts)
|
|
253
|
+
.sort(([, a], [, b]) => b - a)
|
|
254
|
+
.slice(0, 15)
|
|
255
|
+
.map(([name, count]) => ({
|
|
256
|
+
name,
|
|
257
|
+
sessions: count,
|
|
258
|
+
totalSets: muscleGroupSets[name] || 0,
|
|
259
|
+
}));
|
|
260
|
+
// Total volume
|
|
261
|
+
const totalSets = workouts.reduce((sum, w) => sum + w.exercises.reduce((s, e) => s + e.sets.filter((set) => set.type !== "warmup").length, 0), 0);
|
|
262
|
+
return {
|
|
263
|
+
period: dateRange,
|
|
264
|
+
totalSessions,
|
|
265
|
+
totalWorkingSets: totalSets,
|
|
266
|
+
avgSessionDurationMinutes: avgDuration,
|
|
267
|
+
avgDaysBetweenSessions: avgDaysBetween,
|
|
268
|
+
sessionsPerWeek: avgDaysBetween > 0 ? Math.round((7 / avgDaysBetween) * 10) / 10 : 0,
|
|
269
|
+
topExercises,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
function analyzeExerciseProgression(history) {
|
|
273
|
+
const sessions = history
|
|
274
|
+
.sort((a, b) => new Date(a.start_time).getTime() - new Date(b.start_time).getTime())
|
|
275
|
+
.map((entry) => {
|
|
276
|
+
const workingSets = entry.sets.filter((s) => s.type !== "warmup");
|
|
277
|
+
const maxWeight = Math.max(...workingSets.map((s) => s.weight_kg || 0));
|
|
278
|
+
const maxReps = Math.max(...workingSets.map((s) => s.reps || 0));
|
|
279
|
+
const totalVolume = workingSets.reduce((sum, s) => sum + (s.weight_kg || 0) * (s.reps || 0), 0);
|
|
280
|
+
// Epley formula: 1RM = weight × (1 + reps/30)
|
|
281
|
+
const bestSet = workingSets.reduce((best, s) => {
|
|
282
|
+
const e1rm = (s.weight_kg || 0) * (1 + (s.reps || 0) / 30);
|
|
283
|
+
return e1rm > best.e1rm ? { weight: s.weight_kg || 0, reps: s.reps || 0, e1rm } : best;
|
|
284
|
+
}, { weight: 0, reps: 0, e1rm: 0 });
|
|
285
|
+
return {
|
|
286
|
+
date: entry.start_time.split("T")[0],
|
|
287
|
+
workingSets: workingSets.length,
|
|
288
|
+
maxWeightKg: maxWeight,
|
|
289
|
+
maxReps,
|
|
290
|
+
totalVolume: Math.round(totalVolume),
|
|
291
|
+
estimated1RM: Math.round(bestSet.e1rm * 10) / 10,
|
|
292
|
+
bestSet: { weightKg: bestSet.weight, reps: bestSet.reps },
|
|
293
|
+
};
|
|
294
|
+
});
|
|
295
|
+
const allTime1RM = Math.max(...sessions.map((s) => s.estimated1RM));
|
|
296
|
+
const latest1RM = sessions[sessions.length - 1]?.estimated1RM || 0;
|
|
297
|
+
const earliest1RM = sessions[0]?.estimated1RM || 0;
|
|
298
|
+
return {
|
|
299
|
+
sessionCount: sessions.length,
|
|
300
|
+
sessions,
|
|
301
|
+
allTimeBestE1RM: allTime1RM,
|
|
302
|
+
progressionKg: Math.round((latest1RM - earliest1RM) * 10) / 10,
|
|
303
|
+
trend: latest1RM > earliest1RM ? "improving" : latest1RM === earliest1RM ? "plateau" : "declining",
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
//# sourceMappingURL=coaching.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coaching.js","sourceRoot":"","sources":["../../src/tools/coaching.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exercises.d.ts","sourceRoot":"","sources":["../../src/tools/exercises.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAG1D,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,QAgG1E"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { jsonResponse, textResponse, errorResponse, getErrorMessage } from "../utils/response.js";
|
|
3
|
+
export function registerExerciseTools(server, client) {
|
|
4
|
+
server.registerTool("get-exercise-templates", {
|
|
5
|
+
description: "Browse the exercise library. Returns exercise names, muscle groups, equipment, and IDs. Use pageSize up to 100 to search broadly.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
page: z.coerce.number().int().gte(1).default(1),
|
|
8
|
+
pageSize: z.coerce.number().int().gte(1).lte(100).default(100),
|
|
9
|
+
},
|
|
10
|
+
}, async ({ page, pageSize }) => {
|
|
11
|
+
try {
|
|
12
|
+
const result = await client.getExerciseTemplates(page, pageSize);
|
|
13
|
+
if (!result.exercise_templates.length)
|
|
14
|
+
return textResponse("No exercise templates found.");
|
|
15
|
+
return jsonResponse(result);
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
return errorResponse(getErrorMessage(error));
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
server.registerTool("get-exercise-template", {
|
|
22
|
+
description: "Get details of a specific exercise by ID — name, muscle groups, equipment type.",
|
|
23
|
+
inputSchema: {
|
|
24
|
+
exerciseTemplateId: z.string().min(1),
|
|
25
|
+
},
|
|
26
|
+
}, async ({ exerciseTemplateId }) => {
|
|
27
|
+
try {
|
|
28
|
+
const template = await client.getExerciseTemplate(exerciseTemplateId);
|
|
29
|
+
if (!template)
|
|
30
|
+
return textResponse("Exercise template not found.");
|
|
31
|
+
return jsonResponse(template);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
return errorResponse(getErrorMessage(error));
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
server.registerTool("get-exercise-history", {
|
|
38
|
+
description: "Get the user's performance history for a specific exercise. Shows past sets, weights, reps, and RPE over time. Filter by date range.",
|
|
39
|
+
inputSchema: {
|
|
40
|
+
exerciseTemplateId: z.string().min(1),
|
|
41
|
+
page: z.coerce.number().int().gte(1).default(1),
|
|
42
|
+
pageSize: z.coerce.number().int().gte(1).lte(10).default(5),
|
|
43
|
+
},
|
|
44
|
+
}, async ({ exerciseTemplateId, page, pageSize }) => {
|
|
45
|
+
try {
|
|
46
|
+
const history = await client.getExerciseHistory(exerciseTemplateId, page, pageSize);
|
|
47
|
+
return jsonResponse(history);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
return errorResponse(getErrorMessage(error));
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
server.registerTool("create-exercise-template", {
|
|
54
|
+
description: "Create a custom exercise in the user's Hevy library.",
|
|
55
|
+
inputSchema: {
|
|
56
|
+
title: z.string().min(1),
|
|
57
|
+
type: z.enum([
|
|
58
|
+
"weight_reps",
|
|
59
|
+
"reps_only",
|
|
60
|
+
"duration",
|
|
61
|
+
"weight_duration",
|
|
62
|
+
"distance_duration",
|
|
63
|
+
"weight_distance",
|
|
64
|
+
"distance_reps",
|
|
65
|
+
"weight_reps_duration",
|
|
66
|
+
]),
|
|
67
|
+
primary_muscle_group: z.string().min(1),
|
|
68
|
+
secondary_muscle_groups: z.array(z.string()).optional(),
|
|
69
|
+
equipment: z.string().optional(),
|
|
70
|
+
},
|
|
71
|
+
}, async ({ title, type, primary_muscle_group, secondary_muscle_groups, equipment }) => {
|
|
72
|
+
try {
|
|
73
|
+
const template = await client.createExerciseTemplate({
|
|
74
|
+
title,
|
|
75
|
+
type,
|
|
76
|
+
primary_muscle_group,
|
|
77
|
+
secondary_muscle_groups,
|
|
78
|
+
equipment,
|
|
79
|
+
});
|
|
80
|
+
return jsonResponse(template);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
return errorResponse(getErrorMessage(error));
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=exercises.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exercises.js","sourceRoot":"","sources":["../../src/tools/exercises.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routines.d.ts","sourceRoot":"","sources":["../../src/tools/routines.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAmB1D,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,QAiIzE"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { jsonResponse, textResponse, errorResponse, getErrorMessage } from "../utils/response.js";
|
|
3
|
+
const setSchema = z.object({
|
|
4
|
+
type: z.enum(["warmup", "normal", "failure", "dropset"]).default("normal"),
|
|
5
|
+
weight_kg: z.coerce.number().nullable().optional(),
|
|
6
|
+
reps: z.coerce.number().int().nullable().optional(),
|
|
7
|
+
distance_meters: z.coerce.number().int().nullable().optional(),
|
|
8
|
+
duration_seconds: z.coerce.number().int().nullable().optional(),
|
|
9
|
+
rpe: z.coerce.number().nullable().optional(),
|
|
10
|
+
});
|
|
11
|
+
const exerciseSchema = z.object({
|
|
12
|
+
exercise_template_id: z.string().min(1),
|
|
13
|
+
superset_id: z.coerce.number().nullable().optional(),
|
|
14
|
+
notes: z.string().optional(),
|
|
15
|
+
sets: z.array(setSchema),
|
|
16
|
+
});
|
|
17
|
+
export function registerRoutineTools(server, client) {
|
|
18
|
+
server.registerTool("get-routines", {
|
|
19
|
+
description: "Get a paginated list of saved workout routines.",
|
|
20
|
+
inputSchema: {
|
|
21
|
+
page: z.coerce.number().int().gte(1).default(1),
|
|
22
|
+
pageSize: z.coerce.number().int().gte(1).lte(10).default(5),
|
|
23
|
+
},
|
|
24
|
+
}, async ({ page, pageSize }) => {
|
|
25
|
+
try {
|
|
26
|
+
const result = await client.getRoutines(page, pageSize);
|
|
27
|
+
if (!result.routines.length)
|
|
28
|
+
return textResponse("No routines found.");
|
|
29
|
+
return jsonResponse(result);
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
return errorResponse(getErrorMessage(error));
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
server.registerTool("get-routine", {
|
|
36
|
+
description: "Get a specific routine by ID with all exercises and sets.",
|
|
37
|
+
inputSchema: {
|
|
38
|
+
routineId: z.string().min(1),
|
|
39
|
+
},
|
|
40
|
+
}, async ({ routineId }) => {
|
|
41
|
+
try {
|
|
42
|
+
const routine = await client.getRoutine(routineId);
|
|
43
|
+
if (!routine)
|
|
44
|
+
return textResponse("Routine not found.");
|
|
45
|
+
return jsonResponse(routine);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
return errorResponse(getErrorMessage(error));
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
server.registerTool("create-routine", {
|
|
52
|
+
description: "Create a new workout routine in Hevy. Provide title, optional folder ID, and exercises with sets (weight, reps, RPE targets).",
|
|
53
|
+
inputSchema: {
|
|
54
|
+
title: z.string().min(1),
|
|
55
|
+
folderId: z.coerce.number().optional(),
|
|
56
|
+
notes: z.string().optional(),
|
|
57
|
+
exercises: z.array(exerciseSchema),
|
|
58
|
+
},
|
|
59
|
+
}, async ({ title, folderId, notes, exercises }) => {
|
|
60
|
+
try {
|
|
61
|
+
const routine = await client.createRoutine({
|
|
62
|
+
title,
|
|
63
|
+
folder_id: folderId,
|
|
64
|
+
notes,
|
|
65
|
+
exercises,
|
|
66
|
+
});
|
|
67
|
+
return jsonResponse(routine);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
return errorResponse(getErrorMessage(error));
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
server.registerTool("update-routine", {
|
|
74
|
+
description: "Update an existing routine by ID. Replaces all exercises and sets.",
|
|
75
|
+
inputSchema: {
|
|
76
|
+
routineId: z.string().min(1),
|
|
77
|
+
title: z.string().min(1),
|
|
78
|
+
folderId: z.coerce.number().optional(),
|
|
79
|
+
notes: z.string().optional(),
|
|
80
|
+
exercises: z.array(exerciseSchema),
|
|
81
|
+
},
|
|
82
|
+
}, async ({ routineId, title, folderId, notes, exercises }) => {
|
|
83
|
+
try {
|
|
84
|
+
const routine = await client.updateRoutine(routineId, {
|
|
85
|
+
title,
|
|
86
|
+
folder_id: folderId,
|
|
87
|
+
notes,
|
|
88
|
+
exercises,
|
|
89
|
+
});
|
|
90
|
+
return jsonResponse(routine);
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
return errorResponse(getErrorMessage(error));
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
server.registerTool("create-routine-folder", {
|
|
97
|
+
description: "Create a folder to organize routines (e.g., by mesocycle or training phase).",
|
|
98
|
+
inputSchema: {
|
|
99
|
+
title: z.string().min(1),
|
|
100
|
+
},
|
|
101
|
+
}, async ({ title }) => {
|
|
102
|
+
try {
|
|
103
|
+
const folder = await client.createRoutineFolder(title);
|
|
104
|
+
return jsonResponse(folder);
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
return errorResponse(getErrorMessage(error));
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
server.registerTool("get-routine-folders", {
|
|
111
|
+
description: "List all routine folders.",
|
|
112
|
+
inputSchema: {
|
|
113
|
+
page: z.coerce.number().int().gte(1).default(1),
|
|
114
|
+
pageSize: z.coerce.number().int().gte(1).lte(10).default(5),
|
|
115
|
+
},
|
|
116
|
+
}, async ({ page, pageSize }) => {
|
|
117
|
+
try {
|
|
118
|
+
const result = await client.getRoutineFolders(page, pageSize);
|
|
119
|
+
return jsonResponse(result);
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
return errorResponse(getErrorMessage(error));
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=routines.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routines.js","sourceRoot":"","sources":["../../src/tools/routines.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workouts.d.ts","sourceRoot":"","sources":["../../src/tools/workouts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAG1D,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,QA2EzE"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { jsonResponse, textResponse, errorResponse, getErrorMessage } from "../utils/response.js";
|
|
3
|
+
export function registerWorkoutTools(server, client) {
|
|
4
|
+
server.registerTool("get-workouts", {
|
|
5
|
+
description: "Get a paginated list of workouts, newest first. Includes exercises, sets, weights, reps, and RPE.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
page: z.coerce.number().int().gte(1).default(1),
|
|
8
|
+
pageSize: z.coerce.number().int().gte(1).lte(10).default(5),
|
|
9
|
+
},
|
|
10
|
+
}, async ({ page, pageSize }) => {
|
|
11
|
+
try {
|
|
12
|
+
const result = await client.getWorkouts(page, pageSize);
|
|
13
|
+
if (!result.workouts.length)
|
|
14
|
+
return textResponse("No workouts found.");
|
|
15
|
+
return jsonResponse(result);
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
return errorResponse(getErrorMessage(error));
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
server.registerTool("get-workout", {
|
|
22
|
+
description: "Get complete details of a specific workout by ID.",
|
|
23
|
+
inputSchema: {
|
|
24
|
+
workoutId: z.string().min(1),
|
|
25
|
+
},
|
|
26
|
+
}, async ({ workoutId }) => {
|
|
27
|
+
try {
|
|
28
|
+
const workout = await client.getWorkout(workoutId);
|
|
29
|
+
if (!workout)
|
|
30
|
+
return textResponse("Workout not found.");
|
|
31
|
+
return jsonResponse(workout);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
return errorResponse(getErrorMessage(error));
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
server.registerTool("get-workout-count", {
|
|
38
|
+
description: "Get total number of logged workouts.",
|
|
39
|
+
inputSchema: {},
|
|
40
|
+
}, async () => {
|
|
41
|
+
try {
|
|
42
|
+
const count = await client.getWorkoutCount();
|
|
43
|
+
return jsonResponse({ workout_count: count });
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
return errorResponse(getErrorMessage(error));
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
server.registerTool("get-workout-events", {
|
|
50
|
+
description: "Get workout events (creates/updates/deletes) since a given date. For syncing and tracking changes.",
|
|
51
|
+
inputSchema: {
|
|
52
|
+
page: z.coerce.number().int().gte(1).default(1),
|
|
53
|
+
pageSize: z.coerce.number().int().gte(1).lte(10).default(5),
|
|
54
|
+
since: z.string().default("1970-01-01T00:00:00Z"),
|
|
55
|
+
},
|
|
56
|
+
}, async ({ page, pageSize, since }) => {
|
|
57
|
+
try {
|
|
58
|
+
const events = await client.getWorkoutEvents(page, pageSize, since);
|
|
59
|
+
return jsonResponse(events);
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
return errorResponse(getErrorMessage(error));
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=workouts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workouts.js","sourceRoot":"","sources":["../../src/tools/workouts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAElG,MAAM,UAAU,oBAAoB,CAAC,MAAiB,EAAE,MAAkB;IACxE,MAAM,CAAC,YAAY,CACjB,cAAc,EACd;QACE,WAAW,EAAE,mGAAmG;QAChH,WAAW,EAAE;YACX,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;YAC/C,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;SAC5D;KACF,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC3B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YACxD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM;gBAAE,OAAO,YAAY,CAAC,oBAAoB,CAAC,CAAC;YACvE,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,aAAa,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,aAAa,EACb;QACE,WAAW,EAAE,mDAAmD;QAChE,WAAW,EAAE;YACX,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;SAC7B;KACF,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE;QACtB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;YACnD,IAAI,CAAC,OAAO;gBAAE,OAAO,YAAY,CAAC,oBAAoB,CAAC,CAAC;YACxD,OAAO,YAAY,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,aAAa,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,mBAAmB,EACnB;QACE,WAAW,EAAE,sCAAsC;QACnD,WAAW,EAAE,EAAE;KAChB,EACD,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,eAAe,EAAE,CAAC;YAC7C,OAAO,YAAY,CAAC,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC;QAChD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,aAAa,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,oBAAoB,EACpB;QACE,WAAW,EAAE,oGAAoG;QACjH,WAAW,EAAE;YACX,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;YAC/C,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;YAC3D,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,sBAAsB,CAAC;SAClD;KACF,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE;QAClC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;YACpE,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,aAAa,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
export interface HevySet {
|
|
2
|
+
index: number;
|
|
3
|
+
type: "warmup" | "normal" | "failure" | "dropset";
|
|
4
|
+
weight_kg: number | null;
|
|
5
|
+
reps: number | null;
|
|
6
|
+
distance_meters: number | null;
|
|
7
|
+
duration_seconds: number | null;
|
|
8
|
+
rpe: number | null;
|
|
9
|
+
custom_metric: number | null;
|
|
10
|
+
}
|
|
11
|
+
export interface HevyExercise {
|
|
12
|
+
index: number;
|
|
13
|
+
title: string;
|
|
14
|
+
exercise_template_id: string;
|
|
15
|
+
superset_id: number | null;
|
|
16
|
+
notes: string | null;
|
|
17
|
+
sets: HevySet[];
|
|
18
|
+
}
|
|
19
|
+
export interface HevyWorkout {
|
|
20
|
+
id: string;
|
|
21
|
+
title: string;
|
|
22
|
+
description: string | null;
|
|
23
|
+
start_time: string;
|
|
24
|
+
end_time: string;
|
|
25
|
+
is_private: boolean;
|
|
26
|
+
exercises: HevyExercise[];
|
|
27
|
+
created_at: string;
|
|
28
|
+
updated_at: string;
|
|
29
|
+
}
|
|
30
|
+
export interface HevyRoutine {
|
|
31
|
+
id: string;
|
|
32
|
+
title: string;
|
|
33
|
+
folder_id: number | null;
|
|
34
|
+
notes: string | null;
|
|
35
|
+
exercises: HevyExercise[];
|
|
36
|
+
created_at: string;
|
|
37
|
+
updated_at: string;
|
|
38
|
+
}
|
|
39
|
+
export interface HevyExerciseTemplate {
|
|
40
|
+
id: string;
|
|
41
|
+
title: string;
|
|
42
|
+
type: string;
|
|
43
|
+
primary_muscle_group: string;
|
|
44
|
+
secondary_muscle_groups: string[];
|
|
45
|
+
equipment: string;
|
|
46
|
+
is_custom: boolean;
|
|
47
|
+
}
|
|
48
|
+
export interface HevyWorkoutEvent {
|
|
49
|
+
id: string;
|
|
50
|
+
type: "created" | "updated" | "deleted";
|
|
51
|
+
workout: HevyWorkout | null;
|
|
52
|
+
occurred_at: string;
|
|
53
|
+
}
|
|
54
|
+
export interface HevyExerciseHistoryEntry {
|
|
55
|
+
workout_id: string;
|
|
56
|
+
start_time: string;
|
|
57
|
+
exercise_template_id: string;
|
|
58
|
+
sets: Array<{
|
|
59
|
+
type: string;
|
|
60
|
+
weight_kg: number | null;
|
|
61
|
+
reps: number | null;
|
|
62
|
+
rpe: number | null;
|
|
63
|
+
distance_meters: number | null;
|
|
64
|
+
duration_seconds: number | null;
|
|
65
|
+
}>;
|
|
66
|
+
}
|
|
67
|
+
export interface HevyRoutineFolder {
|
|
68
|
+
id: number;
|
|
69
|
+
title: string;
|
|
70
|
+
created_at: string;
|
|
71
|
+
updated_at: string;
|
|
72
|
+
}
|
|
73
|
+
export interface RoutineSetInput {
|
|
74
|
+
type?: string;
|
|
75
|
+
weight_kg?: number | null;
|
|
76
|
+
reps?: number | null;
|
|
77
|
+
distance_meters?: number | null;
|
|
78
|
+
duration_seconds?: number | null;
|
|
79
|
+
rpe?: number | null;
|
|
80
|
+
}
|
|
81
|
+
export interface RoutineExerciseInput {
|
|
82
|
+
exercise_template_id: string;
|
|
83
|
+
superset_id?: number | null;
|
|
84
|
+
notes?: string;
|
|
85
|
+
sets: RoutineSetInput[];
|
|
86
|
+
}
|
|
87
|
+
export interface RoutineInput {
|
|
88
|
+
title: string;
|
|
89
|
+
folder_id?: number;
|
|
90
|
+
notes?: string;
|
|
91
|
+
exercises: RoutineExerciseInput[];
|
|
92
|
+
}
|
|
93
|
+
export declare class HevyClient {
|
|
94
|
+
private client;
|
|
95
|
+
constructor(apiKey: string);
|
|
96
|
+
getWorkouts(page?: number, pageSize?: number): Promise<{
|
|
97
|
+
workouts: HevyWorkout[];
|
|
98
|
+
page_count: number;
|
|
99
|
+
}>;
|
|
100
|
+
getWorkout(workoutId: string): Promise<HevyWorkout | null>;
|
|
101
|
+
getWorkoutCount(): Promise<number>;
|
|
102
|
+
getWorkoutEvents(page?: number, pageSize?: number, since?: string): Promise<{
|
|
103
|
+
events: HevyWorkoutEvent[];
|
|
104
|
+
page_count: number;
|
|
105
|
+
}>;
|
|
106
|
+
getRoutines(page?: number, pageSize?: number): Promise<{
|
|
107
|
+
routines: HevyRoutine[];
|
|
108
|
+
page_count: number;
|
|
109
|
+
}>;
|
|
110
|
+
getRoutine(routineId: string): Promise<HevyRoutine | null>;
|
|
111
|
+
createRoutine(routine: RoutineInput): Promise<HevyRoutine>;
|
|
112
|
+
updateRoutine(routineId: string, routine: RoutineInput): Promise<HevyRoutine>;
|
|
113
|
+
getExerciseTemplates(page?: number, pageSize?: number): Promise<{
|
|
114
|
+
exercise_templates: HevyExerciseTemplate[];
|
|
115
|
+
page_count: number;
|
|
116
|
+
}>;
|
|
117
|
+
getExerciseTemplate(templateId: string): Promise<HevyExerciseTemplate | null>;
|
|
118
|
+
getExerciseHistory(templateId: string, page?: number, pageSize?: number): Promise<{
|
|
119
|
+
exercise_history: HevyExerciseHistoryEntry[];
|
|
120
|
+
page_count: number;
|
|
121
|
+
}>;
|
|
122
|
+
createExerciseTemplate(template: {
|
|
123
|
+
title: string;
|
|
124
|
+
type: string;
|
|
125
|
+
primary_muscle_group: string;
|
|
126
|
+
secondary_muscle_groups?: string[];
|
|
127
|
+
equipment?: string;
|
|
128
|
+
}): Promise<HevyExerciseTemplate>;
|
|
129
|
+
getRoutineFolders(page?: number, pageSize?: number): Promise<{
|
|
130
|
+
routine_folders: HevyRoutineFolder[];
|
|
131
|
+
page_count: number;
|
|
132
|
+
}>;
|
|
133
|
+
createRoutineFolder(title: string): Promise<HevyRoutineFolder>;
|
|
134
|
+
private formatRoutineBody;
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=hevy-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hevy-client.d.ts","sourceRoot":"","sources":["../../src/utils/hevy-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
const HEVY_API_BASE = "https://api.hevyapp.com/v1";
|
|
3
|
+
// --- Client ---
|
|
4
|
+
export class HevyClient {
|
|
5
|
+
client;
|
|
6
|
+
constructor(apiKey) {
|
|
7
|
+
this.client = axios.create({
|
|
8
|
+
baseURL: HEVY_API_BASE,
|
|
9
|
+
headers: {
|
|
10
|
+
"api-key": apiKey,
|
|
11
|
+
"Content-Type": "application/json",
|
|
12
|
+
Accept: "application/json",
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
// --- Workouts ---
|
|
17
|
+
async getWorkouts(page = 1, pageSize = 5) {
|
|
18
|
+
const { data } = await this.client.get("/workouts", { params: { page, pageSize } });
|
|
19
|
+
return { workouts: data.workouts ?? [], page_count: data.page_count ?? 1 };
|
|
20
|
+
}
|
|
21
|
+
async getWorkout(workoutId) {
|
|
22
|
+
const { data } = await this.client.get(`/workouts/${workoutId}`);
|
|
23
|
+
return data.workout ?? null;
|
|
24
|
+
}
|
|
25
|
+
async getWorkoutCount() {
|
|
26
|
+
const { data } = await this.client.get("/workouts/count");
|
|
27
|
+
return data.workout_count ?? 0;
|
|
28
|
+
}
|
|
29
|
+
async getWorkoutEvents(page = 1, pageSize = 5, since = "1970-01-01T00:00:00Z") {
|
|
30
|
+
const { data } = await this.client.get("/workouts/events", { params: { page, pageSize, since } });
|
|
31
|
+
return { events: data.events ?? [], page_count: data.page_count ?? 1 };
|
|
32
|
+
}
|
|
33
|
+
// --- Routines ---
|
|
34
|
+
async getRoutines(page = 1, pageSize = 5) {
|
|
35
|
+
const { data } = await this.client.get("/routines", { params: { page, pageSize } });
|
|
36
|
+
return { routines: data.routines ?? [], page_count: data.page_count ?? 1 };
|
|
37
|
+
}
|
|
38
|
+
async getRoutine(routineId) {
|
|
39
|
+
const { data } = await this.client.get(`/routines/${routineId}`);
|
|
40
|
+
return data.routine ?? null;
|
|
41
|
+
}
|
|
42
|
+
async createRoutine(routine) {
|
|
43
|
+
const { data } = await this.client.post("/routines", { routine: this.formatRoutineBody(routine) });
|
|
44
|
+
return data.routine;
|
|
45
|
+
}
|
|
46
|
+
async updateRoutine(routineId, routine) {
|
|
47
|
+
const { data } = await this.client.put(`/routines/${routineId}`, { routine: this.formatRoutineBody(routine) });
|
|
48
|
+
return data.routine;
|
|
49
|
+
}
|
|
50
|
+
// --- Exercise Templates ---
|
|
51
|
+
async getExerciseTemplates(page = 1, pageSize = 100) {
|
|
52
|
+
const { data } = await this.client.get("/exercise_templates", { params: { page, pageSize } });
|
|
53
|
+
return { exercise_templates: data.exercise_templates ?? [], page_count: data.page_count ?? 1 };
|
|
54
|
+
}
|
|
55
|
+
async getExerciseTemplate(templateId) {
|
|
56
|
+
const { data } = await this.client.get(`/exercise_templates/${templateId}`);
|
|
57
|
+
return data.exercise_template ?? null;
|
|
58
|
+
}
|
|
59
|
+
async getExerciseHistory(templateId, page = 1, pageSize = 5) {
|
|
60
|
+
const { data } = await this.client.get(`/exercise_templates/${templateId}/history`, { params: { page, pageSize } });
|
|
61
|
+
return { exercise_history: data.exercise_history ?? [], page_count: data.page_count ?? 1 };
|
|
62
|
+
}
|
|
63
|
+
async createExerciseTemplate(template) {
|
|
64
|
+
const { data } = await this.client.post("/exercise_templates", { exercise_template: template });
|
|
65
|
+
return data.exercise_template;
|
|
66
|
+
}
|
|
67
|
+
// --- Routine Folders ---
|
|
68
|
+
async getRoutineFolders(page = 1, pageSize = 5) {
|
|
69
|
+
const { data } = await this.client.get("/routine_folders", { params: { page, pageSize } });
|
|
70
|
+
return { routine_folders: data.routine_folders ?? [], page_count: data.page_count ?? 1 };
|
|
71
|
+
}
|
|
72
|
+
async createRoutineFolder(title) {
|
|
73
|
+
const { data } = await this.client.post("/routine_folders", { routine_folder: { title } });
|
|
74
|
+
return data.routine_folder;
|
|
75
|
+
}
|
|
76
|
+
// --- Private ---
|
|
77
|
+
formatRoutineBody(routine) {
|
|
78
|
+
return {
|
|
79
|
+
...routine,
|
|
80
|
+
exercises: routine.exercises.map((ex, i) => ({
|
|
81
|
+
...ex,
|
|
82
|
+
index: i,
|
|
83
|
+
sets: ex.sets.map((s, j) => ({ ...s, index: j, type: s.type ?? "normal" })),
|
|
84
|
+
})),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=hevy-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hevy-client.js","sourceRoot":"","sources":["../../src/utils/hevy-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare function jsonResponse(data: unknown): {
|
|
2
|
+
content: {
|
|
3
|
+
type: "text";
|
|
4
|
+
text: string;
|
|
5
|
+
}[];
|
|
6
|
+
};
|
|
7
|
+
export declare function textResponse(text: string): {
|
|
8
|
+
content: {
|
|
9
|
+
type: "text";
|
|
10
|
+
text: string;
|
|
11
|
+
}[];
|
|
12
|
+
};
|
|
13
|
+
export declare function errorResponse(message: string): {
|
|
14
|
+
content: {
|
|
15
|
+
type: "text";
|
|
16
|
+
text: string;
|
|
17
|
+
}[];
|
|
18
|
+
isError: boolean;
|
|
19
|
+
};
|
|
20
|
+
export declare function getErrorMessage(error: unknown): string;
|
|
21
|
+
//# sourceMappingURL=response.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response.d.ts","sourceRoot":"","sources":["../../src/utils/response.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO;;;;;EAIzC;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM;;;;;EAIxC;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM;;;;;;EAK5C;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAGtD"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function jsonResponse(data) {
|
|
2
|
+
return {
|
|
3
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
4
|
+
};
|
|
5
|
+
}
|
|
6
|
+
export function textResponse(text) {
|
|
7
|
+
return {
|
|
8
|
+
content: [{ type: "text", text }],
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export function errorResponse(message) {
|
|
12
|
+
return {
|
|
13
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
14
|
+
isError: true,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export function getErrorMessage(error) {
|
|
18
|
+
if (error instanceof Error)
|
|
19
|
+
return error.message;
|
|
20
|
+
return String(error);
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=response.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response.js","sourceRoot":"","sources":["../../src/utils/response.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY,CAAC,IAAa;IACxC,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;KAC1E,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC;KAC3C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,OAAO,EAAE,EAAE,CAAC;QAC/D,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,IAAI,KAAK,YAAY,KAAK;QAAE,OAAO,KAAK,CAAC,OAAO,CAAC;IACjD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "hevy-coach",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "AI Personal Training MCP Server — turns Claude into your strength, conditioning, mobility, and longevity coach via Hevy",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"hevy-coach": "dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"docs",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc",
|
|
17
|
+
"dev": "tsx watch --env-file .env src/cli.ts",
|
|
18
|
+
"start": "node --env-file .env dist/cli.js",
|
|
19
|
+
"typecheck": "tsc --noEmit",
|
|
20
|
+
"lint": "biome check src/",
|
|
21
|
+
"test": "vitest --run"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"mcp",
|
|
25
|
+
"hevy",
|
|
26
|
+
"fitness",
|
|
27
|
+
"personal-trainer",
|
|
28
|
+
"ai-coaching",
|
|
29
|
+
"workout",
|
|
30
|
+
"strength",
|
|
31
|
+
"conditioning",
|
|
32
|
+
"mobility"
|
|
33
|
+
],
|
|
34
|
+
"author": "Furkan Tanyol",
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "git+https://github.com/AugmentedMind/hevy-coach.git"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@modelcontextprotocol/sdk": "^1.27.0",
|
|
42
|
+
"axios": "^1.13.5",
|
|
43
|
+
"zod": "^3.23.0"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/node": "^22.19.13",
|
|
47
|
+
"tsx": "^4.21.0",
|
|
48
|
+
"typescript": "^5.7.0",
|
|
49
|
+
"vitest": "^2.0.0"
|
|
50
|
+
},
|
|
51
|
+
"engines": {
|
|
52
|
+
"node": ">=20.0.0"
|
|
53
|
+
}
|
|
54
|
+
}
|