Building a ClickHouse MCP Server
Query a ClickHouse columnar warehouse from an MCP tool, with an enforced row limit and read-only guardrails.
Quick Answer / TL;DR
A ClickHouse MCP server uses the official @clickhouse/client package to run read-only SQL over the HTTP interface, with an enforced LIMIT so a model-generated query can't return an unbounded result set.
Key Takeaways
- ClickHouse is column-oriented - selecting only the columns actually needed matters far more for performance than in a row-oriented database.
- Append a LIMIT to any query that doesn't already have one before executing it, rather than trusting the model to include one.
- Reject INSERT/ALTER/DROP the same way a read-only Postgres tool would - ingestion belongs in a dedicated pipeline, not a query tool.
Why not just copy a reference implementation?
The official MCP servers repository states its own scope plainly: "The servers in this repository are intended as reference implementations to demonstrate MCP features and SDK usage... not as production-ready solutions." A tool built by following that same educational pattern against ClickHouse typically has no row cap and no rejection of write statements - both are added explicitly below, not inherited for free from the SDK.
A row-limited query tool
The @clickhouse/client package's query() method returns a stream-like result you resolve to JSON; wrapping every query with a LIMIT check before execution keeps a single bad query from returning millions of rows to the model.
import { createClient } from "@clickhouse/client";
const client = createClient({
url: process.env.CLICKHOUSE_URL ?? "http://localhost:8123",
username: process.env.CLICKHOUSE_USER,
password: process.env.CLICKHOUSE_PASSWORD,
});
async function runQuery(sql: string, maxRows = 500) {
if (/\b(INSERT|ALTER|DROP|TRUNCATE)\b/i.test(sql)) {
throw new Error("Only SELECT queries are permitted through this tool.");
}
const bounded = /LIMIT\s+\d+/i.test(sql) ? sql : `${sql} LIMIT ${maxRows}`;
const resultSet = await client.query({ query: bounded, format: "JSONEachRow" });
return resultSet.json();
}Building a ClickHouse MCP Server FAQs
Direct answers for developers, operators, and Indian teams evaluating MCP.