technogym-mcp
technogym-mcp
An MCP server that gives AI assistants read access to your Technogym mywellness training history: workout sessions, per-exercise data with per-set reps / weight / rest, per-second exercise analytics (machine channels + heart rate) and whole-session heart-rate traces.
It runs as a persistent local HTTP server that starts with Windows, so every MCP client on the machine (Claude Desktop, Claude Code, Cursor, ...) can connect to the same endpoint.
How it works / caveat. Technogym's official API is partner-only (B2B). This server speaks the same JSON API the official end-user web app (endusernext.mywellness.com) uses, logging in with your normal email + password and identifying itself with that app's client headers. No HTML scraping is involved, but it will still break if Technogym changes the login flow or the client-trust rules. The old
mywellness.com/cloudportal that earlier tools (e.g. lcanis/gymexport) scraped was retired in 2026 and now redirects to technogym.com.
Tools
Tool | What it returns |
| Logs in and returns user id, name, culture, facilities and current Movergy score. Use to verify credentials. |
| Sessions in a range (default: last 30 days), newest first: |
| Every exercise with machine, status, duration, calories, MOVEs, muscles, performed and prescribed sets (reps, kg, rest), plus session efficacy and muscle scores. |
| Lists and fully loads all sessions from the last N days. |
| Per-second machine channels, HR samples, HR zones and summary metrics (total weight, est. 1RM, METs...) for one exercise. |
| Timestamped HR trace, HR zones and avg/min/max HR for a whole session. |
A session is addressed by session_id and its date (the API partitions by day). Pass the
date whenever you have it; if omitted, the last year of history is scanned to find it.
GET /health on the same port reports liveness and whether a session is authenticated.
Setup
Requires uv (it manages Python for you).
git clone https://github.com/ErikAnkerKilbergSkallevold/technogym_mcp
cd technogym_mcp
copy .env.example .env # then fill in MYWELLNESS_EMAIL / MYWELLNESS_PASSWORD
uv syncRun once (foreground)
uv run technogym-mcp # HTTP on http://127.0.0.1:8765/mcp
uv run technogym-mcp --transport stdio # for clients that spawn the server themselvesStart with Windows (always available)
powershell -ExecutionPolicy Bypass -File scripts\install-startup.ps1This registers a Scheduled Task named Technogym MCP Server that starts silently at logon
(via uvw.exe, no console window), restarts on failure, and never times out. Logs go to
logs\technogym-mcp.log. Remove it with scripts\uninstall-startup.ps1. After editing
.env, restart it: Restart-ScheduledTask "Technogym MCP Server".
Expose it publicly (Cloudflare Tunnel)
To reach the server from other machines or from a hosted Claude, tunnel it out through Cloudflare instead of opening a port. One-time prerequisites:
winget install Cloudflare.cloudflared
cloudflared tunnel login # browser: pick your zoneSet TECHNOGYM_MCP_PUBLIC_HOST=technogym.example.com in .env, restart the server task, then:
powershell -ExecutionPolicy Bypass -File scripts\install-tunnel.ps1 -Hostname technogym.example.comThis creates a named tunnel, routes the DNS record, and installs cloudflared as a Windows
service (it will ask for elevation once). The MCP endpoint is then https://technogym.example.com/mcp.
Alternatively, create the tunnel in the Zero Trust dashboard (Networks → Tunnels → Create,
choose Windows, run the provided cloudflared service install <token> command) and add a public
hostname there pointing at http://localhost:<port>. That also installs an auto-starting Windows
service; skip the script in that case, since it would create a second tunnel.
The MCP endpoint has no authentication of its own. Pick one of two ways to protect it:
Cloudflare Access (best when your clients can complete a browser login, e.g. Claude Code with
claude mcp add --transport http): add an Access application for the hostname (Zero Trust → Access → Applications → Self-hosted) with a policy that allows only your email.Unguessable path (needed for clients that cannot send auth headers or do a Cloudflare login, e.g. claude.ai custom connectors): set
TECHNOGYM_MCP_PATH=/<32 random hex>/mcpin.env, restart the server task, and treat the full URL as a secret. Requests to any other path get 404. Optionally still put Access on/healthand/.
Adding to claude.ai
Make sure the tunnel is up and
https://<host>/healthanswers.In claude.ai go to Settings → Connectors → Add custom connector.
Name it
Technogym, paste the full endpoint URL (https://<host><TECHNOGYM_MCP_PATH>), leave OAuth fields empty, and click Add.In a chat, open the tools menu (the sliders icon) and enable the Technogym connector.
Connecting a client
Claude Code
claude mcp add -s user --transport http technogym http://127.0.0.1:8765/mcpClaude Desktop (claude_desktop_config.json), either pointing at the running server:
{
"mcpServers": {
"technogym": { "type": "http", "url": "http://127.0.0.1:8765/mcp" }
}
}or spawning it over stdio:
{
"mcpServers": {
"technogym": {
"command": "uv",
"args": ["run", "--directory", "C:\\path\\to\\technogym_mcp", "technogym-mcp", "--transport", "stdio"]
}
}
}Configuration (.env)
Variable | Default | Purpose |
| Your mywellness login | |
| Your mywellness password | |
|
| Bind address. Keep on loopback; there is no auth on the MCP endpoint. |
|
| Port |
| Public hostname(s) accepted in the Host header, e.g. | |
|
| URL path of the MCP endpoint. Use an unguessable path when the endpoint must be reachable without auth headers (see claude.ai below). |
|
| Logging level |
API notes (for maintainers)
Login:
POST https://core.mywellness.com/v2/enduser/authentication/loginwith{username, password, keepMeLoggedIn}and headersX-MWAPPS-APPID: EC1D38D7-D359-48D0-A60C-D8C0B8FB9DF9,X-MWAPPS-CLIENT: enduserweb. Returnstoken,userContext.id,facilities[].url.Data:
POST https://services.mywellness.com/{facilityUrl}/Training/User/{userId}/<Action>withAuthorization: Bearer <token>and the same X-MWAPPS headers. Actions used:ActivityHistory,GetPerformedWorkoutSessionByIdCr,GetHrSession,MyMovergy; plusTraining/CardioLog/{analyticsId}/Details. Dates areyyyyMMddpartition keys.Localised strings (exercise names, units) come back in the account's culture.
Development
uv run pytest
uv run ruff check .License
MIT