clickhouse-readonly-mcp
by MP-Trade
README.md
# clickhouse-readonly-mcp
Минимальный MCP-сервер для read-only доступа к ClickHouse: даёт AI-агенту
(Claude Code, Cursor и т.п.) возможность смотреть схему баз/таблиц/вью
и делать SELECT-запросы напрямую — без ручных экспортов CSV из DataLens.
Написан по образцу [`azure-sql-mcp`](../azure-sql-mcp). Весь код
(`server.py`) прозрачен и лежит в этом репозитории. Сторонних MCP-пакетов нет.
## Почему это безопасно (read-only в двух независимых местах)
1. **На уровне базы**: сервер подключается под отдельным пользователем
ClickHouse, у которого DBA выдал только `SELECT` на нужные таблицы/вью
(`GRANT SELECT ON database.table TO readonly_user`). Никакого
`INSERT / UPDATE / DROP / ALTER`.
2. **В коде**: `ch_run_select` до отправки запроса проверяет, что это ровно
один `SELECT` (в т.ч. `WITH … SELECT`), без `INSERT / DELETE / DROP /
ALTER / CREATE / SYSTEM / TRUNCATE` и без `;` внутри (чтобы нельзя было
дописать второй оператор). Плюс сессия открывается с `readonly=1` и
`max_execution_time=30` — даже если проверка ошибётся, ClickHouse не даст
ничего записать.
Даже если код-проверка №2 где-то ошибётся — база физически не даст ничего,
кроме `SELECT`, потому что у пользователя нет прав на запись.
## Установка
Требуется Python 3.10+.
```bash
cd clickhouse-readonly-mcp
pip install -r requirements.txt
cp .env.example .env # Windows: copy .env.example .env
```
Открой `.env` и заполни:
```env
CH_HOST=clickhouse.mptrd.ru
CH_PORT=443
CH_DATABASE=default_marts
CH_USER=your_readonly_user
CH_PASSWORD=your_password
CH_SECURE=true # true = HTTPS/TLS (у нас порт 443, не 8443); false = HTTP (порт 8123)
CH_VERIFY=true # false — если self-signed сертификат
```
`.env` не попадает в git (см. `.gitignore`) — пароль остаётся только на
локальной машине.
## Подключение к Claude Code / Cursor
В конфиге MCP-серверов (`~/.cursor/mcp.json` или аналогичный для Claude Code):
```json
{
"mcpServers": {
"clickhouse-readonly": {
"command": "python",
"args": ["ПОЛНЫЙ_ПУТЬ/clickhouse-readonly-mcp/server.py"]
}
}
}
```
После добавления нужен полный перезапуск клиента.
## Доступные инструменты
| Инструмент | Что делает |
|---|---|
| `ch_connection_status` | Проверить подключение, вернуть пользователя / версию CH |
| `ch_list_databases` | Список баз данных, видимых текущему пользователю |
| `ch_list_tables` | Таблицы и вью базы: имя, движок, примерное кол-во строк, размер |
| `ch_describe_table` | Колонки таблицы/вью: имя, тип, default, комментарий |
| `ch_table_sample` | Быстрый `SELECT * LIMIT N` — посмотреть форму данных |
| `ch_run_select` | Произвольный read-only `SELECT` (с лимитом строк и защитой от записи) |
## Что попросить у DBA (пример)
```sql
-- Создать пользователя
CREATE USER agent_readonly IDENTIFIED BY 'strong_password_here';
-- Выдать SELECT только на нужные вью в Marts
GRANT SELECT ON default_marts.bv_ozon_product_queries_details TO agent_readonly;
GRANT SELECT ON default_marts.bv_gg_turnover_daily TO agent_readonly;
GRANT SELECT ON default_marts.bv_gg_turnover_summary TO agent_readonly;
GRANT SELECT ON default_marts.bv_ozon_orders_by_clusters TO agent_readonly;
GRANT SELECT ON default_marts.bv_ozon_orders_stock TO agent_readonly;
-- Проверка (запустить от имени agent_readonly)
SELECT * FROM default_marts.bv_ozon_product_queries_details LIMIT 1;
```
## Диагностика
- **`Connection refused` / `timeout`** — проверь `CH_HOST`, `CH_PORT` и что
firewall разрешает входящие соединения с твоего IP. Частая ошибка онбординга:
порт `8443` (типичный для ClickHouse HTTPS) у MP-Trade **не слушается** —
нужен `CH_PORT=443` при `CH_SECURE=true`.
- **`TLS handshake failed`** — попробуй `CH_VERIFY=false` (если self-signed
сертификат), или убедись что `CH_SECURE=true` и порт `443`.
- **`ch_run_select` отклоняет обычный SELECT** — скорее всего, в тексте
запроса встретилось запрещённое слово как часть идентификатора
(например, алиас `into_basket`). Правь `_FORBIDDEN_KEYWORDS` в `server.py`
осознанно, с пониманием, а не в обход.
- **Список инструментов не обновился после правки `server.py`** — нужен
полный перезапуск клиента (не только чата).
## Зависимости
| Библиотека | Для чего |
|---|---|
| `fastmcp` | Реализация протокола MCP (тот же выбор, что в `azure-sql-mcp`) |
| `clickhouse-connect` | Официальный Python-клиент ClickHouse Inc., поддерживает HTTP/HTTPS |
| `python-dotenv` | Загрузка `.env` без хардкода пароля в коде |
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing