|
| 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` |
0 commit comments