ClickHouse

官方

查询您的ClickHouse数据库服务器。

你可以用 ClickHouse MCP 做什么?

  • 运行 SQL 查询 — 通过 run_query 在您的 ClickHouse 集群上执行任何 SQL 查询,并可通过 params 使用可选命名参数。
  • 列出数据库 — 使用 list_databases 发现 ClickHouse 集群上所有可用的数据库。
  • 使用筛选器浏览表 — 使用 list_tables 探索数据库中的表,应用 like/not_like 模式,并通过 page_token 和 page_size 进行分页。
  • 检查查询模式 — 在执行前,通过 run_query 请求 DESCRIBE (<query>) 或 EXPLAIN ESTIMATE <query>,以检查输出列或预估读取量。
  • 查询嵌入式 chDB 数据 — 使用 run_chdb_select_query 直接对 chDB 的嵌入式引擎运行 SQL,无需 ETL 即可查询文件、URL 或数据库。

文档

ClickHouse MCP 服务器

PyPI - Version

一个用于 ClickHouse 的 MCP 服务器。

mcp-clickhouse MCP server

该服务器实现了 MCP 2026-07-28,并支持来自 2024-11-05 到 2025-11-25 的旧版初始化握手。现代客户端使用无会话请求和 server/discover。现有客户端可以继续协商旧版协议。

[!NOTE] 没有 MCP-Protocol-Version 的 HTTP 请求会通过旧版处理进行路由,以便 2025-06-18 之前的客户端可以继续连接。MCP 2026-07-28 允许支持这些客户端的服务器采用此行为。现代客户端应在每个 POST 请求中发送该标头。

功能

ClickHouse 工具

ClickHouse 工具响应是 JSON 编码的字符串。超出 [-9007199254740991, 9007199254740991] 范围的整数以十进制字符串形式返回,以在 JavaScript 客户端中保留精确值。这适用于查询行和整数表元数据。安全范围内的整数和布尔值保留其 JSON 类型。

  • run_query

    • 在您的 ClickHouse 集群上执行 SQL 查询。
    • 输入:query(字符串):要执行的 SQL 查询。
    • 可选输入:params(对象):ClickHouse {name:Type} 占位符的命名值。请参阅 查询参数。
    • 查询默认以只读模式运行(CLICKHOUSE_ALLOW_WRITE_ACCESS=false),但如有需要,可以显式启用写入。
    • DESCRIBE (<query>) 和 EXPLAIN ESTIMATE <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:匹配所提供过滤器的表的总数。

Agents Schema 发现

服务器指令建议在 list_databases 显示 AGENTS 数据库时,通过 run_query 读取 Agents Schema 的规范 AGENTS.ROOT,然后再编写分析性 SQL。这是对代理的指导:不会自动获取元数据,工具结果不变,现有的 ClickHouse 权限仍然适用。如果 AGENTS.ROOT 缺失或无法访问,正常的发现和查询仍然可用。

查询参数

通过可选的 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 传输未配置其中任何一种,启动将失败。

设置身份验证

  1. 生成安全令牌(可以是任何随机字符串):

    # Using uuidgen (macOS/Linux)
    uuidgen
    
    # Using openssl
    openssl rand -hex 32
    
  2. 使用令牌配置服务器:

    export CLICKHOUSE_MCP_AUTH_TOKEN="your-generated-token"
    
  3. 配置您的 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 POST 一个 JSON-RPC 请求,带和不带 Authorization 标头,并确认未身份验证的调用返回 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.Auth0ProviderFASTMCP_SERVER_AUTH_AUTH0_
