Poke HabitTracker MCP
README.md
# Poke HabitTracker MCP
This is Daniel's private Poke-compatible MCP server. The MVP lets Poke read and update today's HabitTracker habits directly through Supabase.
## Architecture
```text
Poke / Telegram / SMS
|
FastMCP server in this repo
|
Supabase HabitTracker tables
|
HabitTracker web/iOS clients
```
HabitTracker remains the source of truth. This server does not add API routes to HabitTracker and does not create schema migrations.
## Current Tools
- `health()`: returns safe server/config status without secrets.
- `list_today_habits()`: lists active habits for today with completion status.
- `complete_habit(habit_name)`: marks today's matching habit complete.
- `uncomplete_habit(habit_name)`: marks today's matching habit incomplete without deleting rows.
- `get_today_dashboard()`: returns completed/incomplete habit summary for today.
- Body-weight metric tools (`get_latest_body_weight`, `get_body_weight_history`, `get_body_weight_trend`, `get_metric_summary`) read imported `daily_metrics`/`metric_events` data.
Tasks and check-ins are not part of the current MCP surface. HabitTracker is habits-first and has no task concept; those tools will only be added if HabitTracker gains the schemas.
## Environment
Create `.env` from the example:
```powershell
Copy-Item .env.example .env
```
Fill the required HabitTracker Supabase values:
```text
SUPABASE_URL=
SUPABASE_SERVICE_ROLE_KEY=
DANIEL_USER_ID=
```
Optional:
```text
APP_ENV=development
APP_TIMEZONE=America/Chicago
MCP_HOST=127.0.0.1
MCP_PORT=8000
MCP_PATH=/mcp
POKE_MCP_API_KEY=
```
`SUPABASE_SERVICE_ROLE_KEY` must stay server-side. Every operation in this repo is scoped to `DANIEL_USER_ID`.
When `POKE_MCP_API_KEY` is set, the MCP endpoint requires FastMCP bearer auth:
```text
Authorization: Bearer <POKE_MCP_API_KEY>
```
The `/health` HTTP route remains public and secret-safe for platform health checks.
## Local Setup
```powershell
python -m venv .venv
.\.venv\Scripts\python -m pip install -e ".[dev]"
```
## Run Tests
Run unit tests and lint:
```powershell
.\.venv\Scripts\python -m pytest
.\.venv\Scripts\python -m ruff check .
```
## Run The Server
Run the MCP server locally:
```powershell
.\.venv\Scripts\python -m poke_mcp.server
```
The default local MCP URL is:
```text
http://127.0.0.1:8000/mcp
```
The server uses FastMCP HTTP transport at `MCP_PATH`, default `/mcp`.
## Manual Smoke Tests
The smoke script uses an in-memory FastMCP client. It always checks tool registration and `health()`. It calls real Supabase read tools only when `SUPABASE_URL`, `SUPABASE_SERVICE_ROLE_KEY`, and `DANIEL_USER_ID` are present.
Read-only smoke test:
```powershell
.\.venv\Scripts\python scripts\smoke_test.py
```
When env vars are present, the read-only smoke test calls:
- `health()`
- `list_today_habits()`
- `get_today_dashboard()`
Intentional write smoke test:
```powershell
.\.venv\Scripts\python scripts\smoke_test.py --write --habit "Creatine"
```
Write mode calls both `complete_habit()` and `uncomplete_habit()` against real Supabase. It chooses the order so the habit ends with the same visible completed/incomplete state it had at the start. If the habit starts incomplete, this may create a `completed=false` `habit_logs` row because this MVP intentionally does not delete logs.
## Deploy To HTTPS
Use a host that can run Python 3.12 and expose HTTPS, such as Render, Railway, or Fly.io. This repo includes:
- `Dockerfile`: production container image.
- `render.yaml`: Render Blueprint for a Docker web service.
- `railway.toml`: Railway config-as-code using the Dockerfile.
- `fly.toml`: Fly app config using the Dockerfile.
Runtime behavior:
- The server binds `MCP_HOST`, default `127.0.0.1`.
- The server uses `MCP_PORT`; if `MCP_PORT` is absent, platform `PORT` is accepted.
- The MCP endpoint is mounted at `MCP_PATH`, default `/mcp`.
- `/health` is a plain HTTP health route for deployment checks. It is secret-safe and returns the same config booleans as the `health()` MCP tool.
Recommended deployment shape:
```text
Build/install: python -m pip install -e .
Start: python -m poke_mcp.server
Environment:
APP_ENV=production
MCP_HOST=0.0.0.0
MCP_PORT=<numeric platform port; PORT is also accepted>
MCP_PATH=/mcp
SUPABASE_URL=<project url>
SUPABASE_SERVICE_ROLE_KEY=<server-side secret>
DANIEL_USER_ID=<Daniel's auth.users id>
```
Terminate TLS at the hosting provider and connect Poke to:
```text
https://your-public-host.example.com/mcp
```
Do not expose the endpoint publicly without setting `POKE_MCP_API_KEY` or using a host/proxy rule that enforces equivalent bearer auth.
### Render
Use `render.yaml` as a Blueprint, or create a Docker web service from the GitHub repo.
Set these secret/env values in Render:
```text
APP_ENV=production
APP_TIMEZONE=America/Chicago
MCP_HOST=0.0.0.0
MCP_PATH=/mcp
SUPABASE_URL=<project url>
SUPABASE_SERVICE_ROLE_KEY=<server-side secret>
DANIEL_USER_ID=<Daniel's auth.users id>
```
Render provides `PORT`, so `MCP_PORT` is optional. Health check path: `/health`.
### Railway
Railway will use `railway.toml` and the Dockerfile. Set the same production env vars as Render. Railway provides `PORT`, so `MCP_PORT` is optional. After deploy, create or use the public Railway domain and use:
```text
https://your-railway-domain.up.railway.app/mcp
```
### Fly.io
Edit `fly.toml` if the app name `poke-mcp` is unavailable, then set secrets and deploy:
```powershell
fly secrets set SUPABASE_URL="<project url>" SUPABASE_SERVICE_ROLE_KEY="<server-side secret>" DANIEL_USER_ID="<Daniel's auth.users id>"
fly deploy
```
`fly.toml` sets `MCP_PORT=8080` and maps Fly's public HTTPS service to internal port `8080`. Health check path: `/health`.
## Deployed Smoke-Test Checklist
After a deployment finishes:
1. Confirm logs show the server starting on `0.0.0.0` and the expected port.
2. Open `https://your-public-host.example.com/health`.
3. Confirm the health payload has `status: "ok"`, `supabase_configured: true`, and no secret values.
4. Run a read-only remote MCP smoke test:
```powershell
.\.venv\Scripts\python scripts\smoke_test.py --url https://your-public-host.example.com/mcp
```
If the remote MCP endpoint requires bearer auth, pass the key through FastMCP's HTTP auth path:
```powershell
.\.venv\Scripts\python scripts\smoke_test.py --url https://your-public-host.example.com/mcp --api-key "<secret>"
```
5. Confirm the smoke test lists tools and returns today's habit dashboard.
6. Connect Poke to `https://your-public-host.example.com/mcp`.
7. From Poke, ask "What habits do I have left today?"
8. Only after read-only checks pass, intentionally test writes with a low-risk habit:
```powershell
.\.venv\Scripts\python scripts\smoke_test.py --url https://your-public-host.example.com/mcp --api-key "<secret>" --write --habit "Creatine"
```
## Connect From Poke
MCP URL:
```text
https://your-public-host.example.com/mcp
```
Auth behavior in this MVP:
- If `POKE_MCP_API_KEY` is set on the server, `/mcp` requires `Authorization: Bearer <POKE_MCP_API_KEY>`.
- `scripts/smoke_test.py --api-key` sends that exact header using FastMCP's HTTP `auth=` support.
- Poke should be configured to send `Authorization: Bearer <POKE_MCP_API_KEY>` when connecting to the MCP URL.
- `health()` reports whether `POKE_MCP_API_KEY` is configured, but it does not reveal the key.
Example Poke prompts:
- "What habits do I have left today?"
- "Show my habit dashboard."
- "Mark Creatine complete."
- "Mark Cardio incomplete for today."
- "Did I finish all my habits?"
## HabitTracker Schema Assumptions
The MVP only uses:
- `habits`: `id`, `user_id`, `title`, `active_from`, `active_until`, `created_at`
- `habit_logs`: `habit_id`, `date`, `completed`
Active habits are those where `active_from <= today` and `active_until` is null or after today. Missing `active_from` falls back to `created_at`, matching HabitTracker's app logic.
## Known Limitations
- Task and check-in tools are intentionally not registered; HabitTracker has no task or check-in schema.
- No Google Calendar integration in this MVP.
- `uncomplete_habit` upserts `completed=false`; HabitTracker web currently often represents incomplete as no log row.
- Production remote auth should be finalized when Poke custom integration requirements are known.
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues