dbt-coverage
Calculates per-column test coverage for a dbt model, identifying which columns have tests and table-level coverage percentage.
Instructions
Per-column test coverage for a dbt model (which columns have tests, table-level tests, coverage %)
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| uniqueId | No | dbt unique_id | |
| name | No | Model name (resolved if uniqueId not provided) |
Implementation Reference
- src/tools/dbt-models.ts:187-219 (handler)Main handler: loads the manifest, resolves the model by uniqueId or name, iterates its columns and tests, computes per-column and table-level test coverage, and returns coverage stats.
export async function dbtCoverage(args: z.infer<typeof dbtCoverageSchema>): Promise<unknown> { const manifest = loadManifest(); let model: DbtNode | undefined; if (args.uniqueId) model = manifest.nodes[args.uniqueId]; else if (args.name) model = Object.values(manifest.nodes).find((n) => isModel(n) && n.name === args.name); if (!model) throw new Error(`Model not found: ${args.uniqueId ?? args.name}`); const columns = Object.values(model.columns ?? {}); const tests = Object.values(manifest.nodes).filter( (n) => n.resource_type === "test" && (n.depends_on?.nodes ?? []).includes(model.unique_id), ); const columnsCovered = new Set<string>(); for (const t of tests) { if (t.column_name) columnsCovered.add(t.column_name); } const tableLevelTests = tests.filter((t) => !t.column_name).map((t) => t.name); return { model: { uniqueId: model.unique_id, name: model.name }, totalColumns: columns.length, columnsWithTests: columnsCovered.size, coveragePct: columns.length === 0 ? 0 : Math.round((columnsCovered.size / columns.length) * 1000) / 10, columns: columns.map((c) => ({ name: c.name, hasTests: columnsCovered.has(c.name), testCount: tests.filter((t) => t.column_name === c.name).length, })), tableLevelTests, totalTests: tests.length, }; } - src/tools/dbt-models.ts:182-185 (schema)Input schema for dbt-coverage tool, accepts either uniqueId or name of the model.
export const dbtCoverageSchema = z.object({ uniqueId: z.string().optional().describe("dbt unique_id"), name: z.string().optional().describe("Model name (resolved if uniqueId not provided)"), }); - src/index.ts:90-90 (registration)Registers the dbt-coverage tool with the MCP server, associating the schema and handler.
tool("dbt-coverage", "Per-column test coverage for a dbt model (which columns have tests, table-level tests, coverage %)", dbtCoverageSchema.shape, wrapToolHandler(dbtCoverage)); - src/index.ts:11-16 (registration)Import of the dbtCoverageSchema and dbtCoverage handler into the registration file.
import { dbtListModelsSchema, dbtListModels, dbtGetModelSchema, dbtGetModel, dbtGraphSchema, dbtGraph, dbtCoverageSchema, dbtCoverage, } from "./tools/dbt-models.js"; - src/clients/dbt-artifacts.ts:167-169 (helper)Helper used by the handler to load the dbt manifest.json file (with caching) to access nodes, columns, and tests.
export function loadManifest(): DbtManifest { return readWithCache<DbtManifest>("manifest", targetPath("manifest.json")); }