Zero-config data-quality monitoring: profile a warehouse, detect anomalies, gate CI.
MCP Server: io.github.rbmuller/scherlok
This MCP server provides “Zero-config data-quality monitoring,” including profiling a warehouse, detecting anomalies, and gating CI. It is positioned as an open-source tool for data observability and quality workflows, with support indicated across warehouse and database ecosystems and tooling.
🛠️ Key Features
Zero-config data-quality monitoring
Profile a warehouse
Detect anomalies
Gate CI
🚀 Use Cases
Data-quality monitoring for warehouses
Automated anomaly detection in data pipelines
CI gating based on monitoring results
⚡ Developer Benefits
Python-based tooling (Python 3.10+ indicated)
Integrates with the Model Context Protocol (MCP)
⚠️ Limitations
Source data does not specify authentication, deployment model, or supported transport details.
Zero-config anomaly detection for your database tables.
No YAML, no rules, no thresholds. Scherlok learns what "normal" looks like, then tells you when something changes.
bash
pip install scherlok
scherlok ci postgres://user:pass@host/db # profiles on the first run, detects anomalies on every run after
No database handy? The demo seeds one, learns it, breaks it, and catches it, in about a second:
bash
uvx --from "scherlok[duckdb]" scherlok demo
Works with PostgreSQL, BigQuery, Snowflake, MySQL, DuckDB and dbt. Alerts go to Slack, Discord, Teams, email, or your CI exit code.
The Problem
Every data team has the same nightmare:
A source API silently changes from dollars to cents. Revenue dashboards show wrong numbers for 3 weeks before anyone notices.
A column starts returning NULLs. A table stops updating. Row counts drop 40% on a Tuesday. Nobody knows until the CEO asks why the report looks weird.
Current tools (Great Expectations, Soda, dbt tests) require you to define what "correct" looks like before you can detect what's wrong. Hundreds of rules. Dozens of YAML files. And you still miss things — because you can't write rules for problems you haven't imagined yet.
What It Catches
Anomaly
What Happened
Severity
Volume drop
Row count dropped 40% overnight
CRITICAL
Volume spike
3x more rows than normal
WARNING
Freshness alert
Table hasn't updated in 12h (normally every 2h)
CRITICAL
Schema drift
Column removed or type changed
CRITICAL
NULL surge
NULL rate jumped from 2% to 45%
WARNING
Distribution shift
Column mean shifted 3+ standard deviations (Shewhart-style control limit)
INFO, WARNING above 5σ
Cardinality explosion
Status column went from 5 values to 500
CRITICAL
Every anomaly is auto-scored: INFO, WARNING, or CRITICAL. No thresholds to configure.
How It Works
Scherlok takes the opposite approach of rule-based tools: learn first, then detect.
bash
scherlok connect postgres://user:pass@host/db # connect once
scherlok investigate # learn your data
scherlok watch # detect anomalies
Three commands. Five minutes. Done. (scherlok ci <url> runs all three in one step for pipelines.)
After five valid profiles, Scherlok learns per-metric variability from the
latest 30 profiles using robust historical baselines for volume, numeric mean
shifts, NULL rates, and distinct counts. During cold start or when history is
not usable, it keeps the conservative fixed defaults.
If Scherlok detects a critical anomaly, the pipeline fails. Bad data never reaches production.
Works with dbt
Already running dbt? Scherlok complements dbt test with automatic anomaly detection — no rules to write.
bash
pip install scherlok[dbt]
# After `dbt run`, point Scherlok at your project
scherlok dbt --project-dir ./my_dbt_project
Scherlok reads target/manifest.json, discovers every materialized model (table, incremental, view), auto-resolves the connection from your profiles.yml, and profiles each model:
The wrapper runs dbt run by default and uses the successful model nodes recorded in
target/run_results.json, so partial runs profile only what dbt actually built. Use
--build to run dbt build; successful models are still profiled when a test failure
causes downstream models to be skipped on dbt's handled failure path (exit 1), while
the wrapper preserves dbt build's exit code. Unhandled failures fail fast without
reading the artifact.
Both dbt and dbt-run-and-watch accept --output json for CI parsers — a single JSON document on stdout, nothing else.
One self-contained HTML file (~28 KB): KPIs, per-table incidents grouped with first-seen timestamps, +/−/~ schema-drift diff, sparklines, and full anomaly history. Auto dark/light theme via prefers-color-scheme.
The agent gets list_tables, investigate, watch, status, history, and check as tools. Credentials are resolved server-side (never passed by the model), every operation is read-only on the warehouse, and there's no arbitrary-SQL tool.
When anomalies fire, Scherlok makes one Claude call for the whole batch and injects a short root-cause hypothesis into the same Slack/Discord/Teams/email/JSON alert:
Works on watch, ci, check, dbt, and dbt-run-and-watch. On dbt projects the hypothesis is lineage-aware: upstream parents from manifest.json go into the prompt, so cascading failures get traced to the source model instead of alerting on every downstream symptom.
What it costs — one call per fired run (not per anomaly), Claude Haiku 4.5 by default: well under a cent per run (~$0.003). Override the model with SCHERLOK_EXPLAIN_MODEL. Runs with zero anomalies make no API call.
What it sends — aggregates only: the anomaly type/severity/message strings already in your alert, dbt model names, detection timestamps. Never warehouse rows, cell values, or credentials — the test suite pins this as a contract.
How to turn it off — it's opt-in; don't pass --explain. If the API call fails (no key, timeout, rate limit), the original alert is delivered unchanged with a one-line note. Alerting never blocks on the LLM.