Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

Free Clickhouse

БесплатноНе проверен

Free ClickHouse MCP server — free cloud ClickHouse OLAP database for Claude, ChatGPT and AI analytics

GitHubEmbed

Описание

Free ClickHouse MCP server — free cloud ClickHouse OLAP database for Claude, ChatGPT and AI analytics

README

ClickHouse OLAP MCP Free tier

Symptom

You connect an assistant to your analytics data and ask what should be a two-second question: which acquisition channel had the best week-one retention last month? It runs a SELECT with a LIMIT 1000, gets a thousand rows of raw pageviews, decides that isn't enough, raises the limit, and either fills its context window with event rows or gives you an answer computed from a sample it chose arbitrarily.

The model isn't being stupid. It's doing the only thing available when the database it's been handed is a row store holding raw events, or when the tool it's been given returns rows rather than answers.

The fix is not a better prompt. It's putting the aggregation on the database side of the wire. Ask ClickHouse the retention question and it reads three columns out of a hundred million rows, does the grouping in vectorised batches, and hands back nine numbers. Nine numbers fit in a context window. A hundred million rows never will.

SELECT
    channel,
    uniqExact(user_id)                                          AS cohort,
    uniqExactIf(user_id, days_since_signup BETWEEN 7 AND 13)    AS week_one,
    round(100 * week_one / cohort, 1)                           AS pct
FROM events_enriched
WHERE signup_month = '2024-02-01'
GROUP BY channel
ORDER BY pct DESC;

That query is the entire payload. This repo is about making it the thing your agent actually runs.

Install

Create an instance at freebase.cloud, choose the ClickHouse engine, then Settings → MCP → New Token and copy the URL. The token lives in the URL path, so no client needs custom headers.

claude mcp add --transport http events https://freebase.cloud/api/mcp/YOUR_TOKEN

The connection is called events throughout this README; your tool names will follow whatever you named yours.

Config for other clients
// Claude Code .mcp.json — omitting "type" is a startup error
{ "mcpServers": { "events": { "type": "http", "url": "https://freebase.cloud/api/mcp/YOUR_TOKEN" } } }
// Cursor .cursor/mcp.json — no "type" key at all
{ "mcpServers": { "events": { "url": "https://freebase.cloud/api/mcp/YOUR_TOKEN" } } }
// VS Code / Copilot Chat .vscode/mcp.json — "servers", not "mcpServers"
{ "servers": { "events": { "type": "http", "url": "https://freebase.cloud/api/mcp/YOUR_TOKEN" } } }
// Windsurf ~/.codeium/windsurf/mcp_config.json — "serverUrl"
{ "mcpServers": { "events": { "serverUrl": "https://freebase.cloud/api/mcp/YOUR_TOKEN" } } }
// Warp — paste into Settings > AI > Manage MCP servers, no wrapper object
{ "events": { "url": "https://freebase.cloud/api/mcp/YOUR_TOKEN" } }

Claude Desktop, Claude web and Cowork: Settings → Connectors → Add custom connector (walkthrough). Remote HTTP servers can't be declared in claude_desktop_config.json.

From LangChain:

from langchain_mcp_adapters.client import MultiServerMCPClient
client = MultiServerMCPClient({"events": {"transport": "http", "url": "https://freebase.cloud/api/mcp/YOUR_TOKEN"}})
tools = await client.get_tools()

The table

Web analytics: one row per event, a few million a week, queried by date range and by property. The DDL runs unchanged on a free ClickHouse 24.1 instance.

