Skip to content

Commit 1861fb0

Browse files
authored
Gather comments from CH tables as well (#13)
1 parent 34b38a1 commit 1861fb0

File tree

3 files changed

+48
-4
lines changed

3 files changed

+48
-4
lines changed

mcp_clickhouse/mcp_server.py

+21
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,21 @@ def list_tables(database: str, like: str = None):
4444
query += f" LIKE '{like}'"
4545
result = client.command(query)
4646

47+
# Get all table comments in one query
48+
table_comments_query = f"SELECT name, comment FROM system.tables WHERE database = '{database}'"
49+
table_comments_result = client.query(table_comments_query)
50+
table_comments = {row[0]: row[1] for row in table_comments_result.result_rows}
51+
52+
# Get all column comments in one query
53+
column_comments_query = f"SELECT table, name, comment FROM system.columns WHERE database = '{database}'"
54+
column_comments_result = client.query(column_comments_query)
55+
column_comments = {}
56+
for row in column_comments_result.result_rows:
57+
table, col_name, comment = row
58+
if table not in column_comments:
59+
column_comments[table] = {}
60+
column_comments[table][col_name] = comment
61+
4762
def get_table_info(table):
4863
logger.info(f"Getting schema info for table {database}.{table}")
4964
schema_query = f"DESCRIBE TABLE {database}.`{table}`"
@@ -55,6 +70,11 @@ def get_table_info(table):
5570
column_dict = {}
5671
for i, col_name in enumerate(column_names):
5772
column_dict[col_name] = row[i]
73+
# Add comment from our pre-fetched comments
74+
if table in column_comments and column_dict['name'] in column_comments[table]:
75+
column_dict['comment'] = column_comments[table][column_dict['name']]
76+
else:
77+
column_dict['comment'] = None
5878
columns.append(column_dict)
5979

6080
create_table_query = f"SHOW CREATE TABLE {database}.`{table}`"
@@ -63,6 +83,7 @@ def get_table_info(table):
6383
return {
6484
"database": database,
6585
"name": table,
86+
"comment": table_comments.get(table),
6687
"columns": columns,
6788
"create_table_query": create_table_result,
6889
}

tests/test_tool.py

+26-3
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,18 @@ def setUpClass(cls):
1717
cls.test_db = "test_tool_db"
1818
cls.test_table = "test_table"
1919
cls.client.command(f"CREATE DATABASE IF NOT EXISTS {cls.test_db}")
20+
21+
# Drop table if exists to ensure clean state
22+
cls.client.command(f"DROP TABLE IF EXISTS {cls.test_db}.{cls.test_table}")
23+
24+
# Create table with comments
2025
cls.client.command(f"""
21-
CREATE TABLE IF NOT EXISTS {cls.test_db}.{cls.test_table} (
22-
id UInt32,
23-
name String
26+
CREATE TABLE {cls.test_db}.{cls.test_table} (
27+
id UInt32 COMMENT 'Primary identifier',
28+
name String COMMENT 'User name field'
2429
) ENGINE = MergeTree()
2530
ORDER BY id
31+
COMMENT 'Test table for unit testing'
2632
""")
2733
cls.client.command(f"""
2834
INSERT INTO {cls.test_db}.{cls.test_table} (id, name) VALUES (1, 'Alice'), (2, 'Bob')
@@ -68,6 +74,23 @@ def test_run_select_query_failure(self):
6874
self.assertIsInstance(result, str)
6975
self.assertIn("error running query", result)
7076

77+
def test_table_and_column_comments(self):
78+
"""Test that table and column comments are correctly retrieved."""
79+
result = list_tables(self.test_db)
80+
self.assertIsInstance(result, list)
81+
self.assertEqual(len(result), 1)
82+
83+
table_info = result[0]
84+
# Verify table comment
85+
self.assertEqual(table_info["comment"], "Test table for unit testing")
86+
87+
# Get columns by name for easier testing
88+
columns = {col["name"]: col for col in table_info["columns"]}
89+
90+
# Verify column comments
91+
self.assertEqual(columns["id"]["comment"], "Primary identifier")
92+
self.assertEqual(columns["name"]["comment"], "User name field")
93+
7194

7295
if __name__ == "__main__":
7396
unittest.main()

uv.lock

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

0 commit comments

Comments
 (0)