Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ We are providing groupings of tools and associated helpful prompts to support al
- [Plot Tools](./src/teradata_mcp_server/tools/plot/README.md)
- **BAR** tools, prompts and resources for database backup and restore operations:
- [BAR Tools](src/teradata_mcp_server/tools/bar/README.md) integrate AI agents with Teradata DSA (Data Stream Architecture) for comprehensive backup management across multiple storage solutions including disk files, cloud storage (AWS S3, Azure Blob, Google Cloud), and enterprise systems (NetBackup, IBM Spectrum).
- **QueryGrid** tools, prompts and resources for managing Teradata QueryGrid:
- [QueryGrid Tools](src/teradata_mcp_server/tools/qg/README.md)

## Quick start with Claude Desktop (no installation)
> Prefer to use other tools? Check out our Quick Starts for [VS Code/Copilot](https://github.com/Teradata/teradata-mcp-server/blob/main/docs/server_guide/QUICK_START_VSCODE.md), [Open WebUI](https://github.com/Teradata/teradata-mcp-server/blob/main/docs/server_guide/QUICK_START_OPEN_WEBUI.md), or dive into [simple code examples](https://github.com/Teradata/teradata-mcp-server/blob/main/examples/README.md#client-applications)!
Expand Down
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ bar = [
"requests>=2.25.0",
]

# QueryGrid functionality
qg = [
"requests>=2.25.0",
]

# Development dependencies
dev = [
"ruff>=0.1.0",
Expand Down
28 changes: 27 additions & 1 deletion src/teradata_mcp_server/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import inspect
import os
import re
import sys
from importlib.resources import files as pkg_files
from typing import Annotated, Any

Expand Down Expand Up @@ -64,6 +65,7 @@ def create_mcp_app(settings: Settings):
enableEFS = True if any(re.match(pattern, 'fs_*') for pattern in config.get('tool', [])) else False
enableTDVS = True if any(re.match(pattern, 'tdvs_*') for pattern in config.get('tool', [])) else False
enableBAR = True if any(re.match(pattern, 'bar_*') for pattern in config.get('tool', [])) else False
enableQG = True if any(re.match(pattern, 'qg_*') for pattern in config.get('tool', [])) else False

# Initialize TD connection and optional teradataml/EFS context
# Pass settings object to TDConn instead of just connection_url
Expand Down Expand Up @@ -128,6 +130,18 @@ def create_mcp_app(settings: Settings):
logger.warning(f"BAR system dependencies not available - disabling BAR functionality: {e}")
enableBAR = False

# QueryGrid dependencies (optional)
qg_manager = None
if enableQG:
try:
# Check for QG system availability by importing required modules
import requests
from teradata_mcp_server.tools.qg.qgm.querygrid_manager import QueryGridManager
qg_manager = QueryGridManager()
except (AttributeError, ImportError, ModuleNotFoundError) as e:
logger.warning(f"QG system dependencies not available - disabling QG functionality: {e}")
enableQG = False

# Middleware (auth + request context)
from teradata_mcp_server.tools.auth_cache import SecureAuthCache
auth_cache = SecureAuthCache(ttl_seconds=settings.auth_cache_ttl)
Expand Down Expand Up @@ -321,6 +335,10 @@ def make_tool_wrapper(func):
inject_kwargs["fs_config"] = fs_config
removable.add("fs_config")

if "qg_manager" in sig.parameters:
inject_kwargs["qg_manager"] = qg_manager
removable.add("qg_manager")

params = [
p for name, p in sig.parameters.items()
if name not in removable and p.kind in (inspect.Parameter.POSITIONAL_OR_KEYWORD, inspect.Parameter.KEYWORD_ONLY)
Expand Down Expand Up @@ -358,6 +376,10 @@ def executor(**kwargs):
if tool_name.startswith("bar_") and not enableBAR:
logger.info(f"Skipping BAR tool: {tool_name} (BAR functionality disabled)")
continue
# Skip QueryGrid tools if the functionality is disabled
if tool_name.startswith("qg_") and not enableQG:
logger.info(f"Skipping QueryGrid tool: {tool_name} (functionality disabled)")
continue
wrapped = make_tool_wrapper(func)
mcp.tool(name=tool_name, description=wrapped.__doc__)(wrapped)
logger.info(f"Created tool: {tool_name}")
Expand Down Expand Up @@ -795,4 +817,8 @@ def get_glossary_term(term_name: str) -> dict:
return {"error": f"Glossary term not found: {term_name}"}

# Return the configured app and some handles used by the entrypoint if needed
return mcp, logger
def cleanup():
if qg_manager:
qg_manager.close()

return mcp, logger, cleanup
12 changes: 12 additions & 0 deletions src/teradata_mcp_server/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ class Settings:
max_overflow: int = 10
pool_timeout: int = 30

# QueryGrid Manager
qg_manager_host: str | None = None
qg_manager_port: int | None = None
qg_manager_username: str | None = None
qg_manager_password: str | None = None
qg_manager_verify_ssl: bool = True

# Logging
logging_level: str = os.getenv("LOGGING_LEVEL", "WARNING")

Expand All @@ -57,5 +64,10 @@ def settings_from_env() -> Settings:
pool_size=int(os.getenv("TD_POOL_SIZE", "5")),
max_overflow=int(os.getenv("TD_MAX_OVERFLOW", "10")),
pool_timeout=int(os.getenv("TD_POOL_TIMEOUT", "30")),
qg_manager_host=os.getenv("QG_MANAGER_HOST") or None,
qg_manager_port=int(os.getenv("QG_MANAGER_PORT")) if os.getenv("QG_MANAGER_PORT") else None,
qg_manager_username=os.getenv("QG_MANAGER_USERNAME") or None,
qg_manager_password=os.getenv("QG_MANAGER_PASSWORD") or None,
qg_manager_verify_ssl=os.getenv("QG_MANAGER_VERIFY_SSL", "true").lower() in ["true", "1", "yes"],
logging_level=os.getenv("LOGGING_LEVEL", "WARNING"),
)
10 changes: 9 additions & 1 deletion src/teradata_mcp_server/config/profiles.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,12 @@ bar:
prompt:
- ^bar_*
resource:
- ^bar_*
- ^bar_*

qg:
tool:
- ^qg_*
prompt:
- ^qg_*
resource:
- ^qg_*
18 changes: 16 additions & 2 deletions src/teradata_mcp_server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import asyncio
import os
import signal
import sys
from dotenv import load_dotenv

from teradata_mcp_server.config import Settings, settings_from_env
Expand All @@ -28,6 +29,14 @@ def parse_args_to_settings() -> Settings:
parser.add_argument('--auth_mode', type=str, required=False)
parser.add_argument('--auth_cache_ttl', type=int, required=False)
parser.add_argument('--logging_level', type=str, required=False)
# querygrid arguments can be added here as needed
parser.add_argument('--qg_manager_host', type=str, required=False, help='QueryGrid Manager host')
parser.add_argument('--qg_manager_port', type=int, required=False, help='QueryGrid Manager port')
parser.add_argument('--qg_manager_username', type=str, required=False, help='QueryGrid Manager username')
parser.add_argument('--qg_manager_password', required=False, help='QueryGrid Manager password')
parser.add_argument('--qg_manager_verify_ssl', type=str, required=False, help='Verify SSL certificates for QueryGrid Manager (true/false, default: true)')



args, _ = parser.parse_known_args()

Expand All @@ -43,20 +52,25 @@ def parse_args_to_settings() -> Settings:
auth_mode=(args.auth_mode or env.auth_mode).lower(),
auth_cache_ttl=args.auth_cache_ttl if args.auth_cache_ttl is not None else env.auth_cache_ttl,
logging_level=(args.logging_level or env.logging_level).upper(),
qg_manager_host=args.qg_manager_host if args.qg_manager_host is not None else env.qg_manager_host,
qg_manager_port=args.qg_manager_port if args.qg_manager_port is not None else env.qg_manager_port,
qg_manager_username=args.qg_manager_username if args.qg_manager_username is not None else env.qg_manager_username,
qg_manager_password=args.qg_manager_password if args.qg_manager_password is not None else env.qg_manager_password,
qg_manager_verify_ssl=args.qg_manager_verify_ssl.lower() in ["true", "1", "yes"] if args.qg_manager_verify_ssl is not None else env.qg_manager_verify_ssl,
)


async def main():
load_dotenv()
settings = parse_args_to_settings()
mcp, logger = create_mcp_app(settings)
mcp, logger, cleanup = create_mcp_app(settings)

# Graceful shutdown
try:
loop = asyncio.get_running_loop()
for s in (signal.SIGTERM, signal.SIGINT):
logger.info(f"Registering signal handler for {s.name}")
loop.add_signal_handler(s, lambda s=s: os._exit(0))
loop.add_signal_handler(s, lambda s=s: (cleanup(), os._exit(0)))
except NotImplementedError:
logger.warning("Signal handling not supported on this platform")

Expand Down
1 change: 1 addition & 0 deletions src/teradata_mcp_server/tools/module_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class ModuleLoader:
'base': 'teradata_mcp_server.tools.base',
'dba': 'teradata_mcp_server.tools.dba',
'fs': 'teradata_mcp_server.tools.fs',
'qg': 'teradata_mcp_server.tools.qg',
'qlty': 'teradata_mcp_server.tools.qlty',
'rag': 'teradata_mcp_server.tools.rag',
'sql_opt': 'teradata_mcp_server.tools.sql_opt',
Expand Down
208 changes: 208 additions & 0 deletions src/teradata_mcp_server/tools/qg/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
# Teradata QueryGrid (QG) tools

## Prerequisites

**Teradata QueryGrid (QG) Infrastructure** must be properly configured and running before using QueryGrid tools

### Environment Variables

The QG tools require the following environment variables for making connection:

- `QG_MANAGER_HOST` - Hostname for QG Manager (QGM) APIs (default: localhost)
- `QG_MANAGER_PORT` - Port for QG Manager (QGM) APIs (default: 9443)
- `QG_MANAGER_USERNAME` - Username for QGM authentication (default: support)
- `QG_MANAGER_PASSWORD` - Password for QGM authentication (default: teradata)
- `QG_MANAGER_VERIFY_SSL` - Whether to verify SSL certificates (default: true)

### QG Profile Configuration
The QG profile is defined in `config/profiles.yml` and controls access to QG-related tools and resources.

**Profile Configuration:**
```yaml
qg:
tool:
- ^qg_*
prompt:
- ^qg_*
resource:
- ^qg_*
```
**What the QG profile enables:**
- Access to all `qg_*` tools for managing QueryGrid

**Usage:** Specify `--profile qg` when running MCP server to enable QG-specific functionality

## Available QueryGrid Tools

The QueryGrid MCP server provides **56 GET methods** for retrieving QueryGrid configuration and status information. All tools follow the naming convention `qg_get_*` and provide read-only access to QueryGrid Manager data.

### Core Resource Methods (42 total)

#### Managers (2 tools)
- `qg_get_managers` - Get all QueryGrid managers with optional filtering
- `qg_get_manager_by_id` - Get a specific manager by ID

#### Nodes (3 tools)
- `qg_get_nodes` - Get all nodes with advanced filtering options
- `qg_get_node_by_id` - Get a specific node by ID
- `qg_get_node_heartbeat_by_id` - Get the latest heartbeat sent by a specific node

#### Systems (2 tools)
- `qg_get_systems` - Get all systems with optional filtering
- `qg_get_system_by_id` - Get a specific system by ID

#### Connectors (6 tools)
- `qg_get_connectors` - Get all connectors with filtering
- `qg_get_connector_by_id` - Get a specific connector by ID
- `qg_get_connector_active` - Get active connector configuration
- `qg_get_connector_pending` - Get pending connector configuration
- `qg_get_connector_previous` - Get previous connector configuration
- `qg_get_connector_drivers` - Get connector drivers by version

#### Fabrics (5 tools)
- `qg_get_fabrics` - Get all fabrics with filtering
- `qg_get_fabric_by_id` - Get a specific fabric by ID
- `qg_get_fabric_active` - Get active fabric configuration
- `qg_get_fabric_pending` - Get pending fabric configuration
- `qg_get_fabric_previous` - Get previous fabric configuration

#### Networks (5 tools)
- `qg_get_networks` - Get all networks with filtering
- `qg_get_network_by_id` - Get a specific network by ID
- `qg_get_network_active` - Get active network configuration
- `qg_get_network_pending` - Get pending network configuration
- `qg_get_network_previous` - Get previous network configuration

#### Links (5 tools)
- `qg_get_links` - Get all links with filtering
- `qg_get_link_by_id` - Get a specific link by ID
- `qg_get_link_active` - Get active link configuration
- `qg_get_link_pending` - Get pending link configuration
- `qg_get_link_previous` - Get previous link configuration

#### Communication Policies (5 tools)
- `qg_get_comm_policies` - Get all communication policies
- `qg_get_comm_policy_by_id` - Get a specific communication policy by ID
- `qg_get_comm_policy_active` - Get active communication policy configuration
- `qg_get_comm_policy_pending` - Get pending communication policy configuration
- `qg_get_comm_policy_previous` - Get previous communication policy configuration

#### Bridges (2 tools)
- `qg_get_bridges` - Get all bridges with filtering
- `qg_get_bridge_by_id` - Get a specific bridge by ID

#### Data Centers (2 tools)
- `qg_get_datacenters` - Get all datacenters with filtering
- `qg_get_datacenter_by_id` - Get a specific datacenter by ID

#### Node Virtual IPs (2 tools)
- `qg_get_node_virtual_ips` - Get all node virtual IPs
- `qg_get_node_virtual_ip_by_id` - Get a specific node virtual IP by ID

### Query & Software Methods (6 total)

#### Queries (3 tools)
- `qg_get_query_summary` - Get query summary with filtering options
- `qg_get_query_by_id` - Get a specific query by ID
- `qg_get_query_details` - Get detailed information for a specific query

#### Software (3 tools)
- `qg_get_software` - Get QueryGrid software information
- `qg_get_software_by_id` - Get a specific software package by ID
- `qg_get_software_jdbc_driver` - Get QueryGrid JDBC driver software information
- `qg_get_software_jdbc_driver_by_name` - Get software information for a specific JDBC driver

### User Management Methods (4 total)

#### Users (2 tools)
- `qg_get_users` - Get all QueryGrid users
- `qg_get_user_by_username` - Get a specific user by username

#### User Mappings (2 tools)
- `qg_get_user_mappings` - Get all user mappings with filtering
- `qg_get_user_mapping_by_id` - Get a specific user mapping by ID

### Monitoring & Diagnostics (5 total)

#### Issues (2 tools)
- `qg_get_issues` - Get all active QueryGrid issues
- `qg_get_issue_by_id` - Get a specific issue by ID

#### Diagnostics (3 tools)
- `qg_get_diagnostic_check_status` - Get diagnostic check status
- `qg_get_nodes_auto_install_status` - Get automatic node installation status
- `qg_get_create_foreign_server_status` - Get CONNECTOR_CFS diagnostic check status

### API Information (1 tool)
- `qg_get_api_info` - Get QueryGrid API information

## Tool Parameters

Most tools support optional parameters for filtering and configuration:

- `extra_info` (bool) - Include additional information in responses
- `filter_by_name` (str) - Filter results by name (supports wildcards with '*')
- `filter_by_tag` (str) - Filter by tag (comma-separated key:value pairs)
- `flatten` (bool) - Flatten nested response structures

Query-specific tools support additional parameters:
- `last_modified_after` (str) - Filter queries modified after ISO8601 timestamp
- `completed` (bool) - Include only completed queries
- `query_text_phrase` (str) - Filter by text phrase in query
- `query_ref_ids` (str) - Filter by comma-separated query reference IDs
- `initiator_query_id` (str) - Filter by initiator query ID

Node-specific filtering parameters:
- `filter_by_system_id` (str) - Filter nodes by system ID
- `filter_by_bridge_id` (str) - Filter nodes by bridge ID
- `filter_by_fabric_id` (str) - Filter nodes by fabric ID
- `filter_by_connector_id` (str) - Filter nodes by connector ID
- `fabric_version` (str) - Filter by fabric version
- `connector_version` (str) - Filter by connector version
- `drivers` (str) - Filter with drivers parameter
- `details` (bool) - Include detailed information

## Usage Examples

```bash
# Get all managers
qg_get_managers

# Get managers with extra info
qg_get_managers extra_info=true

# Get specific manager
qg_get_manager_by_id id=my_manager_id

# Get nodes with filtering
qg_get_nodes filter_by_system_id=my_system_id filter_by_fabric_id=my_fabric_id

# Get systems filtered by name
qg_get_systems filter_by_name=my_system

# Get connectors with extra info
qg_get_connectors extra_info=true

# Get query summary with filters
qg_get_query_summary completed=true last_modified_after=2024-01-01T00:00:00Z

# Get fabrics flattened
qg_get_fabrics flatten=true

# Get networks filtered by tag
qg_get_networks filter_by_tag=env:production,team:backend
```

## Test Coverage

The QueryGrid tools include comprehensive test coverage with **96 test cases** across all 56 tools. Each tool has at least one test case, with complex tools having multiple test scenarios covering different parameter combinations.

Test cases are located in `tests/cases/qg_test_cases.json` and cover:
- Default parameter usage
- Optional parameter combinations
- Edge cases and filtering scenarios
- All supported parameter types (boolean, string, UUID, etc.)

---

[← Return to Main README](../../../../README.md)
Loading