mcp-clickhouse-multids
# mcp-clickhouse-multids
同一 MCP 进程连接多个 ClickHouse 实例(`host:port` + 运行时注册 / 可选 YAML)。
- **License:** [Apache-2.0](LICENSE)
- **Repository:** [https://github.com/wtkid/mcp-clickhouse-multids](https://github.com/wtkid/mcp-clickhouse-multids)
---
## 快速开始
无需 YAML、无需 `CLICKHOUSE_*` env 即可起步。按部署方式二选一:
- [方式一:Docker](#方式一docker) — 拉取镜像部署(推荐 HTTP 远程连接)
- [方式二:stdio(本地 IDE)](#方式二stdio本地-ide) — Cursor / Claude Desktop 拉起子进程
多库时:可多次调用 `register_datasource`,或在后续章节配置 YAML(**可选**)。
镜像:`registry.cn-hangzhou.aliyuncs.com/wtns/mcp:clickhouse-multids-v1.0.0`
### 方式一:Docker
**1. 构建镜像**(也可跳过此步,直接使用上方 registry 镜像)
```bash
git clone https://github.com/wtkid/mcp-clickhouse-multids.git
cd mcp-clickhouse-multids
docker build --no-cache -t mcp-clickhouse-multids:v1.0.0 .
```
**2. 启动容器(HTTP)**
#### Docker + HTTP(Cursor / 远程客户端)
通过 **HTTP** 连接 MCP(例如 `url: http://192.168.2.14:8000/mcp`)时,启动容器需显式开启 HTTP 并配置鉴权:
```bash
# 使用已有镜像启动,如自行构建时修改为自己的镜像即可
docker run -d --name mcp-clickhouse-multids \
-p 8000:8000 \
-e CLICKHOUSE_MCP_SERVER_TRANSPORT=http \
-e CLICKHOUSE_MCP_BIND_HOST=0.0.0.0 \
-e CLICKHOUSE_MCP_BIND_PORT=8000 \
-e CLICKHOUSE_MCP_AUTH_TOKEN=your-generated-token \
registry.cn-hangzhou.aliyuncs.com/wtns/mcp:clickhouse-multids-v1.0.0
```
Cursor 客户端配置:
```json
{
"mcpServers": {
"clickhouse-multids": {
"url": "http://192.168.2.14:8000/mcp",
"headers": {
"Authorization": "Bearer your-generated-token"
}
}
}
}
```
`CLICKHOUSE_MCP_AUTH_TOKEN` 与 `Authorization: Bearer` 后的 token 必须一致。更多选项见 [二、MCP 传输与鉴权](#二mcp-传输与鉴权)、[7.4 HTTP 远程](#74-http-远程--bearer-鉴权--yamlyaml-可换为-register)。
### 方式二:stdio(本地 IDE)
由 IDE 通过 `command` + `args` 启动,**不经 HTTP**;**无需**在 `mcp.json` 里配置 `CLICKHOUSE_*` 环境变量,数据源通过 `register_datasource` **动态注册**。
> **需要配置** `Authorization` **吗?**
> **不需要。** `Authorization: Bearer ...` 仅在使用 **HTTP / SSE** 连接 MCP 时生效(见 [二、MCP 传输与鉴权](#二mcp-传输与鉴权))。
> stdio 模式**不用**设置 `CLICKHOUSE_MCP_AUTH_TOKEN`,`mcp.json` 里也**不用**写 `headers.Authorization`。
**1. 安装**
需先安装 [uv](https://docs.astral.sh/uv/getting-started/installation/),然后:
```bash
git clone https://github.com/wtkid/mcp-clickhouse-multids.git
cd mcp-clickhouse-multids
uv sync
```
> `uv sync` 会在项目下创建 `.venv`(以点开头,文件树中可能默认隐藏)并按 `uv.lock` 安装依赖。之后用 `uv run` 启动时,若环境缺失或过期,**uv 也会自动同步**,一般不必重复执行。
**2. Cursor / Claude Desktop(`mcp.json`)**
仅启动 MCP 进程,**不写** `env`(或 `env` 留空)。可参考仓库根目录 [mcp.json.example](mcp.json.example)。
推荐用 `uv run`:`cwd` 指向项目根目录,uv 会自动使用/创建 `.venv` 并安装依赖,无需手动指定 Python 路径。
```json
{
"mcpServers": {
"clickhouse-multids": {
"command": "uv",
"args": ["run", "mcp-clickhouse-multids"],
"cwd": "/path/to/mcp-clickhouse-multids"
}
}
}
```
Windows 下若 Cursor 提示找不到 `uv`,将 `command` 改为 `uv` 的完整路径,例如 `C:\\Users\\you\\AppData\\Local\\Programs\\Python\\Python312\\Scripts\\uv.exe`。
保存后**完全重启 Cursor**,在 MCP 面板确认 `clickhouse-multids` 已连接。
**3. 动态注册数据源**(首次使用或新增库时)
在对话中让 AI 调用工具 `register_datasource`。可直接用自然语言描述连接信息,例如:
> 192.168.2.14:8123,用户名 default,密码 123456
对应工具参数示例:
```json
{
"host": "192.168.2.14",
"port": 8123,
"user": "default",
"password": "123456"
}
```
可用 `list_registered_datasources` 查看已注册列表(不含密码);`unregister_datasource` 可注销。
**4. 查询**(必须带 `host`;该 host 仅一条源时可省略 `port`)
`run_query` 示例:
```json
{ "host": "192.168.2.14", "query": "SELECT 1" }
```
`list_databases` 示例:
```json
{ "host": "192.168.2.14" }
```
---
## 连接默认值(`secure` / `verify`)
注册数据源(`register_datasource`)、YAML 条目或 legacy env **未显式指定**时,使用下表默认值。
| 参数 | 默认值 | 说明 |
| -------- | --------------------------- | ----------------------------- |
| `secure` | `false`(HTTP,端口默认 **8123**) | MCP 进程是否用 HTTPS 连接 ClickHouse |
| `verify` | `false` | 是否校验 TLS 证书 |
- 内网 HTTP(如 `8123`):`secure` / `verify` 均可省略。
- **ClickHouse Cloud 等 HTTPS**:请显式设置 `"secure": true`,并按需 `"verify": true`。
- Legacy env:`CLICKHOUSE_SECURE`、`CLICKHOUSE_VERIFY` 未设置时默认为 `false`。
---
## 配置分层(重要)
两类配置互不替代,不要混用:
| 层级 | 作用 | 典型变量 / 方式 |
| ------------------ | ------------------ | ----------------------------------------- |
| **ClickHouse 数据源** | 连哪台库、用什么账号 | legacy env、`register_datasource`、YAML(可选) |
| **MCP 服务本身** | 怎么暴露给客户端、是否鉴权、查询超时 | `CLICKHOUSE_MCP_*` |
- 数据库的 `user` / `password` ≠ MCP 的 `Authorization: Bearer`。
- `CLICKHOUSE_SECURE` 等只影响 **连 ClickHouse**,不影响 MCP HTTP 是否 TLS。
---
## 核心能力(多数据源)
- **数据源主键**:`host:port`(`port` 可省略时,按该源的 `secure` 默认:**8123** / **8443**)
- **ClientRegistry**:按 `host:port` 懒创建并复用 `clickhouse_connect.Client`
- **配置来源**(三选一或组合,**均不强制 YAML / env**):
1. 运行时:`register_datasource` / `unregister_datasource` / `list_registered_datasources`(见 [快速开始](#快速开始))
2. YAML:`MCP_CLICKHOUSE_DATASOURCES_FILE`(可选,适合预置多台库)
3. Legacy env:`CLICKHOUSE_HOST` + `CLICKHOUSE_USER` + `CLICKHOUSE_PASSWORD`(可选,启动时写入一条)
- **调用约定**:`run_query` / `list_databases` / `list_tables` 必须传 `host`(同一 host 仅一条源时可省略 `port`)
---
## 一、数据源配置
数据源有三种方式,**任选其一即可**,不必同时使用,也**不需要**任何 YAML 文件:
| 方式 | 适用场景 |
| --------------------- | --------------------------------------- |
| `register_datasource` | **推荐起步**:动态增删库、无需改配置文件(见 [快速开始](#快速开始)) |
| YAML 文件 | 预置多台库、容器挂载配置(**完全可选**) |
| Legacy env | 单库、启动时注册一条数据源(**可选**) |
### 1.1 YAML 多数据源(可选)
> **说明**:YAML **不是必选**。不配置 `MCP_CLICKHOUSE_DATASOURCES_FILE` 时服务可正常启动;多台库可在运行时通过 `register_datasource` 注册,无需事先准备配置文件。
仅在需要**启动即加载**一批固定数据源时,再设置:
```bash
export MCP_CLICKHOUSE_DATASOURCES_FILE=/path/to/datasources.yml
```
- 未设置该变量:跳过 YAML,不影响启动。
- 设置了但文件不存在:打日志并跳过,**不会启动失败**。
示例文件见 [config/datasources.example.yml](config/datasources.example.yml):
```yaml
datasources:
- alias: prod # 可选,仅展示用,不是工具入参
host: "ch-prod.example.com"
port: 8443
user: "readonly"
password: "secret"
secure: true
verify: true
database: "analytics" # 可选,默认库
role: "readonly_role" # 可选
proxy_path: "/clickhouse" # 可选,反代路径前缀
server_host_name: "ch.internal" # 可选,SNI / 证书校验主机名
connect_timeout: 30
send_receive_timeout: 300
- alias: local
host: "localhost"
user: "default"
password: "clickhouse"
secure: false
verify: false
# port 省略 → secure=false 时默认 8123
```
YAML 字段与 `register_datasource` 工具参数一致(`user` 也可用 `username`,会自动映射)。若已用 `register_datasource` 注册过相同 `host:port`,YAML 启动加载或再次 register 会**覆盖**该条目。
### 1.2 Legacy 单库环境变量(无需 YAML)
未设置 YAML 时,若存在以下变量,启动时自动注册 **一条** 数据源(`alias=legacy-env`):
| 变量 | 必填 | 说明 |
| --------------------------------- | --- | ------------------------------------------- |
| `CLICKHOUSE_HOST` | 是 | ClickHouse 主机名 |
| `CLICKHOUSE_USER` | 是 | 数据库用户名 |
| `CLICKHOUSE_PASSWORD` | 是 | 数据库密码(可为空字符串) |
| `CLICKHOUSE_PORT` | 否 | HTTP 端口;省略时 `secure=true`→8443,`false`→8123 |
| `CLICKHOUSE_SECURE` | 否 | 默认 `false`;见 [连接默认值](#连接默认值secure--verify) |
| `CLICKHOUSE_VERIFY` | 否 | 默认 `false`;见 [连接默认值](#连接默认值secure--verify) |
| `CLICKHOUSE_ROLE` | 否 | ClickHouse role |
| `CLICKHOUSE_DATABASE` | 否 | 默认数据库 |
| `CLICKHOUSE_PROXY_PATH` | 否 | HTTP 路径前缀 |
| `CLICKHOUSE_SERVER_HOST_NAME` | 否 | SNI / 证书主机名 |
| `CLICKHOUSE_CONNECT_TIMEOUT` | 否 | 默认 `30`(秒) |
| `CLICKHOUSE_SEND_RECEIVE_TIMEOUT` | 否 | 默认 `300`(秒) |
调用工具时仍须传 `host`(及 `port`,多源同 host 时必填),例如 env 里 host 为 `localhost`:
```json
{ "host": "localhost", "port": 8123, "query": "SELECT 1" }
```
### 1.3 运行时注册(无 YAML、无 legacy env 亦可)
即使未配置 env、也未准备 YAML,进程仍可启动;catalog 为空时,通过 `register_datasource` 添加第一台库后再查询:
```json
{
"host": "10.0.0.5",
"user": "app",
"password": "secret",
"port": 8123
}
```
(省略 `secure` / `verify` 时见 [连接默认值](#连接默认值secure--verify)。)
管理工具:
| 工具 | 说明 |
| ----------------------------- | -------------------------------- |
| `register_datasource` | 注册或覆盖 `host:port`,会丢弃已缓存的 Client |
| `list_registered_datasources` | 列出已注册源(**不返回 password**) |
| `unregister_datasource` | 注销并关闭对应 Client |
---
## 二、MCP 传输与鉴权
### 2.1 传输方式
| 变量 | 默认 | 说明 |
| --------------------------------- | ----------- | ------------------------------ |
| `CLICKHOUSE_MCP_SERVER_TRANSPORT` | `stdio` | `stdio` / `http` / `sse` |
| `CLICKHOUSE_MCP_BIND_HOST` | `127.0.0.1` | HTTP/SSE 监听地址;远程访问可设 `0.0.0.0` |
| `CLICKHOUSE_MCP_BIND_PORT` | `8000` | HTTP/SSE 监听端口 |
| `CLICKHOUSE_MCP_QUERY_TIMEOUT` | `30` | 查询类工具超时(秒) |
- **Cursor 本地**:通常用 `stdio`(默认),无需 HTTP、无需 `Authorization`。
- **远程 / Docker / K8s**:用 `http` 或 `sse`,需配置鉴权(见下)。
HTTP 模式下端点示例:
- MCP:`http://<bind_host>:<bind_port>/mcp`
- 健康检查:`http://<bind_host>:<bind_port>/health`(**无鉴权**,仅进程存活)
### 2.2 Authorization Header(Bearer Token)
使用 **HTTP 或 SSE** 时,以下 **二选一**(互斥):
| 模式 | 环境变量 | 客户端请求头 |
| ----------------- | ----------------------------------- | ---------------------------------- |
| **静态 Bearer(常用)** | `CLICKHOUSE_MCP_AUTH_TOKEN=<随机字符串>` | `Authorization: Bearer <同一 token>` |
| **关闭鉴权(仅开发)** | `CLICKHOUSE_MCP_AUTH_DISABLED=true` | 无 |
生成 token 示例:
```bash
# Linux/macOS
openssl rand -hex 32
```
服务端:
```bash
export CLICKHOUSE_MCP_SERVER_TRANSPORT=http
export CLICKHOUSE_MCP_BIND_HOST=0.0.0.0
export CLICKHOUSE_MCP_BIND_PORT=8000
export CLICKHOUSE_MCP_AUTH_TOKEN=your-generated-token
```
Cursor / 其他 MCP 客户端(HTTP):
```json
{
"mcpServers": {
"clickhouse-multids": {
"url": "http://192.168.1.100:8000/mcp",
"headers": {
"Authorization": "Bearer your-generated-token"
}
}
}
}
```
验证鉴权:对 `/mcp` 发请求,无 Header 应返回 `401`;`/health` 始终无需 token。
---
## 三、全局 ClickHouse 工具安全策略
对所有数据源 **统一生效**(不按单库区分):
| 变量 | 默认 | 说明 |
| ------------------------------- | ------- | ---------------------------------------------- |
| `CLICKHOUSE_ALLOW_WRITE_ACCESS` | `false` | `true` 允许 INSERT/DDL 等写操作 |
| `CLICKHOUSE_ALLOW_DROP` | `false` | 须同时 `ALLOW_WRITE_ACCESS=true`;允许 DROP/TRUNCATE |
默认只读:`run_query` 会带 `readonly=1`(在服务端允许的前提下)。
---
## 四、Middleware
通过环境变量加载自定义中间件 Python 模块:
```bash
export MCP_MIDDLEWARE_MODULE=your_middleware_module
```
模块需提供 `setup_middleware(mcp)` 函数,在其中向 FastMCP 实例注册中间件。
---
## 五、健康检查
| 项目 | 行为 |
| ---------------- | -------------------- |
| `GET /health` 鉴权 | 无 |
| 是否探测 ClickHouse | **否**(仅表示 MCP 进程已启动) |
| 响应 | 固定 `200` + `OK` |
---
## 六、MCP 工具一览
### 远程 ClickHouse(需 `host`)
| 工具 | 主要参数 |
| ----------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `run_query` | `host`, `query`, `port?` |
| `list_databases` | `host`, `port?` |
| `list_tables` | `host`, `database`, `port?`, `like?`, `not_like?`, `page_token?`, `page_size?`, `include_detailed_columns?` |
| `register_datasource` | `host`, `user`, `password`, `port?`, `secure?`, … |
| `list_registered_datasources` | 无 |
| `unregister_datasource` | `host`, `port?` |
---
## 七、配置示例
### 7.1 Cursor 本地 stdio + 动态注册(推荐,无 YAML / 无 env)
与 [快速开始](#快速开始) 相同:
```json
{
"mcpServers": {
"clickhouse-multids": {
"command": "uv",
"args": ["run", "mcp-clickhouse-multids"],
"cwd": "/path/to/mcp-clickhouse-multids"
}
}
}
```
连接后调用 `register_datasource` 注册库,再执行 `run_query` 等工具。
### 7.2 Cursor 本地 stdio + Legacy env 单库(可选)
启动时自动注册一条数据源,工具调用仍须传 `host`:
```json
{
"mcpServers": {
"clickhouse-multids": {
"command": "uv",
"args": ["run", "mcp-clickhouse-multids"],
"env": {
"CLICKHOUSE_HOST": "localhost",
"CLICKHOUSE_USER": "default",
"CLICKHOUSE_PASSWORD": "clickhouse",
"CLICKHOUSE_SECURE": "false",
"CLICKHOUSE_VERIFY": "false"
}
}
}
}
```
### 7.3 Cursor 本地 stdio + YAML 多库(可选)
预置多台库时使用;也可改用多次 `register_datasource`,无需 YAML。
```json
{
"mcpServers": {
"clickhouse-multids": {
"command": "uv",
"args": ["run", "mcp-clickhouse-multids"],
"env": {
"MCP_CLICKHOUSE_DATASOURCES_FILE": "/path/to/datasources.yml",
"CLICKHOUSE_ALLOW_WRITE_ACCESS": "false"
}
}
}
}
```
### 7.4 HTTP 远程 + Bearer 鉴权 + YAML(YAML 可换为 register)
**裸进程**环境变量示例:
```bash
CLICKHOUSE_MCP_SERVER_TRANSPORT=http
CLICKHOUSE_MCP_BIND_HOST=0.0.0.0
CLICKHOUSE_MCP_BIND_PORT=8000
CLICKHOUSE_MCP_AUTH_TOKEN=your-token
MCP_CLICKHOUSE_DATASOURCES_FILE=/app/config/datasources.yml
```
**Docker** 等价启动(与 [方式一 Docker + HTTP](#docker--httpcursor--远程客户端) 相同):
```bash
docker run -d --name mcp-clickhouse-multids \
-p 8000:8000 \
-e CLICKHOUSE_MCP_SERVER_TRANSPORT=http \
-e CLICKHOUSE_MCP_BIND_HOST=0.0.0.0 \
-e CLICKHOUSE_MCP_BIND_PORT=8000 \
-e CLICKHOUSE_MCP_AUTH_TOKEN=your-token \
-v /path/to/datasources.yml:/app/config/datasources.yml:ro \
-e MCP_CLICKHOUSE_DATASOURCES_FILE=/app/config/datasources.yml \
registry.cn-hangzhou.aliyuncs.com/wtns/mcp:clickhouse-multids-v1.0.0
```
客户端见 [2.2 Authorization Header](#22-authorization-headerbearer-token)。
### 7.5 HTTP 本地开发(关闭鉴权)
```bash
CLICKHOUSE_MCP_SERVER_TRANSPORT=http
CLICKHOUSE_MCP_AUTH_DISABLED=true
```
**勿在生产或公网暴露。**
---
## 开发与测试
```bash
uv sync --extra dev
uv run ruff check .
uv run pytest -v tests
```
安装、启动 MCP、跑测试均通过 `uv`;`uv run` 会在需要时自动维护项目 `.venv`。
---
## 许可
本项目采用 [Apache-2.0](LICENSE)。部分代码参考自 [ClickHouse/mcp-clickhouse](https://github.com/ClickHouse/mcp-clickhouse),详见 [NOTICE](NOTICE)。
本项目与 ClickHouse Inc. 无隶属关系。TDQS
Scored across 6 tools
Tool names like 'list_registered_datasources' and 'list_databases' suggest distinct purposes, but missing descriptions for most tools could cause ambiguity for an agent, especially between datasource and database/tables listing. However, the naming is sufficiently clear to differentiate them.
All tool names follow a consistent verb_noun pattern in snake_case (e.g., list_registered_datasources, register_datasource, run_query). No mixing of styles or conventions.
With 6 tools covering datasource management, database/table listing, and query execution, the count is well within the ideal range (3-15) for a focused multi-datasource ClickHouse server.
The tool set covers basic CRUD for datasources (list, register, unregister) and read operations (list databases/tables, run query). Missing update datasource and write operations (though run_query can be configured for writes). Notable gaps for a full lifecycle.