dbt MCP server: what to let an agent do with it

By Arshad Ansari

Install it, then turn most of it off.

That is my honest take on the dbt MCP server. The useful part is the read side: asking what a model does, where a column comes from, which test failed, what a metric actually means. The part that gets written up as the headline — an assistant that runs dbt build for you — is the part I would leave disabled until I had a specific reason not to. An agent that can run dbt build against production is an agent that can rewrite your warehouse and spend your compute, and it will do both cheerfully on a misread instruction.

Below: what it is, how to get it running in about ten minutes, and which of its tools I would actually hand over.

What it is

MCP, the Model Context Protocol, is "an open-source standard for connecting AI applications to external systems". A server exposes a set of named tools; any compatible client calls them. I wrote up that general pattern, including the read-only database role that makes it survivable, in connecting an AI assistant to your database with MCP.

The dbt MCP server is dbt Labs' own implementation, at github.com/dbt-labs/dbt-mcp. It is Apache 2.0 licensed — the same licence as dbt Core, which I went through in dbt Core vs dbt Cloud — and it is developed in the open. At the time of writing (September 2026) the newest release is v2.3.1, published on 11 September 2026, and the repository had commits the same week.

What it hands the assistant is not a database connection. It is dbt's view of your work: the project graph, the compiled SQL, the tests, the job history, the metric definitions. That distinction is most of why it is more useful than pointing a model at your warehouse and hoping.

The tool groups

Tools come in groups, and each group is switched on or off as a unit. The names below are the current ones, read off the repository and the docs today.

GroupWhat it doesNeeds a dbt platform account
dbt CLIcompile, parse, list, show, run, build, test, docs, clone, plus local lineage and node detailsNo
Codegengenerate_source, generate_staging_model, generate_model_yamlNo
Language server / dbt v2Column-level lineage and SQL compilation via the dbt v2 engineNo
DiscoveryMetadata from the hosted API: get_all_models, get_model_details, get_lineage, get_model_parents, get_model_children, get_model_health, get_model_performance, search, and the restYes
Semantic Layerlist_metrics, get_dimensions, get_entities, get_dimension_values, query_metrics, get_metrics_compiled_sql, list_saved_queriesYes
SQLexecute_sql and text_to_sqlYes
Administrative APIlist_jobs, get_job_run_details, get_job_run_error, artifacts — and trigger_job_run, retry_job_run, cancel_job_runYes

Two small extras sit alongside these: a product-docs group that searches dbt's own published documentation, and a server-metadata group that reports the MCP server's version and branch. Availability of the hosted groups varies by plan, so check dbt's availability table against the plan you are on rather than mine.

The shape worth noticing: everything in the top three rows runs against files on your disk, and everything in the bottom four calls dbt's hosted APIs with a token. That is the line that decides both what you can use and what you have to think about.

Ten minutes to a working setup

You need uv installed, a local dbt project, and dbt itself on your path. For Claude Code, the docs give one command:

claude mcp add dbt \
  -e DBT_PROJECT_DIR=/Users/you/projects/analytics \
  -e DBT_PATH=/opt/homebrew/bin/dbt \
  -- uvx dbt-mcp

DBT_PROJECT_DIR is the folder holding dbt_project.yml. DBT_PATH is the output of which dbt. For Claude Desktop the same thing goes in claude_desktop_config.json:

{
  "mcpServers": {
    "dbt": {
      "command": "uvx",
      "args": ["dbt-mcp"],
      "env": {
        "DBT_PROJECT_DIR": "/Users/you/projects/analytics",
        "DBT_PATH": "/opt/homebrew/bin/dbt"
      }
    }
  }
}

If the client reports spawn uvx ENOENT, put the full path from which uvx in the command field — that is the single most common setup failure in the troubleshooting docs.

To add the hosted groups you supply DBT_HOST (your dbt platform hostname), DBT_TOKEN (a personal access token or a service token), DBT_PROD_ENV_ID, and DBT_ACCOUNT_ID for the Administrative API. DBT_DEV_ENV_ID and DBT_USER_ID are needed for execute_sql, which requires a personal access token specifically — a service token will not work for it. Pass the numeric IDs, not the browser URLs they appear in; the docs call that mistake out because people keep making it.

Then test it the boring way. Ask the assistant to compile one model and list your models, and check the answer against your actual project. If it is guessing rather than calling a tool, you will see it immediately.

Now decide what it is allowed to do

This is the part I care about, and the part most write-ups skip.

The server ships with sensible-ish defaults — the SQL group and codegen are off until you enable them, and the metadata group is off too — but the CLI, Discovery, Semantic Layer, Administrative API and language-server groups are all on by default on a self-hosted install. So out of the box, an assistant that can reach your project can also run it.

dbt Labs is straight about this. The repository warns that letting your client use dbt commands through the MCP tooling "could modify your data models, sources, and warehouse objects. Proceed only if you trust the client and understand the potential impact."

Five rules, all of which I have argued for before in how to connect an LLM to your database, safely, and none of which are specific to dbt:

1. Start with everything that writes or runs disabled. Turn groups off with DISABLE_DBT_CLI, DISABLE_ADMIN_API, DISABLE_DISCOVERY, DISABLE_SEMANTIC_LAYER and friends, or take the allow-list route with the matching DBT_MCP_ENABLE_* variables. There is also finer-grained control: DISABLE_TOOLS takes a comma-separated list of individual tool names, and DBT_MCP_ENABLE_TOOLS is its allow-list twin. That is what lets you keep compile and show while dropping run, build and clone. Do not set a disable flag and an enable flag for the same group — the docs say the behaviour is unpredictable, which is a polite way of saying do not find out.

claude mcp add dbt \
  -e DBT_PROJECT_DIR=/Users/you/projects/analytics \
  -e DBT_PATH=/opt/homebrew/bin/dbt \
  -e DISABLE_ADMIN_API=true \
  -e DISABLE_TOOLS=run,build,clone \
  -- uvx dbt-mcp

2. Point the CLI tools at a dev target with a role that cannot reach production. The MCP server inherits your dbt profile, so the safety boundary is the warehouse role in that profile, not anything the server does. A development target writing to a development schema, with a role that has no rights on production schemas, is the control that actually holds. Everything else is a preference.

3. Give the token the narrowest scope that works. A token for reading metadata and querying metrics does not need permission to trigger jobs. If your plan supports service tokens with scoped permissions, use one, and keep your personal access token for the one tool that demands it.

4. Keep a human between the agent and anything consequential. trigger_job_run is the clearest example: it starts your production scheduler from a chat message. A proposal an engineer reads and approves is a different object from an action an agent takes. That gate is the central idea of AEGIS, the automation platform I build and run — the model does the expensive thinking, and a person presses the button on anything that changes state.

5. Log what the agent asked for. Every tool call is an event with a name and arguments. Keep them. When a number looks wrong or a run appears that nobody remembers starting, the trail is the difference between an answer and a shrug. The server's DBT_MCP_LOG_LEVEL variable gives you a DEBUG setting when you want the detail.

None of this is exotic. It is the same read-only-by-default, allow-list, approve-before-acting, log-everything shape I apply to any LLM with access to real systems.

Which tools for which job

What you are doingEnableLeave off
Understanding a project you did not writeDiscovery, product docs; CLI limited to compile, parse, list, showCLI run, build, clone; SQL; Administrative API
Writing and testing a model in devThe above plus run, build, test against a dev target, plus codegenAdministrative API; anything pointed at a production target
Answering business questions from metricsSemantic Layer, plus Discovery for contextCLI entirely; SQL; Administrative API
Operating jobsAdministrative API read tools: list_jobs, get_job_run_details, get_job_run_errortrigger_job_run, retry_job_run, cancel_job_run — unless a person approves each one

The second row is the one to be deliberate about. An agent iterating on a model in dev — write, run, read the error, fix — is genuinely good at the job, which is the whole argument of letting Claude Code write your dbt models. It is also the row where a wrong profiles.yml target turns a helpful loop into a production incident. Check the target before you enable the group, not after.

Why metrics beat text-to-SQL here

The SQL group contains text_to_sql, and it is tempting: ask a question in English, get SQL, run it. I would reach for the Semantic Layer first, and only fall back to free-written SQL when the question genuinely has not been modelled.

The reason is narrow and practical. With query_metrics, the model is not composing a query over your raw tables — it is picking a metric, a set of dimensions and a filter from a list you wrote. Revenue means what your team agreed revenue means, joins are the ones defined in the semantic model, and the space of wrong answers is bounded by what you exposed. With text-to-SQL, the model is inventing the definition every time it is asked, and a plausible-looking number with a subtly wrong join is worse than no number, because someone will act on it. get_metrics_compiled_sql closes the loop by letting you see the SQL a metric query would produce before you trust it.

The cost is that you only get answers to questions you modelled, and building that model is real work. I unpack what the dbt Semantic Layer is and when it earns that work in the semantic layer explained. If you have one, it is the safest interface on this whole server. If you do not, that is an argument for building one before it is an argument for text_to_sql.

One billing detail worth knowing: as of September 2026, text_to_sql is the only MCP tool that consumes your dbt Copilot action allotment, and when an account runs out of actions the remote server blocks every tool until the limit resets. So an unmetered convenience it is not.

Local or remote

There are two servers, and the choice is mostly made for you by what you want to do.

The self-hosted server runs on your machine with uvx dbt-mcp. It can see your project directory, which is why it is the only one that supports CLI commands, codegen and the local language-server tools. It is the development setup.

The remote server is hosted by dbt and reached over HTTP at your account's MCP endpoint, authenticated with an Authorization header and environment-id headers, or with OAuth on the paid plans. Nothing to install, nothing to keep updated — and no local project, so no dbt CLI commands at all. It is the consumption setup: metrics, metadata, lineage, job history. Rate limits follow dbt's standard API limits rather than anything MCP-specific.

If you want an agent that helps write models, you want local. If you want an assistant that answers questions about a project it will never edit, remote is less machinery and a smaller surface — which, for a tool used by people who are not engineers, is a feature.

The neighbours

dbt is not the only one shipping a server. MotherDuck maintains mcp-server-motherduck, an MIT-licensed local server for both DuckDB and MotherDuck, which is the obvious companion if your analytical store is a DuckDB file rather than a warehouse. Snowflake documents a Snowflake-managed MCP server that exposes its Cortex surface and SQL engine to agents without you deploying anything, and most of the large warehouse vendors now have something equivalent. They solve a different problem from dbt's: they expose the data, dbt exposes the definitions and the graph over it. Running both is reasonable, and it doubles the number of write-capable tools sitting in one assistant's context — which is an argument for auditing the whole set, not each one on its own.

Where I would start

Install the self-hosted server against a dev project, with run, build and clone disabled and the Administrative API off. Spend a week asking it questions you would otherwise have answered by reading the DAG. Enable the write side only when you have a development target you would be comfortable letting a junior engineer rebuild at 2am — because that is the thing you are actually granting.

If you want to check the rest of your AI setup with the same eyes, the AI workflow teardown is the list of questions I ask before an LLM workflow goes near production. It is free and there is no email box in the way.

Common questions

