With task installed, simply run task to see the list of available commands. For comments, questions, or requests open a GitHub issue.
- Clone the repository:
git clone https://github.com/dbt-labs/dbt-mcp.git
cd dbt-mcp-
Run
task install -
Configure environment variables:
cp .env.example .env
Then edit
.envwith your specific environment variables (see our docs to determine the values). -
Run
task clientto chat with dbt MCP in your terminal.
Refer to ./cursor/rules for standards and stylistic guidelines.
This repo has automated tests which can be run with task test:unit.
The integration tests exercise system interactions greater than just the unit tests. They require a dbt Platform environment that is setup with semantic layer, developer license, and PAT. These tests can be run with task test:integration.
For dbt Labs employees, a staging environment has been set up. Credentials for this environment can be found by searching for dbt MCP Integration Test Credentials in 1Password.
To test in a client like Cursor or Claude, use a configuration file like this:
{
"mcpServers": {
"dbt": {
"command": "<path-to-uv>",
"args": [
"--directory",
"<path-to-this-directory>/dbt-mcp",
"run",
"dbt-mcp",
"--env-file",
"<path-to-this-directory>/dbt-mcp/.env"
]
}
}
}
Or, if you would like to test with Oauth, use a configuration like this:
{
"mcpServers": {
"dbt": {
"command": "<path-to-uv>",
"args": [
"--directory",
"<path-to-this-directory>/dbt-mcp",
"run",
"dbt-mcp",
],
"env": {
"DBT_HOST": "<dbt-host-with-custom-subdomain>",
}
}
}
}
For improved debugging, you can set the DBT_MCP_SERVER_FILE_LOGGING=true environment variable to log to a ./dbt-mcp.log file.
Tools are defined using the @dbt_mcp_tool decorator and registered with the MCP server via register_tools().
- Add a
ToolNameentry insrc/dbt_mcp/tools/tool_names.py - Map it to a toolset in
src/dbt_mcp/tools/toolsets.py(e.g.,DISCOVERY,SEMANTIC_LAYER,SQL) - Write a prompt file in
src/dbt_mcp/prompts/<category>/describing the tool - Define the tool function in the appropriate
tools.pymodule:@dbt_mcp_tool( description=get_prompt("category/tool_name"), title="My Tool", read_only_hint=True, destructive_hint=False, idempotent_hint=True, ) async def my_tool(context: MyToolContext, param: str) -> dict: return await context.fetcher.do_something(param)
- Add it to the tool list (e.g.,
DISCOVERY_TOOLS) in the same module - The registration function (e.g.,
register_discovery_tools) handles context binding and registration
MCP Apps are tools that have an associated interactive UI rendered by the host (e.g., Claude, VS Code). They build on top of regular tools with two additions:
-
Use
structured_outputandmetato link the tool to a UI resource:@dbt_mcp_tool( description=get_prompt("category/tool_name"), title="My Visualization", read_only_hint=True, structured_output=True, meta={"ui": {"resourceUri": "ui://dbt-mcp/my-app"}}, ) async def my_viz_tool(context: MyToolContext, param: str) -> MyResult: ...
structured_output=Trueis required so the host can pass structured JSON to the UI. The return type should be a Pydantic model. -
Register an MCP resource at the matching
ui://URI to serve the HTML app:@dbt_mcp.resource( uri="ui://dbt-mcp/my-app", name="My App", mime_type="text/html;profile=mcp-app", ) def get_my_app_ui() -> str: return Path("packages/my-app/dist/index.html").read_text()
-
Build a frontend in
packages/using@modelcontextprotocol/ext-apps. The app receives tool results via theontoolresultcallback and must be bundled as a single HTML file (e.g., usingvite-plugin-singlefile) or reference external resources via CSPresourceDomains.
The ui:// URI convention is ui://<server-name>/<resource-name>. The meta field is passed through the full tool registration pipeline (@dbt_mcp_tool → GenericToolDefinition → adapt_context → register_tools → FastMCP.add_tool).
Before committing changes, ensure that you have set up signed commits. This repo requires signing on all commits for PRs.
Every PR requires a changelog entry. Install changie and run changie new to create a new changelog entry.
The dbt-mcp server runs with stdio transport by default which does not allow for Python debugger support. For debugging with breakpoints, use streamable-http transport.
- Run
task inspector- this starts both the server and inspector automatically - Open MCP Inspector UI
- Use "STDIO" Transport Type to connect
- Test tools interactively in the inspector UI (uses
stdiotransport, no debugger support)
- Set breakpoints in your code
- Press
F5or select "debug dbt-mcp" from the Run menu - Open MCP Inspector UI via
npx @modelcontextprotocol/inspector - Connect to
http://localhost:8000/mcp/v1using "Streamable HTTP" transport and "Via Proxy" connection type - Call tools from Inspector - your breakpoints will trigger
- Run
task dev- this starts the server withstreamable-httptransport onhttp://localhost:8000 - Set breakpoints in your code
- Attach your debugger manually (see debugpy documentation for examples)
- Open MCP Inspector via
npx @modelcontextprotocol/inspector - Connect to
http://localhost:8000/mcp/v1using "Streamable HTTP" transport and "Via Proxy" connection type - Call tools from Inspector - your breakpoints will trigger
Note: task dev uses streamable-http by default. The streamable-http transport allows the debugger and MCP Inspector to work simultaneously without conflicts. To override, use MCP_TRANSPORT=stdio task dev.
If you encounter any problems, you can try running task run to see errors in your terminal.
Only people in the CODEOWNERS file should trigger a new release with these steps:
- Consider these guidelines when choosing a version number:
- Major
- Removing a tool or toolset without replacement, or in a way that would result in agents behaving much differently.
- Changing the behavior of existing environment variables or configurations
- Minor
- Changes to config system related to the function signature of the register functions (e.g.
register_discovery_tools) - Adding optional parameters to a tool function signature
- Adding a new tool or toolset
- Removing or adding non-optional parameters from tool function signatures
- Renaming a tool
- Removing a tool which overlaps or provides similar functionality as other tool(s)
- Changes to config system related to the function signature of the register functions (e.g.
- Patch
- Bug and security fixes - only major security and bug fixes will be back-ported to prior minor and major versions
- Dependency updates which don’t change behavior
- Minor enhancements
- Editing a tool or parameter description prompt
- Adding an allowed environment variable with the
DBT_MCP_prefix
- Trigger the Create release PR Action.
- If the release is NOT a pre-release, select
auto(default) to automatically determine the version bump based on changelog entries, or manually pick patch, minor or major if needed - If the release is a pre-release, set the bump and the pre-release suffix. We support alpha.N, beta.N and rc.N.
- use alpha for early releases of experimental features that specific people might want to test. Significant changes can be expected between alpha and the official release.
- use beta for releases that are mostly stable but still in development. It can be used to gather feedback from a group of peopleon how a specific feature should work.
- use rc for releases that are mostly stable and already feature complete. Only bugfixes and minor changes are expected between rc and the official release.
- Picking the prerelease suffix will depend on whether the last release was the stable release or a pre-release:
| Last Stable | Last Pre-release | Bump | Pre-release Suffix | Resulting Version |
|---|---|---|---|---|
| 1.2.0 | - | minor | beta.1 | 1.3.0-beta.1 |
| 1.2.0 | 1.3.0-beta.1 | minor | beta.2 | 1.3.0-beta.2 |
| 1.2.0 | 1.3.0-beta.2 | minor | rc.1 | 1.3.0-rc.1 |
| 1.2.0 | 1.3.0-rc.1 | minor | 1.3.0 | |
| 1.2.0 | 1.3.0-beta.2 | minor | - | 1.3.0 |
| 1.2.0 | - | major | rc.1 | 2.0.0-rc.1 |
| 1.2.0 | 2.0.0-rc.1 | major | - | 2.0.0 |
- Get this PR approved & merged in (if the resulting release name is not the one expected in the PR, just close the PR and try again step 1)
- This will trigger the
Release dbt-mcpAction. On theSummarypage of this Action a member of theCODEOWNERSfile will have to manually approve the release. The rest of the release process is automated.