Skip to content

Support mTLS in ClickHouse MCP - #168

Open
JaspreetSandhu wants to merge 2 commits into
ClickHouse:mainfrom
JaspreetSandhu:support-mtls
Open

Support mTLS in ClickHouse MCP#168
JaspreetSandhu wants to merge 2 commits into
ClickHouse:mainfrom
JaspreetSandhu:support-mtls

Conversation

@JaspreetSandhu

@JaspreetSandhu JaspreetSandhu commented Apr 14, 2026

Copy link
Copy Markdown

Enable mutual TLS in mcp-clickhouse connections to CH server.

@CLAassistant

CLAassistant commented Apr 14, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@JaspreetSandhu
JaspreetSandhu force-pushed the support-mtls branch 2 times, most recently from 809e4d6 to c661616 Compare April 15, 2026 20:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds mutual TLS (mTLS) support for mcp-clickhouse connections by allowing ClickHouse client certificate configuration via environment variables, updating config validation behavior, and documenting the new setup path.

Changes:

  • Add CLICKHOUSE_CLIENT_CERT / CLICKHOUSE_CLIENT_CERT_KEY support and pass-through to clickhouse_connect.get_client(...).
  • Make CLICKHOUSE_PASSWORD optional when client cert configuration is present.
  • Add tests and README documentation for mTLS configuration.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
mcp_clickhouse/mcp_env.py Adds env var accessors for client cert/key, modifies password handling, and updates required-var validation.
tests/test_config_interface.py Adds unit tests for client cert pass-through and password requirement changes.
README.md Documents mTLS configuration examples and new environment variables.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread mcp_clickhouse/mcp_env.py
Comment on lines 48 to +52
CLICKHOUSE_ENABLED: Enable ClickHouse server (default: true)
CLICKHOUSE_ALLOW_WRITE_ACCESS: Allow write operations (DDL and DML) (default: false)
CLICKHOUSE_ALLOW_DROP: Allow destructive operations (DROP, TRUNCATE) when writes are also enabled (default: false)
CLICKHOUSE_CLIENT_CERT: Path to TLS client certificate for mTLS authentication (default: None)
CLICKHOUSE_CLIENT_CERT_KEY: Path to TLS client private key for mTLS authentication (default: None)

Copilot AI Apr 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The class docstring still lists CLICKHOUSE_PASSWORD as a required env var, but _validate_required_vars now makes it optional when client certs are used. Update the docstring’s “Required environment variables” section so it matches the new validation rules (and document the client-cert alternative explicitly).

Copilot uses AI. Check for mistakes.
Comment thread mcp_clickhouse/mcp_env.py
return os.environ["CLICKHOUSE_PASSWORD"]
"""Get the ClickHouse password.

Returns empty string when not set and client certificates are configured.

Copilot AI Apr 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

password now returns an empty string whenever CLICKHOUSE_PASSWORD is unset, but the docstring says that only happens when client certificates are configured. Either adjust the docstring to reflect the actual behavior, or change the implementation to only default to "" when mTLS config is present (and otherwise let validation/KeyError surface).

Suggested change
Returns empty string when not set and client certificates are configured.
Returns an empty string when CLICKHOUSE_PASSWORD is not set.

Copilot uses AI. Check for mistakes.
Comment thread mcp_clickhouse/mcp_env.py
Comment on lines +227 to +229
if "CLICKHOUSE_PASSWORD" not in os.environ and not self.client_cert:
missing_vars.append("CLICKHOUSE_PASSWORD")

Copilot AI Apr 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current validation only checks CLICKHOUSE_CLIENT_CERT to decide whether CLICKHOUSE_PASSWORD is required, but it doesn’t define/validate what constitutes a complete mTLS configuration (e.g., cert without key, key without cert). This can lead to configs that the README describes as invalid being accepted. Consider validating that the client-cert settings are consistent (and raising a clear ValueError that names the missing counterpart) or updating the docs to match the intended flexibility (e.g., cert file may already include the key).

Copilot uses AI. Check for mistakes.
Comment on lines +125 to +132
def test_client_cert_configuration(monkeypatch: pytest.MonkeyPatch):
"""Test that client cert and key are passed through when set."""
monkeypatch.setenv("CLICKHOUSE_HOST", "localhost")
monkeypatch.setenv("CLICKHOUSE_USER", "test")
monkeypatch.setenv("CLICKHOUSE_CLIENT_CERT", "/path/to/client.pem")
monkeypatch.setenv("CLICKHOUSE_CLIENT_CERT_KEY", "/path/to/client.key")
monkeypatch.delenv("CLICKHOUSE_PASSWORD", raising=False)

Copilot AI Apr 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new test suite doesn’t cover misconfigured mTLS env combinations (e.g., only CLICKHOUSE_CLIENT_CERT set, only CLICKHOUSE_CLIENT_CERT_KEY set) and what the expected behavior/error should be. Add explicit tests for these partial configurations once the validation rule is clarified, so regressions don’t silently change the authentication requirements.

Copilot uses AI. Check for mistakes.
Comment thread README.md
Comment on lines +574 to +577
* Must be used with `CLICKHOUSE_CLIENT_CERT_KEY`
* `CLICKHOUSE_CLIENT_CERT_KEY`: Path to TLS client private key for mTLS authentication
* Default: None
* Must be used with `CLICKHOUSE_CLIENT_CERT`

Copilot AI Apr 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The README states CLICKHOUSE_CLIENT_CERT “must be used with” CLICKHOUSE_CLIENT_CERT_KEY (and vice versa), but the implementation currently treats these as independently optional and only uses CLICKHOUSE_CLIENT_CERT to waive the password requirement. Either tighten validation to enforce the documented requirement, or relax/reword the README to reflect the actual supported configurations (e.g., combined cert+key PEM).

Suggested change
* Must be used with `CLICKHOUSE_CLIENT_CERT_KEY`
* `CLICKHOUSE_CLIENT_CERT_KEY`: Path to TLS client private key for mTLS authentication
* Default: None
* Must be used with `CLICKHOUSE_CLIENT_CERT`
* Can be used by itself if the PEM file contains both the client certificate and private key
* Use with `CLICKHOUSE_CLIENT_CERT_KEY` when the certificate and private key are stored in separate files
* `CLICKHOUSE_CLIENT_CERT_KEY`: Path to TLS client private key for mTLS authentication
* Default: None
* Optional when `CLICKHOUSE_CLIENT_CERT` points to a combined cert+key PEM file
* Set this when the private key is stored separately from `CLICKHOUSE_CLIENT_CERT`

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants