Altinity / Altinity/altinity-mcp
Expose ClickHouse-compatible HTTP API alongside MCP/OpenAPI
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 38
- Forks
- 8
- Avg merge
- 6d 14h
- Merged PRs (30d)
- 8
Description
Problem
altinity-mcp with --openapi already looks more like a ClickHouse frontend than a pure MCP server. To make it a drop-in plug-in replacement in front of ClickHouse, it should also speak the native ClickHouse HTTP API documented at https://clickhouse.com/docs/interfaces/http, so existing tools, dashboards, and clients can point at altinity-mcp without changes:
curl 'http://mcp.example.com/?query=SELECT+1'
curl -u alice:pass 'http://mcp.example.com/?query=SELECT+1&database=analytics&default_format=JSONCompact'
curl -X POST 'http://mcp.example.com/' --data-binary 'SELECT 1'
Today any of these hit the MCP streamable-HTTP endpoint and fail.
Feasibility — hook points already exist
The HTTP router is centralized:
cmd/altinity-mcp/main.go— mux setup aroundmcpRoutePatterns(MCP transport) andopenAPIRoutePatterns(lines 407-433); a newchHTTPRoutePatternscan be added to the same mux or, better, registered as a catch-all that sniffs?query=or a POST body before handing off to MCP.pkg/server/server.go:2519— the OpenAPI dispatcher already routes by path suffix in aswitch. Adding acasethat matches?query=is a one-line addition.handleExecuteQueryOpenAPI(pkg/server/server.go) — the core 'parse request → run query → serialize' pipeline already exists. The CH-compat handler can reuse it; the work is input parsing (CH params/headers/body) and output formatting (TSV/JSON-variants), not query execution.GetClickHouseClientFromCtx/GetClickHouseClientWithOAuth— already resolves the right backend connection based on JWE/OAuth/cluster-secret context. The CH-compat handler should funnel through the same path so all three auth modes work identically to MCP/OpenAPI.
Proposed dispatch
In the HTTP mux, before the MCP handler, route to a new handleClickHouseHTTP when any of these is true on the request:
- Method is
GETand?query=is non-empty - Method is
POSTandContent-Typeistext/plain; charset=UTF-8(CH's native format) or the body starts with SQL keywords - Request has
X-ClickHouse-User/X-ClickHouse-Key/X-ClickHouse-Databaseheaders (unambiguous CH-client signal)
Otherwise fall through to existing MCP/OpenAPI handlers. This keeps MCP and OpenAPI clients unaffected.
Scope — phase 1 (minimum viable plug-in)
Request parsing
-
?query=(URL-encoded SQL) -
?database=→ overrides default database -
?default_format=→ picks response format - POST body as query (when URL has no
?query=) - Mixed mode:
?query=SELECT+1+FROM++ POST body = concatenation (matches CH semantics) - HTTP Basic Auth (username:password) → maps to ClickHouse user via cluster-secret / static / JWE / OAuth mode (whichever altinity-mcp is configured for)
-
X-ClickHouse-User/X-ClickHouse-Key/X-ClickHouse-Databaseheaders (higher priority than basic auth, per CH docs)
Response formats (pick the most useful subset first)
-
TabSeparated(CH default — required) -
TabSeparatedWithNames -
JSONCompact -
JSONEachRow -
FORMATclause detection in the SQL (CH-compat: trailingFORMAT JSONCompactwins overdefault_format)
Errors
- Query errors → HTTP 500 with CH-style plain-text body (
Code: 62. DB::Exception: ... (SYNTAX_ERROR)) - Auth failures → HTTP 401 with
WWW-Authenticate: Basicheader - Unknown user / permission denied → HTTP 403
Preserves
- Read-only mode flag still enforced
-
clickhouse-limitstill applied (or: bypass since a real CH client expects unbounded results?) - Cluster-secret impersonation still uses
oauthClaims.Emailif the request arrives authenticated via OAuth
Scope — phase 2 (nice-to-have, file separate issues as needed)
- Streaming responses for large result sets (currently we buffer everything in memory in
executeSelect) -
INSERT ... FORMATwith body data (POST to upload TSV/CSV) - Additional formats:
RowBinary,Native,Values,Pretty*,CSV,CSVWithNames -
?param_<name>=query parameters (CH's{name:Type}substitution) - Compression (
Accept-Encoding: gzip,lz4) -
X-ClickHouse-Progress,X-ClickHouse-Summaryresponse headers -
readonly,max_result_rows,max_execution_timeand other settings as query params
Out of scope
- Binary native-protocol HTTP upgrades
- Replica / cluster discovery endpoints (
/replicas_status,/pingetc. — these are trivial to add if asked, but not part of 'query execution' plug-in) - TLS termination differences — inherit from existing server TLS
Why this is cleaner than it sounds
The CH HTTP API is substantial but altinity-mcp already has:
- Query execution with auth context —
handleExecuteQueryOpenAPIpath - Per-request ClickHouse client resolution with JWE/OAuth/cluster-secret context
QueryResult { Columns, Types, Rows, Count }internal type — straightforward to serialize to TSV/JSON variants
Phase 1 is mostly a format writer + a request parser + one route case. The heavy lifting (auth, execution, OpenAPI parity) stays untouched.
Acceptance criteria
curl 'http://localhost:8080/?query=SELECT+1'returns1\nwithContent-Type: text/tab-separated-valuescurl -u user:pass 'http://localhost:8080/?query=SELECT+currentUser()'runs asuser(cluster-secret / JWE / OAuth mode, whichever is configured)curl 'http://localhost:8080/?query=SELECT+1&default_format=JSONCompact'returns valid JSONCompact- Invalid SQL returns HTTP 500 with
Code:prefix body - Existing MCP clients and
/openapiendpoints continue to work unchanged - Integration test: point a
clickhouse-client --urlat altinity-mcp and execute a simple SELECT
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the mux setup in cmd/altinity-mcp/main.go around mcpRoutePatterns and openAPIRoutePatterns, then read the dispatcher at pkg/server/server.go:2519 and handleExecuteQueryOpenAPI. Trace the existing client-resolution helpers and query result handling before running the project’s tests. Done means phase-one ClickHouse HTTP requests, formats, authentication, errors, and the listed curl/integration acceptance checks work without changing MCP or OpenAPI behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- clickhouse, go
- Domain
- api, authentication, databases
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100