Claude MCP tool that refuses to help you code until your webcam confirms you have a drink.
Devs skip meals when focused. A reminder that runs locally and won't shut up until you prove (via webcam) that you have water within arm's reach.
The tool: a background process watching your webcam for cups/bottles, and an MCP server that locks Claude until one is detected. YOLOv8 nano does the vision locally — no cloud, no machine learning infrastructure, just pattern matching against a 35MB model.
pip install -r requirements.txtThen configure your Claude Desktop settings file to point at mcp_server.py:
Mac: ~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"hydration_hostage": {
"command": "python",
"args": ["/absolute/path/to/hydration-hostage/mcp_server.py"]
}
}
}(Use pwd in the hydration-hostage directory to get the absolute path.)
Terminal 1:
python watcher.pyYou should see:
Starting hydration watcher (interval: 1800s, camera: 0)
✗ No water detected. You are dehydrated.
Restart Claude Desktop. Then in Claude, ask it for help with code, and it will check your status first.
watcher.py samples your webcam every 30 minutes (by default) using YOLOv8 nano to look for COCO classes 39 (bottle) and 41 (cup). On detection, it writes hydration_state.json. mcp_server.py reads that file and either locks or unlocks Claude.
That's it. No sound analysis, no edge-case ML — just "is there a cup in frame and confidence > 0.6?".
# Check every 10 seconds instead of 30 minutes (for testing)
python watcher.py --interval 10
# Use a different camera if you have multiple
python watcher.py --camera 1
# Lower confidence threshold if detection is missing cups (0.0–1.0)
python watcher.py --confidence 0.5Parameters live at the top of watcher.py.
check_hydration_status() — returns LOCKED, PASSED, or STALE.
If the watcher hasn't reported in over an hour (crashed, camera unplugged, permission revoked), the server returns STALE instead of trusting an old LOCKED result — Claude is told to proceed normally rather than enforce a lock off dead data. Stuck open a different way: run python watcher.py --unlock to force-clear the state file immediately.
Claude follows the LOCKED instruction because it's told to, not because anything blocks it from responding. There's no code-level gate — if you tell Claude to ignore the check, it can. Treat this as a nudge and an accountability gimmick, not a lock you can't talk your way past. The actual safety property this repo cares about is the opposite one: never leaving someone stuck if the watcher dies.
MIT