From 965592bc7c8fef86837711abc4bf696a55eceddc Mon Sep 17 00:00:00 2001 From: Joe S Date: Thu, 9 Oct 2025 11:39:20 -0700 Subject: [PATCH 1/4] explicitly set interface based on secure value --- mcp_clickhouse/mcp_env.py | 1 + tests/test_config_interface.py | 85 ++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 tests/test_config_interface.py diff --git a/mcp_clickhouse/mcp_env.py b/mcp_clickhouse/mcp_env.py index 40c0424..aec6826 100644 --- a/mcp_clickhouse/mcp_env.py +++ b/mcp_clickhouse/mcp_env.py @@ -173,6 +173,7 @@ def get_client_config(self) -> dict: "port": self.port, "username": self.username, "password": self.password, + "interface": "https" if self.secure else "http", "secure": self.secure, "verify": self.verify, "connect_timeout": self.connect_timeout, diff --git a/tests/test_config_interface.py b/tests/test_config_interface.py new file mode 100644 index 0000000..682ec90 --- /dev/null +++ b/tests/test_config_interface.py @@ -0,0 +1,85 @@ +import os + +from mcp_clickhouse.mcp_env import ClickHouseConfig + + +def test_interface_http_when_secure_false(): + """Test that interface is set to 'http' when CLICKHOUSE_SECURE=false.""" + os.environ["CLICKHOUSE_HOST"] = "localhost" + os.environ["CLICKHOUSE_USER"] = "test" + os.environ["CLICKHOUSE_PASSWORD"] = "test" + os.environ["CLICKHOUSE_SECURE"] = "false" + os.environ["CLICKHOUSE_PORT"] = "8123" + + config = ClickHouseConfig() + client_config = config.get_client_config() + + assert client_config["interface"] == "http" + assert client_config["secure"] is False + assert client_config["port"] == 8123 + + +def test_interface_https_when_secure_true(): + """Test that interface is set to 'https' when CLICKHOUSE_SECURE=true.""" + os.environ["CLICKHOUSE_HOST"] = "example.com" + os.environ["CLICKHOUSE_USER"] = "test" + os.environ["CLICKHOUSE_PASSWORD"] = "test" + os.environ["CLICKHOUSE_SECURE"] = "true" + os.environ["CLICKHOUSE_PORT"] = "8443" + + config = ClickHouseConfig() + client_config = config.get_client_config() + + assert client_config["interface"] == "https" + assert client_config["secure"] is True + assert client_config["port"] == 8443 + + +def test_interface_https_by_default(): + """Test that interface defaults to 'https' when CLICKHOUSE_SECURE is not set.""" + os.environ["CLICKHOUSE_HOST"] = "example.com" + os.environ["CLICKHOUSE_USER"] = "test" + os.environ["CLICKHOUSE_PASSWORD"] = "test" + if "CLICKHOUSE_SECURE" in os.environ: + del os.environ["CLICKHOUSE_SECURE"] + if "CLICKHOUSE_PORT" in os.environ: + del os.environ["CLICKHOUSE_PORT"] + + config = ClickHouseConfig() + client_config = config.get_client_config() + + assert client_config["interface"] == "https" + assert client_config["secure"] is True + assert client_config["port"] == 8443 + + +def test_interface_http_with_custom_port(): + """Test that interface is 'http' with custom port when CLICKHOUSE_SECURE=false.""" + os.environ["CLICKHOUSE_HOST"] = "localhost" + os.environ["CLICKHOUSE_USER"] = "test" + os.environ["CLICKHOUSE_PASSWORD"] = "test" + os.environ["CLICKHOUSE_SECURE"] = "false" + os.environ["CLICKHOUSE_PORT"] = "9000" + + config = ClickHouseConfig() + client_config = config.get_client_config() + + assert client_config["interface"] == "http" + assert client_config["secure"] is False + assert client_config["port"] == 9000 + + +def test_interface_https_with_custom_port(): + """Test that interface is 'https' with custom port when CLICKHOUSE_SECURE=true.""" + os.environ["CLICKHOUSE_HOST"] = "example.com" + os.environ["CLICKHOUSE_USER"] = "test" + os.environ["CLICKHOUSE_PASSWORD"] = "test" + os.environ["CLICKHOUSE_SECURE"] = "true" + os.environ["CLICKHOUSE_PORT"] = "9443" + + config = ClickHouseConfig() + client_config = config.get_client_config() + + assert client_config["interface"] == "https" + assert client_config["secure"] is True + assert client_config["port"] == 9443 From bdc15da06c449fa6d426f3ec9143b6c8e063e38c Mon Sep 17 00:00:00 2001 From: Joe S Date: Thu, 9 Oct 2025 14:25:16 -0700 Subject: [PATCH 2/4] use monkeypatch to prevent env var leakage --- tests/test_config_interface.py | 63 +++++++++++++++++----------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/tests/test_config_interface.py b/tests/test_config_interface.py index 682ec90..0cb972c 100644 --- a/tests/test_config_interface.py +++ b/tests/test_config_interface.py @@ -1,15 +1,16 @@ import os +import pytest from mcp_clickhouse.mcp_env import ClickHouseConfig -def test_interface_http_when_secure_false(): +def test_interface_http_when_secure_false(monkeypatch: pytest.MonkeyPatch): """Test that interface is set to 'http' when CLICKHOUSE_SECURE=false.""" - os.environ["CLICKHOUSE_HOST"] = "localhost" - os.environ["CLICKHOUSE_USER"] = "test" - os.environ["CLICKHOUSE_PASSWORD"] = "test" - os.environ["CLICKHOUSE_SECURE"] = "false" - os.environ["CLICKHOUSE_PORT"] = "8123" + monkeypatch.setenv("CLICKHOUSE_HOST", "localhost") + monkeypatch.setenv("CLICKHOUSE_USER", "test") + monkeypatch.setenv("CLICKHOUSE_PASSWORD", "test") + monkeypatch.setenv("CLICKHOUSE_SECURE", "false") + monkeypatch.setenv("CLICKHOUSE_PORT", "8123") config = ClickHouseConfig() client_config = config.get_client_config() @@ -19,13 +20,13 @@ def test_interface_http_when_secure_false(): assert client_config["port"] == 8123 -def test_interface_https_when_secure_true(): +def test_interface_https_when_secure_true(monkeypatch: pytest.MonkeyPatch): """Test that interface is set to 'https' when CLICKHOUSE_SECURE=true.""" - os.environ["CLICKHOUSE_HOST"] = "example.com" - os.environ["CLICKHOUSE_USER"] = "test" - os.environ["CLICKHOUSE_PASSWORD"] = "test" - os.environ["CLICKHOUSE_SECURE"] = "true" - os.environ["CLICKHOUSE_PORT"] = "8443" + monkeypatch.setenv("CLICKHOUSE_HOST", "example.com") + monkeypatch.setenv("CLICKHOUSE_USER", "test") + monkeypatch.setenv("CLICKHOUSE_PASSWORD", "test") + monkeypatch.setenv("CLICKHOUSE_SECURE", "true") + monkeypatch.setenv("CLICKHOUSE_PORT", "8443") config = ClickHouseConfig() client_config = config.get_client_config() @@ -35,15 +36,13 @@ def test_interface_https_when_secure_true(): assert client_config["port"] == 8443 -def test_interface_https_by_default(): +def test_interface_https_by_default(monkeypatch: pytest.MonkeyPatch): """Test that interface defaults to 'https' when CLICKHOUSE_SECURE is not set.""" - os.environ["CLICKHOUSE_HOST"] = "example.com" - os.environ["CLICKHOUSE_USER"] = "test" - os.environ["CLICKHOUSE_PASSWORD"] = "test" - if "CLICKHOUSE_SECURE" in os.environ: - del os.environ["CLICKHOUSE_SECURE"] - if "CLICKHOUSE_PORT" in os.environ: - del os.environ["CLICKHOUSE_PORT"] + monkeypatch.setenv("CLICKHOUSE_HOST", "example.com") + monkeypatch.setenv("CLICKHOUSE_USER", "test") + monkeypatch.setenv("CLICKHOUSE_PASSWORD", "test") + monkeypatch.delenv("CLICKHOUSE_SECURE", raising=False) + monkeypatch.delenv("CLICKHOUSE_PORT", raising=False) config = ClickHouseConfig() client_config = config.get_client_config() @@ -53,13 +52,13 @@ def test_interface_https_by_default(): assert client_config["port"] == 8443 -def test_interface_http_with_custom_port(): +def test_interface_http_with_custom_port(monkeypatch: pytest.MonkeyPatch): """Test that interface is 'http' with custom port when CLICKHOUSE_SECURE=false.""" - os.environ["CLICKHOUSE_HOST"] = "localhost" - os.environ["CLICKHOUSE_USER"] = "test" - os.environ["CLICKHOUSE_PASSWORD"] = "test" - os.environ["CLICKHOUSE_SECURE"] = "false" - os.environ["CLICKHOUSE_PORT"] = "9000" + monkeypatch.setenv("CLICKHOUSE_HOST", "localhost") + monkeypatch.setenv("CLICKHOUSE_USER", "test") + monkeypatch.setenv("CLICKHOUSE_PASSWORD", "test") + monkeypatch.setenv("CLICKHOUSE_SECURE", "false") + monkeypatch.setenv("CLICKHOUSE_PORT", "9000") config = ClickHouseConfig() client_config = config.get_client_config() @@ -69,13 +68,13 @@ def test_interface_http_with_custom_port(): assert client_config["port"] == 9000 -def test_interface_https_with_custom_port(): +def test_interface_https_with_custom_port(monkeypatch: pytest.MonkeyPatch): """Test that interface is 'https' with custom port when CLICKHOUSE_SECURE=true.""" - os.environ["CLICKHOUSE_HOST"] = "example.com" - os.environ["CLICKHOUSE_USER"] = "test" - os.environ["CLICKHOUSE_PASSWORD"] = "test" - os.environ["CLICKHOUSE_SECURE"] = "true" - os.environ["CLICKHOUSE_PORT"] = "9443" + monkeypatch.setenv("CLICKHOUSE_HOST", "example.com") + monkeypatch.setenv("CLICKHOUSE_USER", "test") + monkeypatch.setenv("CLICKHOUSE_PASSWORD", "test") + monkeypatch.setenv("CLICKHOUSE_SECURE", "true") + monkeypatch.setenv("CLICKHOUSE_PORT", "9443") config = ClickHouseConfig() client_config = config.get_client_config() From 52022294f6f7f170b335c623c5e53b48627c3772 Mon Sep 17 00:00:00 2001 From: Joe S Date: Thu, 9 Oct 2025 14:26:56 -0700 Subject: [PATCH 3/4] fix deprecated deps in fastmcp constructor --- fastmcp.json | 16 ++++++++++++++++ mcp_clickhouse/mcp_server.py | 10 +--------- 2 files changed, 17 insertions(+), 9 deletions(-) create mode 100644 fastmcp.json diff --git a/fastmcp.json b/fastmcp.json new file mode 100644 index 0000000..6b905e7 --- /dev/null +++ b/fastmcp.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://gofastmcp.com/public/schemas/fastmcp.json/v1.json", + "source": { + "path": "mcp_clickhouse/mcp_server.py", + "entrypoint": "mcp" + }, + "environment": { + "dependencies": [ + "clickhouse-connect", + "python-dotenv", + "pip-system-certs", + "chdb" + ] + } +} + diff --git a/mcp_clickhouse/mcp_server.py b/mcp_clickhouse/mcp_server.py index 589ff2e..a3fa081 100644 --- a/mcp_clickhouse/mcp_server.py +++ b/mcp_clickhouse/mcp_server.py @@ -67,15 +67,7 @@ class Table: load_dotenv() -mcp = FastMCP( - name=MCP_SERVER_NAME, - dependencies=[ - "clickhouse-connect", - "python-dotenv", - "pip-system-certs", - "chdb", - ], -) +mcp = FastMCP(name=MCP_SERVER_NAME) @mcp.custom_route("/health", methods=["GET"]) From f5ca25b567892440e370627ee681ee59767e1e6c Mon Sep 17 00:00:00 2001 From: Joe S Date: Thu, 9 Oct 2025 14:28:44 -0700 Subject: [PATCH 4/4] ruff fix --- tests/test_config_interface.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_config_interface.py b/tests/test_config_interface.py index 0cb972c..d39a460 100644 --- a/tests/test_config_interface.py +++ b/tests/test_config_interface.py @@ -1,4 +1,3 @@ -import os import pytest from mcp_clickhouse.mcp_env import ClickHouseConfig