aimharder-mcp
# aimharder-mcp
An [MCP server](https://modelcontextprotocol.io/) for AimHarder, run locally for one account or deployed as your own remote connector for Claude and ChatGPT, shared with the friends you invite. Ask an AI client about classes and who is attending them, published workouts, bookings, personal activity and RMs. It can also make and cancel bookings, and save or delete strength results (PRs), always after your explicit confirmation.
It is an independent project, neither affiliated with nor endorsed by AimHarder. It talks to AimHarder's own web and mobile-app APIs, which are undocumented and can change without notice. See [docs/aimharder-api.md](docs/aimharder-api.md).
## Get started
1. Install Node.js **24 or newer**.
2. Build the server:
```sh
npm ci --ignore-scripts
npm run build
```
3. Put your settings in a private environment file outside the repository (`chmod 600`). [`.env.example`](.env.example) lists every option:
```dotenv
AIMHARDER_USERNAME=you@example.com
AIMHARDER_PASSWORD=your-password
AIMHARDER_TIME_ZONE=Europe/Madrid
AIMHARDER_BOOKING_WINDOW_DAYS=7
AIMHARDER_WORKOUT_CLASS=CROSS
```
4. Add the server to your MCP client as a stdio command, for example in Claude Desktop:
```json
{
"mcpServers": {
"aimharder": {
"command": "node",
"args": ["--env-file=/absolute/path/to/aimharder.env", "/absolute/path/to/aimharder-mcp/dist/index.js"]
}
}
}
```
The first tool call signs in. Use `get_account_context` to see your gym and its time zone. An account with several gyms also sets `AIMHARDER_GYM`. See [configuration](docs/configuration.md) for details.
## Use it from Claude or ChatGPT on the web and mobile
**New to this?** Follow the [step-by-step setup guide](docs/setup-guide.md): no programming knowledge needed.
Deploy your own instance (the [Dockerfile](Dockerfile) works on Fly.io and similar platforms with a persistent volume, or on your computer behind a tunnel) with `MCP_TRANSPORT=http`, `MCP_PUBLIC_URL` and an `MCP_OWNER_SECRET`. Then add `https://<your-host>/mcp` as a [custom connector in Claude](docs/setup-guide.md#step-10-connect-claude) or a [personal plugin in ChatGPT](docs/setup-guide.md#step-11-connect-chatgpt-optional), and approve it by signing in with your AimHarder account. Invite friends from the server's `/admin` page: each joins with their own AimHarder account, and everyone edits their weekly plan, workout class and friends at `/settings`, where they can also create a private calendar link to subscribe to their upcoming bookings. See [remote use](docs/remote.md).
## Tools
| Tool | Example question |
| --- | --- |
| `get_account_context` | Which gyms can I query? |
| `get_class_sessions` | Which CROSS classes are there this week, and when does booking open? |
| `get_class_participants` | Who is coming to today's 14:00 CROSS? Which of my friends? |
| `prepare_booking_creation` / `execute_booking_creation` | Book next Monday's 14:00 CROSS. |
| `prepare_planned_bookings` | Book my usual classes next week. |
| `prepare_booking_cancellation` / `execute_booking_cancellation` | Cancel Wednesday's class. |
| `execute_late_booking_cancellation` | Cancel inside the late window, accepting a possible credit loss. |
| `get_upcoming_bookings` / `get_booking_history` | When am I booked? Which classes did I attend? |
| `get_published_workouts` | What is today's WOD? And the HYROX one? |
| `get_published_workouts_range` | Summarize this week's CROSS workouts. |
| `get_personal_activity` | What did I record this month? |
| `get_exercise_1rm` / `find_exercise_1rm` / `get_exercise_rm_progression` | What is my Back Squat 1RM, and how has it progressed? |
| `prepare_exercise_result` / `execute_exercise_result` | Save 5 × 5 Back Squat at 90 kg today. |
| `prepare_exercise_result_deletion` / `execute_exercise_result_deletion` | Delete that result. |
Every write is a two-step flow: a read-only preview with a two-minute, single-use reference, then one confirmed request that is never retried automatically, followed by a fresh read to confirm the outcome. Details are in [tools](docs/tools.md).
## Development
```sh
npm run check # typecheck, tests and build
```
Tests run against simulated AimHarder responses (msw), never the real service. Contributor notes are in [AGENTS.md](AGENTS.md).
## License
[MIT](LICENSE).
TDQS
Scored across 21 tools
Prepare/execute pairs are explicitly paired and each targets a distinct action (create, cancel, late cancel, save result, delete result), so boundaries are mostly clear. The riskiest overlaps are the read-side trio of get_upcoming_bookings / get_booking_history / get_personal_activity and the 1RM trio (get_exercise_1rm / find_exercise_1rm / get_exercise_rm_progression), which descriptions do distinguish but an agent could still misselect.
All names use snake_case with a predictable verb-first pattern (get_/find_/prepare_/execute_) plus a resource noun, with suffixes like _range for variants. Minor deviation is that prepare_* tools are actually read-only previews while get_* is used for other reads, so the verb doesn't perfectly signal read vs. stage.
21 tools is on the heavy side for a single gym-app integration, inflated by four prepare/execute safety pairs (bookings, cancellation, exercise results, deletion). The domain is broad enough (sessions, booking, workouts, 1RM, activity) that most tools earn their place, but it sits at the borderline of heavy.
Booking lifecycle, cancellation with late-cancellation credit handling, schedules, participants, published workouts, 1RM data, and personal activity are all covered with both preview and execution paths. Gaps are minor: no waitlist join/leave despite waitlisted states being reported, and no way to edit the booking plan or preferences (only read via get_account_context).