Deployment¶
Railway (Recommended)¶
Railway provides the simplest deployment with built-in PostgreSQL.
1. Create a Railway Project¶
- Create a new project on Railway
- Connect your GitHub repository
- Add a PostgreSQL database to the project
2. Set Environment Variables¶
In Railway's dashboard, set the required variables:
DATABASE_URL=<auto-set by Railway PostgreSQL plugin>
SECRET_KEY=<generate a random string>
ENCRYPTION_KEY=<generate a random string>
GARMIN_EMAIL=your@email.com
GARMIN_PASSWORD=your-password
ANTHROPIC_API_KEY=sk-ant-...
MCP_SERVER_URL=https://your-app.up.railway.app
3. Deploy¶
Railway auto-detects the Procfile and runs:
Heroku¶
The Procfile is Heroku-compatible. Add a PostgreSQL addon and set the same environment variables.
Any Docker/VPS Host¶
# Clone and set up
git clone https://github.com/ladkam/coaching-mcp.git
cd coaching-mcp
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
# Set environment variables
export DATABASE_URL=postgresql://user:pass@host:5432/cadence
export SECRET_KEY=your-secret
export ENCRYPTION_KEY=your-encryption-key
# ... other variables
# Run
python server.py --http
Production Checklist¶
- [ ] Set
SECRET_KEYto a strong random value - [ ] Set
ENCRYPTION_KEYfor credential encryption - [ ] Use PostgreSQL (
DATABASE_URL) instead of SQLite - [ ] Set
MCP_SERVER_URLto your public URL (enables OAuth for MCP clients) - [ ] Set
MCP_AUTH_SECRETto require login for MCP auth - [ ] Set
SIGNUP_MODEtoinviteorclosedif you want to restrict access - [ ] Configure email (
RESEND_API_KEY) for verification and password resets - [ ] Set WHOOP/Strava redirect URIs to your production URL
Database¶
Cadence auto-detects the database:
DATABASE_URLset → PostgreSQLDATABASE_URLnot set → SQLite (file atDB_PATH, defaultcoaching_bot.db)
Migrations run automatically on startup. Both engines use the same migration system with dialect-specific SQL where needed.
MCP Authentication¶
When MCP_SERVER_URL is set, Cadence runs a full OAuth2 provider for MCP clients:
- Clients register automatically
- Users authenticate via the web login page
- Access tokens expire after 1 hour, refresh tokens after 24 hours
- Token state is persisted to the database (survives restarts)
When MCP_SERVER_URL is not set, MCP auth is disabled and all clients are auto-approved with a default user — suitable for local/personal use.