dbt logoMCP

Driving dbt Governance from an AI Agent over MCP

Ask an AI agent "did anything in our dbt project drift from what the business agreed it means?" and it should not have to screen-scrape a dashboard or guess. CoreModels exposes its dbt integration as first-class MCP tools, so an agent connected to your CoreModels server can check integration status, audit a manifest, and produce enforced dbt contracts — with the same role checks and the same read-only guarantees as the HTTP API. This article walks through the four integration tools an agent uses for dbt, with real arguments.

Driving dbt Governance from an AI Agent over MCP

Ask an AI agent "did anything in our dbt project drift from what the business agreed it means?" and it should not have to screen-scrape a dashboard or guess. CoreModels exposes its dbt integration as first-class MCP tools, so an agent connected to your CoreModels server can check integration status, audit a manifest, and produce enforced dbt contracts — with the same role checks and the same read-only guarantees as the HTTP API. This article walks through the four integration tools an agent uses for dbt, with real arguments.

Connecting

The MCP endpoint is streamable HTTP with OAuth. From Claude Code:

claude mcp add --transport http coremodels https://coremodels.example.com/mcp

then complete the OAuth flow when prompted. In claude.ai or Claude Desktop, add a custom connector pointing at the same URL. Generic MCP clients configure it as:

{
  "mcpServers": {
    "coremodels": { "type": "http", "url": "https://coremodels.example.com/mcp" }
  }
}

There are two endpoints with a deliberate split: /mcp serves only read-only (Viewer-role) tools; /mcp-admin additionally serves write tools. For dbt that means audit_vendor_project, generate_vendor_artifacts, and get_vendor_integration_status are available on both, while import_vendor_project (Admin role) exists only on the admin endpoint. The enforced boundary is always the per-project role check — a write tool requires actual Admin membership on the target project regardless of which endpoint the token came through. Every tool declares a readOnlyHint, so a well-behaved agent knows before calling which tools can change anything.

Step 1 — Discover what's connected

get_vendor_integration_status is the agent's entry point. Called with just a project id, it lists every registered connector with capabilities and expected artifacts:

{ "tool": "get_vendor_integration_status",
  "arguments": { "graphProjectId": "a1b2c3d4e5f60718293a4b5c6d7e8f90" } }

Called with a vendor, it returns that vendor's last-import state for the project — whether an import has happened, tool and artifact versions, fingerprint, counts, and how many datasets are currently governed:

{ "tool": "get_vendor_integration_status",
  "arguments": { "graphProjectId": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
                 "vendor": "dbt" } }

graphProjectId is always the 32-character hex CoreModels project id (the input schema enforces the pattern ^[a-f0-9]{32}$).

Step 2 — Audit a manifest

audit_vendor_project is the free Schema Audit as a tool call: it compares fresh vendor artifacts against the governed graph — coverage, drift, and conformance — and writes nothing. For a small project, the agent can inline the manifest text directly:

{ "tool": "audit_vendor_project",
  "arguments": {
    "graphProjectId": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
    "vendor": "dbt",
    "artifacts": { "manifest": "<contents of target/manifest.json>" }
  } }

Required arguments are graphProjectId and vendor; artifacts arrive via artifacts (name → raw content), artifactUrls (name → URL), or both. For dbt, manifest is required and catalog / semantic_manifest are optional. An optional spaces array scopes the audit to specific space ids.

The result carries error/warning/info counts, the individual findings (section, severity, code, subject, message, detail), audit metrics, and a markdown field with the complete human-readable report — an agent can quote the markdown verbatim to a human or reason over the structured findings itself. The contract for automation is the same everywhere in CoreModels: an error count above zero means the artifacts violate governed meaning.

One honest difference from the HTTP surface: the MCP audit tool has no history-recording argument. It is purely read-only, every time. If you want audit runs appended to the project's rolling drift trail (for the badge and the history view), that is the HTTP audit route's opt-in recordHistory flag — typically CI's job, not the agent's.

The artifactUrls flow — when the manifest doesn't fit in a prompt

A real enterprise manifest.json can run to tens or hundreds of megabytes. No MCP client should paste that into a tool call, and most can't. So the artifact-bearing tools accept URLs, fetched server-side:

{ "tool": "audit_vendor_project",
  "arguments": {
    "graphProjectId": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
    "vendor": "dbt",
    "artifactUrls": {
      "manifest": "https://artifacts.example.com/dbt/run-4711/manifest.json",
      "catalog":  "https://artifacts.example.com/dbt/run-4711/catalog.json"
    }
  } }

Your CI can upload the artifacts somewhere addressable (an artifact store, a pre-signed object URL) and hand the agent the links. Because these are server-side requests to caller-supplied URLs, the fetch is deliberately locked down: https only, redirects disabled, hosts that resolve to loopback, link-local, or private address ranges are refused, and the response size is capped at 256 MB. A refused or failed fetch does not silently vanish — it comes back in a fetchProblems list in the tool result, next to whatever did load. You can mix artifacts and artifactUrls in one call; the tool errors only when neither yields anything usable.

Step 3 — Import (admin endpoint only)

When the agent is allowed to bring an estate under governance in the first place, import_vendor_project takes the same argument shape:

{ "tool": "import_vendor_project",
  "arguments": {
    "graphProjectId": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
    "vendor": "dbt",
    "artifactUrls": { "manifest": "https://artifacts.example.com/dbt/run-4711/manifest.json" }
  } }

This is the one write among the four, so it requires Admin membership and is served on /mcp-admin only. The semantics match the HTTP import exactly: datasets become Types, columns become Elements, accepted values become Taxonomies, relationships become references, plus lineage edges and vendor metadata — and the operation is additive on re-import. Already-governed nodes are never mutated; the tool's own description tells the agent to run audit_vendor_project to see drift instead. The result reports the counts (datasets, fields, lineage edges, enriched nodes) plus lossiness and errors.

Step 4 — Generate contracts back out

generate_vendor_artifacts closes the loop from the governed model to the dbt repo:

{ "tool": "generate_vendor_artifacts",
  "arguments": {
    "graphProjectId": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
    "vendor": "dbt",
    "typeNames": ["orders", "customers"],
    "targetVersion": "1.8"
  } }

For dbt this produces models/coremodels_contracts.yml: enforced model contracts with column data types, not_null/unique constraints and tests, accepted_values tests from governed taxonomies, and relationships tests from governed references. typeNames restricts output to named models (omit for everything eligible); the default target emits the dbt ≥ 1.8 data_tests: key, while "1.7" emits the legacy tests: key. The tool is read-only and Viewer-role — it returns file content and lossiness notes; nothing lands in your repo until a human commits it. That division of labor is intentional: subject-matter experts change meaning once in CoreModels, and engineers get a reviewed contract diff.

What an agent session actually looks like

Put together, a governance check the agent can run unattended:

  1. get_vendor_integration_status with vendor: "dbt" — is this estate imported, and when did it last change?
  2. audit_vendor_project with artifactUrls pointing at the latest CI build's manifest — coverage, drift, conformance.
  3. If findings need explaining, quote the markdown report; if a fix belongs in dbt, call generate_vendor_artifacts and open a pull request with the emitted schema.yml for humans to review.

The agent never holds a warehouse credential at any point in that loop — artifacts in, artifacts out, and every governed fact it reads comes from the same graph your team governs interactively.

The equivalent HTTP calls, plus the CI-gate recipe these tools pair with, are covered in the dbt quickstart that ships with CoreModels.