Google BigQuery logoMCP

Governing BigQuery from an AI Agent over MCP

*The same import–audit–generate loop, driven by tool calls instead of curl — including how agents ship multi-megabyte extracts.*

Governing BigQuery from an AI Agent over MCP

The same import–audit–generate loop, driven by tool calls instead of curl — including how agents ship multi-megabyte extracts.

"Has anything drifted in the analytics dataset since we last agreed the model?" is a question an AI agent can now answer directly, with evidence. CoreModels (by ARAMAI) exposes its vendor-integration verbs as MCP tools, so any MCP-capable agent — Claude, Claude Code, or anything speaking streamable HTTP — can check a BigQuery estate against its governed model, import a new estate, and generate governed DDL, all under the same role checks a human user faces. This article walks the four tools that matter for BigQuery and the arguments they actually take.

Connecting

CoreModels serves two MCP endpoints. /mcp is the public endpoint: read-only tools only, which for integrations means audit, generate, and status. /mcp-admin additionally serves the write tools, including vendor import. Both use OAuth 2.0 with dynamic client registration and PKCE — an unauthenticated request gets a 401 pointing at the resource metadata, and spec-compliant clients complete the flow automatically. From Claude Code:

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

and, when the agent should be able to import:

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

The endpoint split is convenience, not the security boundary. The enforced boundary is the per-project role check: write tools require Editor or Admin membership on the target project regardless of which endpoint the token came through.

Discovery: get_vendor_integration_status

An agent should never hard-code what connectors exist. Called with just a project id, this tool lists every registered connector with capabilities and expected artifacts:

{ "graphProjectId": "3f2a9c81d4b6470e8a1c5d9e2b7f4a63" }

The BigQuery entry reports key bigquery, display name Google BigQuery, capabilities Import, Audit, Generate, and one required artifact, information_schema, with a note describing what it is. Add the vendor argument and the tool switches to project status:

{ "graphProjectId": "3f2a9c81d4b6470e8a1c5d9e2b7f4a63", "vendor": "bigquery" }

Now it returns whether an import has happened, the last-import state (timestamps, fingerprint, counts), and how many governed datasets currently resolve in the graph. This is the agent's orientation move: one call tells it whether there is anything to audit yet.

The audit: audit_vendor_project

The workhorse. It compares fresh BigQuery artifacts against the governed graph and reports coverage, drift, and conformance — read-only, Viewer role, available on both endpoints. Required arguments are graphProjectId (32-char hex) and vendor; the artifacts come either inline or by URL:

{
  "graphProjectId": "3f2a9c81d4b6470e8a1c5d9e2b7f4a63",
  "vendor": "bigquery",
  "artifacts": {
    "information_schema": "<the JSON rows exported by the documented extraction query>"
  }
}

The result carries the error/warning/info counts, the individual findings — each with section, severity, a stable kebab-case code such as field-type-drift or semi-structured-column, subject, message, and detail — plus a markdown report ready to paste into a pull request or a chat reply. The contract an agent should internalize: errorCount > 0 means governed meaning is violated; warnings and infos are advisory. An optional spaces array scopes the audit to specific space ids.

Large extracts: the artifactUrls flow

A real estate extract can be far bigger than an agent wants to inline in a tool call. Both artifact-bearing tools therefore accept artifactUrls — artifact name to URL — and CoreModels fetches the content server-side:

{
  "graphProjectId": "3f2a9c81d4b6470e8a1c5d9e2b7f4a63",
  "vendor": "bigquery",
  "artifactUrls": {
    "information_schema": "https://artifacts.example.com/extracts/information_schema.json"
  }
}

Because these are server-side GETs to caller-supplied URLs, the fetch is deliberately locked down: HTTPS only, redirects disabled, hosts resolving to loopback, link-local, or private ranges refused, a 60-second timeout, and a hard response-size cap of 256 MB. Anything refused or failed does not silently vanish — it comes back in the tool result's fetch-problems list, and you can mix artifacts and artifactUrls in one call. The practical pattern: a pipeline drops the fresh extract onto object storage with a short-lived HTTPS URL, and the agent passes the URL instead of the payload.

The import: import_vendor_project

Import is the one verb in this loop that writes, so it requires the Admin role and is served on /mcp-admin only. The arguments are the same shape as the audit — graphProjectId, vendor, and artifacts and/or artifactUrls:

{
  "graphProjectId": "3f2a9c81d4b6470e8a1c5d9e2b7f4a63",
  "vendor": "bigquery",
  "artifactUrls": {
    "information_schema": "https://artifacts.example.com/extracts/information_schema.json"
  }
}

The semantics matter more than the mechanics: import is additive. Datasets become governed Types, columns become Elements with their native BigQuery types preserved as vendor metadata, is_nullable = NO becomes a NotNull check — but already-governed nodes are never mutated. An agent re-importing a grown estate adds the new tables and touches nothing else; the result reports how many datasets were added versus skipped as already existing, plus a lossiness list for everything honestly approximated (BigQuery's STRUCT/ARRAY/JSON columns, for instance, are governed as String because the flat extract cannot see their inner schemas). When the agent wants to know what changed rather than what is new, the answer is not re-import — it is audit_vendor_project.

Closing the loop: generate_vendor_artifacts

BigQuery has the Generate capability, so an agent can also emit governance back toward the warehouse:

{
  "graphProjectId": "3f2a9c81d4b6470e8a1c5d9e2b7f4a63",
  "vendor": "bigquery",
  "typeNames": ["orders", "customers"]
}

typeNames is optional — empty means every eligible governed type. The tool returns one artifact, coremodels_bigquery_tables.sql: CREATE TABLE IF NOT EXISTS DDL with NOT NULL from governed checks and OPTIONS(description=...) on both columns and tables — with governed allowed-value lists and references written into the column descriptions. Read-only like the audit — the tool hands the SQL to the agent; applying it in BigQuery remains a human-owned act, ideally via the same review process as any other DDL change.

What an agent session actually looks like

A governance check-in composes naturally from these pieces. The agent calls get_vendor_integration_status with vendor: "bigquery" to confirm the estate is imported and when it last changed. It asks the pipeline for a fresh extract URL and calls audit_vendor_project with artifactUrls. If errorCount is zero it reports the warning-level story — perhaps three undocumented tables and one STRUCT column worth governing explicitly. If not, it pastes the markdown report, names the drifted objects, and proposes the two legitimate resolutions: change the estate back, or change the governed model deliberately and let generate_vendor_artifacts express the new agreement as DDL.

Two honest boundaries to plan around. First, the drift-trail verbs — reaudit, history, and the SVG badge — live on the HTTP surfaces, not MCP; an agent that wants a fresh verdict simply runs audit_vendor_project again with fresh artifacts, which is the same engine the reaudit verb uses. Second, nothing here ever touches Google credentials: the agent audits what was extracted and uploaded, which is exactly why a read-only agent on /mcp can be given this power without a security review of your GCP estate.

For the extraction query that produces the information_schema artifact and the full HTTP equivalents of every call above, see the Google BigQuery quickstart in the CoreModels documentation.