| import os |
| from pathlib import Path |
|
|
| import clickhouse_connect |
| from dotenv import load_dotenv |
| from mcp.server import FastMCP |
|
|
| load_dotenv(dotenv_path=Path(__file__).resolve().parent.parent / ".env") |
|
|
| server = FastMCP(name="clickhouse") |
|
|
|
|
| def get_clickhouse_client(): |
| host = os.getenv("CLICKHOUSE_HOST") |
| port = os.getenv("CLICKHOUSE_PORT") |
| username = os.getenv("CLICKHOUSE_USER") |
| password = os.getenv("CLICKHOUSE_PASSWORD") |
|
|
| if not host or not port or not username or not password: |
| raise ValueError( |
| "Missing one or more ClickHouse environment variables: " |
| "CLICKHOUSE_HOST, CLICKHOUSE_PORT, CLICKHOUSE_USER, CLICKHOUSE_PASSWORD" |
| ) |
|
|
| |
| os.environ["NO_PROXY"] = host |
| os.environ["no_proxy"] = host |
|
|
| return clickhouse_connect.get_client( |
| host=host, |
| port=int(port), |
| username=username, |
| password=password, |
| secure=True, |
| ) |
|
|
|
|
| try: |
| result = get_clickhouse_client().query("SELECT 1") |
| print("ClickHouse Connected:", result.result_rows) |
| except Exception as e: |
| print("Connection Failed:", str(e)) |
|
|
|
|
| @server.tool() |
| def health_check(): |
| try: |
| result = get_clickhouse_client().query("SELECT 1") |
| return {"status": "connected", "result": result.result_rows} |
| except Exception as e: |
| return {"status": "error", "message": str(e)} |
|
|
|
|
| @server.tool() |
| def list_tables(): |
| return get_clickhouse_client().query("SHOW TABLES").result_rows |
|
|
|
|
| @server.tool() |
| def run_query(query: str): |
| if not query.lower().strip().startswith("select"): |
| return "Only SELECT queries allowed" |
|
|
| result = get_clickhouse_client().query(query) |
| return result.result_rows |
|
|
|
|
| @server.tool() |
| def get_schema(): |
| return get_clickhouse_client().query( |
| """ |
| SELECT table, name, type |
| FROM system.columns |
| WHERE database = currentDatabase() |
| """ |
| ).result_rows |
|
|
|
|
| if __name__ == "__main__": |
| server.run() |
|
|