Skip to content

Commit 042f7a1

Browse files
authored
Allow parameters definition in prompt declarations (#130)
* Allowed parameters definition for prompts declared in *_objects.yml * moved to build management hatchling * include tools/*/*_objects.yml files in wheel
1 parent e10cc09 commit 042f7a1

18 files changed

+872
-3554
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ working/
88
*.egg-info/
99
**/.ipynb_checkpoints/
1010
env
11-
test_results/
1211
custom*_objects.yaml
1312
CLAUDE.md
1413
var/

Dockerfile

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ WORKDIR /app
66
ARG ENABLE_FS_MODULE=false
77
ARG ENABLE_EVS_MODULE=false
88

9-
COPY pyproject.toml uv.lock* /app/
9+
# Copy essential files for dependency installation
10+
COPY pyproject.toml uv.lock* README.md /app/
11+
12+
# Install system dependencies and Python dependencies
1013
RUN apt-get update && \
1114
apt-get install -y --no-install-recommends build-essential gcc && \
1215
pip install --upgrade pip && \
@@ -15,17 +18,19 @@ RUN apt-get update && \
1518
UV_EXTRAS="" && \
1619
if [ "$ENABLE_FS_MODULE" = "true" ]; then UV_EXTRAS="$UV_EXTRAS --extra fs"; fi && \
1720
if [ "$ENABLE_EVS_MODULE" = "true" ]; then UV_EXTRAS="$UV_EXTRAS --extra evs"; fi && \
18-
uv sync $UV_EXTRAS && \
19-
uv build && \
21+
uv sync $UV_EXTRAS
22+
23+
# Copy source code before building
24+
COPY ./src /app/src
25+
26+
# Build and install the package
27+
RUN uv build && \
2028
pip install . && \
2129
apt-get purge -y build-essential gcc && \
2230
rm -rf /var/lib/apt/lists/*
2331

24-
# Copy everything *except* src (excluded via .dockerignore)
32+
# Copy everything else
2533
COPY . /app
26-
27-
# Copy src with conditional module directories
28-
COPY ./src /app/src
2934
# Remove optional module directories if not enabled
3035
RUN if [ "$ENABLE_FS_MODULE" != "true" ]; then rm -rf /app/src/teradata_mcp_server/tools/fs; fi && \
3136
if [ "$ENABLE_EVS_MODULE" != "true" ]; then rm -rf /app/src/teradata_mcp_server/tools/evs; fi
File renamed without changes.

custom_sales_objects.yml

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Custom tool definitions here
2+
sales_top_customers:
3+
type: tool
4+
description: "Get the top 20 customers by lifetime value."
5+
sql: |
6+
sel top 20 * from dim_customers order by customer_lifetime_value desc;
7+
8+
sales_customer_profile:
9+
type: tool
10+
description: "Get customer profile and metrics."
11+
sql: |
12+
sel dim_customers.*, customer_nk as customer_email from dim_customers
13+
join key_customer
14+
on dim_customers.customer_key = key_customer.customer_key
15+
where dim_customers.customer_key = :customer_key;
16+
parameters:
17+
customer_key:
18+
description: "The key (integer) for the customer to lookup."
19+
20+
sales_cube:
21+
type: cube
22+
description: "Get the key sales metrics: USD amount and number of orders."
23+
sql: |
24+
sel customer_key, extract(year from order_date) sales_year, extract(month from order_date) sales_month, gift_card_amount_usd, amount amount_usd
25+
from fct_orders o
26+
measures:
27+
gift_amount_usd:
28+
description: "Total gift card amount used for the order in USD"
29+
expression: "SUM(gift_card_amount_usd)"
30+
total_amount_usd:
31+
description: "Total order amount in USD"
32+
expression: "SUM(amount_usd)"
33+
order_count:
34+
description: "Total number of orders"
35+
expression: "COUNT(1)"
36+
dimensions:
37+
customer_key:
38+
description: "Key for the customer"
39+
expression: "customer_key"
40+
sales_year:
41+
description: "Year of the sale"
42+
expression: "sales_year"
43+
sales_month:
44+
description: "Month of the sale"
45+
expression: "sales_month"
46+
47+
sales_prompt:
48+
type: prompt
49+
description: "my prompt description"
50+
prompt: |
51+
You are a data analyst working for a sales team.
52+
Your task is to analyze the sales data using the tools you have and provide insights.
53+
All your answers must be based on the data you retrieve using the tools, and you must be ready to provide data for your answers.
54+
55+
sales_glossary:
56+
type: glossary
57+
customer:
58+
definition: "A person or organization that purchases goods or services from our business."
59+
synonyms:
60+
- Clients
61+
62+
sales:
63+
definition: "The key metrics related to completed orders: USD amount and number of orders."
64+
synonyms:
65+
- revenue
66+
- sales figures
67+
tools:
68+
- sales_cube

docs/CUSTOMIZING.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ A semantic layer in this context is a collection of custom tools, prompts, cubes
1919
- **Profiles:** Named sets of tools, prompts, and resources that enable domain-specific server instantiations.
2020

2121
### Declarative Specification
22-
All custom objects can be defined in a YAML file (e.g., `sales_objects.yaml`, `finance_objects.yaml`). The file is a dictionary keyed by object name, with each entry specifying its type and details:
22+
All custom objects can be defined in a YAML file (e.g., `sales_objects.yml`, `finance_objects.yml`). The file is a dictionary keyed by object name, with each entry specifying its type and details:
2323

2424
```yaml
2525
sales_by_region:
@@ -92,7 +92,7 @@ For example, to run the server with the pre-defined dba profile:
9292
## Custom Objects Implementation Details
9393

9494
### File Naming and Loading
95-
All customizations must be defined in files named `*_objects.yaml` (e.g., `sales_objects.yaml`, `finance_objects.yaml`).
95+
All customizations must be defined in files named `*_objects.yml` (e.g., `sales_objects.yml`, `finance_objects.yml`).
9696

9797
### Supported Object Types and Attribute Rules
9898
Each entry in the YAML file is keyed by its name and must specify a `type`. Supported types and their required/optional attributes:
@@ -101,8 +101,8 @@ Each entry in the YAML file is keyed by its name and must specify a `type`. Supp
101101
- **Required:**
102102
- `type`: Must be `tool`
103103
- `sql`: SQL query string (it can be a prepared statement with parameters)
104-
- `parameters`: Dictionary of parameter definitions
105104
- **Optional:**
105+
- `parameters`: Dictionary of parameter name (key) and definitions (value) - if used in the sql
106106
- `description`: Text description of the tool
107107

108108
#### Cube
@@ -119,6 +119,7 @@ Each entry in the YAML file is keyed by its name and must specify a `type`. Supp
119119
- `type`: Must be `prompt`
120120
- `prompt`: Text of the prompt
121121
- **Optional:**
122+
- `parameters`: Dictionary of parameter name (key) and definitions (value) - if used in the prompt
122123
- `description`: Text description of the prompt
123124

124125
#### Glossary
@@ -145,4 +146,4 @@ Each entry in the YAML file is keyed by its name and must specify a `type`. Supp
145146

146147
## Example
147148

148-
See the provided [`custom_objects.yaml`](../custom_objects.yaml) (or your domain-specific YAML file) for a complete example.
149+
See the provided [`custom_objects.yml`](../custom_objects.yml) (or your domain-specific YAML file) for a complete example.

docs/developer_guide/DEVELOPER_GUIDE.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,14 @@ Two guides have been created to show how to add tools and prompts:
122122

123123
<br>
124124

125+
## Interactive testing using the MCP Inspector
126+
127+
The MCP inspector provides you with a convenient way to browse and test tools, resources and prompts:
128+
129+
```
130+
uv run mcp dev ./src/teradata_mcp_server/server.py
131+
```
132+
125133
## Tools testing
126134

127135
Use the provided testing tool to run tests, add tests if you add a new tool.

pyproject.toml

Lines changed: 91 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,131 @@
11
[project]
22
name = "teradata-mcp-server"
33
version = "0.1.1"
4-
description = "Initial version of the Teradata MCP Server"
4+
description = "Model Context Protocol (MCP) server for Teradata, Community edition"
55
readme = "README.md"
6-
requires-python = ">=3.13"
6+
license = {text = "MIT"}
7+
authors = [
8+
{name = "Teradata"}
9+
]
10+
requires-python = ">=3.11"
11+
keywords = ["teradata", "mcp", "database", "sql", "model-context-protocol"]
12+
classifiers = [
13+
"Development Status :: 3 - Alpha",
14+
"Intended Audience :: Developers",
15+
"License :: OSI Approved :: MIT License",
16+
"Operating System :: OS Independent",
17+
"Programming Language :: Python :: 3",
18+
"Programming Language :: Python :: 3.11",
19+
"Programming Language :: Python :: 3.12",
20+
"Programming Language :: Python :: 3.13",
21+
"Topic :: Database",
22+
"Topic :: Software Development :: Libraries :: Python Modules",
23+
]
724
dependencies = [
8-
"pydantic>=2.11.3",
9-
"mcp[cli]==1.9.3",
10-
"teradatasqlalchemy>=20.0.0.0",
11-
"python-dotenv>=1.0.0",
12-
"PyYAML>=6.0.0",
13-
"sqlalchemy>=2.0.0",
25+
"pydantic>=2.8.0,<3.0.0",
26+
"mcp>=1.0.0,<2.0.0",
27+
"teradatasqlalchemy>=20.0.0.0",
28+
"python-dotenv>=1.0.0",
29+
"PyYAML>=6.0.0",
30+
"sqlalchemy>=2.0.0,<3.0.0",
1431
]
1532

1633
[project.optional-dependencies]
17-
test = [
18-
"anthropic>=0.49.0",
19-
"boto3>=1.37.37",
20-
"langchain-core>=0.3.54",
21-
"langchain-mcp-adapters>=0.0.9",
22-
"langchain-openai>=0.3.14",
23-
"langgraph>=0.3.31",
24-
"openai>=1.75.0",
25-
"litellm>=1.68.2",
26-
"nest-asyncio>=1.6.0",
27-
"google-adk>=1.3.0",
28-
"jinja2>=3.1.0",
29-
]
34+
# Feature Store functionality
3035
fs = [
31-
"teradataml>=20.0.0.5",
32-
"tdfs4ds==0.2.4.16",
36+
"teradataml>=20.0.0.5",
37+
"tdfs4ds>=0.2.4.0",
3338
]
39+
# Enterprise Vector Store functionality
3440
evs = [
35-
"teradatagenai>=20.0.0.0",
41+
"teradatagenai>=20.0.0.0",
42+
]
43+
# Development dependencies
44+
dev = [
45+
"ruff>=0.1.0",
46+
"mypy>=1.5.0",
3647
]
3748

3849
[project.scripts]
3950
teradata-mcp-server = "teradata_mcp_server:main"
4051
teradata-test = "teradata_mcp_server.testing.cli:main"
4152

53+
[project.urls]
54+
Homepage = "https://github.com/Teradata/teradata-mcp-server"
55+
Documentation = "https://github.com/Teradata/teradata-mcp-server#readme"
56+
Repository = "https://github.com/Teradata/teradata-mcp-server.git"
57+
"Bug Tracker" = "https://github.com/Teradata/teradata-mcp-server/issues"
58+
"Source" = "https://github.com/Teradata/teradata-mcp-server"
59+
"Discussions" = "https://github.com/Teradata/teradata-mcp-server/discussions"
60+
4261
[build-system]
43-
requires = ["setuptools>=65", "wheel"]
44-
build-backend = "setuptools.build_meta"
62+
requires = ["hatchling>=1.17.0"]
63+
build-backend = "hatchling.build"
64+
65+
[tool.hatch.build.targets.wheel]
66+
packages = ["src/teradata_mcp_server"]
67+
include = [
68+
"src/teradata_mcp_server/tools/**/*.yml",
69+
]
4570

