cronwatchBLOCK
CronWatch records every run of your scheduled jobs in your own database, and speaks up when one is missed, fails, gets stuck, runs slow or costs too much.
Overview
From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.
Cron and scheduled-job monitoring that lives inside your app. Wrap a job once; CronWatch records every run in a database you already have and tells you when a run is missed, fails, gets stuck, runs slow, goes over budget, or quietly does nothing. No server to run, no account to make. MIT.
Site and docs: cronwatch.dev
// lib/cronwatch.ts
import { cronwatch } from "@cronwatch/sdk";
import { sqlite } from "@cronwatch/sdk/sqlite";
import { slack } from "@cronwatch/sdk/slack";
export const cw = cronwatch({
store: sqlite({ path: "./data/cronwatch.db" }),
alerts: [slack({ webhookUrl: process.env.SLACK_WEBHOOK_URL! })],
});
export const nightlyReport = cw.job("nightly-report", {
schedule: "0 2 * * *", timezone: "UTC", grace: "15m", expect: "Report written",
});// app/api/cron/nightly-report/route.ts: checks Authorization: Bearer CRON_SECRET
import { nightlyReport } from "@/lib/cronwatch";
export const GET = nightlyReport.handler(async (job) => {
const report = await buildReport();
job.log("Report written:", report.path);
job.metric("cost", report.usdCost);
});// app/cronwatch/[[...path]]/route.ts: a dashboard and JSON API behind CRONWATCH_TOKEN
import { cw } from "@/lib/cronwatch";
export const { GET, POST, DELETE } = cw.routes();Packages
ae2b8530078cOBSERVED · 2026-10-11Connect
Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.
claude mcp add cronwatch-site --env CRONWATCH_TOKEN=${CRONWATCH_TOKEN} --env CRON_SECRET=${CRON_SECRET} --env RESEND_API_KEY=${RESEND_API_KEY} --env TWILIO_AUTH_TOKEN=${TWILIO_AUTH_TOKEN} -- npx -y cronwatch-site{
"mcpServers": {
"cronwatch-site": {
"command": "npx",
"args": [
"-y",
"cronwatch-site"
],
"env": {
"CRONWATCH_TOKEN": "${CRONWATCH_TOKEN}",
"CRON_SECRET": "${CRON_SECRET}",
"RESEND_API_KEY": "${RESEND_API_KEY}",
"TWILIO_AUTH_TOKEN": "${TWILIO_AUTH_TOKEN}"
}
}
}
}Exposed tools (9)
8 read · 1 write · 0 destructive.
| Tool | Risk | Description |
|---|---|---|
CronWatch | read | The scheduled jobs of this app: their health, their last day, and their runs. |
forget_job | read | |
get_job | read | |
get_setup_guide | read | |
list_jobs | read | |
nul2 | read | ab |
run_check | write | |
silence_job | read | |
unsilence_job | read |
Trust audit
BLOCKgrade F · trust 40/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | PASS |
| L1 | Static analysis of the code | FAIL |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- declared (5 observation(s))
- Network
- declared (3 observation(s))
- Shell
- declared (14 observation(s))
- Dependencies
- not all pinned
- Secrets in source
- found
Findings (25)
"input": "sk-ant-api03-Ab_-Ab_-Ab_-Ab_-Ab_-Ab_-Ab_-Ab_-Ab_-Ab_-",
"input": "export GITHUB_TOKEN=ghp_a1B2a1B2a1B2a1B2a1B2a1B2a1B2a1B2a1B2",
"text": "ghp_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
"input": "-----BEGIN RSA PRIVATE KEY-----\nMIIEow\nIBAAK==\n-----END RSA PRIVATE KEY-----\nafter",
"input": "key:\n-----BEGIN PRIVATE KEY-----\nMIIE\nabc",
"input": "-----BEGIN OPENSSH PRIVATE KEY-----\nb3Blbn\n-----END OPENSSH PRIVATE KEY-----",
"input": "-----BEGIN EC PRIVATE KEY-----\nMHc\n-----END RSA PRIVATE KEY----- x",
"input": "a -----BEGIN PRIVATE KEY-----\nk1\n-----END PRIVATE KEY----- b -----BEGIN PRIVATE KEY-----\nk2\n-----END PRIVATE KEY----- c",
"input": "xoxb-1234567890-abc",
"xoxb-1234567890-abc", "xoxp-12345", "xoxq-1234567890", "sk_live_abcdefghij12", "rk_test_abcdefghij", "pk_live_abcdefghi",
@written_details = [Marshal.load(Marshal.dump(details)), Alert.string_keys(written)] if written.is_a?(Hash)
func (re *Regexp) exec(m *matcher, from int) bool {err = retryBusy(ctx, func() error { return exec(ctx, conn, "PRAGMA journal_mode = WAL") })err = exec(ctx, conn, "PRAGMA busy_timeout = 5000")
err = exec(ctx, conn, "PRAGMA synchronous = NORMAL")
func exec(ctx context.Context, q querier, text string, args ...any) error {return importlib.import_module(f"{__name__}.{name}")return getattr(importlib.import_module(new), name)
return sorted(vars(importlib.import_module(new)))
console.log(`Sign in: http://localhost:${PORT}${BASE}/?token=${TOKEN}`);proxy_pass http://127.0.0.1:3790;
"triage": "<b>Likely</b> cause & fix: tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
"output": "````\nzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
"message": "Started 2026-01-05 09:30:00 UTC (now), ran 2s.\nError: long\nOutput (tail):\n````\nzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
"body": "{\"schema\":1,\"type\":\"failed\",\"run\":{\"id\":\"r1\",\"job\":\"nightly\",\"status\":\"failed\",\"startedAt\":1767605400000,\"finishedAt\":1767605401500,\"durationMs\":1500,\"error\":\"ErrGates applied: critical_finding, no_behavioural_pass.
ae2b8530078cfull audit observations/trust-audit/mcp-server/phillips-jon__cronwatch.json · Report an issue / request a re-scanAudit history
Every audit this server has had. A grade with a past is a grade somebody is still checking.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-11 | ae2b8530078c | BLOCK | F | 40 | first audit |
Questions
What is the cronwatch MCP server?
CronWatch records every run of your scheduled jobs in your own database, and speaks up when one is missed, fails, gets stuck, runs slow or costs too much.
What tools does cronwatch expose?
9 in total: 8 read-only, 1 that write, and 0 that can delete or overwrite. Every one is listed on this page with its risk.
Is cronwatch safe to connect to an agent?
No — not without reading the findings first. The audit graded it F (40/100) and found 16 critical or high issues in the source. Each one is listed on this page with the file and line it is on.
What credentials does cronwatch need?
It reads CRONWATCH_TOKEN, CRON_SECRET, RESEND_API_KEY and TWILIO_AUTH_TOKEN from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.
How does cronwatch run?
It speaks stdio, so it runs as a local process your client starts. It is published on npm as cronwatch-site.
How current is this page?
The grade is for one exact copy of the source (ae2b8530078c), read on 2026-10-11. The repository is watched and re-audited when it changes.