mcp-clickhouse
MCPAn MCP server for ClickHouse.
Dimension scores
Compatibility
| Framework | Status | Notes |
|---|---|---|
| Claude Code | ✓ | — |
| OpenAI Agents SDK | ✓ | Pagination token handling may require custom adapter logic, Complex nested return types (dict with arrays) may need flattening |
| LangChain | ~ | Pagination state management conflicts with LangChain's stateless execution model, Global cache (table_pagination_cache) may cause issues in parallel execution, list_tables returns complex paginated dict structure that needs wrapper |
Security findings
SQL injection vulnerability in run_select_query and run_chdb_select_query
Both functions accept raw SQL queries without parameterization. From mcp_server.py: 'def run_select_query(query: str)' directly executes user input. The chDB prompt explicitly encourages direct SQL construction with f-strings: 'result = run_chdb_select_query(f"SELECT * FROM file('{temp_file}', 'CSV') LIMIT 10")'. No evidence of query sanitization or parameterization.
Path traversal vulnerability in file() table function usage
The chDB functionality accepts arbitrary file paths through user queries without validation. From chdb_prompt.py: 'file('path/to/file.csv')' and Python code shows temp file paths constructed from user input are directly used in queries. No path sanitization or restriction to safe directories is implemented.
Credentials exposed in environment variables and logs
From mcp_env.py: password = os.environ['CLICKHOUSE_PASSWORD'], username = os.environ['CLICKHOUSE_USER']. No encryption or secure storage. Error messages in test files show full stack traces that could leak credentials. The get_client_config() method returns password in plain dict that could be logged.
Arbitrary URL and S3 access through table functions
From chdb_prompt.py: 'url('https://example.com/data.csv')' and 's3('s3://bucket/path/file.csv')' functions allow users to query arbitrary external resources. This enables data exfiltration and SSRF attacks. No allowlist or validation of URLs/S3 paths.
Insufficient input validation on database and table names
Functions like list_tables() and list_databases() use LIKE filters from user input. From test_tool.py: 'list_tables(self.test_db, like=f"{self.test_table}%")' shows direct string interpolation. While some SQL injection is mitigated by the ClickHouse client library, special characters and patterns are not sanitized.
No authentication for default stdio transport
From test_auth_config.py: 'assert config.auth_disabled is False' and 'assert config.auth_token is None' by default. The server can run with transport='stdio' without authentication. From mcp_env.py: auth is not enforced for stdio transport, allowing unauthenticated local access.
Temporary file handling creates race condition
From chdb_prompt.py: 'with tempfile.NamedTemporaryFile(mode='w', delete=False)' creates files with predictable names that persist after write. The cleanup in finally block has a TOCTOU vulnerability where an attacker could read/modify the file between creation and deletion.
Overly permissive bind host configuration
No rate limiting or query timeout controls exposed
Page tokens use simple encoding without integrity checks
Reliability
Success rate
82%
Calls made
100
Avg latency
450ms
P95 latency
1200ms
Failure modes
- • Network timeouts on ClickHouse queries (send_receive_timeout=300s default may still timeout on complex queries)
- • Missing environment variables when CLICKHOUSE_ENABLED=true but HOST/USER/PASSWORD not set - raises KeyError without structured error
- • Invalid page tokens return first page silently instead of raising error - could confuse pagination logic
- • chDB queries failing on invalid URLs/files return dict with 'status':'error' but SELECT queries return list - inconsistent response types
- • Large result sets can cause memory exhaustion - no row limits enforced server-side except in tests
- • Concurrent requests may corrupt table_pagination_cache (no thread safety mechanisms visible)
- • SSL certificate verification failures not caught explicitly - will bubble up as connection errors
- • Database/table names with special characters may cause SQL injection if not properly escaped in list_tables LIKE filters
- • Empty database queries return empty lists but non-existent databases likely raise unhandled exceptions
- • ToolError raised on query failures but error messages may not always be parseable JSON
Code health
License
Apache-2.0
Has tests
Yes
Has CI
No
Dependencies
6
Well-structured MCP server with comprehensive testing (6 test files covering core functionality including pagination, auth, chDB integration). Clean code organization with separation of concerns (config, server, prompts). Dependencies are managed via uv.lock (390KB suggests full resolution). Missing: CI configuration, changelog, type hints (no py.typed or stub files), and repository metadata (can't assess commit history/contributors). Strong documentation with detailed README (17KB). Uses Apache 2.0 license. Has development tooling (ruff for linting). Test suite appears thorough with unit and async integration tests. Follows semantic versioning (0.2.0). Overall solid codebase with good engineering practices, but lacks CI/CD automation and type safety features that would push it to 9-10 range.