Skip to main content
Glama
wtkid

mcp-clickhouse-multids

by wtkid
README.md
# 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

C2.2/5.0

Scored across 6 tools

Disambiguation4/5

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.

Naming Consistency5/5

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.

Tool Count5/5

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.

Completeness3/5

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.

Maintenance

ActivityMaintained
ResponsivenessSyncing