MCP Toolbox 中 clickhouse-sql 工具:以预编译语句连接 LLM 与 ClickHouse
2026/9/14 16:12:05 网站建设 项目流程

MCP Toolbox 中 clickhouse-sql 工具:以预编译语句连接 LLM 与 ClickHouse

【免费下载链接】mcp-toolboxMCP Toolbox for Databases is an open source MCP server for databases.项目地址: https://gitcode.com/GitHub_Trending/ge/mcp-toolbox

本文基于 MCP Toolbox 官方文档 clickhouse-sql 工具说明,系统讲解clickhouse-sql工具的完整配置语法:普通参数(预编译语句占位符)、模板参数(SQL 文本定制)与向量化参数(embeddedBy)三类能力的用法与限制。读完本文,你可以直接编写可运行的 ClickHouse 工具配置,并理解 Toolbox 在底层如何把参数解析、模板替换、向量格式化串成一次database/sql查询。

工具定位:它与其他 ClickHouse 工具的区别

MCP Toolbox 对 ClickHouse 提供四类工具,定义在 internal/tools/clickhouse 下:

工具类型用途是否支持参数
clickhouse-execute-sql执行一条完整 SQL不支持
clickhouse-list-databases列出所有数据库不支持
clickhouse-list-tables列出指定库中的表不支持
clickhouse-sql执行带参数的 SQL 模板支持普通参数与模板参数