fastmcp.server.auth.providers.aws.AWSCognitoProviderFASTMCP_SERVER_AUTH_AWS_COGNITO_
fastmcp.server.auth.providers.azure.AzureProviderFASTMCP_SERVER_AUTH_AZURE_
fastmcp.server.auth.providers.descope.DescopeProviderFASTMCP_SERVER_AUTH_DESCOPEPROVIDER_
fastmcp.server.auth.providers.discord.DiscordProviderFASTMCP_SERVER_AUTH_DISCORD_
fastmcp.server.auth.providers.github.GitHubProviderFASTMCP_SERVER_AUTH_GITHUB_
fastmcp.server.auth.providers.google.GoogleProviderFASTMCP_SERVER_AUTH_GOOGLE_
fastmcp.server.auth.providers.introspection.IntrospectionTokenVerifierFASTMCP_SERVER_AUTH_INTROSPECTION_
fastmcp.server.auth.providers.jwt.JWTVerifierFASTMCP_SERVER_AUTH_JWT_
fastmcp.server.auth.providers.oci.OCIProviderFASTMCP_SERVER_AUTH_OCI_
fastmcp.server.auth.providers.scalekit.ScalekitProviderFASTMCP_SERVER_AUTH_SCALEKITPROVIDER_
fastmcp.server.auth.providers.supabase.SupabaseProviderFASTMCP_SERVER_AUTH_SUPABASE_
fastmcp.server.auth.providers.workos.WorkOSProviderFASTMCP_SERVER_AUTH_WORKOS_
fastmcp.server.auth.providers.workos.AuthKitProviderFASTMCP_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。

  1. 打开位于以下位置的 Claude Desktop 配置文件:

    • 在 macOS 上:~/Library/Application Support/Claude/claude_desktop_config.json
    • 在 Windows 上:%APPDATA%/Claude/claude_desktop_config.json
  2. 添加以下内容:

{
  "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"
      }
    }
  }
}
  1. 找到 uv 的命令条目,并将其替换为 uv 可执行文件的绝对路径。这可以确保在启动服务器时使用正确版本的 uv。在 Mac 上,您可以使用 which uv 找到此路径。

  2. 重启 Claude Desktop 以应用更改。

可选写入访问

默认情况下,此 MCP 强制执行只读查询,以防止在探索期间发生意外修改。要允许 DDL 或 INSERT 语句,请将 CLICKHOUSE_ALLOW_WRITE_ACCESS 环境变量设置为 true。如果 ClickHouse 实例本身禁止写入,服务器将继续强制执行只读模式。

只读模式仍允许 ClickHouse 用户取消自己的查询,包括使用同一用户的其他连接发出的查询。即使在只读模式下,也请使用专用的 ClickHouse 用户。对于不得相互取消查询的工作负载,请使用单独的 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 安装包并直接运行:

  1. 使用 pip 安装包:

    python3 -m pip install mcp-clickhouse
    

    要同时安装 chDB 支持:

    python3 -m pip install 'mcp-clickhouse[chdb]'
    

    要升级到最新版本:

    python3 -m pip install --upgrade mcp-clickhouse
    
  2. 更新您的 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 协议消息(工具调用、资源读取、提示等)。

使用方法

  1. 创建一个 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())
  1. 将 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"
      }
    }
  }
}
  1. 确保您的中间件模块位于 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 客户端之前使工具调用失败。CLICKHOUSE_ROLE 保持有效,除非覆盖显式 提供 settings.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 用户、角色 和授权来强制实施租户隔离。

开发

  1. 在 test-services 目录中运行 docker compose up -d 以启动 ClickHouse 集群。

  2. 在仓库根目录的 .env 文件中添加以下变量。

注意:在此上下文中使用 default 用户仅用于本地开发目的。

CLICKHOUSE_HOST=localhost
CLICKHOUSE_PORT=8123
CLICKHOUSE_USER=default
CLICKHOUSE_PASSWORD=clickhouse
  1. 运行 uv sync 安装依赖。如需安装 uv,请按照此处的说明操作。然后执行 source .venv/bin/activate。

  2. 为便于使用 MCP Inspector 进行测试,运行 uv run fastmcp dev inspector mcp_clickhouse/mcp_server.py:mcp 启动 MCP 服务器。

  3. 如需使用 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
    

代码布局

该包采用扁平模块布局。从 mcp_server.py 开始了解服务器组装和注册,然后跟随实现进入其所属模块。

模块职责
mcp_server.py、main.py启动组装、工具和提示词注册、关闭协调以及 CLI 启动
clients.py请求配置、ClickHouse 连接缓存和客户端租约
queries.py查询执行、取消和破坏性操作防护
metadata.py数据库和表发现、元数据模型和分页
chdb_backend.py、chdb_prompt.py可选的 chDB 初始化、查询执行和提示词内容
health.py、executors.py健康探测与缓存,以及服务器操作使用的工作池
auth.py、transport.py、http_security.pyDotenv 加载、认证、HTTP/SSE 应用构建以及 Host/Origin 验证
mcp_env.py、serialization.py环境配置和 JSON 结果编码
mcp_middleware_hook.py、skills_advisor.py自定义中间件加载和服务器指令

