Skip to main content
Glama

compare_tables

Read-onlyIdempotent

Compares a table before and after a pipeline change to detect lost or duplicated rows, changed keys and values, null spikes, shifted totals, and schema changes, returning pass, review, or block.

Instructions

Compare one table before and after a pipeline change and say whether the change harmed the data.

It looks for the damage that a green job and passing tests miss: rows lost or duplicated (a join that
fans out, a dedupe that drops too much), keys that disappeared, values that changed in columns the
change was not meant to touch, a jump in nulls, a shifted total (a unit or currency change), new or
vanished categories, and schema or type changes.

Use this after you edit a SQL query, dbt model, Spark job or load, or after an agent applies a fix,
and before you report the work as done, merge it or publish the table. Use check_against_source
instead when there is no earlier snapshot but you have the raw input the table was built from, and
run_config when the project already has a pipeverify.yml listing its tables.

Behavior: read-only and repeatable. Both snapshots are read (files are opened read-only; Snowflake,
dbt and SQL sources run one SELECT each, with credentials already configured on this machine, never
passed as arguments) and loaded into a temporary in-memory DuckDB where the checks run. Nothing is
written anywhere. Each snapshot is loaded whole, so for a large warehouse table pass a SELECT or a
'where' filter covering the slice you changed. Usually takes seconds. Fails with a readable error
if a file, table, dbt model, key column or login is wrong.

Returns verdict ("pass", "review" or "block"), headline (one sentence you can show the user), and
tables: one entry with stats (row counts and more) and findings, each with check, severity, message,
column and metrics. On "review" or "block", tell the user every finding and do not apply the change.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "before": "<before>",
      "after": "<after>"
    },
    "name": "compare_tables"
  }
}

Input Schema

NameRequiredDescriptionDefault
keyNoColumn or columns that together identify one row, for example ["order_id"] or ["store_id", "sale_date"]. Without a key only table-level checks run (row counts, schema, null rates, totals), so give one whenever the table has it.
nameNoName to show for the table in the report, for example gold.daily_sales. Defaults to 'table'.
afterYesThe same table after the change (for example the pull request's build). Same forms as 'before'.
beforeYesThe table as it was before the change (for example production, or yesterday's snapshot). A file path (.csv, .parquet, .json, .xlsx; CSV and JSON may be .gz or .zst), 'duckdb:<file.db>:<table or SELECT>', 'snowflake:<DB.SCHEMA.TABLE or SELECT>', 'dbt:<model>', or an object such as {"dbt": "fct_orders", "project_dir": "analytics", "target": "prod", "manifest": "prod-manifest.json"}, {"snowflake": "DB.SCHEMA.T", "connection": "name", "where": "..."} or {"url": "<SQLAlchemy URL>", "table": "schema.table"}. Relative paths are relative to the server's working folder.
ignoreNoColumns to skip because they always differ, such as load timestamps or run ids.
thresholdsNoOptional overrides for when a difference becomes review or block, in percent of rows, for example {"row_change_block_pct": 20, "sum_shift_review_pct": 1}. Omit to use the defaults.
expect_changeNoColumns this change is meant to modify. Differences in them are reported as expected instead of flagged. Omit when the change should not alter any existing value.
expect_row_changeNoSet true when the change is meant to add or remove rows, so a row-count change alone is not flagged.

Output Schema

NameRequiredDescriptionDefault
tablesYes
secondsYes
verdictYes
versionYes
headlineYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observedv0.1.0

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations it discloses the execution model: both snapshots are read read-only (one SELECT each for Snowflake/dbt/SQL), credentials come from the machine and are never passed as arguments, data lands in a temporary in-memory DuckDB, and nothing is written anywhere. It also flags the scaling caveat that each snapshot is loaded whole, so large warehouse tables need a SELECT or 'where' slice, notes the runtime (seconds), and describes failure behavior for bad paths, keys or logins.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well front-loaded: purpose, then when-to-use, then the listed damage classes, then routing to siblings, then behavior. Some of the Behavior paragraph restates what annotations already declare ('read-only and repeatable', 'nothing is written anywhere') and could be trimmed against readOnlyHint/idempotentHint.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An 8-parameter, multi-source tool with an output schema, and the description still covers the inputs an agent gets wrong: scoping large snapshots, key semantics, and what to do on 'review' or 'block' ('tell the user every finding and do not apply the change'). Return shape is briefly mapped even though the output schema owns the detail.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the body adds real meaning: it tells the agent to pass a SELECT or 'where' filter to scope a large table's before/after snapshots, and the key parameter's importance ('without a key only table-level checks run') is reinforced by the usage framing. It stops short of explaining threshold keys or expect_change interactions, which the schema already handles.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb and resource ('compare one table before and after a pipeline change') plus an explicit outcome statement ('say whether the change harmed the data'). It even enumerates the concrete failure classes it detects, so an agent knows exactly what this tool answers that a green job does not.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a concrete trigger ('after you edit a SQL query, dbt model, Spark job or load, or after an agent applies a fix, and before you report the work as done, merge it or publish'), and names both siblings with the exact condition selecting each: check_against_source when there is no earlier snapshot but raw input exists, run_config when pipeverify.yml already lists tables.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Deploy Server

Other Tools