Prerequisites
A working MCP workflow expressible as a script — the script should run the MCP prompt, capture the output, and deliver it. See how to send MCP reports to Telegram, Discord, or email.
A Cryptohopper MCP API key stored as an environment variable or secret. Never hardcode it in the script — see API key security best practices.
The base pattern
All three scheduling systems wrap the same script. The structure is always: run the MCP prompt → capture output → deliver it. Make sure environment variables are set and output is captured to a log.
# /home/you/scripts/daily_digest.py
import os
import requests
API_KEY = os.environ["CRYPTOHOPPER_MCP_KEY"]
TELEGRAM_TOKEN = os.environ["TELEGRAM_BOT_TOKEN"]
TELEGRAM_CHAT_ID = os.environ["TELEGRAM_CHAT_ID"]
def run_mcp_workflow(prompt: str) -> str:
# Your MCP client library call here — producing the report text.
...
def send_telegram(text: str) -> None:
requests.post(
f"https://api.telegram.org/bot{TELEGRAM_TOKEN}/sendMessage",
json={"chat_id": TELEGRAM_CHAT_ID, "text": text, "parse_mode": "Markdown"},
).raise_for_status()
if __name__ == "__main__":
prompt = open("/home/you/prompts/daily_digest.txt").read()
report = run_mcp_workflow(prompt)
send_telegram(report)
Setup — cron (macOS / Linux)
Test the script manually first
export CRYPTOHOPPER_MCP_KEY="..."
export TELEGRAM_BOT_TOKEN="..."
export TELEGRAM_CHAT_ID="..."
python3 /home/you/scripts/daily_digest.py
2. Edit your crontab
Run crontab -e and add the entry below. Cron does not inherit your shell's environment — declare variables at the top of the crontab.
CRYPTOHOPPER_MCP_KEY=your_key
TELEGRAM_BOT_TOKEN=your_token
TELEGRAM_CHAT_ID=your_chat_id
PATH=/usr/local/bin:/usr/bin:/bin
# Daily at 08:00 local time
0 8 * * * /usr/bin/python3 /home/you/scripts/daily_digest.py >> /home/you/logs/daily.log 2>&1
3. Verify
After the scheduled time, check the log. An empty log means cron didn't run the script. Errors in the log mean it ran but failed.
bashtail -50 /home/you/logs/daily.log
Setup — Task Scheduler (Windows)
Test the script from Powershell
$env:CRYPTOHOPPER_MCP_KEY = "..."
$env:TELEGRAM_BOT_TOKEN = "..."
$env:TELEGRAM_CHAT_ID = "..."
python C:\Users\you\scripts\daily_digest.py
2. Set a trigger
Under Triggers, configure the schedule (daily at 08:00, weekly, etc.).
3. Configure the action
Under Actions: Program/script → python (or full path to python.exe). Add arguments → C:\Users\you\scripts\daily_digest.py. Start in → C:\Users\you\scripts.
4. Handle environment variables
Two options: set them as system-wide variables via Control Panel → System → Environment Variables, or load them from a .env file using the python-dotenv library.
5. Verify
Check the task's Last Run Result in Task Scheduler. 0x0 means success; anything else is an error.
Setup — GitHub Actions (cloud-hosted)
Create a GitHub repository for your scheduled workflows
Add your script to the repo. Do not commit secrets.
Add repository secrets
Go to Settings → Secrets and variables → Actions and add:
CRYPTOHOPPER_MCP_KEY,TELEGRAM_BOT_TOKEN,TELEGRAM_CHAT_ID.
Create the workflow file
# .github/workflows/daily_digest.yml
name: Daily digest
on:
schedule:
- cron: "0 7 * * *" # 07:00 UTC daily
workflow_dispatch: # allows manual trigger
jobs:
run:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install -r requirements.txt
- name: Run digest
env:
CRYPTOHOPPER_MCP_KEY: ${{ secrets.CRYPTOHOPPER_MCP_KEY }}
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}
run: python scripts/daily_digest.py
GitHub Actions schedules use UTC — convert your local time accordingly. Monitor runs in the repo's Actions tab; GitHub emails you when a scheduled run fails.
Choosing where to schedule
Option | Best for | Downside |
cron | Local/personal workflows on a machine that's always on | Dies when your laptop sleeps |
Task Scheduler | Personal workflows on Windows | Clunky UI, env-var handling awkward |
GitHub Actions | Reliable, cloud-hosted, free for most personal use | Runs can be delayed during GitHub congestion |
VPS + systemd/cron | Production-grade reliability | You manage the server |
For most users, GitHub Actions is the right default: free, reliable, and logs are discoverable when something breaks.
Troubleshooting
Cron job doesn't fire
Check grep CRON /var/log/syslog (Linux) or log show --predicate 'process == "cron"' (macOS). The most common cause is a missing PATH or missing env vars — cron runs in a minimal environment.
Cron runs but the script errors out immediately
Almost always a missing environment variable. Have the script print a clear error and exit early if a required env var is absent — don't let it fail silently inside the MCP call.
Scheduled task runs at a different time than expected
Time zones. Cron uses the machine's local time zone; GitHub Actions uses UTC. Test the schedule at a predictable time before setting the real cadence.
Log file is empty even though the script fires
The redirect isn't capturing stderr. Use >> log 2>&1 — the double arrow appends; a single > overwrites each run and loses previous output.
GitHub Actions schedule is being skipped
GitHub throttles scheduled workflows during high load and occasionally skips runs. For workflows that must fire reliably, use a second scheduling mechanism as a backup or pay for a dedicated runner. For most workflows, occasional skips are tolerable.
Scheduled runs are eating your quota faster than expected
Every run is a cost. Monitor usage via how to monitor your Cryptohopper MCP spend. A weekly sum check from the MCP usage endpoint catches runaway schedules quickly.
You want sub-minute scheduling precision
None of these schedulers provide reliable sub-minute precision, and you rarely actually need it. If you think you do, step back — the workflow is likely better designed as an event-driven webhook.
