-
Notifications
You must be signed in to change notification settings - Fork 122
Expand file tree
/
Copy pathdefinitions.py
More file actions
99 lines (84 loc) · 3 KB
/
definitions.py
File metadata and controls
99 lines (84 loc) · 3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
from collections.abc import Callable
from dataclasses import dataclass
from enum import Enum
from functools import partial
from typing import Any
from mcp.server.fastmcp.tools.base import Tool
from mcp.types import ToolAnnotations
from dbt_mcp.tools.injection import adapt_with_mapper
from dbt_mcp.tools.tool_names import ToolName
@dataclass
class GenericToolDefinition[NameEnum: Enum]:
fn: Callable[..., Any]
title: str # Human-friendly title for the tool
description: str
name_enum: type[NameEnum]
name: str | None = None # Machine-friendly name for the tool
annotations: ToolAnnotations | None = None
structured_output: bool = True
meta: dict[str, Any] | None = None
def get_name(self) -> NameEnum:
return self.name_enum((self.name or self.fn.__name__).lower())
def to_fastmcp_internal_tool(self) -> Tool:
return Tool.from_function(
fn=self.fn,
name=self.name,
title=self.title,
description=self.description,
annotations=self.annotations,
structured_output=self.structured_output,
meta=self.meta,
)
def adapt_context(
self, context_mapper: Callable[..., Any]
) -> "GenericToolDefinition[NameEnum]":
"""
Adapt the tool definition to accept a different context object.
"""
return type(self)(
fn=adapt_with_mapper(self.fn, context_mapper),
description=self.description,
name_enum=self.name_enum,
name=self.name,
title=self.title,
annotations=self.annotations,
structured_output=self.structured_output,
meta=self.meta,
)
@dataclass
class ToolDefinition(GenericToolDefinition[ToolName]):
name_enum: type[ToolName] = ToolName
def generic_dbt_mcp_tool[NameEnum: Enum](
*,
description: str,
title: str,
name_enum: type[NameEnum],
name: str | None = None,
read_only_hint: bool = False,
destructive_hint: bool = True,
idempotent_hint: bool = False,
open_world_hint: bool = True,
structured_output: bool = True,
meta: dict[str, Any] | None = None,
) -> Callable[[Callable], GenericToolDefinition[NameEnum]]:
"""Decorator to define a tool definition for dbt MCP"""
def decorator(fn: Callable) -> GenericToolDefinition[NameEnum]:
return GenericToolDefinition(
fn=fn,
description=description,
name_enum=name_enum,
name=name,
title=title,
annotations=ToolAnnotations(
title=title,
readOnlyHint=read_only_hint,
destructiveHint=destructive_hint,
idempotentHint=idempotent_hint,
openWorldHint=open_world_hint,
),
structured_output=structured_output,
meta=meta,
)
return decorator
# Wrapper with ToolName pre-supplied for the common case
dbt_mcp_tool = partial(generic_dbt_mcp_tool, name_enum=ToolName)