Skip to content

Commit a0462b0

Browse files
remi-tdclaude
andcommitted
Merge origin/main into db-tool-registry
Resolves conflicts preserving both feature sets: - Progressive disclosure of tools (this branch) - Dynamic DB-defined objects via registry (this branch) - SHOW command DDL extraction (main) - Ruff formatting / snake_case renames (main) - CI workflow, CLAUDE.md, auth improvements (main) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2 parents 940ad52 + f3b907c commit a0462b0

51 files changed

Lines changed: 6359 additions & 4623 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# CI/CD
2+
3+
## GitHub Actions Workflow
4+
5+
The CI workflow (`.github/workflows/ci.yml`) runs on every push to `main` and on pull requests targeting `main`. It consists of three parallel jobs:
6+
7+
### Jobs
8+
9+
| Job | What it does |
10+
|-----|-------------|
11+
| **Lint** | Runs `ruff check` and `ruff format --check` against `src/` |
12+
| **Type Check** | Runs `mypy` against `src/` (installs the `dev` extra for type stubs) |
13+
| **Integration Tests** | Runs the test suite against a live Teradata database |
14+
15+
All jobs use `uv sync --frozen` to ensure the lock file is up to date — if `uv.lock` is stale relative to `pyproject.toml`, the job will fail.
16+
17+
### Running Checks Locally
18+
19+
```bash
20+
# Lint
21+
uv run ruff check src/
22+
uv run ruff format --check src/
23+
24+
# Type check
25+
uv sync --extra dev
26+
uv run mypy src/
27+
28+
# Integration tests (requires a live Teradata connection)
29+
export DATABASE_URI="teradata://user:pass@host:1025/database"
30+
uv run python tests/run_mcp_tests.py "uv run teradata-mcp-server"
31+
```
32+
33+
### Configuring the `DATABASE_URI` Secret
34+
35+
The integration test job requires a `DATABASE_URI` repository secret to connect to a Teradata instance. Without it, the test job logs a warning and skips.
36+
37+
To configure:
38+
39+
1. Go to **Settings > Secrets and variables > Actions** in the GitHub repository
40+
2. Click **New repository secret**
41+
3. Name: `DATABASE_URI`
42+
4. Value: a Teradata connection URI, e.g. `teradata://user:pass@host:1025/database`
43+
44+
You need to be on the Teradata VPN to access the test database, so this secret should only be added by authorized Teradata personnel. If you don't have access, the tests will simply be skipped.
45+
46+
The test job is automatically skipped on fork PRs (where secrets are unavailable) to avoid failures.
47+
48+
### Concurrency
49+
50+
The workflow uses concurrency groups scoped to the branch/PR ref. If a new commit is pushed while a previous run is still in progress, the older run is cancelled to save CI minutes and avoid database contention.

.github/workflows/ci.yml

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
concurrency:
10+
group: ${{ github.workflow }}-${{ github.ref }}
11+
cancel-in-progress: true
12+
13+
jobs:
14+
lint:
15+
name: Lint (Ruff)
16+
runs-on: ubuntu-latest
17+
steps:
18+
- uses: actions/checkout@v4
19+
- uses: astral-sh/setup-uv@v4
20+
with:
21+
enable-cache: true
22+
- uses: actions/setup-python@v5
23+
with:
24+
python-version: "3.11"
25+
- run: uv sync --frozen --extra dev
26+
- run: uv run ruff check src/
27+
- run: uv run ruff format --check src/
28+
29+
typecheck:
30+
name: Type Check (Mypy)
31+
runs-on: ubuntu-latest
32+
steps:
33+
- uses: actions/checkout@v4
34+
- uses: astral-sh/setup-uv@v4
35+
with:
36+
enable-cache: true
37+
- uses: actions/setup-python@v5
38+
with:
39+
python-version: "3.11"
40+
- run: uv sync --frozen --extra dev
41+
- run: uv run mypy src/
42+
43+
test:
44+
name: Integration Tests
45+
runs-on: ubuntu-latest
46+
if: ${{ github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository }}
47+
steps:
48+
- uses: actions/checkout@v4
49+
- uses: astral-sh/setup-uv@v4
50+
with:
51+
enable-cache: true
52+
- uses: actions/setup-python@v5
53+
with:
54+
python-version: "3.11"
55+
- run: uv sync --frozen
56+
- name: Run integration tests
57+
if: ${{ env.DATABASE_URI != '' }}
58+
env:
59+
DATABASE_URI: ${{ secrets.DATABASE_URI }}
60+
run: uv run python tests/run_mcp_tests.py "uv run teradata-mcp-server"
61+
- name: Warn if DATABASE_URI not configured
62+
if: ${{ env.DATABASE_URI == '' }}
63+
env:
64+
DATABASE_URI: ${{ secrets.DATABASE_URI }}
65+
run: echo "::warning::DATABASE_URI secret is not configured — integration tests were skipped. See .github/README.md for setup instructions."

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ working/
88
*.egg-info/
99
**/.ipynb_checkpoints/
1010
/env
11-
CLAUDE.md
11+
docker-compose.dev.yml
1212
var/
1313
/# Only ignore root-level overrides
1414
/profiles.yml
1515
/*_objects.yml
1616
examples/app-flowise/.*
1717
test_*.py
18+
.planning/
19+
.ruff_cache/

CLAUDE.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
Teradata MCP Server — a Model Context Protocol server for interacting with Teradata databases. Built on FastMCP, distributed on PyPI as `teradata-mcp-server`. Python 3.11+.
8+
9+
## Build & Development Commands
10+
11+
```bash
12+
# Install dependencies
13+
uv sync
14+
15+
# Install with optional modules
16+
uv sync --extra fs # Feature Store (teradataml)
17+
uv sync --extra tdvs # Vector Store (teradatagenai)
18+
uv sync --extra bar # Backup & Restore
19+
uv sync --extra dev # Dev tools (ruff, mypy)
20+
21+
# Run the server locally (stdio mode)
22+
uv run teradata-mcp-server --database_uri "teradata://user:pass@host:1025/db"
23+
24+
# Run with specific profile and transport
25+
uv run teradata-mcp-server --profile dba --mcp_transport streamable-http --mcp_port 8001
26+
27+
# Lint
28+
uv run ruff check src/
29+
uv run ruff format --check src/
30+
31+
# Type check
32+
uv run mypy src/
33+
34+
# Run tests (requires a live Teradata connection)
35+
export DATABASE_URI="teradata://user:pass@host:1025/database"
36+
uv run python tests/run_mcp_tests.py "uv run teradata-mcp-server"
37+
38+
# Docker
39+
docker compose up teradata-mcp-server
40+
```
41+
42+
## Architecture
43+
44+
### Request Flow
45+
46+
1. **`server.py`** — CLI argument parsing, calls `create_mcp_app()`
47+
2. **`app.py`** — FastMCP app factory. Creates the MCP instance, registers tools/prompts/resources based on profile, configures middleware
48+
3. **`middleware.py`**`RequestContextMiddleware` extracts per-request headers, auth, and session info. Sets Teradata QueryBand for tracing
49+
4. **Tool handlers** — Plain sync functions (`handle_*`) in `tools/` subdirectories. Wrapped to async via `asyncio.to_thread`
50+
51+
### Profile-Based Module Loading
52+
53+
Tools are organized into domain modules under `src/teradata_mcp_server/tools/`:
54+
- **base/** — Core queries (readQuery, tableList, columnDescription, etc.)
55+
- **dba/** — Administration & monitoring
56+
- **sec/** — Security & permissions
57+
- **rag/** — Retrieval-augmented generation workflows
58+
- **fs/** — Feature Store (optional, requires teradataml)
59+
- **tdvs/** — Vector Store operations
60+
- **bar/** — Backup & restore (optional)
61+
- **chat/** — Chat completion
62+
- **qlty/** — Data quality / EDA
63+
- **plot/** — Visualization (charts)
64+
- **sql_opt/** — SQL optimization
65+
- **tmpl/** — Template tools
66+
67+
Profiles (defined in `config/profiles.yml`) control which modules load. The `module_loader.py` uses regex pattern matching against tool name prefixes to determine which modules to import. Available profiles: `all`, `dba`, `dataScientist`, `eda`, `bar`, `llmUser`, `tester`.
68+
69+
### Configuration System
70+
71+
Layered config loading (`config_loader.py`):
72+
1. Packaged defaults from `src/teradata_mcp_server/config/*.yml`
73+
2. User overrides from working directory or `CONFIG_DIR` env var
74+
75+
Settings dataclass in `config/__init__.py` merges CLI args, environment variables, and defaults.
76+
77+
### Database Connectivity
78+
79+
`TDConn` class in `tools/td_connect.py` manages SQLAlchemy engine creation for Teradata. Supports connection pooling (`TD_POOL_SIZE`, `TD_MAX_OVERFLOW`, `TD_POOL_TIMEOUT`), auth modes (TD2, LDAP via `LOGMECH`), and rate-limited authentication.
80+
81+
Tool handlers receive either a SQLAlchemy `Connection` or raw `TeradataConnection` as their first parameter — the wrapper in `app.py` handles injection.
82+
83+
### Transport Modes
84+
85+
Set via `MCP_TRANSPORT` env var or `--mcp_transport` flag:
86+
- **stdio** (default) — for Claude Desktop and CLI clients
87+
- **streamable-http** — HTTP with streaming on configurable host/port
88+
- **sse** — Server-Sent Events, this will be merged into streamable-http as the MCP standard is depricating SSE as a separate transport
89+
90+
For stdio transport, logs go to file only (to avoid polluting MCP stdout). Log locations: macOS `~/Library/Logs/TeradataMCP/`, Linux `~/.local/state/teradata_mcp_server/logs/`.
91+
92+
### Testing
93+
94+
Tests require a live Teradata database. Test cases are JSON files in `tests/cases/` (e.g., `core_test_cases.json`). The test runner (`tests/run_mcp_tests.py`) dynamically discovers available tools and only runs matching test cases. Results are saved as timestamped JSON in `var/test-reports/`.
95+
96+
## Code Conventions
97+
98+
- **Ruff** for linting/formatting: line length 120, target py311, rules: E, W, F, I, N, B, UP, C4, SIM, PIE, PL
99+
- Tool handler functions are named `handle_<tool_name>` and stay synchronous
100+
- Tool names are prefixed by module: `base_*`, `dba_*`, `sec_*`, `rag_*`, etc.
101+
- Structured JSON logging via `CustomJSONFormatter` in `utils.py`

docs/server_guide/CUSTOMIZING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ my-teradata-config/
217217
```
218218
219219
### Complete Example
220-
See the provided [`custom_objects.yml`](../custom_objects.yml) in the repository for a complete working example.
220+
See the provided [`custom_objects.yml`](../../examples/server-customisation/custom_objects.yml) in the repository for a complete working example.
221221
222222
### Running with Custom Configuration
223223
```bash

0 commit comments

Comments
 (0)