4671
[tool.uv]
4772
package = true
4873

4974
[tool.ruff]
5075
line-length = 120
51-
target-version = "py313"
76+
target-version = "py311"
77+
src = ["src"]
5278

5379
[tool.ruff.lint]
54-
select = ["E", "W", "F", "I", "N", "B", "UP"]
80+
select = [
81+
"E", # pycodestyle errors
82+
"W", # pycodestyle warnings
83+
"F", # pyflakes
84+
"I", # isort
85+
"N", # pep8-naming
86+
"B", # flake8-bugbear
87+
"UP", # pyupgrade
88+
"C4", # flake8-comprehensions
89+
"SIM", # flake8-simplify
90+
"PIE", # flake8-pie
91+
"PL", # pylint
92+
]
5593
ignore = [
5694
"F403", # Wildcard imports (temporarily ignore for gradual refactoring)
5795
"F401", # Unused imports in __init__.py files (common pattern for re-exports)
5896
"E402", # Module level import not at top (some tools have conditional imports)
59-
"E501", # Line too long (let formatter handle this)
6097
"N816", # Variable naming (existing legacy naming)
6198
"N802", # Function naming (preserve existing naming conventions)
6299
"N803", # Argument naming (preserve existing naming conventions)
63100
"B905", # zip() without explicit strict parameter (backwards compatibility)
64101
"B008", # Function call in default argument (existing pattern)
65102
"F841", # Unused variable (may be intentional in some cases)
103+
"PLR0913", # Too many arguments (common in database tools)
104+
"PLR0912", # Too many branches (common in conditional logic)
105+
"PLR0915", # Too many statements (common in setup functions)
66106
]
67107

68108
[tool.ruff.lint.per-file-ignores]
69109
"*/__init__.py" = ["F403", "F401"] # Allow wildcard imports and unused imports in __init__.py
110+
"tests/*" = ["F401", "F403", "PLR0913"] # More lenient for test files
111+
112+
[tool.ruff.lint.isort]
113+
known-first-party = ["teradata_mcp_server"]
114+
115+
[tool.mypy]
116+
python_version = "3.11"
117+
warn_return_any = true
118+
warn_unused_configs = true
119+
disallow_untyped_defs = false # Gradually enable this
120+
ignore_missing_imports = true
121+
strict_optional = true
122+
123+
124+
125+
126+
[tool.hatch.build.targets.sdist]
127+
include = [
128+
"src/teradata_mcp_server",
129+
"README.md",
130+
"LICENSE",
131+
]

0 commit comments

Comments
 (0)