mcp server
accountability-buddy
Self-hosted personal accountability assistant: chat with Claude Code over Telegram to log habits (Habitify), workouts (Hevy), and runs (Strava), with voice-note support.
Set up
Runs on your computer. Pick your agent and operating system.
This project does not publish an install method we can turn into a config. Follow the README instead.
README
synced Oct 23, 2026Accountability Buddy
An easily extendible personal accountability system that plugs into health, fitness and habit trackers.
Current integrations:
- Habitify — habit tracking (via custom MCP proxy with OAuth refresh)
- Hevy — workout tracking (via chrisdoc/hevy-mcp)
- Strava — running & cycling, read-only (via r-huijts/strava-mcp)
- Telegram — primary interface, including voice notes transcribed with OpenAI Whisper
Architecture
The system runs as a long-lived Claude Code instance with the Telegram channels plugin, acting as an always-on assistant you interact with via Telegram (text and voice notes).
You (Telegram) <-> Claude Code + Telegram plugin <-> MCP servers (Habitify, Hevy, Strava)
Deployment
This is not a bot you fire up on your laptop when you want it. To be useful, the assistant has to be reachable from Telegram whenever you message it — including when your computer is asleep or you're away from it. That means it should run on an always-on host.
Recommended: a remote, always-on machine.
- A small cloud VPS (e.g. DigitalOcean, Hetzner, Fly.io, an EC2 instance) or a home server / Raspberry Pi that stays powered on.
- The cheapest tier is plenty — this is a single Claude Code process talking to a few APIs, not a heavy workload.
- Run Claude Code inside a tmux session so it survives SSH disconnects and keeps running after you log out. You SSH in once to start it, then leave it running indefinitely; reattach only when you want to check on it or change config.
Why not just your own computer? You can run it locally to try it out, but the moment your laptop sleeps, loses network, or shuts down, the assistant goes offline and your Telegram messages won't be answered until it's back. An always-on host avoids that entirely.
The setup steps below work the same whether you're on a VPS or a local machine — the only difference is where you run them. If you're deploying for real, do the setup on your always-on host (over SSH). The Launch Claude Code step covers running it under tmux so it persists.
Setup
1. Prerequisites
- A Unix-like environment (Linux, macOS, or WSL on Windows) — the launcher scripts are bash, and the deployment assumes tmux. An always-on host (VPS, home server) is ideal so the assistant stays reachable.
- Claude Code CLI installed and authenticated
- The Telegram channels plugin installed and paired with your Telegram bot
- tmux
- Python 3.9+
- Node.js 22+ (system default), plus nvm if you want Hevy (needs Node 24+)
2. Clone and install Python dependencies
git clone https://github.com/acrdlph/accountability-buddy.git habit-tracking
cd habit-tracking
python3 -m venv .venv
.venv/bin/pip install "mcp[cli]>=1.27" httpx python-dotenv openai
All credentials live in .env (gitignored). Copy .env.example as a starting template.
Integrations below are independent — set up only the ones you want.
3. Habitify (habit tracking)
Uses a custom MCP proxy that handles OAuth refresh automatically.
Run the one-time OAuth setup:
.venv/bin/python habitify_oauth_setup.py
It prints an auth URL; open it in any browser, authorize, then paste the redirect URL back into the terminal. The script saves HABITIFY_CLIENT_ID and HABITIFY_REFRESH_TOKEN to .env.
4. Hevy (workout tracking)
Requires a Hevy PRO subscription (~$3/mo) to access the API.
-
Install Node 24 (hevy-mcp needs ≥24, but keep your system default untouched):
nvm install 24 nvm alias default 22hevy_launcher.shpicks up Node 24 automatically from~/.nvm/versions/node/v24.15.0/. -
Get an API key at https://hevy.com/settings?developer
-
Add to
.env:HEVY_API_KEY=<your-uuid>
5. Strava (running & cycling, read-only)
Strava is read-only — activities come from your watch/phone automatically, so the MCP server only reads them.
-
Create a Strava API app at https://www.strava.com/settings/api
- Set Authorization Callback Domain to
localhost - Upload any logo (required)
- Set Authorization Callback Domain to
-
Add the app credentials to
.env:STRAVA_CLIENT_ID=<number> STRAVA_CLIENT_SECRET=<hex> -
Run the one-time OAuth setup:
.venv/bin/python strava_oauth_setup.pySame flow as Habitify: open auth URL → authorize → paste redirect URL back. The script saves
STRAVA_ACCESS_TOKENandSTRAVA_REFRESH_TOKENto.env. The MCP server handles refresh automatically afterwards.
6. OpenAI (Whisper, for voice notes)
Add your API key to .env:
OPENAI_API_KEY=sk-...
This powers transcribe.py, which the assistant calls when a Telegram voice note arrives.
7. Register the MCP servers in ~/.mcp.json
Claude Code looks for MCP server definitions in ~/.mcp.json — in your home directory, not in this repo, since it's user-level config with machine-specific absolute paths.
Create or edit ~/.mcp.json (omit any servers you don't use):
{
"mcpServers": {
"habitify": {
"type": "stdio",
"command": "/ABSOLUTE/PATH/TO/habit-tracking/.venv/bin/python",
"args": ["/ABSOLUTE/PATH/TO/habit-tracking/habitify_proxy.py"]
},
"hevy": {
"type": "stdio",
"command": "/ABSOLUTE/PATH/TO/habit-tracking/hevy_launcher.sh"
},
"strava": {
"type": "stdio",
"command": "/ABSOLUTE/PATH/TO/habit-tracking/strava_launcher.sh"
}
}
}
Replace /ABSOLUTE/PATH/TO/habit-tracking with your actual clone path.
8. Launch Claude Code
tmux new -s buddy
cd /path/to/habit-tracking
claude --dangerously-skip-permissions --channels plugin:telegram@claude-plugins-official
To leave the assistant running, simply close the terminal window — the tmux session keeps going in the background (the usual Ctrl+B, D detach doesn't always punch through Claude Code's TUI). Reattach later with tmux attach -t buddy.
The --channels flag is required. Without it, Claude Code doesn't route inbound Telegram notifications into the session — you'll still be able to send replies, but user messages never arrive. If Telegram messages stop appearing in your session, this flag is almost always the cause.
The --dangerously-skip-permissions flag lets the assistant act autonomously on tool calls. Drop it if you want interactive approval, but expect the experience to be awkward on a headless server.
Customize for yourself
The assistant's behavior is split across two files:
CLAUDE.md(committed) — the generic rules: how each integration works, how to interpret messages, response style. You usually don't need to touch this.CLAUDE.local.md(gitignored) — your personal layer: your habit name mappings, workout rotation, diet preferences. Claude Code auto-loads it alongsideCLAUDE.md, and silently does nothing if it's absent.
To set up your personal layer, copy the worked example and edit it:
cp CLAUDE.local.md.example CLAUDE.local.md
CLAUDE.local.md.example contains the maintainer's real config as a starting point. Because CLAUDE.local.md is gitignored, your personal habits and preferences never get committed.
Your nutrition logs are similarly private: meal logs live in nutrition/ (gitignored). See docs/nutrition-example.md for the file format.
Files
| File | Purpose |
|---|---|
habitify_proxy.py | Habitify MCP proxy (stdio) with auto OAuth refresh |
habitify_oauth_setup.py | One-time Habitify OAuth PKCE setup |
hevy_launcher.sh | Wrapper that loads .env and runs hevy-mcp on Node 24 |
strava_launcher.sh | Wrapper that loads .env and runs strava-mcp via npx |
strava_oauth_setup.py | One-time Strava OAuth flow (obtains access + refresh tokens) |
transcribe.py | Voice note transcription via OpenAI Whisper |
CLAUDE.md | Generic assistant behavior rules (input parsing, cross-service logic, response style) |
CLAUDE.local.md.example | Worked example of the personal layer (habits, rotation, diet) — copy to CLAUDE.local.md |
.env | API keys and tokens (gitignored) |
.env.example | Template of the env vars required by the integrations |
.mcp.json.example | Template for ~/.mcp.json MCP server registration |
logos/ | Architecture visualization (flow_animation.html, preview.png, render scripts) |
docs/nutrition-example.md | Nutrition log file-format reference |
Troubleshooting
- Telegram messages aren't reaching the session — almost always means you launched
claudewithout--channels plugin:telegram@claude-plugins-official. Exit and relaunch with the flag. - Habitify auth failures — the refresh token probably expired. Re-run
.venv/bin/python habitify_oauth_setup.pyto get a fresh one. - Strava auth failures — re-run
.venv/bin/python strava_oauth_setup.py(only needed if the refresh token itself was invalidated; access tokens refresh automatically). npx -y hevy-mcpcomplains about Node version — make sure Node 24 is installed via nvm (nvm install 24); the launcher picks it up from~/.nvm/versions/node/v24.15.0/.
Roadmap
- Switch Strava to the official MCP server. Strava recently released a first-party MCP server, so we should migrate off the community r-huijts/strava-mcp integration once the official one is stable.
Feel free to open issues or PRs for new integrations.