clickhouse-sql的独特之处在于它同时支持两类参数:

  • 普通参数(parameters:作为预编译语句的值(prepared statement values)绑定到 SQL 中的占位符;
  • 模板参数(templateParameters:在 SQL 执行前替换语句文本中的{{占位符}},用于定制列名、表名等无法参数化的部分。

这与clickhouse-execute-sql形成互补:后者的 SQL 是写死的,而clickhouse-sql让 LLM 只需提供少量受控参数,既能灵活查询,又避免了让模型直接拼接整条 SQL 带来的注入风险。

前置条件:配置一个 ClickHouse Source

clickhouse-sqlsource字段必须指向一个type: clickhouse的数据源。Source 配置字段与取值范围以 ClickHouse Source 文档 和 source 源码 为准:

字段类型必填说明
typestring必须为clickhouse
hoststringIP 或主机名,如127.0.0.1clickhouse.example.com
portstring端口,HTTPS 默认8443,HTTP 默认8123
databasestring要连接的数据库名
userstringClickHouse 用户名
passwordstring用户密码
protocolstringhttps(默认)或http,见 协议校验逻辑
secureboolean是否使用 TLS,默认false

一个典型的 source 配置如下(推荐用${ENV_NAME}环境变量引用注入密钥):

kind: source name: my-clickhouse-instance type: clickhouse host: clickhouse.example.com port: "8443" database: analytics user: ${CLICKHOUSE_USER} password: ${CLICKHOUSE_PASSWORD} protocol: https secure: true

从源码结构看,连接池在 initClickHouseConnectionPool 中创建:若protocol未填写则回退为https;DSN 采用scheme://user:pass@host:port/db形式,HTTPS 时附加?secure=true&skip_verify=false;连接池固定为最多 25 个打开连接、5 个空闲连接、连接最长生命周期 5 分钟。

基础配置:statement 与普通参数

工具的最小可用配置由四个必填字段组成:type: clickhouse-sqlsourcedescriptionstatement。一个查询用户行为分析的工具示例:

kind: tool name: my_analytics_query type: clickhouse-sql source: my-clickhouse-instance description: Get user analytics for a specific date range statement: | SELECT user_id, count(*) as event_count, max(timestamp) as last_event FROM events WHERE date >= ? AND date <= ? GROUP BY user_id ORDER BY event_count DESC LIMIT ? parameters: - name: start_date description: Start date for the query (YYYY-MM-DD format) - name: end_date description: End date for the query (YYYY-MM-DD format) - name: limit description: Maximum number of results to return

关键约定:

  • SQL 中的?占位符按出现顺序parameters列表中的参数一一对应。上方语句中date >= ?对应start_datedate <= ?对应end_dateLIMIT ?对应limit
  • description是必填项,会被传给 LLM 作为工具的语义描述——从 Initialize 实现 可见,缺失description会直接初始化失败;
  • 参数可以额外声明type: string等类型与required约束,完整参数语法与本文一致,本文示例遵循官方文档写法。

模板参数:让 LLM 定制 SQL 文本

对于列名、表名这类无法用预编译占位符表达的部分,templateParameters允许 LLM 提供文本,在执行前替换进 statement:

kind: tool name: flexible_table_query type: clickhouse-sql source: my-clickhouse-instance description: Query any table with flexible columns statement: | SELECT {{columns}} FROM {{table_name}} WHERE created_date >= ? LIMIT ? templateParameters: - name: columns description: Comma-separated list of columns to select - name: table_name description: Name of the table to query parameters: - name: start_date description: Start date filter - name: limit description: Maximum number of results

从 Invoke 执行链 可以确认处理顺序:

  1. parameters.ResolveTemplateParams先用模板参数渲染{{columns}}{{table_name}},得到最终 SQL 文本;
  2. parameters.GetParams再把普通参数抽取为有序值列表;
  3. 调用 source 的RunSQL(ctx, newStatement, newParams)执行。

也就是说,模板参数先于预编译绑定发生:{{ }}只出现在 SQL 文本层,?只出现在绑定值层,两者互不干扰。需要留意的是,模板参数直接拼接进 SQL 文本,其安全性取决于你在description中对取值形态的约束(例如"逗号分隔的列名"),配置时应尽量收窄 LLM 可填入的内容。

向量化查询:embeddedBy 与 Array(Float32)

clickhouse-sql还有一个文档明确的能力:透明地把字符串参数嵌入为向量。Toolbox 会通过原生 embedding model 配置 把声明了embeddedBy的参数文本编码成向量,并以原生Array(Float32)类型绑定到?占位符——这样你就可以直接写 ClickHouse 的向量函数(如cosineDistanceL2Distance),无需任何字符串解析。

源码依据有两处:

  • EmbedParams 方法 在调用前对参数执行嵌入,并使用embeddingmodels.FormatVectorForClickHouse做向量格式化;
  • 单元测试 覆盖了带embeddedBy+valueFromParam的参数解析场景,确认配置能正确落进Parameters

完整工作流:建表、嵌入、检索

第 1 步:准备目标表。假设向量表结构如下:

CREATE TABLE documents ( id UUID DEFAULT generateUUIDv4(), content String, embedding Array(Float32) ) ENGINE = MergeTree ORDER BY tuple();

第 2 步:在配置中定义 embedding model。

kind: embeddingModel name: gemini-model type: gemini apiKey: ${GOOGLE_API_KEY} model: gemini-embedding-001 dimension: 768

embedding model 的实现位于 internal/embeddingmodels,type: gemini的解析见 gemini.go。

第 3 步:定义写入工具。技巧是把content镜像到一个第二参数text_to_embed上,并用valueFromParam: content声明取值来源,再在该参数上挂embeddedBy提示——LLM 只需要提供content,向量由这个参数承载:

kind: tool name: insert_doc type: clickhouse-sql source: my-clickhouse-instance description: Indexes a new document and its vector embedding. statement: | INSERT INTO documents (content, embedding) VALUES (?, ?) parameters: - name: content type: string description: The text content to store. - name: text_to_embed type: string description: The text content used to generate the vector. valueFromParam: content embeddedBy: gemini-model

第 4 步:定义检索工具。查询文本由 LLM 直接给出,嵌入后按余弦距离排序:

kind: tool name: search_docs type: clickhouse-sql source: my-clickhouse-instance description: Finds the most semantically similar document to a query. statement: | SELECT content, cosineDistance(embedding, ?) AS distance FROM documents ORDER BY distance ASC LIMIT 1 parameters: - name: query type: string description: The search query. embeddedBy: gemini-model

文档中同时给出了两条硬性限制:

  • 只有string类型的参数才能声明embeddedBy
  • embedding model 必须定义在与工具相同的配置文件里kind: embeddingModel)。

字段参考(Reference)

以下为官方文档中的完整字段表,编写配置时可对照检查:

字段类型必填说明
typestring必须为clickhouse-sql
sourcestring要执行 SQL 的 ClickHouse source 名称
descriptionstring传给 LLM 的工具描述
statementstring要执行的 SQL 语句模板
parametersarray of Parameter预编译语句的值参数
templateParametersarray of ParameterSQL 文本定制参数

执行链路速览:从配置到 SQL 执行

把全文串起来,一次clickhouse-sql调用的完整链路是:

  1. 配置解析init阶段把clickhouse-sql注册进 tools 注册表,YAML 解码进Config结构体(Config 定义,注意parameterstemplateParameters是并列字段);
  2. 初始化Initialize校验description、合并两类参数生成参数 manifest;未配置annotations时默认使用 destructive 标注(GetAnnotationsOrDefault 调用);
  3. 调用Invoke依次完成模板渲染、参数抽取,最后调用 Source.RunSQL。

RunSQL的实现细节值得注意:它基于 Go 的database/sqlclickhouse-go驱动执行QueryContext,把每一行结果扫描为map[string]any返回(列名为 key),并对String/FixedString列做[]bytestring的转换(结果映射逻辑)。因此工具返回给 LLM 的是一组"列名 → 值"的行对象,天然适合 JSON 序列化展示。

实战建议

  • 占位符顺序即参数顺序?按出现顺序绑定parameters,调整语句时务必同步调整参数列表顺序;
  • 用 description 收窄 LLM 输入:例如日期参数注明YYYY-MM-DD format,模板参数注明取值形态,这是引导 LLM 正确调用的关键;
  • 写操作要有预期:source 的IsReadOnly返回false(源码),INSERT/UPDATE/DELETE均可通过该工具执行,工具默认带 destructive 标注,配置annotations可按需调整;
  • 向量场景遵守两条限制embeddedBy仅限string参数,且 embedding model 与工具必须在同一配置文件内定义。

相关文档与代码入口:ClickHouse 集成首页、ClickHouse Source 配置、工具实现、数据源实现、单元测试。

【免费下载链接】mcp-toolboxMCP Toolbox for Databases is an open source MCP server for databases.项目地址: https://gitcode.com/GitHub_Trending/ge/mcp-toolbox

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询