Skip to content

Commit 5f700f8

Browse files
committed
fix more things
1 parent f046ce4 commit 5f700f8

File tree

8 files changed

+354
-10
lines changed

8 files changed

+354
-10
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
.ruff_cache/
2+
13
# Byte-compiled / optimized / DLL files
24
__pycache__/
35
*.py[cod]

README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ An MCP server for ClickHouse.
66

77
### Tools
88

9-
* `run-select-query`
9+
* `run_select_query`
1010
- Execute SQL queries on your ClickHouse cluster.
1111
- Input: `sql` (string): The SQL query to execute.
1212
- All ClickHouse queries are run with `readonly = 1` to ensure they are safe.
1313

14-
* `list-databases`
14+
* `list_databases`
1515
- List all databases on your ClickHouse cluster.
1616

17-
* `list-tables`
17+
* `list_tables`
1818
- List all tables in a database.
1919
- Input: `database` (string): The name of the database.
2020

hello.py

-6
This file was deleted.

mcp_clickhouse/main.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
from .mcp_server import mcp
12

23

34
def main():
4-
print("Hello, World!")
5+
mcp.run()
56

67

78
if __name__ == "__main__":

mcp_clickhouse/mcp_server.py

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
from fastmcp import FastMCP
2+
from typing import Sequence
3+
from dotenv import load_dotenv
4+
import clickhouse_connect
5+
import os
6+
7+
8+
MCP_SERVER_NAME = "mcp-clickhouse"
9+
10+
load_dotenv()
11+
mcp = FastMCP(MCP_SERVER_NAME)
12+
13+
14+
@mcp.tool()
15+
def list_databases():
16+
client = create_clickhouse_client()
17+
return client.command("SHOW DATABASES")
18+
19+
20+
@mcp.tool()
21+
def list_tables(database: str, like: str = None):
22+
client = create_clickhouse_client()
23+
query = f"SHOW TABLES FROM {database}"
24+
if like:
25+
query += f" LIKE '{like}'"
26+
result = client.command(query)
27+
28+
def get_table_info(table):
29+
schema_query = f"DESCRIBE TABLE {database}.{table}"
30+
schema_result = client.query(schema_query)
31+
32+
columns = []
33+
column_names = schema_result.column_names
34+
for row in schema_result.result_rows:
35+
column_dict = {}
36+
for i, col_name in enumerate(column_names):
37+
column_dict[col_name] = row[i]
38+
columns.append(column_dict)
39+
40+
create_table_query = f"SHOW CREATE TABLE {database}.{table}"
41+
create_table_result = client.command(create_table_query)
42+
43+
return {
44+
"database": database,
45+
"name": table,
46+
"columns": columns,
47+
"create_table_query": create_table_result,
48+
}
49+
50+
tables = []
51+
if isinstance(result, str):
52+
# Single table result
53+
tables.append(get_table_info(result))
54+
elif isinstance(result, Sequence):
55+
# Multiple table results
56+
for table in result:
57+
tables.append(get_table_info(table))
58+
59+
return tables
60+
61+
62+
@mcp.tool()
63+
def run_select_query(query: str):
64+
client = create_clickhouse_client()
65+
try:
66+
res = client.query(query, settings={"readonly": 1})
67+
column_names = res.column_names
68+
rows = []
69+
for row in res.result_rows:
70+
row_dict = {}
71+
for i, col_name in enumerate(column_names):
72+
row_dict[col_name] = row[i]
73+
rows.append(row_dict)
74+
return rows
75+
except Exception as err:
76+
return f"error running query: {err}"
77+
78+
79+
def create_clickhouse_client():
80+
return clickhouse_connect.get_client(
81+
host=os.getenv("CLICKHOUSE_HOST"),
82+
port=os.getenv("CLICKHOUSE_PORT"),
83+
username=os.getenv("CLICKHOUSE_USER"),
84+
password=os.getenv("CLICKHOUSE_PASSWORD"),
85+
)

pyproject.toml

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ requires-python = ">=3.13"
77
dependencies = [
88
"mcp>=1.0.0",
99
"python-dotenv>=1.0.1",
10+
"fastmcp>=0.4.0",
11+
"uvicorn>=0.34.0",
12+
"clickhouse-connect>=0.8.0",
1013
]
1114

1215
[project.scripts]

test-services/docker-compose.yaml

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
services:
2+
clickhouse:
3+
image: clickhouse/clickhouse-server:latest
4+
ports:
5+
- "8123:8123"
6+
- "9000:9000"
7+
volumes:
8+
- clickhouse-data:/var/lib/clickhouse
9+
environment:
10+
- CLICKHOUSE_USER=default
11+
- CLICKHOUSE_PASSWORD=clickhouse
12+
- CLICKHOUSE_DB=default
13+
14+
volumes:
15+
clickhouse-data:

uv.lock

+244
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)