每个服务器组装都拥有自己的工作池、客户端缓存、活动查询、分页缓存、健康状态和 chDB 后端。工作线程和客户端清理在进程退出时运行。包导入会初始化默认服务器,包括首次导入提取的模块时。

在测试中,请在代码读取依赖项的位置修补模块或所有者实例。例如,修补 mcp_clickhouse.clients.clickhouse_connect.get_client 以进行客户端创建。mcp_server.py 中的兼容性导入可以是与实现所使用的绑定不同的绑定。

环境变量

配置分为独立的组。混淆它们是导致难以调试的连接失败的常见原因:

组变量控制项
ClickHouse 数据库连接CLICKHOUSE_HOST、CLICKHOUSE_PORT、CLICKHOUSE_SECURE、CLICKHOUSE_VERIFY、证书变量此 MCP 服务器如何通过 HTTP 接口连接到您的 ClickHouse 集群
MCP 服务器 / 传输CLICKHOUSE_MCP_*、FASTMCP_SERVER_AUTH、FASTMCP_SERVER_AUTH_*、FASTMCP_ENV_FILEMCP 传输、认证和查询工具执行限制
中间件 / chDBMCP_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 使用
    • 如果服务器响应 Port 9000 is for clickhouse-client program,则您指向的是原生协议;请切换到 HTTP 端口(8123/8443 或您部署的 HTTP 映射)
  • CLICKHOUSE_ROLE:用于认证的 ClickHouse 角色
    • 默认值:None
    • 如果您的用户需要特定角色,请设置此项
  • CLICKHOUSE_SECURE:为 ClickHouse 数据库连接启用 HTTPS(而非为 MCP 客户端)
    • 默认值:"true"
    • 仅当 MCP 服务器通过纯 HTTP 访问 ClickHouse 时设置为 "false"(典型情况为本地 Docker Compose 使用端口 8123)
    • 对于 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 证书捆绑包路径
    • 默认值:None(使用操作系统信任库,除非 truststore 注入被禁用或失败)
    • 当 ClickHouse 服务器或私有代理呈现由私有 CA 签名的证书时,单独使用此项。这会更改服务器证书验证,且不会启用客户端证书认证。
    • 需要 CLICKHOUSE_SECURE=true 和 CLICKHOUSE_VERIFY=true
  • CLICKHOUSE_CLIENT_CERT:用于 ClickHouse HTTPS 连接的 PEM 客户端证书路径
    • 默认值:None
    • 该文件也可能包含私钥。否则请设置 CLICKHOUSE_CLIENT_CERT_KEY。
    • ClickHouse 用户仍来自 CLICKHOUSE_USER。
  • CLICKHOUSE_CLIENT_CERT_KEY:CLICKHOUSE_CLIENT_CERT 的 PEM 私钥路径
    • 默认值:None
    • 当私钥包含在客户端证书文件中时为可选
    • 不能在没有 CLICKHOUSE_CLIENT_CERT 的情况下使用
  • CLICKHOUSE_TLS_MODE:clickhouse-connect 如何使用 CLICKHOUSE_CLIENT_CERT
    • 默认值:None,当设置客户端证书时行为等同于 "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 覆盖和证书验证的服务器主机名
    • 默认值:None(使用连接主机名)
    • 当通过代理或负载均衡器连接且证书主机名与连接主机名不同时,此选项很有用。设置后,此主机名将用于 TLS 握手期间的 SNI(服务器名称指示)和证书主机名验证。
  • CLICKHOUSE_PROXY_PATH:ClickHouse HTTP 端点的 URL 路径前缀
    • 默认值:None
    • 当 ClickHouse HTTP 接口通过反向代理在路径前缀下暴露时设置此项(例如,/clickhouse)
  • CLICKHOUSE_CONNECT_TIMEOUT:ClickHouse 客户端的连接超时时间(秒)
    • 默认值:"30"
    • 如果遇到连接超时,请增大此值
  • CLICKHOUSE_SEND_RECEIVE_TIMEOUT:ClickHouse 客户端的发送/接收超时时间(秒)
    • 默认值:300 或 CLICKHOUSE_MCP_QUERY_TIMEOUT + 5 中的较小值,以便工作线程在查询超时后不久解除阻塞
    • 如果显式设置,则按原样使用该值(例如,长时间运行的查询使用 "300")
  • CLICKHOUSE_DATABASE:要使用的默认 ClickHouse 数据库
    • 默认值:None(使用服务器默认值)
    • 设置此项以自动连接到特定数据库
  • 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

YouTube 概述

YouTube