Skip to content

Commit 2f05adf

Browse files
DI-4002 consolidate 8 get_*_details Discovery tools into get_details
Replaces get_model_details, get_source_details, get_exposure_details, get_test_details, get_seed_details, get_snapshot_details, get_macro_details, and get_semantic_model_details with a single get_details(resource_type, ...) tool that dispatches to the existing ResourceDetailsFetcher. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent ad7ae8e commit 2f05adf

18 files changed

Lines changed: 124 additions & 476 deletions
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
kind: Enhancement or New Feature
2+
body: Consolidate 8 get_*_details Discovery tools into a single get_details(resource_type, ...) tool
3+
time: 2026-06-22T10:39:00.432662-07:00

README.md

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,20 +45,13 @@ To learn more about the dbt Discovery API, click [here](https://docs.getdbt.com/
4545
- `get_all_macros`: Retrieves macros; option to filter by package or return package names only.
4646
- `get_all_models`: Retrieves name and description of all models.
4747
- `get_all_sources`: Gets all sources with freshness status; option to filter by source name.
48-
- `get_exposure_details`: Gets exposure details including owner, parents, and freshness status.
48+
- `get_details`: Gets full details for any dbt resource type (model, source, exposure, test, seed, snapshot, macro, semantic_model).
4949
- `get_exposures`: Gets all exposures (downstream dashboards, apps, or analyses).
5050
- `get_lineage`: Gets full lineage graph (ancestors and descendants) with type and depth filtering; use depth=1 to get immediate parents or children.
51-
- `get_macro_details`: Gets details for a specific macro.
5251
- `get_mart_models`: Retrieves all mart models.
53-
- `get_model_details`: Gets model details including compiled SQL, columns, and schema.
5452
- `get_model_health`: Gets health signals: run status, test results, and upstream source freshness.
5553
- `get_model_performance`: Gets execution history for a model; option to include test results.
5654
- `get_related_models`: Finds similar models using semantic search.
57-
- `get_seed_details`: Gets details for a specific seed.
58-
- `get_semantic_model_details`: Gets details for a specific semantic model.
59-
- `get_snapshot_details`: Gets details for a specific snapshot.
60-
- `get_source_details`: Gets source details including columns and freshness.
61-
- `get_test_details`: Gets details for a specific test.
6255
- `search`: [Alpha] Searches for resources across the dbt project (not generally available).
6356

6457
### dbt CLI

src/dbt_mcp/discovery/param_descriptions.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,10 @@
3333
MACRO_INCLUDE_DEFAULT_DBT_PACKAGES = (
3434
"When true, include default dbt Labs core/adapter macro packages"
3535
)
36+
37+
RESOURCE_TYPE_DESCRIPTION = (
38+
"The type of dbt resource to fetch details for. "
39+
"One of: model, source, exposure, test, seed, snapshot, macro, semantic_model. "
40+
"Tip: the resource_type is encoded in the unique_id prefix "
41+
"(e.g. `model.my_project.orders` → model)."
42+
)

src/dbt_mcp/discovery/tools.py

Lines changed: 9 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
MACRO_RETURN_PACKAGE_NAMES_ONLY,
2424
MODEL_PERF_INCLUDE_TESTS,
2525
MODEL_PERF_NUM_RUNS,
26+
RESOURCE_TYPE_DESCRIPTION,
2627
SOURCE_NAMES_FILTER,
2728
SOURCE_UNIQUE_IDS_FILTER,
2829
)
@@ -139,20 +140,23 @@ async def get_all_models(
139140

140141

141142
@dbt_mcp_tool(
142-
description=get_prompt("discovery/get_model_details"),
143-
title="Get Model Details",
143+
description=get_prompt("discovery/get_details"),
144+
title="Get Details",
144145
read_only_hint=True,
145146
destructive_hint=False,
146147
idempotent_hint=True,
147148
)
148-
async def get_model_details(
149+
async def get_details(
149150
context: DiscoveryToolContext,
151+
resource_type: Annotated[
152+
AppliedResourceType, Field(description=RESOURCE_TYPE_DESCRIPTION)
153+
],
150154
name: str | None = NAME_FIELD,
151155
unique_id: str | None = UNIQUE_ID_FIELD,
152156
) -> list[dict]:
153157
config = await context.config_provider.get_config()
154158
return await context.resource_details_fetcher.fetch_details(
155-
resource_type=AppliedResourceType.MODEL,
159+
resource_type=resource_type,
156160
unique_id=unique_id,
157161
name=name,
158162
config=config,
@@ -243,27 +247,6 @@ async def get_exposures(
243247
return await context.exposures_fetcher.fetch_exposures(config=config)
244248

245249

246-
@dbt_mcp_tool(
247-
description=get_prompt("discovery/get_exposure_details"),
248-
title="Get Exposure Details",
249-
read_only_hint=True,
250-
destructive_hint=False,
251-
idempotent_hint=True,
252-
)
253-
async def get_exposure_details(
254-
context: DiscoveryToolContext,
255-
name: str | None = NAME_FIELD,
256-
unique_id: str | None = UNIQUE_ID_FIELD,
257-
) -> list[dict]:
258-
config = await context.config_provider.get_config()
259-
return await context.resource_details_fetcher.fetch_details(
260-
resource_type=AppliedResourceType.EXPOSURE,
261-
unique_id=unique_id,
262-
name=name,
263-
config=config,
264-
)
265-
266-
267250
@dbt_mcp_tool(
268251
description=get_prompt("discovery/get_all_sources"),
269252
title="Get All Sources",
@@ -286,27 +269,6 @@ async def get_all_sources(
286269
)
287270

288271

289-
@dbt_mcp_tool(
290-
description=get_prompt("discovery/get_source_details"),
291-
title="Get Source Details",
292-
read_only_hint=True,
293-
destructive_hint=False,
294-
idempotent_hint=True,
295-
)
296-
async def get_source_details(
297-
context: DiscoveryToolContext,
298-
name: str | None = NAME_FIELD,
299-
unique_id: str | None = UNIQUE_ID_FIELD,
300-
) -> list[dict]:
301-
config = await context.config_provider.get_config()
302-
return await context.resource_details_fetcher.fetch_details(
303-
resource_type=AppliedResourceType.SOURCE,
304-
unique_id=unique_id,
305-
name=name,
306-
config=config,
307-
)
308-
309-
310272
@dbt_mcp_tool(
311273
description=get_prompt("discovery/get_all_macros"),
312274
title="Get All Macros",
@@ -335,128 +297,16 @@ async def get_all_macros(
335297
)
336298

337299

338-
@dbt_mcp_tool(
339-
description=get_prompt("discovery/get_macro_details"),
340-
title="Get Macro Details",
341-
read_only_hint=True,
342-
destructive_hint=False,
343-
idempotent_hint=True,
344-
)
345-
async def get_macro_details(
346-
context: DiscoveryToolContext,
347-
name: str | None = NAME_FIELD,
348-
unique_id: str | None = UNIQUE_ID_FIELD,
349-
) -> list[dict]:
350-
config = await context.config_provider.get_config()
351-
return await context.resource_details_fetcher.fetch_details(
352-
resource_type=AppliedResourceType.MACRO,
353-
unique_id=unique_id,
354-
name=name,
355-
config=config,
356-
)
357-
358-
359-
@dbt_mcp_tool(
360-
description=get_prompt("discovery/get_seed_details"),
361-
title="Get Seed Details",
362-
read_only_hint=True,
363-
destructive_hint=False,
364-
idempotent_hint=True,
365-
)
366-
async def get_seed_details(
367-
context: DiscoveryToolContext,
368-
name: str | None = NAME_FIELD,
369-
unique_id: str | None = UNIQUE_ID_FIELD,
370-
) -> list[dict]:
371-
config = await context.config_provider.get_config()
372-
return await context.resource_details_fetcher.fetch_details(
373-
resource_type=AppliedResourceType.SEED,
374-
unique_id=unique_id,
375-
name=name,
376-
config=config,
377-
)
378-
379-
380-
@dbt_mcp_tool(
381-
description=get_prompt("discovery/get_semantic_model_details"),
382-
title="Get Semantic Model Details",
383-
read_only_hint=True,
384-
destructive_hint=False,
385-
idempotent_hint=True,
386-
)
387-
async def get_semantic_model_details(
388-
context: DiscoveryToolContext,
389-
name: str | None = NAME_FIELD,
390-
unique_id: str | None = UNIQUE_ID_FIELD,
391-
) -> list[dict]:
392-
config = await context.config_provider.get_config()
393-
return await context.resource_details_fetcher.fetch_details(
394-
resource_type=AppliedResourceType.SEMANTIC_MODEL,
395-
unique_id=unique_id,
396-
name=name,
397-
config=config,
398-
)
399-
400-
401-
@dbt_mcp_tool(
402-
description=get_prompt("discovery/get_snapshot_details"),
403-
title="Get Snapshot Details",
404-
read_only_hint=True,
405-
destructive_hint=False,
406-
idempotent_hint=True,
407-
)
408-
async def get_snapshot_details(
409-
context: DiscoveryToolContext,
410-
name: str | None = NAME_FIELD,
411-
unique_id: str | None = UNIQUE_ID_FIELD,
412-
) -> list[dict]:
413-
config = await context.config_provider.get_config()
414-
return await context.resource_details_fetcher.fetch_details(
415-
resource_type=AppliedResourceType.SNAPSHOT,
416-
unique_id=unique_id,
417-
name=name,
418-
config=config,
419-
)
420-
421-
422-
@dbt_mcp_tool(
423-
description=get_prompt("discovery/get_test_details"),
424-
title="Get Test Details",
425-
read_only_hint=True,
426-
destructive_hint=False,
427-
idempotent_hint=True,
428-
)
429-
async def get_test_details(
430-
context: DiscoveryToolContext,
431-
name: str | None = NAME_FIELD,
432-
unique_id: str | None = UNIQUE_ID_FIELD,
433-
) -> list[dict]:
434-
config = await context.config_provider.get_config()
435-
return await context.resource_details_fetcher.fetch_details(
436-
resource_type=AppliedResourceType.TEST,
437-
unique_id=unique_id,
438-
name=name,
439-
config=config,
440-
)
441-
442-
443300
DISCOVERY_TOOLS = [
444301
get_mart_models,
445302
get_all_models,
446-
get_model_details,
303+
get_details,
447304
get_model_health,
448305
get_model_performance,
449306
get_lineage,
450307
get_exposures,
451-
get_exposure_details,
452308
get_all_sources,
453-
get_source_details,
454309
get_all_macros,
455-
get_macro_details,
456-
get_seed_details,
457-
get_semantic_model_details,
458-
get_snapshot_details,
459-
get_test_details,
460310
]
461311

462312

0 commit comments

Comments
 (0)