What is the dbt MCP server?
It is dbt Labs' own Model Context Protocol server: a small program that exposes your dbt project and your dbt platform account to an AI client such as Claude Code, Claude Desktop, Cursor or VS Code as a set of named tools. Instead of a raw database connection, the assistant gets dbt's view of things — models, lineage, tests, job runs, governed metrics — plus the ability to run dbt commands if you let it. The source is at github.com/dbt-labs/dbt-mcp and it is Apache 2.0 licensed. At the time of writing (September 2026) the latest release is v2.3.1, published on 11 September 2026.
Is the dbt MCP server free?
The server itself is free and open source under the Apache 2.0 licence, the same licence as dbt Core. What is not free is what some of its tools talk to. The dbt CLI, codegen and language-server tools work against a local project with no account at all. The Semantic Layer, Discovery, SQL and Administrative API tools call dbt platform APIs, so they need a dbt platform account and a token, and which of those APIs you can reach depends on your plan. As of September 2026 the `text_to_sql` tool also consumes your dbt Copilot action allotment; the other tools do not.
Does the dbt MCP server work with dbt Core?
Yes, for a useful subset. Point it at a local project with two environment variables — `DBT_PROJECT_DIR` for the folder holding `dbt_project.yml` and `DBT_PATH` for your dbt executable — and the dbt CLI tools work with no dbt platform account: `compile`, `parse`, `list`, `show`, `run`, `build`, `test`, `docs`, `clone`, plus local lineage and node details. Codegen and the language-server tools are local too. Everything that reads from dbt's hosted APIs — metadata discovery, metrics, job runs — needs an account.
How do I connect Claude to dbt?
For Claude Code, install `uv` and run one command from the dbt docs, at the time of writing (September 2026): `claude mcp add dbt -e DBT_PROJECT_DIR=/path/to/project -e DBT_PATH=/path/to/dbt -- uvx dbt-mcp`. For Claude Desktop, add the same command and environment variables to `claude_desktop_config.json` under `mcpServers` and restart the app. If you get a `spawn uvx ENOENT` error, replace `uvx` with its full path. Then ask the assistant to compile a model or list your models, and check it answers from your real project.
Is it safe to let an AI agent run dbt?
It is safe in a development target with a warehouse role that cannot touch production schemas, and it is not safe anywhere else without a person in the loop. `dbt run`, `dbt build` and `dbt clone` create and replace objects in your warehouse and spend compute doing it, and dbt Labs says so plainly in the repository. Allowing a client to use dbt commands through the MCP tooling "could modify your data models, sources, and warehouse objects. Proceed only if you trust the client and understand the potential impact." Start with those tools disabled, enable them against dev only, and keep a human approving anything that changes production data or triggers a job.
What is the difference between the local and remote dbt MCP server?
The self-hosted server runs on your machine via `uvx dbt-mcp` and can see your local dbt project, so it is the one that supports CLI commands and codegen. The remote server is hosted by dbt and reached over HTTP at your account's MCP endpoint, so there is nothing to install — but it has no access to a local project and does not support dbt CLI commands such as `dbt run`, `dbt build` or `dbt test`. As of September 2026 remote is for consumption: querying metrics, exploring metadata, reading lineage and job history. It authenticates with an Authorization header plus environment-id headers, or with OAuth on the Starter, Enterprise and Enterprise+ plans.
Can an LLM query my metrics through dbt?
Yes, through the Semantic Layer tools, and this is the interface I would give it first. The model calls `list_metrics`, `get_dimensions`, `get_entities` and `get_dimension_values` to see what exists, then `query_metrics` to get numbers back — it picks from definitions you wrote rather than writing SQL over your raw tables. `get_metrics_compiled_sql` shows the SQL that would run, so you can check it. The Semantic Layer is a dbt platform feature, so this needs an account and the right plan.
Which dbt MCP tools should I disable?
Start with everything that writes, runs or spends, and add back what you need. That means the Administrative API group, whose `trigger_job_run`, `retry_job_run` and `cancel_job_run` operate your production scheduler; the SQL group, which is off by default anyway; and the write-side CLI tools `run`, `build` and `clone` until you have a development target wired up. The self-hosted server has a `DISABLE_TOOLS` variable that takes a comma-separated list of individual tool names, and `DBT_MCP_ENABLE_TOOLS` for the allow-list version. Do not set both a disable and an enable flag for the same group.

Get new posts by email

Data engineering notes like this one — pipelines, warehouse cost, and what actually breaks in production. A few a month, never padded to hit a schedule.

No sequence, no pitch deck. Reply 'stop' once and you're off — it reaches me, not a queue.

Want the whole playbook?

If this was useful, the long version is my book. Local-First Analytics — 314 pages, runnable code for every chapter — is the full build: DuckDB, Parquet and Arrow, from install to production. On Amazon, or request a free review copy.

Get the book

Not ready to buy? Read chapter 1 free — the whole chapter, no email required.

Rather talk it through? Book a free 30-minute call. No slot that suits your time zone? Email [email protected].