ClickHouse
官方查询您的ClickHouse数据库服务器。
你可以用 ClickHouse MCP 做什么?
- 运行 SQL 查询 — 通过
run_query在您的 ClickHouse 集群上执行任何 SQL 查询,支持可选命名参数。 - 列出数据库 — 使用
list_databases查看 ClickHouse 集群上所有可用的数据库。 - 使用过滤器浏览表 — 通过
list_tables使用LIKE/NOT LIKE模式及分页功能列出数据库中的表。 - 检查查询模式 — 在运行查询前,使用
DESCRIBE检查查询的输出列和类型。 - 估算查询成本 — 使用
EXPLAIN ESTIMATE预览SELECT查询的预计读取量(分区、行数、标记数)。
文档
ClickHouse MCP 服务器
一个用于 ClickHouse 的 MCP 服务器。
该服务器实现了 MCP 2026-07-28,并支持来自 2024-11-05 到 2025-11-25 的旧版初始化握手。现代客户端使用无会话请求和 server/discover。现有客户端可以继续协商旧版协议。
[!NOTE] 没有
MCP-Protocol-Version的 HTTP 请求会通过旧版处理进行路由,因此来自2025-06-18之前的客户端可以继续连接。MCP2026-07-28允许支持这些客户端的服务器采用此行为。现代客户端应在每个 POST 请求中发送该标头。
功能
ClickHouse 工具
ClickHouse 工具响应是 JSON 编码的字符串。超出 [-9007199254740991, 9007199254740991] 范围的整数以十进制字符串形式返回,以在 JavaScript 客户端中保留精确值。这适用于查询行和整数表元数据。安全范围内的整数和布尔值保留其 JSON 类型。
-
run_query -
list_databases- 列出您的 ClickHouse 集群上的所有数据库。
-
list_tables- 列出数据库中的表,支持分页。
- 必需输入:
database(字符串)。 - 可选输入:
like/not_like(字符串):对表名应用LIKE或NOT LIKE过滤器。page_token(字符串):上一次调用返回的一次性令牌。保留时间最长为一小时。page_size(整数,默认50):每页返回的表数量;必须大于0。include_detailed_columns(布尔值,默认true):当为false时,省略列元数据以获得更轻量的响应,同时保留完整的create_table_query。
- 响应结构:
tables:当前页的表对象数组。next_page_token:在过期前传回此一次性值以获取下一页,或当没有更多表时传回null。total_tables:匹配所提供过滤器的表的总数。
查询参数
通过可选的 params 对象将值与 SQL 分开传递:
{
"query": "SELECT {id:UInt32} AS id, {name:String} AS name",
"params": {"id": 13, "name": "O'Reilly"}
}
使用 ClickHouse 的 {name:Type} 占位符,无需加引号。保持左花括号、名称和冒号相邻,如 {id:UInt32} 所示。冒号后和类型内的空格受支持,如 {id: UInt32} 和 {amount:Decimal(18, 4)} 所示。为了兼容支持的驱动程序版本,名称应以字母或下划线开头,并且仅使用字母、数字和下划线。不支持 Python 风格的 %s 或 %(name)s 格式化以及驱动程序的 $name$ 原始二进制参数。仅使用 query 的调用仍然有效。省略 params、传递 null 或传递空对象会使查询保持未绑定状态。
参数值可以是 JSON 字符串、数字、布尔值、null 或数组,前提是它们与声明的 ClickHouse 类型匹配:
- 将
null与Nullable(...)类型一起使用。 - 将 JavaScript 安全范围之外的精确整数作为十进制字符串传递,例如
"18446744073709551615"与{id:UInt64}。日期、时间戳和精确小数也可以作为字符串与相应的 ClickHouse 类型一起传递。 - 将向量绑定为一个数组,例如
{vector:Array(Float32)}与"params": {"vector": [0.25, 0.5, 0.75]}。 - 数组中的空值取决于安装的驱动程序。它们适用于 clickhouse-connect 1.8.0,但在支持的最低版本 1.0.0 上会失败。
- JSON 列表和对象无法绑定到 ClickHouse
Tuple和Map类型。
缺失值和不兼容的类型会返回查询错误。当 params 非空时,带有许多未终止的 {name: 占位符开头的查询会被拒绝,包括注释或字符串字面量中类似占位符的文本。参数化查询使用与其他查询相同的写入保护、超时、取消和 JSON 结果编码。
参数值不会出现在 MCP 服务器的正常 SQL 日志消息中,但仍保留在 MCP 工具参数中,并可能出现在后端错误中。ClickHouse 26.3.20.7 在 system.query_log、system.processes 和 system.text_log 中将值替换到查询文本中。参数绑定不是隐私功能,也不会减少工具调用中发送的向量值数量。
运行前检查查询
run_query 也运行 DESCRIBE 和 EXPLAIN ESTIMATE。两者都是可选检查:当您需要查询的输出列和类型时使用 DESCRIBE,在可能代价高昂的 SELECT 之前使用 EXPLAIN ESTIMATE。
DESCRIBE (<query>) 检查结果模式,并返回与 DESCRIBE TABLE 相同的输出列元数据:
DESCRIBE (SELECT user, sum(amt) FROM events WHERE ts > now() - INTERVAL 30 DAY GROUP BY user)
user String
sum(amt) Decimal(38, 2)
ClickHouse 必须分析查询才能回答,因此分析错误会在此处显示,并带有 ClickHouse 自己的消息,而不是在执行过程中出现:
DESCRIBE (SELECT usr FROM events) -> Code: 47. Unknown expression identifier `usr` ... Maybe you meant: ['user']
DESCRIBE (SELECT * FROM nosuch) -> Code: 60. Unknown table expression identifier 'nosuch'
一个能干净描述的查询在运行时仍可能失败,例如内存限制或远程服务器错误,并且它不说明成本。
EXPLAIN ESTIMATE <query> 返回查询将读取的部分、行和标记,每个表一行,这正是区分主键查找和全表扫描的关键:
EXPLAIN ESTIMATE SELECT count() FROM events WHERE id = 42
database table parts rows marks
default events 1 8192 1
这些是来自 MergeTree 系列表的估计读取量,在主键和分区修剪之后。它们不是运行时间,也不是结果大小,并且不涵盖其他表引擎。
两个语句都不会运行查询主体,但分析并不总是免费的:DESCRIBE (SELECT (SELECT sleep(1))) 在分析时执行标量子查询。两者都是只读的,并在默认的 CLICKHOUSE_ALLOW_WRITE_ACCESS=false 下工作。请参阅 ClickHouse 文档了解 EXPLAIN ESTIMATE 和 DESCRIBE。
chDB 工具
run_chdb_select_query- 使用 chDB 的嵌入式 ClickHouse 引擎执行 SQL 查询。
- 输入:
query(字符串):要执行的 SQL 查询。 - 超出
[-9007199254740991, 9007199254740991]范围的整数以十进制字符串形式返回。 - 直接从各种来源(文件、URL、数据库)查询数据,无需 ETL 流程。
- 需要可选的
chdb附加组件:pip install 'mcp-clickhouse[chdb]'
健康检查端点
当使用 HTTP 或 SSE 传输时,健康检查端点位于 /health。此端点:
- 如果服务器健康且可以连接到 ClickHouse,则返回
200 OK(正文:OK) - 如果服务器无法连接到 ClickHouse,则返回带有通用错误消息的
503 Service Unavailable - 如果 ClickHouse 探测在两秒内未完成,则返回
503。并发请求共享一个进行中的探测 - 在一秒内重用已完成的探测结果,因此快速连续到达的探测不会各自连接到 ClickHouse。因此,失败或恢复可能最多延迟一秒报告
对该端点的 GET 和 HEAD 请求有意不进行身份验证,并且不受 Host 和 Origin 验证的限制,以便编排器探测(例如 Kubernetes 存活/就绪、负载均衡器)可以使用运行时分配的 Pod 或目标 IP,而无需额外配置。/health 被保留,不能用作 MCP 传输路径。响应正文有意保持最小化,以避免泄露后端版本字符串或错误详细信息;通过服务器日志调试失败。
示例:
curl http://localhost:8000/health
# Response: OK
安全性
HTTP/SSE 传输的身份验证
使用 HTTP 或 SSE 传输时,默认需要身份验证。stdio 传输(默认)不需要身份验证,因为它仅通过标准输入/输出进行通信。
支持三种身份验证模式。选择一种:
| 模式 | 使用时机 | 环境变量 |
|---|---|---|
| 静态 Bearer 令牌 | 简单部署、内部服务 | CLICKHOUSE_MCP_AUTH_TOKEN |
| OAuth / OIDC(通过 FastMCP) | Azure Entra、Google、GitHub、WorkOS 等。 | FASTMCP_SERVER_AUTH=<provider-class-path>(+ 特定于提供程序的 FASTMCP_SERVER_AUTH_* 变量) |
| 禁用 | 仅限本地开发 | CLICKHOUSE_MCP_AUTH_DISABLED=true |
如果 HTTP/SSE 传输未配置其中任何一种,启动将失败。
设置身份验证
-
生成一个安全令牌(可以是任何随机字符串):
# Using uuidgen (macOS/Linux) uuidgen # Using openssl openssl rand -hex 32 -
使用令牌配置服务器:
export CLICKHOUSE_MCP_AUTH_TOKEN="your-generated-token" -
配置您的 MCP 客户端以在请求中包含令牌:
对于使用 HTTP/SSE 传输的 Claude Desktop:
{ "mcpServers": { "mcp-clickhouse": { "url": "http://127.0.0.1:8000", "headers": { "Authorization": "Bearer your-generated-token" } } } }注意:
/health端点有意不进行身份验证(请参阅上面的健康检查端点)。要验证 Bearer 令牌身份验证确实拒绝未身份验证的请求,请直接访问 MCP 端点本身,例如使用 MCP Inspector,或向/mcp发送带和不带Authorization标头的 JSON-RPC POST 请求,并确认未身份验证的调用返回401。
通过 FastMCP 进行 OAuth / OIDC
对于使用身份提供商(Azure Entra、Google、GitHub、WorkOS 等)的生产部署,请将身份验证委托给 FastMCP 的内置身份验证提供商,而不是使用静态令牌。将 FASTMCP_SERVER_AUTH 设置为 FastMCP 身份验证提供商的完整类路径,以及特定于提供程序的 FASTMCP_SERVER_AUTH_* 变量,并保持 CLICKHOUSE_MCP_AUTH_TOKEN 未设置。
示例(Azure Entra):
export FASTMCP_SERVER_AUTH=fastmcp.server.auth.providers.azure.AzureProvider
export FASTMCP_SERVER_AUTH_AZURE_TENANT_ID="<tenant-id>"
export FASTMCP_SERVER_AUTH_AZURE_CLIENT_ID="<client-id>"
export FASTMCP_SERVER_AUTH_AZURE_CLIENT_SECRET="<client-secret>"
export FASTMCP_SERVER_AUTH_AZURE_BASE_URL="https://mcp.example.com"
export FASTMCP_SERVER_AUTH_AZURE_REQUIRED_SCOPES="read access_as_user"
mcp-clickhouse 为 FastMCP 4.0.0 内置提供商保留了这些 FastMCP 2.14.7 环境变量前缀:
| 提供商类路径 | 提供商变量前缀 |
|---|---|
fastmcp.server.auth.providers.auth0.Auth0Provider | FASTMCP_SERVER_AUTH_AUTH0_ |
fastmcp.server.auth.providers.aws.AWSCognitoProvider | FASTMCP_SERVER_AUTH_AWS_COGNITO_ |
fastmcp.server.auth.providers.azure.AzureProvider | FASTMCP_SERVER_AUTH_AZURE_ |
fastmcp.server.auth.providers.descope.DescopeProvider | FASTMCP_SERVER_AUTH_DESCOPEPROVIDER_ |
fastmcp.server.auth.providers.discord.DiscordProvider | FASTMCP_SERVER_AUTH_DISCORD_ |
fastmcp.server.auth.providers.github.GitHubProvider | FASTMCP_SERVER_AUTH_GITHUB_ |
fastmcp.server.auth.providers.google.GoogleProvider | FASTMCP_SERVER_AUTH_GOOGLE_ |
fastmcp.server.auth.providers.introspection.IntrospectionTokenVerifier | FASTMCP_SERVER_AUTH_INTROSPECTION_ |
fastmcp.server.auth.providers.jwt.JWTVerifier | FASTMCP_SERVER_AUTH_JWT_ |
fastmcp.server.auth.providers.oci.OCIProvider | FASTMCP_SERVER_AUTH_OCI_ |
fastmcp.server.auth.providers.scalekit.ScalekitProvider | FASTMCP_SERVER_AUTH_SCALEKITPROVIDER_ |
fastmcp.server.auth.providers.supabase.SupabaseProvider | FASTMCP_SERVER_AUTH_SUPABASE_ |
fastmcp.server.auth.providers.workos.WorkOSProvider | FASTMCP_SERVER_AUTH_WORKOS_ |
fastmcp.server.auth.providers.workos.AuthKitProvider | FASTMCP_SERVER_AUTH_AUTHKITPROVIDER_ |
将大写的提供商字段名称附加到前缀。请参阅 FastMCP 文档 了解每个提供商的配置要求。
直接在进程环境中设置的认证值会以不区分大小写的方式优先生效。
默认的 .env 加载从已安装的 mcp_clickhouse 包目录开始,
先解析符号链接,然后向上遍历到文件系统根目录。它加载找到的第一个
.env,如果没有找到则不加载任何内容。它从不读取工作
目录,无论服务器如何启动。源码检出通常会在
仓库根目录找到 .env。该文件也可能提供 FASTMCP_SERVER_AUTH 及其
提供者字段。其值优先于显式或兼容性认证
文件。
为了兼容 FastMCP 2,mcp-clickhouse 会从工作目录中的 .env
读取缺失的提供者字段,但该兼容性回退无法选择
FASTMCP_SERVER_AUTH。进程设置的 FASTMCP_ENV_FILE 会替换该兼容性
回退,并可能同时提供选择器和提供者字段。请在启动前设置它。
mcp-clickhouse 兼容性加载器仅从该文件读取 FASTMCP_SERVER_AUTH 和
FASTMCP_SERVER_AUTH_*,因此它无法注入 CLICKHOUSE_* 设置。
FastMCP 4 可能将同一文件用于其自身更广泛的设置。自定义提供者
不会收到任何环境派生的构造函数参数,并且必须支持无参数构造。
将发现的和工作目录中的 .env 文件都视为受信任的认证
配置。任何能够在从包目录到文件系统根目录的任何目录中创建或写入
.env 的人都可以控制发现哪个文件、选择
提供者并设置其字段。任何能够写入工作目录文件的人都可以控制
进程和已发现配置中缺失的每个提供者字段,包括签名密钥、
颁发者和端点以及客户端密钥。指向
操作员拥有文件的进程设置 FASTMCP_ENV_FILE 会禁用工作目录回退。
FastMCP 4 更改了默认的 OAuth 代理客户端存储。依赖 FastMCP 2 默认 OAuth 代理存储的部署必须让客户端重新注册并重新授权。 兼容的自定义存储、静态承载令牌和 JWT 验证不受影响。
开发模式(禁用认证)
仅用于本地开发和测试,您可以通过设置以下内容来禁用认证:
export CLICKHOUSE_MCP_AUTH_DISABLED=true
export CLICKHOUSE_MCP_ALLOWED_HOSTS=127.0.0.1:8000,localhost:8000
警告: 仅将此用于本地开发。当服务器暴露于任何网络时,请勿禁用认证。
配置
此 MCP 服务器同时支持 ClickHouse 和 chDB。您可以根据需要启用其中一个或两个。 支持 Python 3.10 至 3.14。本地启动推荐使用 Python 3.12。
-
打开位于以下位置的 Claude Desktop 配置文件:
- 在 macOS 上:
~/Library/Application Support/Claude/claude_desktop_config.json - 在 Windows 上:
%APPDATA%/Claude/claude_desktop_config.json
- 在 macOS 上:
-
添加以下内容:
{
"mcpServers": {
"mcp-clickhouse": {
"command": "uv",
"args": [
"run",
"--with",
"mcp-clickhouse",
"--python",
"3.12",
"mcp-clickhouse"
],
"env": {
"CLICKHOUSE_HOST": "<clickhouse-host>",
"CLICKHOUSE_PORT": "<clickhouse-port>",
"CLICKHOUSE_USER": "<clickhouse-user>",
"CLICKHOUSE_PASSWORD": "<clickhouse-password>",
"CLICKHOUSE_ROLE": "<clickhouse-role>",
"CLICKHOUSE_SECURE": "true",
"CLICKHOUSE_VERIFY": "true",
"CLICKHOUSE_CONNECT_TIMEOUT": "30"
}
}
}
}
更新环境变量以指向您自己的 ClickHouse 服务。
或者,如果您想通过 ClickHouse SQL Playground 试用,可以使用以下配置:
{
"mcpServers": {
"mcp-clickhouse": {
"command": "uv",
"args": [
"run",
"--with",
"mcp-clickhouse",
"--python",
"3.12",
"mcp-clickhouse"
],
"env": {
"CLICKHOUSE_HOST": "sql-clickhouse.clickhouse.com",
"CLICKHOUSE_PORT": "8443",
"CLICKHOUSE_USER": "demo",
"CLICKHOUSE_PASSWORD": "",
"CLICKHOUSE_SECURE": "true",
"CLICKHOUSE_VERIFY": "true",
"CLICKHOUSE_CONNECT_TIMEOUT": "30"
}
}
}
}
对于 chDB(嵌入式 ClickHouse 引擎),请添加以下配置:
{
"mcpServers": {
"mcp-clickhouse": {
"command": "uv",
"args": [
"run",
"--with",
"mcp-clickhouse[chdb]",
"--python",
"3.12",
"mcp-clickhouse"
],
"env": {
"CHDB_ENABLED": "true",
"CLICKHOUSE_ENABLED": "false",
"CHDB_DATA_PATH": "/path/to/chdb/data"
}
}
}
}
您还可以同时启用 ClickHouse 和 chDB:
{
"mcpServers": {
"mcp-clickhouse": {
"command": "uv",
"args": [
"run",
"--with",
"mcp-clickhouse[chdb]",
"--python",
"3.12",
"mcp-clickhouse"
],
"env": {
"CLICKHOUSE_HOST": "<clickhouse-host>",
"CLICKHOUSE_PORT": "<clickhouse-port>",
"CLICKHOUSE_USER": "<clickhouse-user>",
"CLICKHOUSE_PASSWORD": "<clickhouse-password>",
"CLICKHOUSE_SECURE": "true",
"CLICKHOUSE_VERIFY": "true",
"CLICKHOUSE_CONNECT_TIMEOUT": "30",
"CHDB_ENABLED": "true",
"CHDB_DATA_PATH": "/path/to/chdb/data"
}
}
}
}
-
找到
uv的命令条目,并将其替换为uv可执行文件的绝对路径。这可以确保在启动服务器时使用正确版本的uv。在 Mac 上,您可以使用which uv找到此路径。 -
重启 Claude Desktop 以应用更改。
可选写入访问
默认情况下,此 MCP 强制只读查询,以防止在探索期间发生意外修改。要允许 DDL 或 INSERT 语句,请将 CLICKHOUSE_ALLOW_WRITE_ACCESS 环境变量设置为 true。如果 ClickHouse 实例本身禁止写入,服务器将继续强制只读模式。
破坏性操作保护
即使启用了写入访问(CLICKHOUSE_ALLOW_WRITE_ACCESS=true),破坏性操作也需要额外的选择加入标志以确保安全。该检查涵盖任何 DROP 语句(包括 ALTER TABLE ... DROP PARTITION / DROP PART / DROP COLUMN 子句)、任何 TRUNCATE、DELETE 和 UPDATE(轻量级语句和 ALTER TABLE ... DELETE / ALTER TABLE ... UPDATE 变更)、REPLACE TABLE、CREATE OR REPLACE、ALTER TABLE ... REPLACE PARTITION、ALTER TABLE ... CLEAR COLUMN / CLEAR INDEX / CLEAR PROJECTION 以及 DETACH ... PERMANENTLY。字符串字面量、带引号的标识符、SQL 注释和 {name:Type} 参数名称中的关键字将被忽略,因此它们既不会触发检查,也不会对检查隐藏语句。
此检查在 MCP 服务器中运行,是对意外事故的尽力防护。它不是安全边界。安全边界是 ClickHouse 用户的授权。只读模式(默认)通过 readonly=1 在服务器端强制执行。破坏性操作门控并非服务器端强制。
对于写入模式,请为 MCP 服务器提供一个专用的 ClickHouse 用户,仅授予其所需的权限:
CREATE USER mcp_agent IDENTIFIED BY '...';
GRANT SELECT, INSERT, CREATE TABLE, ALTER ADD COLUMN ON mydb.* TO mcp_agent;
这些授权之外的每条语句都会在服务器端以 ACCESS_DENIED 失败,无论 MCP 标志如何。服务器设置 max_table_size_to_drop 和 max_partition_size_to_drop 如果通过设置约束固定,也可以限制爆炸半径。
要启用破坏性操作,请设置两个标志:
"env": {
"CLICKHOUSE_ALLOW_WRITE_ACCESS": "true",
"CLICKHOUSE_ALLOW_DROP": "true"
}
这种两层方法使意外删除变得困难:
- 写入操作(INSERT、CREATE、ALTER ADD COLUMN)需要
CLICKHOUSE_ALLOW_WRITE_ACCESS=true - 破坏性操作(DROP、TRUNCATE、DELETE、UPDATE 以及上述列表中的其余操作)额外需要
CLICKHOUSE_ALLOW_DROP=true
不使用 uv 运行(使用系统 Python)
如果您希望使用系统 Python 安装而不是 uv,您可以从 PyPI 安装该包并直接运行:
-
使用 pip 安装包:
python3 -m pip install mcp-clickhouse要同时安装 chDB 支持:
python3 -m pip install 'mcp-clickhouse[chdb]'要升级到最新版本:
python3 -m pip install --upgrade mcp-clickhouse -
更新您的 Claude Desktop 配置以直接使用 Python:
{
"mcpServers": {
"mcp-clickhouse": {
"command": "python3",
"args": [
"-m",
"mcp_clickhouse.main"
],
"env": {
"CLICKHOUSE_HOST": "<clickhouse-host>",
"CLICKHOUSE_PORT": "<clickhouse-port>",
"CLICKHOUSE_USER": "<clickhouse-user>",
"CLICKHOUSE_PASSWORD": "<clickhouse-password>",
"CLICKHOUSE_SECURE": "true",
"CLICKHOUSE_VERIFY": "true",
"CLICKHOUSE_CONNECT_TIMEOUT": "30"
}
}
}
}
或者,您可以直接使用已安装的脚本:
{
"mcpServers": {
"mcp-clickhouse": {
"command": "mcp-clickhouse",
"env": {
"CLICKHOUSE_HOST": "<clickhouse-host>",
"CLICKHOUSE_PORT": "<clickhouse-port>",
"CLICKHOUSE_USER": "<clickhouse-user>",
"CLICKHOUSE_PASSWORD": "<clickhouse-password>",
"CLICKHOUSE_SECURE": "true",
"CLICKHOUSE_VERIFY": "true",
"CLICKHOUSE_CONNECT_TIMEOUT": "30"
}
}
}
}
注意:如果 Python 可执行文件或 mcp-clickhouse 脚本不在系统 PATH 中,请确保使用其完整路径。您可以使用以下命令查找路径:
which python3用于 Python 可执行文件which mcp-clickhouse用于已安装的脚本
自定义中间件
您可以在不修改源代码的情况下向 MCP 服务器添加自定义中间件。FastMCP 提供了一套中间件系统,允许您拦截和处理 MCP 协议消息(工具调用、资源读取、提示等)。
使用方法
- 创建一个 Python 模块,其中包含扩展
Middleware的中间件类和一个setup_middleware(mcp)函数:
# my_middleware.py
import logging
from fastmcp.server.middleware import Middleware, MiddlewareContext, CallNext
logger = logging.getLogger("my-middleware")
class LoggingMiddleware(Middleware):
"""Log all tool calls."""
async def on_call_tool(self, context: MiddlewareContext, call_next: CallNext):
tool_name = context.message.name if hasattr(context.message, 'name') else 'unknown'
logger.info(f"Calling tool: {tool_name}")
result = await call_next(context)
logger.info(f"Tool {tool_name} completed")
return result
def setup_middleware(mcp):
"""Register middleware with the MCP server."""
mcp.add_middleware(LoggingMiddleware())
- 将
MCP_MIDDLEWARE_MODULE环境变量设置为模块名称(不带.py扩展名):
{
"mcpServers": {
"mcp-clickhouse": {
"command": "uv",
"args": ["run", "--with", "mcp-clickhouse", "--python", "3.12", "mcp-clickhouse"],
"env": {
"CLICKHOUSE_HOST": "<clickhouse-host>",
"CLICKHOUSE_USER": "<clickhouse-user>",
"CLICKHOUSE_PASSWORD": "<clickhouse-password>",
"MCP_MIDDLEWARE_MODULE": "my_middleware"
}
}
}
}
- 确保您的中间件模块位于 Python 的导入路径中(例如,与 MCP 服务器运行的目录相同,或作为包安装)。
中间件示例
在 example_middleware.py 中提供了一个示例中间件模块,展示了常见模式:
- 记录所有 MCP 请求
- 专门记录工具调用
- 测量请求处理时间
要使用该示例:
"env": {
"MCP_MIDDLEWARE_MODULE": "example_middleware"
}
中间件能力
Middleware 基类为不同的 MCP 操作提供了钩子:
on_message(context, call_next)- 为所有消息调用on_request(context, call_next)- 为所有请求调用on_notification(context, call_next)- 为所有通知调用on_call_tool(context, call_next)- 当工具被执行时调用on_read_resource(context, call_next)- 当资源被读取时调用on_get_prompt(context, call_next)- 当提示被检索时调用on_list_tools(context, call_next)- 当列出工具时调用on_list_resources(context, call_next)- 当列出资源时调用on_list_resource_templates(context, call_next)- 当列出资源模板时调用on_list_prompts(context, call_next)- 当列出提示时调用
每个钩子接收一个包含消息和元数据的 MiddlewareContext 对象,以及一个用于继续管道的 call_next 函数。
通过上下文状态进行动态客户端配置
中间件可以使用 CLIENT_CONFIG_OVERRIDES_KEY 上下文状态键,按请求覆盖 ClickHouse 客户端配置。服务器会将这些覆盖与环境变量中的基本配置合并。
from fastmcp.server.dependencies import get_context
from fastmcp.server.middleware import CallNext, Middleware, MiddlewareContext
from mcp_clickhouse.mcp_server import CLIENT_CONFIG_OVERRIDES_KEY
class ClientConfigMiddleware(Middleware):
async def on_call_tool(self, context: MiddlewareContext, call_next: CallNext):
ctx = get_context()
await ctx.set_state(
CLIENT_CONFIG_OVERRIDES_KEY,
{
"connect_timeout": 60,
"send_receive_timeout": 120,
},
serializable=False,
)
return await call_next(context)
这支持高级用例,如动态超时调整、租户特定路由或按用户连接设置。
状态值必须是字典。嵌套的 settings 和 generic_args 值必须是
映射,并与基本配置合并。无效值会在创建 ClickHouse
客户端之前使工具调用失败。除非覆盖显式提供
settings.role,否则 CLICKHOUSE_ROLE 保持有效。顶层 role 和 ch_role 键,以及
generic_args 下的相同键,将被拒绝。
仅将 verify、ca_cert、client_cert、client_cert_key、tls_mode、server_host_name、
和 pool_mgr 设置为顶层覆盖。它们不能嵌套在 generic_args 下。自定义
pool_mgr 不能与托管的 CA 或客户端证书设置组合。DSN 查询
参数不能设置这些键,DSN 也不能选择 chdb 后端。使用显式的
顶层 host、port、username、password、database 和 secure 覆盖来更改
连接。转发的 DSN 不会替换已填充的基本连接字段或选择
TLS。它可以填充空字段并提供支持的查询参数,如 query_limit。
secure 和 verify 覆盖接受布尔值或字符串 true 和 false。
verify 也接受 proxy,当 tls_mode 未设置时,其行为类似于
tls_mode: proxy,因此使用环境密码进行基本认证。secure 覆盖选择匹配的 https 或 http 接口,并且
不更改端口。显式的 interface 覆盖必须是 http 或 https,并且与
secure 一致。合并覆盖后,默认和 mutual 客户端证书模式会省略
密码。proxy 和 strict 模式使用环境密码进行基本认证,
除非覆盖提供自己的凭据。
将这些覆盖视为受信任的中间件输入。中间件必须在设置
请求派生值之前对其进行认证和授权。使用 serializable=False 以便 FastMCP 将
值保持在请求本地状态。默认的 serializable=True 存储会话状态,并且
会被服务器拒绝。服务器在分派阻塞数据库
工作之前会快照该值。不要将会话作用域的 Context 状态中的租户数据存储。被拒绝的会话作用域
覆盖仍会附加到旧版 MCP 会话,并导致该会话中的后续工具调用
失败,直到客户端重新连接。按请求的 ClickHouse 角色是连接配置,
不是租户授权边界。使用 ClickHouse 用户、角色
和授权来强制租户隔离。
开发
-
在
test-services目录中运行docker compose up -d以启动 ClickHouse 集群。 -
在仓库根目录的
.env文件中添加以下变量。
注意:在此上下文中使用 default 用户仅用于本地开发目的。
CLICKHOUSE_HOST=localhost
CLICKHOUSE_PORT=8123
CLICKHOUSE_USER=default
CLICKHOUSE_PASSWORD=clickhouse
-
运行
uv sync以安装依赖项。要安装uv,请按照 此处 的说明操作。然后执行source .venv/bin/activate。 -
为了便于使用 MCP Inspector 进行测试,请运行
uv run fastmcp dev inspector mcp_clickhouse/mcp_server.py:mcp以启动 MCP 服务器。 -
要使用 HTTP 传输和健康检查端点进行测试:
# For development, disable authentication CLICKHOUSE_MCP_SERVER_TRANSPORT=http CLICKHOUSE_MCP_AUTH_DISABLED=true CLICKHOUSE_MCP_ALLOWED_HOSTS=127.0.0.1:8000,localhost:8000 python -m mcp_clickhouse.main # Or with authentication (generate a token first) CLICKHOUSE_MCP_SERVER_TRANSPORT=http CLICKHOUSE_MCP_AUTH_TOKEN="your-token" python -m mcp_clickhouse.main # Then in another terminal: curl http://localhost:8000/health
环境变量
配置被拆分为相互独立的组。将它们混用是导致难以排查的连接失败的常见原因:
| 组 | 变量 | 控制内容 |
|---|---|---|
| ClickHouse 数据库连接 | CLICKHOUSE_HOST、CLICKHOUSE_PORT、CLICKHOUSE_SECURE、CLICKHOUSE_VERIFY、证书变量 | 此 MCP 服务器如何通过 HTTP 接口连接到您的 ClickHouse 集群 |
| MCP 服务器 / 传输 | CLICKHOUSE_MCP_*、FASTMCP_SERVER_AUTH、FASTMCP_SERVER_AUTH_*、FASTMCP_ENV_FILE | MCP 传输、身份验证和查询工具执行限制 |
| 中间件 / chDB | MCP_MIDDLEWARE_MODULE、CHDB_* | 可选扩展 |
[!IMPORTANT]
CLICKHOUSE_SECURE、CLICKHOUSE_VERIFY、CLICKHOUSE_CA_CERT、CLICKHOUSE_CLIENT_CERT、CLICKHOUSE_CLIENT_CERT_KEY、CLICKHOUSE_TLS_MODE和CLICKHOUSE_PORT仅适用于出站的 ClickHouse 数据库连接。它们不配置入站 MCP HTTP/SSE 端点的 TLS、客户端证书、端口或身份验证。示例:如果 MCP 服务器在 Kubernetes 中运行,且位于终止 TLS 的 ingress 之后,这属于 MCP 传输层面的问题。保持
CLICKHOUSE_SECURE与 Pod 访问 ClickHouse 本身的方式一致(HTTPS →true,纯 HTTP →false)。因为 MCP 服务器位于 ingress 之后而设置CLICKHOUSE_SECURE=false,会导致服务器通过 HTTP 拨号 ClickHouse——通常指向仅支持 HTTPS 的端口——并在服务器日志中产生难以理解的 HTTP/TLS 错误。
ClickHouse 数据库连接
这些变量配置 clickhouse-connect HTTP 客户端以及 ClickHouse 相关工具(如 run_query、list_databases 和 list_tables)的行为。
mcp-clickhouse 需要 clickhouse-connect 1.x,从 1.0.0 开始。
必需变量
CLICKHOUSE_HOST:您的 ClickHouse 服务器的主机名(数据库端点,而非 MCP 服务器绑定地址)CLICKHOUSE_USER:用于 ClickHouse 身份验证的用户名CLICKHOUSE_PASSWORD:用于 ClickHouse 身份验证的密码- 除非
CLICKHOUSE_CLIENT_CERT使用默认值或"mutual"TLS 模式,否则为必填项 - 在默认或
"mutual"模式下,使用证书身份验证,不发送密码
- 除非
[!CAUTION] 务必将您的 MCP 数据库用户视为任何连接到数据库的外部客户端,仅授予其运行所需的最低必要权限。应始终严格避免使用默认用户或管理员用户。
可选变量
CLICKHOUSE_PORT:您的 ClickHouse 服务器的 HTTP 接口端口- 默认值:
8443(如果CLICKHOUSE_SECURE=true),8123(如果CLICKHOUSE_SECURE=false) - 除非使用非标准端口,否则通常无需设置
- 必须是 HTTP 接口端口,而非
clickhouse-client使用的原生 TCP 协议端口 - 常见值:
- HTTP:
8123(明文)/8443(TLS)——此服务器和 ClickHouse Cloud HTTPS 使用 - 原生 TCP(此处不支持):
9000(明文)/9440(TLS)——clickhouse-client使用
- HTTP:
- 如果服务器响应
Port 9000 is for clickhouse-client program,说明您指向的是原生协议;请切换到 HTTP 端口(8123/8443或您部署的 HTTP 映射)
- 默认值:
CLICKHOUSE_ROLE:用于身份验证的 ClickHouse 角色- 默认值:无
- 如果您的用户需要特定角色,请设置此项
CLICKHOUSE_SECURE:为 ClickHouse 数据库连接启用 HTTPS(而非为 MCP 客户端)- 默认值:
"true" - 仅当 MCP 服务器通过纯 HTTP 访问 ClickHouse 时(典型的本地 Docker Compose 端口为
8123),设置为"false" - 对于 ClickHouse Cloud 和任何 HTTPS 数据库端点,保持
"true"——即使 MCP 服务器本身通过 HTTP、stdio 或单独终止 TLS 的 ingress 暴露 - 此标志与数据库端口不匹配(例如端口
8443上使用CLICKHOUSE_SECURE=false)是常见的配置错误,通常表现为令人困惑的 HTTP 客户端错误,而非清晰的“协议不匹配”消息
- 默认值:
CLICKHOUSE_VERIFY:为 ClickHouse HTTPS 连接启用/禁用 SSL 证书验证- 默认值:
"true" - 设置为
"false"以禁用证书验证(不建议用于生产环境) - TLS 证书:包在启动时通过
truststore.inject_into_ssl()使用操作系统的信任库。如果通过MCP_CLICKHOUSE_TRUSTSTORE_DISABLE=1禁用注入或注入失败,则使用 Python 的默认 SSL 处理。
- 默认值:
MCP_CLICKHOUSE_TRUSTSTORE_DISABLE:禁用进程级操作系统信任库集成以用于 TLS- 默认值:未设置(信任库集成已启用)
- 在启动前设置为恰好
"1"以跳过truststore.inject_into_ssl()并使用 Python 的默认 SSL 证书处理。其他值不会禁用该集成。 - 这不会禁用证书验证。
CLICKHOUSE_VERIFY仍控制 ClickHouse HTTPS 连接的验证。
CLICKHOUSE_CA_CERT:用于 ClickHouse HTTPS 连接的 PEM CA 证书捆绑包路径- 默认值:无(使用操作系统信任库,除非信任库注入被禁用或失败)
- 当 ClickHouse 服务器或私有代理提供由私有 CA 签名的证书时,单独使用此项。这会更改服务器证书验证,且不会启用客户端证书身份验证。
- 需要
CLICKHOUSE_SECURE=true和CLICKHOUSE_VERIFY=true
CLICKHOUSE_CLIENT_CERT:用于 ClickHouse HTTPS 连接的 PEM 客户端证书路径- 默认值:无
- 该文件也可能包含私钥。否则请设置
CLICKHOUSE_CLIENT_CERT_KEY。 - ClickHouse 用户仍来自
CLICKHOUSE_USER。
CLICKHOUSE_CLIENT_CERT_KEY:CLICKHOUSE_CLIENT_CERT的 PEM 私钥路径- 默认值:无
- 当私钥包含在客户端证书文件中时,此项为可选项
- 不能在没有
CLICKHOUSE_CLIENT_CERT的情况下使用
CLICKHOUSE_TLS_MODE:clickhouse-connect 如何使用CLICKHOUSE_CLIENT_CERT- 默认值:无,当设置了客户端证书时行为等同于
"mutual" "mutual":使用客户端证书进行 ClickHouse X.509 用户身份验证。CLICKHOUSE_PASSWORD为可选项,不会发送。"proxy":向 TLS 终止代理呈现客户端证书,然后使用 ClickHouse Basic 身份验证。CLICKHOUSE_PASSWORD为必填项。"strict":因为 ClickHouse 服务器在 TLS 层要求客户端证书而呈现该证书,然后使用 ClickHouse Basic 身份验证。CLICKHOUSE_PASSWORD为必填项。此模式不会加强服务器证书验证。CLICKHOUSE_VERIFY控制该验证。- clickhouse-connect 将
"proxy"和"strict"视为相同。这两个名称用于说明意图。 - 值会被去除首尾空格且不区分大小写。空白值视为未设置。其他值会在创建 ClickHouse 客户端之前被拒绝,即在首次 ClickHouse 工具调用或
/health探测时。 - 需要
CLICKHOUSE_CLIENT_CERT。所有客户端证书选项都需要CLICKHOUSE_SECURE=true。
- 默认值:无,当设置了客户端证书时行为等同于
CLICKHOUSE_SERVER_HOST_NAME:用于 ClickHouse 连接的 SNI 覆盖和证书验证的服务器主机名- 默认值:无(使用连接主机名)
- 当通过代理或负载均衡器连接且证书主机名与连接主机名不同时,此选项非常有用。设置后,该主机名将同时用于 TLS 握手期间的 SNI(服务器名称指示)和证书主机名验证。
CLICKHOUSE_PROXY_PATH:ClickHouse HTTP 端点的 URL 路径前缀- 默认值:无
- 当 ClickHouse HTTP 接口通过反向代理在路径前缀下暴露时设置此项(例如
/clickhouse)
CLICKHOUSE_CONNECT_TIMEOUT:ClickHouse 客户端的连接超时时间(秒)- 默认值:
"30" - 如果遇到连接超时,请增大此值
- 默认值:
CLICKHOUSE_SEND_RECEIVE_TIMEOUT:ClickHouse 客户端的发送/接收超时时间(秒)- 默认值:
300或CLICKHOUSE_MCP_QUERY_TIMEOUT + 5中的较小值,以便工作线程在查询超时后不久解除阻塞 - 如果显式设置,则按原样使用该值(例如长时间运行的查询使用
"300")
- 默认值:
CLICKHOUSE_DATABASE:默认使用的 ClickHouse 数据库- 默认值:无(使用服务器默认值)
- 设置此项以自动连接到特定数据库
CLICKHOUSE_ENABLED:启用/禁用 ClickHouse 数据库工具- 默认值:
"true" - 仅使用 chDB 时,设置为
"false"以禁用 ClickHouse 工具
- 默认值:
CLICKHOUSE_ALLOW_WRITE_ACCESS:允许对 ClickHouse 执行写操作(DDL 和 DML)- 默认值:
"false" - 设置为
"true"以允许非破坏性 DDL 和 DML(CREATE、INSERT、ALTER ADD COLUMN)。破坏性语句还需要CLICKHOUSE_ALLOW_DROP=true - 禁用时(默认),查询以
readonly=1设置运行以防止数据修改
- 默认值:
CLICKHOUSE_ALLOW_DROP:允许破坏性操作(任何DROP或TRUNCATE、DELETE和UPDATE(包括ALTER TABLE变体)、REPLACE TABLE/REPLACE PARTITION/CREATE OR REPLACE、CLEAR COLUMN/CLEAR INDEX/CLEAR PROJECTION以及DETACH ... PERMANENTLY)- 默认值:
"false" - 仅在同时设置
CLICKHOUSE_ALLOW_WRITE_ACCESS=true时生效 - 此门控是 MCP 服务器中尽力而为的事故防护,而非安全边界。请限制 ClickHouse 用户的授权以实现真正的强制(参见 破坏性操作保护)
- 默认值:
ClickHouse TLS 证书文件
证书变量包含文件路径,而非 PEM 内容。mcp-clickhouse 将这些路径传递给 clickhouse-connect。对于 Docker 或 Kubernetes,请将证书和私钥挂载为只读文件,并使用容器内的路径。不要将私钥烘焙到镜像中、提交到源代码控制中,或将其内容放入环境变量。
在 mutual 模式下,配置的客户端证书将此 mcp-clickhouse 进程标识为 CLICKHOUSE_USER。它不会对入站 MCP 客户端进行身份验证,也不会将其身份传递给 ClickHouse。请单独配置 MCP 传输身份验证。
当需要立即轮换或撤销时,请在替换同一路径下的证书或密钥后重启 mcp-clickhouse。缓存的客户端可能保留现有的 TLS 连接,且缓存不会跟踪文件内容或修改时间。
ClickHouse Cloud 不支持数据库用户的 X.509 客户端证书身份验证。请对 ClickHouse Cloud 使用 CLICKHOUSE_USER 和 CLICKHOUSE_PASSWORD。当端点前的私有代理提供由私有 CA 签名的证书时,CA 证书仍然有用。
MCP 服务器和传输
这些变量控制 MCP 进程本身,包括传输、身份验证和查询工具执行限制。它们与上述 ClickHouse 数据库设置相互独立。另请参阅 HTTP/SSE 传输的身份验证。
CLICKHOUSE_MCP_SERVER_TRANSPORT:设置 MCP 服务器的传输方式- 默认值:
"stdio" - 有效选项:
"stdio"、"http"、"sse"。这对使用 MCP Inspector 等工具进行本地开发很有用。 stdio是 Claude Desktop 的典型选择;http/sse会暴露网络监听(绑定下面的主机和端口)"sse"选择已弃用的独立 HTTP+SSE 传输并记录警告。新部署请使用"http"进行 Streamable HTTP。
- 默认值:
CLICKHOUSE_MCP_BIND_HOST:使用 HTTP 或 SSE 传输时 MCP 服务器绑定的主机- 默认值:
"127.0.0.1" - 设置为
"0.0.0.0"以绑定所有网络接口(适用于 Docker 或远程访问) - 仅在传输方式为
"http"或"sse"时使用——与CLICKHOUSE_HOST无关
- 默认值:
CLICKHOUSE_MCP_BIND_PORT:使用 HTTP 或 SSE 传输时 MCP 服务器绑定的端口- 默认值:
"8000" - 仅在传输方式为
"http"或"sse"时使用——与CLICKHOUSE_PORT无关
- 默认值:
CLICKHOUSE_MCP_QUERY_TIMEOUT:查询工具调用的超时时间(秒)- 默认值:
"30" - 如果重查询出现
Query timed out after ...错误,请增大此值 - 查询超时时,服务器会尝试使用
KILL QUERY取消它 - 除非显式设置
CLICKHOUSE_SEND_RECEIVE_TIMEOUT,否则 HTTP 读取超时上限为此值加五秒
- 默认值:
CLICKHOUSE_MCP_MAX_WORKERS:最大并发查询工作线程数- 默认值:
"10" - 如果工作负载需要大量并发工具调用,请增大此值
- 元数据工具使用单独的线程池,包含
min(4, CLICKHOUSE_MCP_MAX_WORKERS)个线程,因此模式发现不会延迟查询
- 默认值:
CLICKHOUSE_MCP_AUTH_TOKEN:HTTP/SSE 传输的静态 Bearer 令牌- 默认值:无
CLICKHOUSE_MCP_AUTH_TOKEN、FASTMCP_SERVER_AUTH或CLICKHOUSE_MCP_AUTH_DISABLED=true之一是 HTTP/SSE 传输必需的- 使用
uuidgen或openssl rand -hex 32生成 - 客户端必须在
Authorization: Bearer <token>头中发送此令牌
FASTMCP_SERVER_AUTH:将身份验证委托给 FastMCP 认证提供程序- 默认值:无
- 值是 AuthProvider 子类的完整类路径,例如
fastmcp.server.auth.providers.azure.AzureProvider或fastmcp.server.auth.providers.google.GoogleProvider - 设置后,mcp-clickhouse 从现有的
FASTMCP_SERVER_AUTH_*环境变量加载提供程序;此模式下请将CLICKHOUSE_MCP_AUTH_TOKEN留空 - 自定义提供程序不接收环境派生的构造函数参数,必须支持无参数构造
- FastMCP 4 不再支持 Supabase HS256 验证。Supabase 部署必须使用 RS256 或 ES256。
FASTMCP_ENV_FILE:包含FASTMCP_SERVER_AUTH和提供程序特定环境变量的可选文件- 默认值:无。未设置时,兼容性加载器从工作目录中的
.env读取缺失的提供程序字段。它不会从该回退文件读取FASTMCP_SERVER_AUTH - 在启动前于进程环境中设置它。从默认
.env加载的值无法重定向兼容性加载器 - 如果由进程设置,此文件可同时提供
FASTMCP_SERVER_AUTH和提供程序字段,并替换工作目录回退 - 进程环境值不区分大小写地优先
- mcp-clickhouse 兼容性加载器仅在构建 HTTP/SSE 身份验证时读取此文件,且仅读取
FASTMCP_SERVER_AUTH和FASTMCP_SERVER_AUTH_*条目。FastMCP 4 可能读取同一文件以获取更广泛的设置 - 默认的
.env加载是独立的。它从已安装的mcp_clickhouse包目录开始,解析符号链接,向上遍历到文件系统根目录,并加载找到的第一个.env或什么都不加载。它从不读取工作目录,无论启动方式如何。该文件可提供FASTMCP_SERVER_AUTH和提供程序字段以及其他服务器设置。源码检出通常会在仓库根目录找到.env
- 默认值:无。未设置时,兼容性加载器从工作目录中的
CLICKHOUSE_MCP_AUTH_DISABLED:禁用 HTTP/SSE 传输的身份验证- 默认值:
"false"(身份验证已启用) - 设置为
"true"以仅用于本地开发/测试时禁用身份验证 - 警告: 仅用于本地开发。暴露到网络时请勿禁用
- 默认值:
CLICKHOUSE_MCP_ALLOWED_HOSTS:HTTP/SSE 服务器响应的逗号分隔的Host头值- 回环绑定的默认值:
127.0.0.1、localhost和[::1]的裸形式和任意端口形式 - 如果设置,值必须至少包含一个 Host 条目。
- 具体的非回环绑定地址默认为该地址和配置的端口。通配符绑定(如
0.0.0.0或::)需要显式的非空值,因为无法推断公共 Host。 - Host 验证是针对 DNS 重绑定的纵深防御。下面的 Origin 验证由 MCP 单独要求。
- 条目是精确的(
localhost:8000)或接受任意端口(localhost:*)。示例:CLICKHOUSE_MCP_ALLOWED_HOSTS=127.0.0.1:8000,localhost:8000 host:*形式仅匹配带端口的值。无端口的 Host(客户端省略:80/:443的标准端口部署)也必须列为裸精确条目(example.com)。- 带有不匹配或缺失
Host头的请求会收到421 Misdirected Request。对/health的 GET 和 HEAD 请求豁免 Host 和 Origin 验证,以便编排器探针继续工作。 - 在反向代理后面,最好保留原始
Host头。您也可以列出代理发送的上游Host值。当启动器(如fastmcp run)为远程访问覆盖绑定地址时,请设置显式列表。 - mcp-clickhouse 强制关闭 FastMCP 的独立 Host 和 Origin 防护。
FASTMCP_HTTP_HOST_ORIGIN_PROTECTION、FASTMCP_HTTP_ALLOWED_HOSTS和FASTMCP_HTTP_ALLOWED_ORIGINS不适用。CLICKHOUSE_MCP_ALLOWED_HOSTS和CLICKHOUSE_MCP_ALLOWED_ORIGINS是权威的。
- 回环绑定的默认值:
CLICKHOUSE_MCP_TRUSTED_PROXIES:其X-Forwarded-*头受信任的代理 IP 地址或 CIDR 网络- 默认值:无。
X-Forwarded-Host被忽略。Uvicorn 对X-Forwarded-For和X-Forwarded-Proto的现有处理不变。 - 条目必须是 IP 地址或 CIDR 网络,例如
127.0.0.1,10.20.0.0/24,2001:db8::1。CIDR 必须使用其网络地址,因此10.20.0.1/24被拒绝。主机名、带作用域的 IPv6 地址、*、0.0.0.0/0和::/0也被拒绝。 - 信任基于直接的原始套接字对端。来自任何其他对端的请求,或没有客户端地址的请求,会忽略
X-Forwarded-Host并验证Host。 - 受信任的对端可以发送恰好一个包含一个非空值的
X-Forwarded-Host头。重复字段、空值和逗号分隔列表会收到421 Misdirected Request。如果头缺失,则验证Host。 - 使用尽可能窄的地址或网络。MCP 服务器必须只能通过配置范围内的代理访问。每个受信任的代理必须剥离并覆盖客户端提供的
X-Forwarded-Host和X-Forwarded-Proto值,并从已验证的连接对端构造X-Forwarded-For。 - 内置服务器和
fastmcp run禁用 Uvicorn 的外部代理头处理,从原始对端验证 Host,然后应用X-Forwarded-For和X-Forwarded-Proto。在此模式下显式启用uvicorn_config["proxy_headers"]会导致启动失败。 - 直接 ASGI 嵌入必须禁用外部 ASGI 服务器中的代理头处理,并调用
mcp.http_app(raw_client_address_preserved=True)。没有该显式断言,配置受信任代理时应用构造会失败。
- 默认值:无。
CLICKHOUSE_MCP_ALLOWED_ORIGINS:HTTP/SSE 上接受的逗号分隔的Origin头值- 默认值:无,这会拒绝每个携带
Origin头的请求 - MCP 要求对 HTTP/SSE 传输连接进行 Origin 验证。没有 Origin 的请求会被接受,因为非浏览器 MCP 客户端通常省略它。不匹配的 Origin 会收到
403 Forbidden。如上所述,/health端点豁免。 - 条目是精确的(
http://localhost:3000)或接受任意端口(http://localhost:*)。与主机一样,任意端口形式仅匹配带端口的 Origin;标准端口 Origin(https://app.example.com)必须精确列出。
- 默认值:无,这会拒绝每个携带
反向代理 Host 处理
尽可能保留 Host。这保持转发的 Host 信任禁用:
location / {
proxy_pass http://mcp-clickhouse:8000;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host "";
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
}
独立于 X-Forwarded-Host 信任清理 X-Forwarded-For 和 X-Forwarded-Proto。即使 CLICKHOUSE_MCP_TRUSTED_PROXIES 未设置,Uvicorn 也可能基于代理对端信任这些头。
CLICKHOUSE_MCP_ALLOWED_HOSTS=mcp.example.com
标准 nginx 会将代理请求的 Host 更改为上游名称。它不会创建或覆盖 X-Forwarded-Host。如果无法保留 Host,请在受信任的边缘覆盖转发的头:
location / {
proxy_pass http://mcp-clickhouse:8000;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
}
CLICKHOUSE_MCP_ALLOWED_HOSTS=mcp.example.com
CLICKHOUSE_MCP_TRUSTED_PROXIES=10.20.0.8
第二个配置仅在 10.20.0.8 是代理的直接源地址、服务器端口与其他客户端隔离、且 nginx 按所示覆盖传入的转发头时才是安全的。对于代理链,每个受信任的跳必须在构造新的转发头之前丢弃未验证的传入值。
在 IPv6 或双栈绑定上,IPv4 代理可能显示为 IPv4 映射地址(如 ::ffff:10.20.0.8);这些会自动与 IPv4 条目匹配。Envoy 的 append_x_forwarded_host 会追加到现有 X-Forwarded-Host 而不是覆盖它,产生被拒绝的逗号分隔列表,因此请配置受信任的跳以覆盖头。在启用源 NAT 的 Kubernetes 上(例如 externalTrafficPolicy: Cluster),观察到的对端可能是节点 IP 而不是代理 Pod,因此请酌情信任 Pod 或节点 CIDR;ingress-nginx 会自行覆盖 Host 和 X-Forwarded-Host。
中间件变量
MCP_MIDDLEWARE_MODULE:包含要注入 MCP 服务器的自定义中间件的 Python 模块名称- 默认值:无(不加载中间件)
- 设置为中间件模块的模块名称(不带
.py扩展名) - 模块必须提供
setup_middleware(mcp)函数 - 有关详细信息和示例,请参阅 自定义中间件
chDB 变量
CHDB_ENABLED:启用/禁用 chDB 功能- 默认值:
"false" - 设置为
"true"以启用 chDB 工具 - 需要安装可选附加组件:
mcp-clickhouse[chdb]
- 默认值:
CHDB_DATA_PATH:chDB 数据目录的路径- 默认值:
":memory:"(内存数据库) - 使用
:memory:进行内存数据库 - 使用文件路径进行持久存储(例如
/path/to/chdb/data)
- 默认值:
常见配置陷阱
CLICKHOUSE_SECURE与 MCP / 入口 TLS — 因为 MCP 服务器位于 Kubernetes 入口、反向代理后面,或通过纯 HTTP 访问而关闭CLICKHOUSE_SECURE并不会禁用数据库 TLS;它只改变此进程连接到 ClickHouse 的方式。请将入口 TLS 与数据库客户端设置分开配置。- 原生协议端口 —
CLICKHOUSE_PORT必须指向 ClickHouse 的 HTTP 接口(默认为8123/8443)。端口9000/9440用于原生 TCP 协议(clickhouse-client),不适用于此服务器。 - 主机混淆 —
CLICKHOUSE_HOST是数据库主机名。CLICKHOUSE_MCP_BIND_HOST只是 MCP HTTP/SSE 服务器监听的地址。
示例配置
用于 Docker 本地开发:
# Required variables
CLICKHOUSE_HOST=localhost
CLICKHOUSE_USER=default
CLICKHOUSE_PASSWORD=clickhouse
# Optional: Override defaults for local development
CLICKHOUSE_SECURE=false # Uses port 8123 automatically
CLICKHOUSE_VERIFY=false
用于 ClickHouse Cloud:
# Required variables
CLICKHOUSE_HOST=your-instance.clickhouse.cloud
CLICKHOUSE_USER=default
CLICKHOUSE_PASSWORD=your-password
# Optional: These use secure defaults
# CLICKHOUSE_SECURE=true # Uses port 8443 automatically
# CLICKHOUSE_DATABASE=your_database
用于 ClickHouse SQL Playground:
CLICKHOUSE_HOST=sql-clickhouse.clickhouse.com
CLICKHOUSE_USER=demo
CLICKHOUSE_PASSWORD=
# Uses secure defaults (HTTPS on port 8443)
用于没有客户端证书认证的私有服务器 CA:
CLICKHOUSE_HOST=your-secure-clickhouse.example.com
CLICKHOUSE_USER=your-user
CLICKHOUSE_PASSWORD=your-password
CLICKHOUSE_SECURE=true
CLICKHOUSE_VERIFY=true
CLICKHOUSE_CA_CERT=/run/secrets/clickhouse-ca.pem
用于 ClickHouse X.509 客户端证书认证:
CLICKHOUSE_HOST=your-secure-clickhouse.example.com
CLICKHOUSE_USER=your-certificate-user
CLICKHOUSE_SECURE=true
CLICKHOUSE_CLIENT_CERT=/run/secrets/clickhouse-client.pem
CLICKHOUSE_CLIENT_CERT_KEY=/run/secrets/clickhouse-client-key.pem
# CLICKHOUSE_CA_CERT=/run/secrets/clickhouse-ca.pem # Only for a private server CA
# CLICKHOUSE_TLS_MODE=mutual # Optional. This is the default with a client certificate.
用于严格 TLS 服务器要求客户端证书而 ClickHouse 使用 Basic 认证的情况:
CLICKHOUSE_HOST=your-secure-clickhouse.example.com
CLICKHOUSE_USER=your-user
CLICKHOUSE_PASSWORD=your-password
CLICKHOUSE_SECURE=true
CLICKHOUSE_CLIENT_CERT=/run/secrets/clickhouse-client.pem
CLICKHOUSE_CLIENT_CERT_KEY=/run/secrets/clickhouse-client-key.pem
CLICKHOUSE_TLS_MODE=strict
当TLS终止代理要求客户端证书,而ClickHouse仍使用Basic认证时,请改用CLICKHOUSE_TLS_MODE=proxy。
仅适用于chDB(内存模式):
# chDB configuration
CHDB_ENABLED=true
CLICKHOUSE_ENABLED=false
# CHDB_DATA_PATH defaults to :memory:
适用于带持久化存储的chDB:
# chDB configuration
CHDB_ENABLED=true
CLICKHOUSE_ENABLED=false
CHDB_DATA_PATH=/path/to/chdb/data
适用于MCP Inspector或通过HTTP传输的远程访问:
CLICKHOUSE_HOST=localhost
CLICKHOUSE_USER=default
CLICKHOUSE_PASSWORD=clickhouse
CLICKHOUSE_MCP_SERVER_TRANSPORT=http
CLICKHOUSE_MCP_BIND_HOST=0.0.0.0 # Bind to all interfaces
CLICKHOUSE_MCP_BIND_PORT=4200 # Custom port (default: 8000)
CLICKHOUSE_MCP_AUTH_TOKEN=your-generated-token # One auth mode required for HTTP/SSE (or FASTMCP_SERVER_AUTH, or CLICKHOUSE_MCP_AUTH_DISABLED=true)
CLICKHOUSE_MCP_ALLOWED_HOSTS=127.0.0.1:4200,localhost:4200,mcp.example.com:4200 # Include every Host value clients and proxies send
适用于本地开发(禁用认证)的HTTP传输:
CLICKHOUSE_HOST=localhost
CLICKHOUSE_USER=default
CLICKHOUSE_PASSWORD=clickhouse
CLICKHOUSE_MCP_SERVER_TRANSPORT=http
CLICKHOUSE_MCP_AUTH_DISABLED=true # Only for local development!
CLICKHOUSE_MCP_ALLOWED_HOSTS=127.0.0.1:8000,localhost:8000
使用HTTP传输时,服务器将运行在配置的端口上(默认8000)。例如,使用上述配置时:
- MCP端点:
http://localhost:8000/mcp - 健康检查:
http://localhost:8000/health
您可以在环境中、.env文件中或Claude Desktop配置中设置这些变量:
{
"mcpServers": {
"mcp-clickhouse": {
"command": "uv",
"args": [
"run",
"--with",
"mcp-clickhouse",
"--python",
"3.12",
"mcp-clickhouse"
],
"env": {
"CLICKHOUSE_HOST": "<clickhouse-host>",
"CLICKHOUSE_USER": "<clickhouse-user>",
"CLICKHOUSE_PASSWORD": "<clickhouse-password>",
"CLICKHOUSE_DATABASE": "<optional-database>",
"CLICKHOUSE_MCP_SERVER_TRANSPORT": "stdio",
"CLICKHOUSE_MCP_BIND_HOST": "127.0.0.1",
"CLICKHOUSE_MCP_BIND_PORT": "8000"
}
}
}
}
注意:绑定主机和端口设置仅在传输方式设置为“http”或“sse”时使用。
运行测试
uv sync --all-extras --dev # install dev dependencies
uv run ruff check . # run linting
docker compose up -d test_services # start ClickHouse
uv run pytest -v tests
uv run pytest -v tests/test_tool.py # ClickHouse only
CHDB_ENABLED=true uv run --extra chdb pytest -v tests/test_chdb_tool.py # chDB only