CREATE TABLE events (
    event_time   DateTime,
    event_date   Date DEFAULT toDate(event_time),
    site         LowCardinality(String),
    event_type   LowCardinality(String),   -- page_view | click | signup | purchase
    user_id      UInt64,
    session_id   UUID,
    path         String,
    referrer     String,
    channel      LowCardinality(String),
    country      LowCardinality(String),
    device       LowCardinality(String),
    duration_ms  UInt32,
    revenue_cents UInt32 DEFAULT 0
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(event_date)
ORDER BY (site, event_date, event_type, user_id);

Three decisions carry all the weight:

ORDER BY is the primary index. ClickHouse stores rows sorted by that tuple and builds a sparse index over it. Put the columns you filter on first, in decreasing order of how often you filter on them. Getting this wrong doesn't produce an error — it produces a table that reads ten times more data than it needs to, forever.

PARTITION BY is for dropping data, not for speed. Monthly partitions mean ALTER TABLE events DROP PARTITION '202401' is instant. Partitioning by day on a small table just creates thousands of tiny parts and makes merges worse.

LowCardinality(String) on anything with a bounded set of values. Country, channel, device, event type. It's a dictionary encoding, and on a column with a few hundred distinct values it's a large reduction in bytes read.

Five questions, five queries

Full versions with sample output are in examples/analytics.sql; each one runs as written against a hosted instance.

1. Traffic by day, last fortnight. The WHERE clause hits the sort key, so ClickHouse skips whole granules rather than scanning.

SELECT event_date, count() AS events, uniq(session_id) AS sessions
FROM events
WHERE site = 'shop' AND event_date >= today() - 14
GROUP BY event_date ORDER BY event_date;

2. Top pages, but only one row per section. LIMIT n BY expr has no standard-SQL equivalent and replaces a window function plus a subquery.

SELECT splitByChar('/', path)[2] AS section, path, count() AS views
FROM events WHERE event_type = 'page_view' AND event_date >= today() - 7
GROUP BY section, path
ORDER BY section, views DESC
LIMIT 3 BY section;

3. A conversion funnel. windowFunnel returns, per user, how deep into an ordered sequence of conditions they got within a time window.

SELECT level, count() AS users FROM (
    SELECT user_id,
           windowFunnel(3600)(event_time,
               event_type = 'page_view',
               event_type = 'click',
               event_type = 'purchase') AS level
    FROM events WHERE event_date >= today() - 30
    GROUP BY user_id
) GROUP BY level ORDER BY level;

4. The last thing each user did. argMax picks the value of one column at the row where another is maximal — one pass, no self-join.

SELECT user_id, argMax(path, event_time) AS last_path, max(event_time) AS seen
FROM events WHERE event_date >= today() - 1
GROUP BY user_id ORDER BY seen DESC LIMIT 20;

5. Revenue with a rolling average. Window functions work as you'd expect from Postgres.

SELECT event_date, revenue,
       avg(revenue) OVER (ORDER BY event_date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS ma7
FROM (
    SELECT event_date, sum(revenue_cents) / 100 AS revenue
    FROM events WHERE event_type = 'purchase'
    GROUP BY event_date
)
ORDER BY event_date;

Materialized views for the questions you ask daily

A ClickHouse materialized view is an insert trigger, not a cached query. Rows arriving in events are transformed and written into the target table as a side effect of the insert. It never re-reads history, so creating one does nothing to existing data — you backfill that yourself with a single INSERT INTO … SELECT.

CREATE TABLE daily_traffic (
    event_date  Date,
    site        LowCardinality(String),
    channel     LowCardinality(String),
    events      UInt64,
    sessions    AggregateFunction(uniq, UUID),
    revenue     UInt64
) ENGINE = AggregatingMergeTree
ORDER BY (site, event_date, channel);

CREATE MATERIALIZED VIEW daily_traffic_mv TO daily_traffic AS
SELECT event_date, site, channel,
       count()             AS events,
       uniqState(session_id) AS sessions,
       sum(revenue_cents)  AS revenue
FROM events
GROUP BY event_date, site, channel;

Reading it back requires the matching -Merge combinator, and this is where people get a wrong number and blame the view:

SELECT site, channel, sum(events) AS events, uniqMerge(sessions) AS sessions
FROM daily_traffic
WHERE event_date >= today() - 30
GROUP BY site, channel;

uniqState stores the partial sketch; uniqMerge combines the sketches. Selecting the raw sessions column without uniqMerge returns unreadable binary state. Put that fact in the table's annotation — it's the single most common ClickHouse mistake a model makes.

ClickHouse SQL that trips agents up

Habit from elsewhere What happens here Write instead
SELECT * Reads every column off disk; on a wide table that's the whole cost Name the columns
COUNT(DISTINCT x) Works, but exact and memory-hungry uniq(x) for approximate, uniqExact(x) when it must be right
a / b on integers Returns Float64 intDiv(a, b) if you want integer division
WHERE col IS NULL Non-Nullable columns can't be null; the check is always false Model absence explicitly, or declare Nullable(T)
Big LEFT JOIN The right table is loaded into memory Filter the right side in a subquery first, or use a dictionary
FINAL on every query Forces a merge at read time and is slow Only with ReplacingMergeTree, and prefer argMax deduplication
WHERE on a heavy column Full column read before filtering PREWHERE on the cheap column to cut rows first
Trusting a SELECT alias in GROUP BY Actually fine — ClickHouse allows it, unlike standard SQL Use it; it's shorter

Most of these belong in events_annotate_table rather than in a system prompt, because the annotation is stored server-side with the connection itself and comes back on every reconnect.

Tool reference

Four tools per connection — the same set every freebase.cloud engine exposes, prefixed with the name you chose:

Tool Arguments Notes
events_query query ClickHouse SQL. This is where the work happens.
events_store table, rows[], mode JSON objects; mode is append or replace
events_list_tables Tables, row counts, columns, annotations
events_annotate_table table, description, format Persisted schema notes

An annotation worth writing on day one:

{
  "table": "daily_traffic",
  "description": "Pre-aggregated daily rollup, populated by daily_traffic_mv as a side effect of inserts into events. It contains no history from before the view was created. `sessions` is an AggregateFunction column: you MUST read it with uniqMerge(sessions), never as a plain column. Prefer this table over `events` for anything at daily granularity.",
  "format": {
    "structure": "event_date, site, channel, events UInt64, sessions AggregateFunction(uniq, UUID), revenue UInt64 (cents)"
  }
}

The last sentence steers the model to the cheap table without you having to say so in every conversation.

What the free tier is for

Development, prototyping and small production analytics on the free ClickHouse tier. That covers a genuine amount of work — a product analytics prototype, a dashboard behind an internal tool, a place to land a few million events and actually explore them — and it does not cover a warehouse. Nothing here promises availability targets or a retention policy; no such figures exist to quote.

Practical notes:

  • You reach the data through the HTTP query API and through MCP. The clickhouse-client and port 9000 references above describe which SQL dialect you are writing — ClickHouse 24.1.5 — and should not be read as an open native-protocol socket.
  • Bulk loading works best in batches. ClickHouse writes a new part per insert and merges in the background, so ten thousand single-row inserts is the pathological case. examples/load_events.mjs batches at 5,000 rows.
  • A query with a bad WHERE will read the whole table here exactly as it would anywhere. If something is slow, check whether the filter touches the ORDER BY prefix before assuming the free tier is the problem.

FAQ

Is this real ClickHouse? ClickHouse 24.1.5. SELECT version() will confirm it.

Can I point Grafana or Metabase at it? Both speak the HTTP interface, which is available. Grafana's official ClickHouse plugin is the usual route.

Do I have to run anything from this repo? No. There is no server here — freebase.cloud hosts the MCP endpoint. These files are the schema, the queries and the loader.

Can I import CSV or JSON in bulk? Yes — INSERT INTO … FORMAT CSV and FORMAT JSONEachRow both work over the HTTP interface. The Node loader uses JSONEachRow.

How does this compare to ClickHouse Cloud? ClickHouse Cloud is the managed product from the company that builds the database, with separated storage and compute, autoscaling and support. This is a free instance for development and small workloads. Different jobs.

Links


MIT. freebase.cloud is an independent service and is not affiliated with ClickHouse, Inc., Anthropic, Grafana Labs, or Microsoft.

from github.com/freebase-cloud/free-clickhouse-mcp-server

Установка Free Clickhouse

У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.

▸ github.com/freebase-cloud/free-clickhouse-mcp-server

FAQ

Free Clickhouse MCP бесплатный?

Да, Free Clickhouse MCP бесплатный — установка в пару кликов через Unyly без оплаты.

Нужен ли API-ключ для Free Clickhouse?

Нет, Free Clickhouse работает без API-ключей и переменных окружения.

Free Clickhouse — hosted или self-hosted?

Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.

Как установить Free Clickhouse в Claude Desktop, Claude Code или Cursor?

Открой Free Clickhouse на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.

Похожие MCP

wenb1n-dev/SmartDB_MCP

A universal database MCP server supporting simultaneous connections to multiple databases. It provides tools for database operations, health analysis, SQL optim

wenb1n-devавтор: wenb1n-dev

Postgres Server

This server enables interaction with PostgreSQL databases through the Model Context Protocol, optimized for the AWS Bedrock AgentCore Runtime. It provides tools

madhurprashавтор: madhurprash

Postgres

Query your database in natural language

Anthropicавтор: Anthropic

PostgreSQL

Read-only database access with schema inspection.

modelcontextprotocolавтор: modelcontextprotocol

Redis

Interact with Redis key-value stores.

modelcontextprotocolавтор: modelcontextprotocol

SQLite

Database interaction and business intelligence capabilities.

modelcontextprotocolавтор: modelcontextprotocol

mxcp

Open-source framework for building enterprise-grade MCP servers using just YAML, SQL, and Python, with built-in auth, monitoring, ETL and policy enforcement.

raw-labsавтор: raw-labs

tadas-github/a2asearch-mcp

MCP server to search 4,800+ MCP servers, AI agents, CLI tools and agent skills. Install: npx -y a2asearch-mcp. Ask Claude: "Find MCP servers for database access

tadas-githubавтор: tadas-github

julien040/anyquery

Query more than 40 apps with one binary using SQL. It can also connect to your PostgreSQL, MySQL, or SQLite compatible database. Local-first and private by desi

julien040автор: julien040

drakonkat/wizzy-mcp-tmdb

A MCP server for The Movie Database API that enables AI assistants to search and retrieve movie, TV show, and person information.

drakonkatавтор: drakonkat

Compare Free Clickhouse with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории data