DBT Core MCP Server
The DBT Core MCP Server enables AI assistants to act as dbt pair programmers through natural language, providing comprehensive project analysis, execution, and management capabilities without requiring dbt dependencies in the server itself.
Key Capabilities:
Project Awareness & Diagnostics: Access project metadata (name, version, adapter type, resource counts) and validate your environment using
dbt debugResource Discovery: List and retrieve detailed information for all dbt resources (models, sources, seeds, snapshots, tests) including compiled SQL and column definitions
Lineage & Impact Analysis: Trace upstream/downstream dependencies and calculate the blast radius of changes with dependency trees and impact statistics
Smart Execution: Run dbt commands (
run,test,build,seed,snapshot) with intelligent selection modes includingmodified_onlyandmodified_downstreamfor change detectionDatabase Querying: Execute SQL queries against your database with full support for dbt Jinja templating (
ref(),source())Package Management: Install dbt packages interactively
Schema Change Detection: Automatically detect column changes and recommend downstream updates
Concurrency Safety: Detect and wait for existing dbt processes to prevent conflicts
Environment Integration:
Works with your existing dbt setup (any adapter, any version 1.9.0+) using a bridge execution pattern
Automatically detects and uses your Python environment (uv, poetry, venv, conda)
No dbt dependencies required in the server itself
Limitations:
Python models are not currently supported (SQL-based models only)
Requires dbt Core 1.9.0 or higher
Enables interaction with DBT (Data Build Tool) projects, allowing querying of project metadata, inspection of models, sources, and tests, viewing compiled SQL, running DBT commands, and accessing DBT documentation and lineage.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@DBT Core MCP Servershow me what depends on the customers model"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
dbt Core MCP Server
Meet your new dbt pair programmer - the one who actually understands your environment, respects your workflow, and does the heavy lifting.
Why This Changes Everything
If you've tried other dbt tools with Copilot (dbt power user, datamate, etc.), you know the pain:
They don't respect your Python environment
They can't see your actual project structure
They fail when adapters are missing from THEIR environment
You end up doing the work yourself anyway
dbt-core-mcp is different. It's not just another plugin - it's a true pair programming partner that:
Zero dbt Dependencies: Our server needs NO dbt-core, NO adapters - works with YOUR environment
Stays in Flow: Keep the conversation going with Copilot while it handles dbt commands, runs tests, and analyzes impact
Respects Your Environment: Detects and uses YOUR exact dbt version, YOUR adapter, YOUR Python setup (uv, poetry, venv, conda)
Actually Helps: Instead of generic suggestions, you get real work done - "run my changes and test downstream" actually does it
Knows Your Project: Full access to your models, lineage, sources, and compiled SQL - no guessing, no manual lookups
Before dbt-core-mcp
You: "Copilot, help me understand what depends on stg_orders"
Copilot: "You should check the manifest.json or run dbt list..."
You: Switches to terminal, runs commands, copies output back...With dbt-core-mcp
You: "What depends on stg_orders?"
Copilot: Shows full lineage, impact analysis, and affected models instantly
You: "Run my changes and test everything downstream"
Copilot: Does it. Reports results. You focus on the next step.
This is pair programming the way it should be - you focus on the logic, Copilot handles the execution. No context switching, no terminal juggling, just flow.
Related MCP server: dbt MCP Server
What You Get (Features & Benefits)
🔥 Zero dbt Dependencies: Server has NO dbt-core, NO adapters - ultimate environment respect
Natural Language Control: Just talk - "run my changes and test downstream" actually works
Bridge Execution: Automatically detects YOUR environment and runs dbt with YOUR versions
Works with ANY Adapter: duckdb, snowflake, postgres, bigquery, databricks - if you have it, we work with it
Smart Selection: Automatic change detection - run only what changed, or changed + downstream
Full Project Awareness: Lineage analysis, impact assessment, compiled SQL - instant access to everything
Peek Inside CTEs: Query individual CTEs inside any model to see intermediate results, debug transformations, and design realistic fixtures
True Pair Programming: Stay in conversation with Copilot while it executes dbt commands and reports results
Schema Change Detection: Automatically detects column changes and recommends downstream updates
No Configuration Needed: Works with your existing dbt setup - any adapter, any database, any version
Concurrency Safe: Detects and waits for existing dbt processes to prevent conflicts
This server provides tools to interact with dbt projects via the Model Context Protocol, enabling AI assistants to:
Query dbt project metadata and configuration
Get detailed model and source information with full manifest metadata
Execute SQL queries with Jinja templating support ({{ ref() }}, {{ source() }})
Inspect models, sources, and tests
Access dbt documentation and lineage
Natural Language, Powerful Results
Just talk to Copilot naturally - no need to memorize commands or syntax:
Explore your project
You: "What models do we have in this project?"
Copilot: Shows all models with materialization types and tagsUnderstand dependencies
You: "Show me what the customers model depends on"
Copilot: Displays full lineage with upstream sources and modelsRun smart builds
You: "Run only the models I changed and test everything downstream"
Copilot: Executes dbt with smart selection, runs tests, reports results
Get It Running (2 Minutes)
If you don't have Python installed, get it at python.org/downloads - you'll need Python 3.9 or higher.
Don't have uv yet? Install it with: pip install uv or see docs.astral.sh/uv
Option 1: One-Click Install (Easiest)
Click the badge for your VS Code version:
That's it! The server will automatically start when you open a dbt project.
Option 2: Manual Configuration
Add this to your .vscode/mcp.json file in your dbt project workspace:
{
"servers": {
"dbt-core": {
"command": "uvx",
"args": ["dbt-core-mcp"]
}
}
}Or if you prefer pipx:
{
"servers": {
"dbt-core": {
"command": "pipx",
"args": ["run", "dbt-core-mcp"]
}
}
}The server will automatically use your workspace directory as the dbt project location.
Option 3: Bleeding Edge (Latest from GitHub)
For the impatient who want the latest features immediately:
With uvx:
{
"servers": {
"dbt-core": {
"command": "uvx",
"args": [
"--from",
"git+https://github.com/NiclasOlofsson/dbt-core-mcp.git",
"dbt-core-mcp"
]
}
}
}With pipx:
{
"servers": {
"dbt-core": {
"command": "pipx",
"args": [
"run",
"--no-cache",
"--spec",
"git+https://github.com/NiclasOlofsson/dbt-core-mcp.git",
"dbt-core-mcp"
]
}
}
}Getting Updates:
When using git installation, uvx and pipx cache the downloaded code. To get the latest changes:
# For uvx users
uv cache clean dbt-core-mcp
# For pipx users (--no-cache prevents caching)
# Already configured in the pipx setup aboveAfter cleaning the cache, restart VS Code or your MCP client to pick up the latest version.
Optional Configuration
Command Timeout
By default, dbt commands have no timeout (they can run as long as needed). For complex models that take a long time to compile, you can set a timeout or explicitly disable it:
{
"servers": {
"dbt-core": {
"command": "uvx",
"args": [
"dbt-core-mcp",
"--dbt-command-timeout", "300" // 5 minutes, or use 0 for no timeout (default)
]
}
}
}Project Directory
The server automatically detects your dbt project from the workspace root. If your dbt project is in a subdirectory or you need to specify a different location, use --project-dir with either a relative or absolute path:
{
"servers": {
"dbt-core": {
"command": "uvx",
"args": [
"dbt-core-mcp",
"--project-dir", "path/to/dbt/project" // relative or absolute path
]
}
}
}Requirements
For the MCP Server:
Python 3.9 or higher
NO dbt-core required, NO adapters required - just install
dbt-core-mcp
For Your dbt Project:
dbt Core 1.9.0 or higher
Any dbt adapter (dbt-duckdb, dbt-postgres, dbt-snowflake, dbt-databricks, etc.)
The server automatically detects and uses YOUR project's dbt installation via bridge execution.
Limitations
Python models: Not currently supported. Only SQL-based dbt models are supported at this time.
dbt Version: Requires dbt Core 1.9.0 or higher
Available Tools
Don't worry about memorizing these - you don't need to know tool names or parameters. Just talk naturally to Copilot and it figures out what to use. This reference is here for the curious who want to understand what's happening under the hood.
Pro tip: Focus on the conversational examples (You: / Copilot:) - they show how to actually use these tools in practice.
Project Information
get_project_info
Get basic information about your dbt project including name, version, adapter type, and resource counts. By default, also runs dbt debug to validate your environment and test the database connection.
You: "What dbt version is this project using?"
Copilot: Shows project info with dbt version, adapter type, and connection statusYou: "How many models and sources are in this project?"
Copilot: Displays counts and project overview with diagnosticsYou: "Is my database connection working?"
Copilot: Shows connection test results from dbt debugYou: "Check my dbt setup"
Copilot: Runs full environment validation and reports any issues
Parameters:
run_debug: Rundbt debugto validate environment and test connection (default: True)
Returns: Project metadata plus diagnostic results including:
Database connection status (ok/failed/unknown)
Environment validation output
System and dependency checks
Note: Set run_debug=False to skip diagnostics and get only basic project info (faster for repeated queries).
Resource Discovery (Unified Tools)
One tool, all resource types - these unified tools work across models, sources, seeds, snapshots, and tests. No need for separate tools for each type.
list_resources
List all resources in your project, or filter by type (models, sources, seeds, snapshots, tests).
You: "Show me all resources in this project"
Copilot: Lists all models, sources, seeds, snapshots, and testsYou: "What models do we have?"
Copilot: Filters to show only models with their materialization typesYou: "List all data sources"
Copilot: Shows configured sources with schemas and descriptionsYou: "Show me the seeds"
Copilot: Displays CSV seed files available in the projectYou: "Which models are materialized as tables?"
Copilot: Filters models by materialization type
Parameters:
resource_type: Optional filter -"model","source","seed","snapshot","test", orNonefor all
Returns: Consistent structure for all types with common fields (name, description, tags) plus type-specific details (materialization, source_name, etc.)
get_resource_info
Get detailed information about any resource - works for models, sources, seeds, snapshots, and tests.
You: "Show me details about the customers model"
Copilot: Displays full model metadata, config, column information, and compiled SQLYou: "What's in the raw_customers source?"
Copilot: Shows source schema, columns, and freshness configurationYou: "Describe the country_codes seed"
Copilot: Returns seed configuration and column definitionsYou: "What columns does the orders model have?"
Copilot: Shows column names, types, and descriptions from databaseYou: "Show me the compiled SQL for customers"
Copilot: Returns model info with compiled SQL (all Jinja resolved)You: "Tell me about the customer_snapshot"
Copilot: Displays snapshot configuration and SCD tracking setup
Parameters:
name: Resource name (e.g., "customers", "jaffle_shop.raw_orders")resource_type: Optional - auto-detects if not specifiedinclude_database_schema: Include actual column types from database (default: true)include_compiled_sql: Include compiled SQL with Jinja resolved (default: true, models only)
Auto-detection: Just provide the name - the tool automatically finds it whether it's a model, source, seed, snapshot, or test. For sources, use "source_name.table_name" format or just the table name.
Compiled SQL: For models, automatically includes compiled SQL with all {{ ref() }} and {{ source() }} resolved to actual table names. Will trigger dbt compile if not already compiled. Set include_compiled_sql=False to skip compilation.
Lineage & Impact Analysis (Unified Tools)
Understand relationships across all resource types - analyze dependencies and impact for models, sources, seeds, snapshots, and tests.
get_lineage
Trace dependency relationships for any resource - shows what it depends on (upstream) and what depends on it (downstream).
You: "Show me the lineage for the customers model"
Copilot: Displays full dependency tree with upstream sources and downstream modelsYou: "What does stg_orders depend on?"
Copilot: Shows upstream dependencies (sources and parent models)You: "What's downstream from the raw_customers source?"
Copilot: Shows all models that use this sourceYou: "Where does the revenue model get its data from?"
Copilot: Displays upstream lineage with all source dataYou: "Show me everything that uses the country_codes seed"
Copilot: Lists all downstream models that reference this seed
Parameters:
name: Resource name (works for models, sources, seeds, snapshots, tests)direction:"upstream"(sources),"downstream"(dependents), or"both"(default)depth: Maximum levels to traverse (None for unlimited, 1 for immediate, etc.)resource_type: Optional - auto-detects if not specified
Returns: Dependency tree with statistics (upstream_count, downstream_count, total_dependencies)
Use cases:
Understand data flow and relationships
Explore where resources get their data
See what depends on specific resources
Impact analysis before making changes
analyze_impact
Analyze the blast radius of changing any resource - shows all downstream dependencies that would be affected.
You: "What's the impact of changing the stg_customers model?"
Copilot: Shows all downstream models, tests, and affected resourcesYou: "If I modify the raw_orders source, what needs to run?"
Copilot: Lists impacted models grouped by distance with recommended commandsYou: "What breaks if I change the country_codes seed?"
Copilot: Shows total impact count and affected resourcesYou: "How many models depend on this snapshot?"
Copilot: Displays impact statistics and dependency count
Parameters:
name: Resource name (works for models, sources, seeds, snapshots, tests)resource_type: Optional - auto-detects if not specified
Returns:
Affected resources grouped by distance from the changed resource
Count of affected tests and other resources
Total impact statistics
Context-aware recommended dbt commands (e.g.,
dbt run -s stg_customers+)Impact level message (No/Low/Medium/High)
Use cases:
Before refactoring: understand blast radius
Planning incremental rollouts
Estimating rebuild time after changes
Risk assessment for modifications
get_column_lineage
Trace column-level lineage through SQL transformations - see exactly how columns flow through CTEs, joins, aggregations, and transformations.
You: "Show me where the revenue column comes from"
Copilot: Traces upstream through CTEs showing each transformation stepYou: "How does customer_id flow through the customers model?"
Copilot: Shows CTE chain: final → customer_agg → orders → stg_ordersYou: "What columns use customer_id downstream?"
Copilot: Displays all downstream models and columns that reference itYou: "Trace order_total from source to final output"
Copilot: Shows complete transformation path with CTEs and expressionsYou: "What transformations happen to price in this model?"
Copilot: Lists each CTE that transforms the column with SQL expressions
Parameters:
model_name: Name of the dbt model to analyzecolumn_name: Name of the column to tracedirection:"upstream"(sources),"downstream"(usage), or"both"(default)depth: Maximum levels to traverse (None for unlimited, 1 for immediate, etc.)
Returns: Column-level dependencies with detailed transformation tracking:
via_ctes: List of CTE names in transformation order (shows the path through internal CTEs)
transformations: Detailed transformation at each step (CTE name, column, SQL expression)
dependencies: Source columns and tables with full qualification
dbt resource mapping: Links to source models and sources
CTE Transformation Tracking:
The tool tracks how columns flow through Common Table Expressions (CTEs) inside models:
customer_agg.order_count
└─ via_ctes: ["final", "customer_agg"]
└─ transformations:
- CTE: final
Column: order_count
Expression: COALESCE(customer_agg.order_count, 0)
- CTE: customer_agg
Column: order_count
Expression: COUNT(orders.order_id)This shows you:
Which CTEs the column passes through (
via_ctes)Exactly how it's transformed at each step (
transformations)The SQL expression used at every transformation point
Use cases:
Understand complex SQL transformations step-by-step
Debug why a column has unexpected values (trace the transformation chain)
Find all sources for a calculated column
See downstream usage before renaming columns
Document data lineage for compliance/auditing
Identify optimization opportunities in CTE chains
Note: Requires the model to be compiled (dbt compile). Uses sqlglot to parse SQL and trace column flows.
Database Queries
query_database
Execute SQL queries against your database using dbt's ref() and source() functions. Results can be displayed inline or exported to CSV/TSV files for analysis.
You: "Show me 10 rows from the customers model"
Copilot: Executes SELECT * FROM {{ ref('customers') }} LIMIT 10 and displays resultsYou: "Show me the customer_agg CTE from customers with order_count > 5"
Copilot: Extracts just that CTE (with upstream deps), applies your filter, and shows the rowsYou: "Great, use that output to shape my CTE unit test fixtures"
Copilot: Done. You get realistic input/output examples without running the whole modelYou: "Count the orders in the staging table"
Copilot: Runs SELECT COUNT() and shows the count*You: "What's the schema of stg_payments?"
Copilot: Queries column information and displays schemaYou: "Export customers data to CSV for analysis"
Copilot: Saves query results to a CSV file you can open in ExcelYou: "Save all orders to a TSV file"
Copilot: Exports data in tab-separated format for import into other toolsYou: "Run the orders_with_flags CTE from customers_enriched sorted by most recent"
Copilot: Executes just that CTE (includes upstream deps), applies ORDER BY/LIMIT, and shows the slice you need to reason about the logicYou: "Use that to build a realistic CTE unit test fixture"
Copilot: Yes—now your fixtures match real shapes and edge cases
What you can do:
Query any model using
{{ ref('model_name') }}or source using{{ source('source_name', 'table_name') }}Query any individual CTE inside a model with
cte_name+model_name, and optionally addsqlfor WHERE/ORDER BY/LIMIT to zoom in on exactly what a step producesGet results displayed directly in the conversation (good for small result sets)
Export to CSV or TSV files (perfect for large datasets or further analysis in Excel/other tools)
Automatically handles large results without overwhelming the conversation
Execution Tools
run_models
Run dbt models with state-based selection for fast development. Requires previous state (from a prior run) to detect modifications.
You: "Run only the models I changed"
Copilot: Uses state comparison to detect and run only modified modelsYou: "Run my changes and everything downstream"
Copilot: Runs modified models plus all downstream dependenciesYou: "Run the customers model"
Copilot: Executes dbt run --select customersYou: "Build all mart models with a full refresh"
Copilot: Runs dbt run --select marts. --full-refresh*You: "Run modified models and check for schema changes"
Copilot: Runs models and detects added/removed columns
State-based selection modes:
select_state_modified: Run only models that changed (requires previous state)select_state_modified_plus_downstream: Run changed models + everything downstream
How state works:
First run establishes baseline state automatically
Subsequent runs compare against this state to detect changes
If no previous state exists, returns success (cannot determine modifications)
State is saved automatically after each successful run
Other parameters:
select: Model selector (e.g., "customers", "tag:mart")exclude: Exclude modelsfull_refresh: Force full refresh for incremental modelsfail_fast: Stop on first failurecheck_schema_changes: Detect column additions/removals
Schema Change Detection: When enabled, detects added or removed columns and recommends running downstream models to propagate changes.
test_models
Run dbt tests with state-based selection. Requires previous state to detect modifications.
You: "Test only the models I changed"
Copilot: Uses state comparison to test only modified modelsYou: "Run tests for my changes and downstream models"
Copilot: Tests modified models and everything affected downstreamYou: "Test the customers model"
Copilot: Executes dbt test --select customersYou: "Run all tests for staging models"
Copilot: Runs dbt test --select staging.
State-based selection modes:
select_state_modified: Test only changed models (requires previous state)select_state_modified_plus_downstream: Test changed models + downstreamIf no previous state exists, returns success (cannot determine modifications)
Other parameters:
select: Test selector (e.g., "customers", "tag:mart")exclude: Exclude testsfail_fast: Stop on first failure
build_models
Run models and tests together in dependency order (most efficient approach). Supports state-based selection.
You: "Build my changes and everything downstream"
Copilot: Uses state comparison to build modified models and dependenciesYou: "Run and test only what I modified"
Copilot: Executes dbt build on changed models onlyYou: "Build the entire mart layer with tests"
Copilot: Runs dbt build --select marts. with all tests*
State-based selection modes:
select_state_modified: Build only changed models (requires previous state)select_state_modified_plus_downstream: Build changed models + downstreamIf no previous state exists, returns success (cannot determine modifications)
seed_data
Load seed data (CSV files) from seeds/ directory into database tables.
You: "Load all seed data"
Copilot: Runs dbt seed and loads all CSV filesYou: "Load only the seeds I changed"
Copilot: Detects modified seed files and loads themYou: "Reload the raw_customers seed file"
Copilot: Executes dbt seed --select raw_customers --full-refreshYou: "Show me what's in the country_codes seed"
Copilot: Displays preview of loaded seed data
Seeds are typically used for reference data like country codes, product categories, etc.
State-based selection modes:
select_state_modified: Load only seeds that changed (requires previous state)select_state_modified_plus_downstream: Load changed seeds + downstream dependenciesIf no previous state exists, returns success (cannot determine modifications)
Other parameters:
select: Seed selector (e.g., "raw_customers", "tag:lookup")exclude: Exclude seedsfull_refresh: Truncate and reload seed tablesshow: Show preview of loaded data
Important: Change detection works via file hash:
Seeds < 1 MiB: Content changes detected ✅
Seeds ≥ 1 MiB: Only file path changes detected ⚠️
For large seeds, use manual selection or run all seeds.
snapshot_models
Execute dbt snapshots to capture slowly changing dimensions (SCD Type 2).
You: "Run all snapshots"
Copilot: Executes dbt snapshot for all snapshot modelsYou: "Execute the customer_history snapshot"
Copilot: Runs dbt snapshot --select customer_historyYou: "Run daily snapshots"
Copilot: Executes snapshots tagged with 'daily'
Snapshots track historical changes by recording when records were first seen, when they changed, and their state at each point in time.
Parameters:
select: Snapshot selector (e.g., "customer_history", "tag:daily")exclude: Exclude snapshots
Note: Snapshots are time-based and should be run on a schedule (e.g., daily/hourly), not during interactive development. They do not support smart selection.
install_deps
Install dbt packages defined in packages.yml to enable interactive package management workflow.
You: "I need to use dbt_utils macros"
Copilot: Checks if installed, adds to packages.yml, runs install_deps()You: "Install the packages defined in packages.yml"
Copilot: Executes dbt deps and shows installed packagesYou: "Add dbt_utils and install it"
Copilot: Edits packages.yml, runs install_deps(), ready to use macros
This tool enables a complete workflow where Copilot can:
Suggest using a dbt package (e.g., dbt_utils)
Edit packages.yml to add the package
Run install_deps() to install it
Write code that uses the package's macros
All without breaking conversation flow.
Returns: Installation status and list of installed packages
Package Discovery:
Use list_resources(type="macro") to see which packages are already installed.
Macros follow the pattern macro.{package_name}.{macro_name}.
Note: This is an interactive development tool (like run_models/test_models), not infrastructure automation. It enables Copilot to complete its own recommendations mid-conversation.
Developer Workflow
Fast iteration with smart selection - just describe what you want:
You: "Run only what I changed"
Copilot: Detects modified models and runs themYou: "Run my changes and test everything downstream"
Copilot: Runs modified models + downstream dependencies, then testsYou: "Build my modified models with tests"
Copilot: Executes dbt build with smart selection
The first run establishes a baseline state automatically. Subsequent runs detect changes and run only what's needed.
Before-and-After Example:
Traditional workflow:dbt run --select customers+ dbt test --select customers+With dbt-core-mcp:
You: "I modified the customers model, run it and test everything affected"
Copilot: Handles everything - runs, tests, and reports results
How It Works
This server executes dbt commands in your project's Python environment using a bridge execution pattern:
Zero dbt Dependencies: MCP server requires NO dbt-core, NO adapters - just Python utilities
Environment Detection: Automatically finds your Python environment (uv, poetry, venv, conda, etc.)
Bridge Execution: Builds Python scripts as strings and executes them in YOUR environment
Uses YOUR dbt: Runs with YOUR dbt-core version, YOUR adapters, YOUR configuration
No Conflicts: Can't have version conflicts when we don't have dbt dependencies!
Concurrency Safety: Detects and waits for existing dbt processes to prevent database lock conflicts
The server reads dbt's manifest.json for metadata and uses dbt show --inline (executed in YOUR environment) for SQL query execution with full Jinja templating support.
In practice:
Your project: dbt-core 1.10.13 + dbt-duckdb
Our server: mcp, fastmcp, pydantic, pyyaml, psutil (no dbt!)
Result: Perfect compatibility - we detect your environment and run YOUR dbt
No configuration needed - it just works with your existing dbt setup, any version, any adapter.
Contributing
Want to help make this better? The best contribution you can make is actually using it - your feedback and bug reports are what really drive improvements.
Of course, code contributions are welcome too! Check out CONTRIBUTING.md for development setup and guidelines. But seriously, just using it and telling us what works (or doesn't) is incredibly valuable.
Learn More
Technical Architecture - Deep dive into zero-config philosophy, bridge architecture, performance optimizations, and design decisions. For the curious who want to understand how it all works under the hood.
CTE Unit Testing - Comprehensive guide to testing SQL CTEs in isolation. Learn how to test complex SQL logic without building massive fixtures, enabling true TDD workflows for dbt models.
License
MIT License - see LICENSE file for details.
Author
Niclas Olofsson - GitHub
Available Tools
14 toolsanalyze_impactA
Analyze the impact of changing any dbt resource with auto-detection.
This unified tool works across all resource types (models, sources, seeds, snapshots, etc.) showing all downstream dependencies that would be affected by changes. Provides actionable recommendations for running affected resources.
Args: name: Resource name. For sources, use "source_name.table_name" or just "table_name" Examples: "stg_customers", "jaffle_shop.orders", "raw_customers" resource_type: Optional filter to narrow search: - "model": Data transformation models - "source": External data sources - "seed": CSV reference data files - "snapshot": SCD Type 2 historical tables - "test": Data quality tests - "analysis": Ad-hoc analysis queries - None: Auto-detect (searches all types)
Returns: Impact analysis with: - List of affected models by distance - Count of affected tests and other resources - Total impact statistics - Resources grouped by distance from changed resource - Recommended dbt command to run affected resources - Human-readable impact assessment message If multiple matches found, returns all matches for LLM to process.
Raises: ValueError: If resource not found
Examples: analyze_impact("stg_customers") -> auto-detect and show impact analyze_impact("jaffle_shop.orders", "source") -> impact of source change analyze_impact("raw_customers", "seed") -> impact of seed data change
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| resource_type | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Despite no annotations, the description fully discloses behavioral traits: it shows downstream dependencies, provides recommendations, returns all matches for LLM to process if multiple found, raises ValueError, and explains resource_type filtering.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (Args, Returns, Raises, Examples) and no wasted words. It is appropriately sized for the complexity of the tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists and the description explains the return structure in detail, the description is fully complete for an impact analysis tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description carries full burden. It provides detailed parameter semantics: name format (with source_name.table_name examples) and resource_type options with descriptions, adding significant meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool analyzes the impact of changing dbt resources with auto-detection, and it distinguishes from sibling tools like get_lineage or get_resource_info by focusing on downstream dependencies and actionable recommendations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains when to use this tool (when changing dbt resources) and provides examples, but it does not explicitly mention when not to use it or compare to alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
build_modelsA
Run dbt build (execute models and tests together in correct dependency order).
When to use: This is the recommended "do everything" command that runs seeds, models, snapshots, and tests in the correct order based on your DAG. It automatically handles dependencies, so you don't need to run load_seeds() → run_models() → test_models() separately.
How it works: Executes resources in dependency order:
Seeds (if selected)
Models (with their upstream dependencies)
Tests (after their parent models complete)
Snapshots (if selected)
State-based selection modes (uses dbt state:modified selector):
select_state_modified: Build only resources modified since last successful run (state:modified)
select_state_modified_plus_downstream: Build modified + downstream dependencies (state:modified+) Note: Requires select_state_modified=True
Manual selection (alternative to state-based):
select: dbt selector syntax (e.g., "customers", "tag:mart", "stg_*")
exclude: Exclude specific models
Args: select: Manual selector exclude: Exclude selector select_state_modified: Use state:modified selector (changed resources only) select_state_modified_plus_downstream: Extend to state:modified+ (changed + downstream) full_refresh: Force full refresh of incremental models resource_types: Filter by resource types (model, test, seed, snapshot) fail_fast: Stop execution on first failure state: Shared state object injected by FastMCP
Returns: Build results with status, models run/tested, and timing info
See also: - run_models(): Run only models (no tests) - test_models(): Run only tests - load_seeds(): Run only seeds
Examples: # Full project build (first-time setup or comprehensive run) build_models()
# Build only what changed (efficient incremental workflow)
build_models(select_state_modified=True)
# Build changed resources + everything downstream
build_models(select_state_modified=True, select_state_modified_plus_downstream=True)
# Build specific model and its dependencies + tests
build_models(select="customers")
# Build all marts (includes their seed dependencies automatically)
build_models(select="tag:mart")
# Quick feedback: stop on first test failure
build_models(fail_fast=True)| Name | Required | Description | Default |
|---|---|---|---|
| select | No | ||
| exclude | No | ||
| select_state_modified | No | ||
| select_state_modified_plus_downstream | No | ||
| full_refresh | No | ||
| resource_types | No | ||
| fail_fast | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, but the description explains the execution order (seeds, models, tests, snapshots), state-based selection mechanics, and return values. It discloses all relevant behavioral traits without contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with sections (overview, when to use, how it works, args, returns, see also, examples). Every sentence adds value, and the length is appropriate for the tool's complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers purpose, usage, parameters, behavior, return info, and provides multiple examples. Given 7 parameters and no annotations, it is fully complete and leaves no gaps for an agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description explains each parameter in detail with examples (e.g., 'select: dbt selector syntax (e.g., "customers", "tag:mart", "stg_*")'). It adds significant meaning beyond the schema names.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Run dbt build (execute models and tests together in correct dependency order)' and differentiates from siblings like run_models and test_models. It provides a specific verb+resource and scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states 'This is the recommended do everything command' and includes a 'See also' section listing alternative tools with their purposes. Examples cover full builds, incremental workflows, and specific selections.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
demo_uiA
Render the demo UI resource (resource://demo/hello).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must carry the full burden of behavioral disclosure. It only states the action ('Render') without explaining side effects, authentication needs, or what the output represents (though an output schema exists). This is insufficient for a tool with no annotation support.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, well-structured sentence that front-loads the key action and resource. Every word is necessary and there is no extraneous information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's low complexity (no parameters, simple purpose) and the presence of an output schema, the description suffices. It tells the agent exactly what action to take and on which resource.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, and the schema coverage is 100% (trivially). The description adds no parameter information, but none is needed. The baseline score for 0 parameters is 4, and perfect clarity warrants a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's action ('Render the demo UI resource') and specifies the exact resource path, making its purpose unambiguous. It also distinguishes itself from sibling tools that deal with data analysis, database queries, and model management.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description does not provide explicit guidance on when to use this tool versus alternatives. Usage is implied by the tool's name and description (rendering a demo UI), but no exclusions or comparison with siblings are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_column_lineageA
Trace column-level lineage through SQL transformations.
Uses sqlglot to parse compiled SQL and track how columns flow through:
CTEs and subqueries
JOINs and aggregations
Transformations (calculations, CASE statements, etc.)
Window functions
This provides detailed column-to-column dependencies that model-level lineage cannot capture.
Args: model_name: Name or unique_id of the dbt model to analyze column_name: Name of the column to trace direction: Direction to trace lineage: - "upstream": Which source columns feed into this column - "downstream": Which downstream columns use this column - "both": Full bidirectional column lineage depth: Maximum levels to traverse (None for unlimited) - depth=1: Immediate column dependencies only - depth=2: Dependencies + their dependencies - None: Full dependency tree
Returns: Column lineage information including: - Source columns this column depends on (upstream) - Downstream columns that depend on this column - Transformations and derivations - CTE transformation paths (via_ctes, transformations) - dbt resource mapping where available
Each dependency includes:
- column: Column name
- table: Source table name
- schema: Source schema (if available)
- database: Source database (if available)
- via_ctes: List of CTE names in transformation order
- transformations: Transformation details per CTE step
- cte: CTE name
- column: Column name at this step
- expression: SQL expression (truncated to 200 chars)Raises: ValueError: If model not found, column not found, or SQL parse fails RuntimeError: If sqlglot is not installed
Examples: # Find which source columns feed into revenue get_column_lineage("fct_sales", "revenue", "upstream")
# See what downstream models use customer_id
get_column_lineage("dim_customers", "customer_id", "downstream")
# Full bidirectional lineage for a column
get_column_lineage("fct_orders", "order_total", "both")Note: Requires sqlglot package. Install with: pip install sqlglot The model must be compiled (run 'dbt compile' first).
| Name | Required | Description | Default |
|---|---|---|---|
| model_name | Yes | ||
| column_name | Yes | ||
| direction | No | upstream | |
| depth | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It explains that the tool parses compiled SQL, tracks columns through CTEs, JOINs, etc., and raises ValueError or RuntimeError for specific conditions. It also notes the need for sqlglot and compiled models.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with sections for Args, Returns, Raises, Examples, and Note. It is front-loaded with the purpose. However, it is somewhat lengthy and could be more concise, especially the detailed return description, but it earns its place given the complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity of column-level lineage, the output schema exists, and the description covers inputs, outputs, error handling, dependencies, and prerequisites. Examples are provided. The tool is fully described for an AI agent to use correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description thoroughly explains each parameter: model_name, column_name, direction (with three options and meanings), depth (with examples like depth=1, depth=2, None). It also details the return structure, adding significant meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool traces column-level lineage through SQL transformations using sqlglot. It specifies the verb 'trace' and resource 'column-level lineage', and distinguishes it from siblings like 'get_lineage' which likely handles model-level lineage.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context on when to use the tool (to trace column dependencies) and includes prerequisites (sqlglot, compiled model). It gives parameter explanations and examples, but does not explicitly compare to sibling tools or state when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_lineageA
Get lineage (dependency tree) for any dbt resource with auto-detection.
This unified tool works across all resource types (models, sources, seeds, snapshots, etc.) showing upstream and/or downstream dependencies with configurable depth.
Args: name: Resource name. For sources, use "source_name.table_name" or just "table_name" Examples: "customers", "jaffle_shop.orders", "raw_customers" resource_type: Optional filter to narrow search: - "model": Data transformation models - "source": External data sources - "seed": CSV reference data files - "snapshot": SCD Type 2 historical tables - "test": Data quality tests - "analysis": Ad-hoc analysis queries - None: Auto-detect (searches all types) direction: Lineage direction: - "upstream": Show where data comes from (parents) - "downstream": Show what depends on this resource (children) - "both": Show full lineage (default) depth: Maximum levels to traverse (None for unlimited) - depth=1: Immediate dependencies only - depth=2: Dependencies + their dependencies - None: Full dependency tree
Returns: Lineage information with upstream/downstream nodes and statistics. If multiple matches found, returns all matches for LLM to process.
Raises: ValueError: If resource not found or invalid direction
Examples: get_lineage("customers") -> auto-detect and show full lineage get_lineage("customers", "model", "upstream") -> where customers model gets data get_lineage("jaffle_shop.orders", "source", "downstream", 2) -> 2 levels of dependents
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| resource_type | No | ||
| direction | No | both | |
| depth | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations, but description details auto-detection, multiple match handling, error raising (ValueError), and depth limits. Does not mention read-only nature or auth, but these are implied. Sufficient behavioral context for safe use.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with Args, Returns, Raises, Examples sections. Some redundancy (e.g., repeating parameter names), but front-loaded with core purpose. Slightly long but justified by complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers purpose, all parameters, return behavior (lineage info with stats, multiple matches), and errors. Output schema exists for return details, so omission is acceptable. Lacks pagination or performance notes, but complete for typical use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so description fully compensates: explains each parameter with examples, default values, and valid options (e.g., source naming format, direction options, depth meaning). Adds significant value beyond schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description states 'Get lineage (dependency tree) for any dbt resource with auto-detection' – specific verb, resource, and scope. Clearly distinguishes from siblings like 'get_column_lineage' by focusing on resource-level, not column-level lineage.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides context on when to use (dependency queries), naming conventions for sources, and examples. However, lacks explicit guidance on when NOT to use or alternatives (e.g., use get_column_lineage for column lineage). Still clear overall.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_project_infoB
Get information about the dbt project with optional diagnostics.
Args:
ctx: MCP context (provided by FastMCP)
run_debug: Run dbt debug to validate environment and test connection (default: True)
state: Shared state object injected by FastMCP
Returns: Dictionary with project information and diagnostic results
| Name | Required | Description | Default |
|---|---|---|---|
| run_debug | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description mentions running `dbt debug` for diagnostics, adding behavioral context beyond the schema. However, it doesn't disclose potential side effects, failure modes, or required permissions. With no annotations, this is adequate but not comprehensive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is somewhat verbose with internal implementation details (like ctx and state) that are not useful for tool users. The core purpose is stated concisely, but the extra boilerplate reduces clarity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has a single parameter and an output schema (stated in context), the description covers the essential purpose and parameter behavior. It lacks detail on what specific information is returned but is otherwise complete for its complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description provides essential semantics for the single parameter run_debug, explaining its function and default. This compensates well for the lack of schema-level descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it retrieves dbt project information with optional diagnostics, and the name aligns with this purpose. However, it does not differentiate from sibling tools like get_resource_info, which might cause ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool versus alternatives (e.g., get_resource_info for specific resources). It only implies diagnostic use via the run_debug parameter but lacks explicit context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_resource_infoA
Get detailed information about any dbt resource (model, source, seed, snapshot, test, etc.).
This unified tool works across all resource types, auto-detecting the resource or filtering by type. Designed for LLM consumption - returns complete data even when multiple matches exist.
Args: name: Resource name. For sources, use "source_name.table_name" or just "table_name" resource_type: Optional filter to narrow search: - "model": Data transformation models - "source": External data sources - "seed": CSV reference data files - "snapshot": SCD Type 2 historical tables - "test": Data quality tests - "analysis": Ad-hoc analysis queries - None: Auto-detect (searches all types) include_database_schema: If True (default), query actual database table schema for models/seeds/snapshots/sources and add as 'database_columns' field include_compiled_sql: If True (default), include compiled SQL with Jinja resolved ({{ ref() }}, {{ source() }} → actual table names). Only applicable to models. Will trigger dbt compile if not already compiled. Set to False to skip compilation. state: Shared state object injected by FastMCP
Returns: Resource information dictionary. If multiple matches found, returns: {"multiple_matches": True, "matches": [...], "message": "..."}
Raises: ValueError: If resource not found
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| resource_type | No | ||
| include_database_schema | No | ||
| include_compiled_sql | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description fully discloses behavioral traits: auto-detection of resource type, return of multiple matches with a special structure, side effects of include_compiled_sql (triggers dbt compile), and error raising (ValueError). It also notes the state parameter injection.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with sections for main description, args, returns, and raises. It is front-loaded with the core purpose. Every sentence adds value without redundancy, making it appropriately concise for a 4-parameter tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists, the description provides sufficient context about the return value (resource info dict, multiple matches handling). All parameters are thoroughly explained. The description is complete for the tool's complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0% description coverage, so the description carries the full burden. It provides detailed explanations for each parameter: name format for sources, resource_type values with descriptions, boolean parameters with their effects (including side effects like triggering compile). This adds significant meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Get detailed information about any dbt resource (model, source, seed, snapshot, test, etc.)'. It is a specific verb-resource combination and distinguishes itself from sibling tools like list_resources (listing) or get_lineage (lineage) by focusing on detailed information retrieval.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides usage context (e.g., source naming convention) but does not explicitly state when to use this tool versus alternatives. It implies it's for detailed resource info, but no when-not or exclusion criteria are given relative to siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
install_depsA
Install dbt packages defined in packages.yml.
This tool enables interactive workflow where an LLM can:
Suggest using a dbt package (e.g., dbt_utils)
Edit packages.yml to add the package
Run install_deps() to install it
Write code that uses the package's macros
This completes the recommendation workflow without breaking conversation flow.
When to use:
After adding/modifying packages.yml
Before using macros from external packages
When setting up a new dbt project
Package Discovery: After installation, use list_resources(resource_type="macro") to verify installed packages and discover available macros.
Returns: Installation results with status and installed packages
Example workflow: User: "Create a date dimension table" LLM: 1. Checks: list_resources(type="macro") -> no dbt_utils 2. Edits: packages.yml (adds dbt_utils package) 3. Runs: install_deps() (installs package) 4. Creates: models/date_dim.sql (uses dbt_utils.date_spine)
Note: This is an interactive development tool, not infrastructure automation. It enables the LLM to act on its own recommendations mid-conversation.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description covers key behavioral aspects: it is interactive, not infrastructure automation, and returns installation results. It could be more explicit about side effects like network access or file system changes, but overall provides good transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections, but it is somewhat lengthy for a no-parameter tool. The example workflow is helpful but could be more concise. Still, every section adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has no parameters and an output schema exists, the description is complete. It explains the workflow, when to use, and even provides an example. No gaps in context for an AI agent to understand usage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0 parameters, so the description does not need to add parameter details. Baseline is 4 for zero parameters, and the description provides context about what the tool operates on (packages.yml) without needing parameter specifics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Install dbt packages defined in packages.yml' with a specific verb and resource. It distinguishes from sibling tools like build_models and load_seeds by focusing on dependency installation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'When to use' bullets: after modifying packages.yml, before using external macros, when setting up a new project. It also provides an alternative workflow using list_resources for verification, giving clear context for when to use this tool versus others.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_resourcesA
List all resources in the dbt project with optional filtering by type.
This unified tool provides a consistent view across all dbt resource types. Returns simplified resource information optimized for LLM consumption.
Args: resource_type: Optional filter to narrow results: - "model": Data transformation models - "source": External data sources - "seed": CSV reference data files - "snapshot": SCD Type 2 historical tables - "test": Data quality tests - "analysis": Ad-hoc analysis queries - "macro": Jinja macros (includes macros from installed packages) - None: Return all resources (default)
Returns: List of resource dictionaries with consistent structure across types. Each resource includes: name, unique_id, resource_type, description, tags, etc.
Package Discovery: Use resource_type="macro" to discover installed dbt packages. Macros follow the naming pattern: macro.{package_name}.{macro_name}
Example - Check if dbt_utils is installed:
macros = list_resources("macro")
has_dbt_utils = any(m["unique_id"].startswith("macro.dbt_utils.") for m in macros)
Example - List all installed packages:
macros = list_resources("macro")
packages = {m["unique_id"].split(".")[1] for m in macros
if m["unique_id"].startswith("macro.") and
m["unique_id"].split(".")[1] != "dbt"}Examples: list_resources() -> all resources list_resources("model") -> only models list_resources("source") -> only sources list_resources("test") -> only tests list_resources("macro") -> all macros (discover installed packages)
| Name | Required | Description | Default |
|---|---|---|---|
| resource_type | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must carry the full burden. It states the tool is for listing resources, returns simplified info for LLM consumption, and explains the default behavior and package discovery. It implies a read operation but does not explicitly state it is read-only or mention any prerequisites.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is structured with clear sections (Args, Returns, Package Discovery, Examples) and is front-loaded with the purpose. While comprehensive, it is slightly lengthy but justifiable given the need to cover package discovery and examples.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an optional output schema (mentioned but not detailed), the description covers parameter usage, return structure, examples, and special package discovery use case. It is complete for a list tool and fits well with sibling tools.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is one parameter with 0% schema coverage. The description compensates fully by listing all possible enum values with explanations, default behavior, and usage examples, making the parameter's meaning and usage very clear.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'List all resources' with optional filtering by type, using a specific verb and resource. It distinguishes from siblings like 'get_resource_info' by indicating it returns a list of all resources rather than details on a single resource.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains when to use filtering and provides examples for each resource_type. It also includes a section on package discovery with specific use cases. However, it does not explicitly mention when not to use this tool or alternatives among siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
load_seedsA
Load seed data (CSV files) from seeds/ directory into database tables.
When to use: Run this before building models or tests that depend on reference data. Seeds must be loaded before models that reference them can execute.
What are seeds: CSV files containing static reference data (country codes, product categories, lookup tables, etc.). Unlike models (which are .sql files), seeds are CSV files that are loaded directly into database tables.
State-based selection modes (detects changed CSV files):
select_state_modified: Load only seeds modified since last successful run (state:modified)
select_state_modified_plus_downstream: Load modified + downstream dependencies (state:modified+) Note: Requires select_state_modified=True
Manual selection (alternative to state-based):
select: dbt selector syntax (e.g., "raw_customers", "tag:lookup")
exclude: Exclude specific seeds
Important: Change detection for seeds works via file hash comparison:
Seeds < 1 MiB: Content hash is compared (recommended)
Seeds >= 1 MiB: Only file path changes are detected (content changes ignored) For large seeds, use manual selection or run all seeds.
Args: select: Manual selector for seeds exclude: Exclude selector select_state_modified: Use state:modified selector (changed seeds only) select_state_modified_plus_downstream: Extend to state:modified+ (changed + downstream) full_refresh: Truncate and reload seed tables (default behavior) show: Show preview of loaded data state: Shared state object injected by FastMCP
Returns: Seed results with status and loaded seed info
See also: - run_models(): Execute .sql model files (not CSV seeds) - build_models(): Runs both seeds and models together in DAG order - test_models(): Run tests (requires seeds to be loaded first if tests reference them)
Examples: # Before running tests that depend on reference data load_seeds() test_models(select="test_customer_country_code")
# After adding a new CSV lookup table
load_seeds(select="new_product_categories")
# Fix "relation does not exist" errors from models referencing seeds
load_seeds() # Load missing seed tables first
run_models(select="stg_orders")
# Incremental workflow: only reload what changed
load_seeds(select_state_modified=True)
# Full refresh of a specific seed
load_seeds(select="country_codes", full_refresh=True)| Name | Required | Description | Default |
|---|---|---|---|
| select | No | ||
| exclude | No | ||
| select_state_modified | No | ||
| select_state_modified_plus_downstream | No | ||
| full_refresh | No | ||
| show | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It details state-based selection modes, file hash change detection, limitations for large seeds (>=1 MiB), and the effect of full_refresh. This fully discloses behavioral traits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with sections, bullet points, and examples. Every sentence is informative without unnecessary verbosity. It earns its length by providing comprehensive guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no annotations and 0% schema description coverage, the description covers all necessary context: what seeds are, when to use, selection mechanisms, large file caveats, examples, and return value. It is complete for the tool's complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description explains all six parameters in detail, including select, exclude, select_state_modified, full_refresh, show, and state. It adds meaning beyond the schema's type/default information.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool loads seed data (CSV files) into database tables. It distinguishes from siblings like run_models, build_models, test_models by explicitly noting seeds are CSV files and providing a 'See also' section with alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Includes a 'When to use' section advising to run before building models or tests that depend on reference data. Also provides examples and mentions alternatives like run_models and build_models, giving clear context for when to use this tool vs. others.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
query_databaseA
Execute a SQL query against the dbt project's database.
This tool compiles and runs SQL with Jinja templating support, allowing you to use {{ ref('model') }} and {{ source('src', 'table') }} in your queries.
SQL Templating:
Use {{ ref('model_name') }} to reference dbt models
Use {{ source('source_name', 'table_name') }} to reference source tables
dbt compiles these to actual table names before execution
CTE Querying (LLM quick reference)
Always pass
cte_name+model_namein parameters (not in SQL)Always write a normal
SELECT ... FROM __cte__ ...__cte__or{{ cte }}is replaced with the CTE name
What happens under the hood
Extracts the target CTE plus upstream CTEs from the model
Runs your query against that extracted CTE
Templating
dbt resolves all
{{ ref() }}/{{ source() }}automatically; no manual table names
Invalid syntax to avoid
{{ ref('model', cte='name') }}does not exist; always usecte_name+model_name
Output Management:
For large result sets (>100 rows), use output_file to save results
If output_file is omitted, all data returns inline (may consume large context)
output_file is automatically created with parent directories
Relative paths are resolved relative to the workspace root
Output Formats:
json (default): Returns data as JSON array of objects
csv: Returns comma-separated values with header row
tsv: Returns tab-separated values with header row
CSV/TSV formats use proper quoting (only when necessary) and are Excel-compatible
Args:
sql: SQL query with Jinja templating: {{ ref('model') }}, {{ source('src', 'table') }}
For exploratory queries, include LIMIT. For aggregations/counts, omit it.
When using cte_name/model_name, provide a full SELECT/WITH query that
selects from __cte__ (or {{ cte }}), which is replaced with the CTE name.
output_file: Optional file path to save results. Recommended for large result sets (>100 rows).
Relative paths are resolved relative to the workspace root.
If provided, only metadata is returned (no preview for CSV/TSV).
If omitted, all data is returned inline (may consume large context).
output_format: Output format - "json" (default), "csv", or "tsv"
cte_name: Optional CTE name to query from a model (requires model_name)
model_name: Optional model name containing the CTE (required when cte_name is specified)
state: Shared state object injected by FastMCP
Returns: JSON inline: {"status": "success", "row_count": N, "rows": [...], "elapsed_time": X.XX} JSON file: {"status": "success", "row_count": N, "saved_to": "path", "preview": [...], "elapsed_time": X.XX} CSV/TSV inline: {"status": "success", "row_count": N, "format": "csv", "csv": "...", "elapsed_time": X.XX} CSV/TSV file: {"status": "success", "row_count": N, "format": "csv", "saved_to": "path", "elapsed_time": X.XX}
Note: elapsed_time is in seconds and represents the total query execution time including compilationRaises: RuntimeError: If query execution fails ValueError: If invalid CTE/model parameters provided
Examples: # Simple query with ref() query_database(sql="SELECT * FROM {{ ref('customers') }} LIMIT 10")
# Query with source()
query_database(sql="SELECT * FROM {{ source('jaffle_shop', 'orders') }} LIMIT 5")
# Aggregation (no LIMIT needed)
query_database(sql="SELECT COUNT(*) as total FROM {{ ref('customers') }}")
# Query a specific CTE from a model
query_database(
cte_name="customer_agg",
model_name="customers",
sql="SELECT * FROM __cte__ LIMIT 10"
)
# Query a CTE with filtering
query_database(
cte_name="customer_agg",
model_name="customers",
sql="SELECT * FROM __cte__ WHERE order_count > 5 LIMIT 20"
)
# Query a CTE with aggregation (full SELECT)
query_database(
cte_name="customer_agg",
model_name="customers",
sql="SELECT customer_id, COUNT(*) AS cnt FROM __cte__ GROUP BY customer_id"
)
# WRONG - Do NOT use ref() with cte parameter (does not exist):
# query_database(sql="SELECT * FROM {{ ref('model', cte='cte_name') }}")
#
# CORRECT - Use cte_name and model_name parameters instead:
# query_database(cte_name="cte_name", model_name="model", sql="SELECT * FROM __cte__ LIMIT 10")
# Save large results to file
query_database(
sql="SELECT * FROM {{ ref('orders') }}",
output_file="temp_auto/orders_export.json"
)
# Export as CSV
query_database(
sql="SELECT * FROM {{ ref('customers') }}",
output_file="temp_auto/customers.csv",
output_format="csv"
)| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes | ||
| output_file | No | ||
| output_format | No | json | |
| cte_name | No | ||
| model_name | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Without annotations, the description fully discloses behavior: SQL execution with Jinja compilation, output formats, file saving with automatic directory creation, error raising (RuntimeError, ValueError), and elapsed time reporting. It also mentions memory considerations for large result sets.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with sections, bullet points, and examples, making it easy to parse. However, the CTE section contains some repetition across examples and notes; a slightly more condensed version would improve conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (5 params, no schema descriptions, no annotations, but output schema detailed), the description covers all necessary aspects: purpose, usage, parameters, return formats, error handling, and examples. It is complete and leaves no ambiguity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Despite 0% schema description coverage, the description thoroughly explains all 5 parameters: sql (templating rules), output_file (path handling, inline vs file), output_format (json/csv/tsv), cte_name and model_name (relation and usage with __cte__ placeholder). It adds meaning beyond the schema by detailing behavior and constraints.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Execute a SQL query against the dbt project's database.' It distinguishes itself from sibling tools (e.g., analyze_impact, build_models) by being the only tool for direct SQL execution with Jinja templating support.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides comprehensive usage guidelines including when to use output_file for large results, when to include LIMIT, and how to use CTE parameters. It includes examples of correct and incorrect usage, and explicitly warns against invalid syntax like {{ ref('model', cte='name') }}.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_modelsA
Run dbt models (compile SQL and execute against database).
What are models: SQL files (.sql) containing SELECT statements that define data transformations. Models are compiled and executed to create/update tables and views in your database.
Important: This tool runs models only (SQL files). For CSV seed files, use load_seeds(). For running everything together (seeds + models + tests), use build_models().
State-based selection modes (uses dbt state:modified selector):
select_state_modified: Run only models modified since last successful run (state:modified)
select_state_modified_plus_downstream: Run modified + downstream dependencies (state:modified+) Note: Requires select_state_modified=True
Manual selection (alternative to state-based):
select: dbt selector syntax (e.g., "customers", "tag:mart", "stg_*")
exclude: Exclude specific models
Args: select: Manual selector (e.g., "customers", "tag:mart", "path:marts/*") exclude: Exclude selector (e.g., "tag:deprecated") select_state_modified: Use state:modified selector (changed models only) select_state_modified_plus_downstream: Extend to state:modified+ (changed + downstream) full_refresh: Force full refresh of incremental models fail_fast: Stop execution on first failure check_schema_changes: Detect schema changes and recommend downstream runs cache_selected_only: Only cache schemas for selected models (default True for performance) state: Shared state object injected by FastMCP
Returns: Execution results with status, models run, timing info, and optional schema_changes
See also: - seed_data(): Load CSV files (must run before models that reference them) - build_models(): Run models + tests together in DAG order - test_models(): Run tests after models complete
Examples: # Run a specific model run_models(select="customers")
# After loading seeds, run dependent models
seed_data()
run_models(select="stg_orders")
# Incremental: run only what changed
run_models(select_state_modified=True)
# Run changed models + everything downstream
run_models(select_state_modified=True, select_state_modified_plus_downstream=True)
# Full refresh marts (rebuild from scratch)
run_models(select="tag:mart", full_refresh=True)| Name | Required | Description | Default |
|---|---|---|---|
| select | No | ||
| exclude | No | ||
| select_state_modified | No | ||
| select_state_modified_plus_downstream | No | ||
| full_refresh | No | ||
| fail_fast | No | ||
| check_schema_changes | No | ||
| cache_selected_only | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Since no annotations are provided, the description carries full burden. It details the execution behavior (compile SQL, execute against database), explains state-based modification detection, full refresh, fail fast, schema change detection, and caching. Lacks explicit idempotency info but is highly transparent overall.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with clear sections (header, what are models, important notes, selection modes, args, returns, see also, examples). While lengthy, every section adds value and is organized logically. Slightly long but earns its length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers all aspects: purpose, usage guidance, parameter details, return values (even without output schema), sibling tool references, and multiple examples including state-based and manual scenarios. Comprehensive for a complex tool with 8 parameters.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It provides thorough explanations for all 8 parameters in the Args section, including default behaviors and relationships (e.g., state-based modes require select_state_modified=True). Adds significant meaning beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states 'Run dbt models (compile SQL and execute against database)' and explains what models are. Distinguishes from siblings by specifying that for CSV seeds use load_seeds() and for everything together use build_models().
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when to use this tool (only for models) and when not to (seeds: use load_seeds, all together: build_models). Covers state-based vs manual selection with detailed descriptions and examples.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
snapshot_modelsA
Snapshot models (capture historical changes - SCD Type 2).
Snapshots capture historical changes in data, enabling you to track slowly changing dimensions over time. This is particularly useful for maintaining accurate historical records in data warehouses.
When to use: To track changes in slowly changing dimensions (SCD Type 2). For example, tracking customer address changes over time while preserving history.
How it works: dbt compares current source data with existing snapshot table, identifies changes, and inserts new rows with validity timestamps (dbt_valid_from, dbt_valid_to, dbt_updated_at). Original rows are closed by setting dbt_valid_to.
Args: select: dbt selector syntax (e.g., "snapshot_name", "tag:daily") exclude: Exclude specific snapshots state: Shared state object injected by FastMCP
Returns: Snapshot results with status and timing info
Examples: # Run all snapshots snapshot_models()
# Run specific snapshot
snapshot_models(select="customers_snapshot")
# Run tagged snapshots
snapshot_models(select="tag:daily")| Name | Required | Description | Default |
|---|---|---|---|
| select | No | ||
| exclude | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. It explains the mechanism: dbt compares source data, identifies changes, inserts new rows with validity timestamps, and closes original rows. This gives good behavioral insight, but could also mention idempotency or side effects like potential data duplication on reruns.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with sections: intro, 'When to use', 'How it works', Args, Returns, and Examples. Front-loaded with purpose. While slightly lengthy, every section adds value. Could be slightly more concise in the 'How it works' explanation, but overall effective.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no annotations and low schema coverage, the description provides sufficient context: usage guidelines, mechanism, parameter explanations, and examples. Output schema exists, so the brief return description is adequate. It covers the essential aspects for effective tool invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema has 0% description coverage, but the description compensates by explaining 'select' as dbt selector syntax with examples (e.g., 'snapshot_name', 'tag:daily') and 'exclude' as 'Exclude specific snapshots'. Examples further clarify usage. The description adds significant meaning beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it 'snapshot models' and 'capture historical changes - SCD Type 2', with a detailed explanation of tracking slowly changing dimensions. This effectively distinguishes it from siblings like 'run_models' or 'build_models' which handle regular model execution.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Includes a 'When to use' section that specifies 'to track changes in slowly changing dimensions (SCD Type 2)'. It does not explicitly say when not to use or mention alternatives, but the context of sibling tool names provides implied differentiation. Additional exclusions would improve it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
test_modelsA
Run dbt tests on models and sources.
When to use: After running models to validate data quality. Tests check constraints like uniqueness, not-null, relationships, and custom data quality rules.
Important: Ensure seeds and models are built before running tests that depend on them.
State-based selection modes (uses dbt state:modified selector):
select_state_modified: Test only models modified since last successful run (state:modified)
select_state_modified_plus_downstream: Test modified + downstream dependencies (state:modified+) Note: Requires select_state_modified=True
Manual selection (alternative to state-based):
select: dbt selector syntax (e.g., "customers", "tag:mart", "test_type:generic")
exclude: Exclude specific tests
Args: select: Manual selector for tests/models to test exclude: Exclude selector select_state_modified: Use state:modified selector (changed models only) select_state_modified_plus_downstream: Extend to state:modified+ (changed + downstream) fail_fast: Stop execution on first failure keep_cte_tests: Keep generated CTE test files for debugging (default: False) state: Shared state object injected by FastMCP
Returns: Test results with status and failures
See also: - run_models(): Execute models before testing them - build_models(): Run models + tests together automatically - load_seeds(): Load seeds if tests reference seed data
Examples: # After building a model, test it run_models(select="customers") test_models(select="customers")
# Test only generic tests (not singular)
test_models(select="test_type:generic")
# Test everything that changed
test_models(select_state_modified=True)
# Stop on first failure for quick feedback
test_models(fail_fast=True)
# Keep CTE test files for debugging
test_models(keep_cte_tests=True)Note: Unit test failures show diffs in the "daff" tabular format: @@ = column headers +++ = row in actual, not in expected (extra row) --- = row in expected, not in actual (missing row) → = row with modified cell(s), shown as old_value→new_value ... = omitted matching rows Full format spec: https://paulfitz.github.io/daff-doc/spec.html
| Name | Required | Description | Default |
|---|---|---|---|
| select | No | ||
| exclude | No | ||
| select_state_modified | No | ||
| select_state_modified_plus_downstream | No | ||
| fail_fast | No | ||
| keep_cte_tests | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description fully bears the transparency burden. It details selection modes (state-based vs manual), fail_fast behavior, keep_cte_tests for debugging, and even the format of unit test failure diffs, leaving no ambiguity about tool behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is efficiently structured with sections (When to use, Important, Args, Returns, See also, Examples, Note). Every sentence adds value, and it front-loads the primary purpose. Despite length, it remains clear and avoids redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity (6 params, no annotations, high behavioral detail needed), the description covers all aspects: purpose, usage conditions, parameter semantics, return values, sibling tools, and examples. It is complete and self-contained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate. It explains all 6 parameters: select and exclude as manual selectors, state-based flags with the 'Note:' on prerequisites, fail_fast, keep_cte_tests, and state object. Examples further clarify usage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Run dbt tests on models and sources' (specific verb+resource). It distinguishes from siblings like run_models (execution) and build_models (run+tests) through the 'See also' section and usage guidance.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states 'When to use: After running models to validate data quality.' Includes important precondition ('Ensure seeds and models are built') and references alternative tools (run_models, build_models, load_seeds).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
12 tool updates
v1.7.0- Added
demo_ui - Added
get_column_lineage - Added
get_lineage - Added
get_project_info - Added
get_resource_info - Added
install_deps - Added
list_resources - Added
load_seeds - Added
query_database - Added
run_models - Added
snapshot_models - Added
test_models
3 tool updates
- Removed
demo_ui - Removed
get_column_lineage - Removed
get_lineage
2 tool updates
- Removed
get_project_info - Removed
get_resource_info
5 tool updates
- Removed
install_deps - Removed
list_resources - Removed
load_seeds - Removed
query_database - Removed
run_models
2 tool updates
- Removed
snapshot_models - Removed
test_models
8 tool updates
v1.1.0- Changed
build_models1 field changed- added
Input schema / properties / resource_typesAdded value: +{ + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null +}
- Added
demo_ui - Added
get_column_lineage - Added
load_seeds - Changed
query_database2 fields changed- added
Input schema / properties / cte_nameAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null +} - added
Input schema / properties / model_nameAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null +}
- Changed
run_models1 field changed- added
Input schema / properties / cache_selected_onlyAdded value: +{ + "default": true, + "type": "boolean" +}
- Removed
seed_data - Changed
test_models1 field changed- added
Input schema / properties / keep_cte_testsAdded value: +{ + "default": false, + "type": "boolean" +}
14 tool updates
v1.0.0- Added
analyze_impact - Added
build_models - Added
get_lineage - Changed
get_project_info1 field changed- added
Input schema / properties / run_debugAdded value: +{ + "default": true, + "type": "boolean" +}
- Added
get_resource_info - Added
install_deps - Removed
list_models - Added
list_resources - Removed
list_sources - Added
query_database - Added
run_models - Added
seed_data - Added
snapshot_models - Added
test_models
3 tool updates
- First observed
get_project_info - First observed
list_models - First observed
list_sources
TDQS
Scored across 14 tools
Each tool has a clearly distinct purpose. Overlaps like get_lineage vs get_column_lineage and build_models vs run_models are complementary, not ambiguous. Descriptions are detailed and steer the agent to the correct tool.
All tool names follow a consistent snake_case verb_noun pattern (e.g., analyze_impact, get_lineage, run_models). No mixing of styles or unconventional naming.
14 tools is well-scoped for a dbt project management server. It covers all major operations without being excessive. Each tool has a clear justification.
The tool set covers the full lifecycle: project info, resource listing, building (models, seeds, snapshots, tests), dependency analysis (lineage, impact), database querying, and package installation. No significant gaps for common dbt workflows.
Maintenance
Related MCP Connectors
Plan Salesforce deploys, open pull requests and trigger pipelines from your AI client.
- mcpOAuthcom.vibgrate
Query your team's drift, vulnerability, and upgrade data from any AI assistant. OAuth 2.1, 51 tools.
Explore, query, and inspect SQLite databases with ease. List tables, preview results, and view det…
- mcpOAuthcom.keboola
Connect your AI assistants to Keboola and expose your data, transformations, SQL queries, ...
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables the analysis of DBT manifests with automatic schema version detection and lineage tracking, allowing users to query model dependencies, access compiled code, and get detailed model information.1MIT
- FlicenseNot gradedqualityNot gradedmaintenanceProvides intelligent dbt assistance through Claude Code integration, enabling users to perform dbt CLI operations, explore project metadata, and execute SQL queries against DuckDB warehouse with context-aware support.-
- AlicenseBqualityDmaintenanceEnables AI assistants and IDEs to execute SQL queries on local DuckDB databases, in-memory databases, or cloud-stored databases with support for flexible connections and configurable result limits.11MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to interact with Databricks workspaces, running SQL queries, managing jobs, and exploring schemas via the Model Context Protocol.1GPL 3.0