news 2026/9/15 13:07:11

MCP Toolbox 中 singlestore-sql 工具实战:从参数化查询到向量检索

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MCP Toolbox 中 singlestore-sql 工具实战:从参数化查询到向量检索

MCP Toolbox 中 singlestore-sql 工具实战:从参数化查询到向量检索

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

本指南以 MCP Toolbox for Databases(开源 MCP 服务器,用于为 Agent 提供数据库能力)中面向 SingleStore 的singlestore-sql工具为主线,系统讲解如何通过 YAML 配置把一条预定义 SQL 语句暴露为可供 LLM/Agent 调用的 MCP 工具,并覆盖参数化查询防注入、模板参数的取舍,以及结合embeddingModelJSON_ARRAY_PACK()/DOT_PRODUCT()实现语义向量检索的完整方案。读完本文,你将能够独立配置基于 SingleStore 的只读查询工具与向量检索工具,并理解其底层执行链路。

singlestore-sql 工具是什么

singlestore-sql是 MCP Toolbox 注册的、面向 SingleStore 数据库的预定义 SQL 工具类型(resourceType"singlestore-sql",见 singlestoresql.go)。它的工作方式与postgres-sqlmysql等同类工具一致:在配置文件中把一条预先写好的 SQL 语句和它的参数声明绑定在一起,运行 MCP 服务器后,该配置会自动转化为一个 MCP Tool,Agent 只需要提供参数值即可完成查询。

它和仓库中另一个面向 SingleStore 的工具singlestore-execute-sql有本质区别:

工具类型输入适用场景
singlestore-sql预定义语句 + 声明参数生产级 Agent 工作流,语句受控、可防注入
singlestore-execute-sql任意sql字符串参数开发者辅助(human-in-the-loop)场景,官方明确提示不应用于生产 Agent

后者在 singlestoreexecutesql.go 中会注册一个名为sql的字符串参数,并把用户输入的语句直接交给数据源执行;而singlestore-sql的语句是静态配置的,Agent 只能按声明好的参数填值。本文聚焦singlestore-sql

兼容的数据源(Compatible Sources)

singlestore-sql要求其source指向实现了以下接口的数据源(见 singlestoresql.go):

type compatibleSource interface { SingleStorePool() *sql.DB RunSQL(context.Context, string, []any) (any, error) }

即必须是类型为singlestore的 source(source 配置文档)。在工具初始化时,ValidateSource会校验数据源类型,不兼容会返回invalid source for "singlestore-sql" tool错误(singlestoresql.go)。

前置准备:配置 singlestore source

在配置工具之前,需要先在配置文件中声明一个kind: sourcetype: singlestore的数据源。以下是文档中给出的最小可运行示例(完整字段见 source.md):

kind: source name: my-singlestore-source type: singlestore host: 127.0.0.1 port: 3306 database: my_db user: ${USER_NAME} password: ${PASSWORD} queryTimeout: 30s # Optional: query timeout duration

从源码看,该 source 的连接建立在 go-sql-driver/mysql 之上(SingleStore 兼容 MySQL 协议)。initSingleStoreConnectionPool会默认设置tls=preferred(服务器支持则启用 SSL/TLS,否则回退明文),并追加vector_type_project_format=JSON参数,这正是向量功能能工作的关键前提之一(singlestore.go)。

如果需要强制加密,可通过connectionParams覆盖:

kind: source name: my-singlestore-source type: singlestore host: svc-abc123.svc.singlestore.com port: 3306 database: my_db user: ${USER_NAME} password: ${PASSWORD} connectionParams: tls: "true" # Require TLS and verify the server certificate

tls还支持"skip-verify"(要求 TLS 但跳过证书校验)和"false"(完全禁用)。connectionParams支持任何 go-sql-driver/mysql 的 DSN 参数,例如压缩等。

提示:密码等敏感信息请使用${ENV_NAME}环境变量替换语法,不要硬编码进配置文件。

基本用法:参数化查询与防注入

singlestore-sql的核心配置项是statement(预定义 SQL)与parameters(参数声明)。官方示例(singlestore-sql.md)给出一个航班查询工具:

kind: tool name: search_flights_by_number type: singlestore-sql source: my-s2-instance statement: | SELECT * FROM flights WHERE airline = ? AND flight_number = ? LIMIT 10 description: | Use this tool to get information for a specific flight. Takes an airline code and flight number and returns info on the flight. Do NOT use this tool with a flight id. Do NOT guess an airline code or flight number. A airline code is a code for an airline service consisting of two-character airline designator and followed by flight number, which is 1 to 4 digit number. For example, if given CY 0123, the airline is "CY", and flight_number is "123". Another example for this is DL 1234, the airline is "DL", and flight_number is "1234". If the tool returns more than one option choose the date closes to today. Example: {{ "airline": "CY", "flight_number": "888", }} Example: {{ "airline": "DL", "flight_number": "1234", }} parameters: - name: airline type: string description: Airline unique 2 letter identifier - name: flight_number type: string description: 1 to 4 digit number

关键要点:

  • 占位符语法:SQL 语句中的参数使用?占位符,与parameters列表中声明的参数按顺序一一对应。
  • 防 SQL 注入:该工具使用参数化查询(prepared statement)执行语句。parameters声明的参数会作为绑定值传给数据源,Agent 提供的任何输入都不会被拼接进 SQL 文本。
  • description是给 LLM 看的:它会被完整传递给模型(对应源码中tools.Manifest{Description: cfg.Description, ...}的构建逻辑,见 singlestoresql.go)。因此描述应当写清楚:何时使用该工具、参数含义、示例 JSON 调用、禁止行为等,示例中甚至示范了如何给出多组{{ "airline": "CY", "flight_number": "888" }}式的输入样例来引导模型。
  • 参数覆盖范围限制:参数化绑定值只能替换表达式,不能替换标识符、列名、表名等 SQL 结构。如果需要在语句中动态改变表名/列名,必须使用下面的templateParameters

参数化执行的底层链路

在 singlestoresql.go 的Invoke中,执行流程为:

  1. params.AsMap()收集 Agent 传入的全部参数值;
  2. ResolveTemplateParams先解析模板参数(若存在);
  3. GetParams按声明顺序提取标准参数值;
  4. source.RunSQL(ctx, newStatement, sliceParams)以绑定参数形式执行查询。

而数据源侧的RunSQL(singlestore.go)使用QueryContext(ctx, statement, params...)执行,逐行扫描并把每行结果转换为map[列名]值的结构返回,列类型转换复用mysqlcommon.ConvertToType。也就是说,Agent 最终拿到的是一组 JSON 对象数组。

模板参数(templateParameters):灵活但需警惕注入

当语句需要动态插入表名、列名等 SQL 结构时,可以使用templateParameters。示例:

kind: tool name: list_table type: singlestore-sql source: my-s2-instance statement: | SELECT * FROM {{.tableName}}; description: | Use this tool to list all information from a specific table. Example: {{ "tableName": "flights", }} templateParameters: - name: tableName type: string description: Table to select from

模板参数在 SQL 中以{{.参数名}}的形式书写,执行前会被替换进语句文本。

⚠️ 安全警告:模板参数允许直接修改 SQL 语句(包括标识符、列名、表名),因此比基本参数更容易遭受 SQL 注入。官方明确建议:出于性能与安全考虑,优先使用基本parameters;只有确有必要时才使用templateParameters。更详细的说明见 tools 配置文档的 Template Parameters 一节。

从源码看,模板参数的处理发生在标准参数之前(ResolveTemplateParams先于GetParams),且模板参数不参与prepared statement 的绑定——它是先完成字符串替换、再把替换后的整条语句作为查询文本执行,这正是其注入风险的来源。

参数声明字段速查

parameterstemplateParameters中的每个参数项支持以下字段(详见 tools/_index.md):

字段类型必填说明
namestring参数名
typestring"string""integer""float""boolean""array"之一
descriptionstring给 Agent 看的自然语言描述
default参数类型默认值,提供后参数变为可选
requiredbool是否必填,默认true
allowedValues[]string允许值白名单,支持正则
excludedValues[]string排除值黑名单,支持正则
escapestring仅 string 类型,配合 templateParameters 使用,取single-quotes/double-quotes/backticks/square-brackets
minValue/maxValueint/float数值上下限(integer/float)
securebool标记为安全参数(需协议版本2026-07-28及扩展),默认false

向量检索:Embedding 与 JSON_ARRAY_PACK 的配合

SingleStore 原生支持向量操作,singlestore-sql工具因此可以组合出完整的「向量入库 + 语义检索」能力。核心机制是:当一个参数声明了embeddedBy引用某个embeddingModel时,工具会自动把该参数的文本转换为向量字符串数组(JSON 格式字符串数组),随后在 SQL 中用 SingleStore 的JSON_ARRAY_PACK()把它打包成二进制向量(BLOB)参与存储与相似度计算。

在 singlestoresql.go 中,工具覆写了EmbedParams,使用parameters.EmbedParams(..., embeddingmodels.FormatVectorForPgvector)对声明了embeddedBy的参数执行嵌入转换;而 source 侧 DSN 中默认追加的vector_type_project_format=JSON参数(singlestore.go)正是为了保证向量以 JSON 数组形式往返,从而能被JSON_ARRAY_PACK()正确解析。

第一步:定义 Embedding 模型

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

完整的embeddingModel配置说明见 embedding-models 文档。

第二步:向量入库工具

下面的工具向vector_table写入原始文本及其向量表示。注意text_to_embed参数使用了valueFromParam: content:它并不要求 Agent 额外传值,而是自动复制content参数的值,再经embeddedBy: gemini-model转成向量——Agent 只需提供一次内容,向量转换逻辑对模型完全透明:

kind: tool name: insert_doc_singlestore type: singlestore-sql source: my-s2-source statement: | INSERT INTO vector_table (id, content, embedding) VALUES (1, ?, JSON_ARRAY_PACK(?)) description: | Index new documents for semantic search in SingleStore. parameters: - name: content type: string description: The text content to store. - name: text_to_embed type: string # Automatically copies 'content' and converts it to a vector string array valueFromParam: content embeddedBy: gemini-model

语句中第一个?绑定原始文本content,第二个?绑定向量数组,经JSON_ARRAY_PACK(?)转为 BLOB 写入embedding列。

第三步:自然语言检索工具

检索工具把 Agent 的自然语言查询转换为向量,用DOT_PRODUCT()计算余弦相似度并返回最相似的结果:

kind: tool name: search_docs_singlestore type: singlestore-sql source: my-s2-source statement: | SELECT id, content, DOT_PRODUCT(embedding, JSON_ARRAY_PACK(?)) AS score FROM vector_table ORDER BY score DESC LIMIT 1 description: | Search for documents in SingleStore using natural language. Returns the most semantically similar result. parameters: - name: query type: string description: The search query to be converted to a vector. embeddedBy: gemini-model

这里只有一个?,即query参数:Agent 输入一句自然语言(例如「What is the refund policy?」),工具自动嵌入为向量数组,JSON_ARRAY_PACK(?)打包后与库中所有向量的DOT_PRODUCT排序,取LIMIT 1返回语义最接近的文档。

注意:以上两个示例中的vector_table表及其embedding列需要提前在 SingleStore 中创建好(可参考 SingleStore 官方向量类型与DOT_PRODUCT文档),工具本身不负责建表。

参考字段表

singlestore-sql工具配置的完整字段如下(来自 singlestore-sql.md 的 Reference,与源码中Config结构体 singlestoresql.go 一一对应):

字段类型必填说明
typestring必须为"singlestore-sql"
sourcestring要执行 SQL 的 source 名称(需为singlestore类型)
descriptionstring工具描述,会传递给 LLM
statementstring要执行的 SQL 语句
parametersparameters将被插入 SQL 语句(以绑定参数方式)的参数列表
templateParameterstemplateParameters在执行 prepared statement 之前插入 SQL 语句的模板参数列表

其中sourcestatementdescription在源码中均带validate:"required"校验,且description为空会在初始化时报错description is required for tool(singlestoresql.go)。

快速体验:使用预构建配置

如果不想从零写配置,仓库还提供了 SingleStore 的预构建配置(见 prebuilt-configs/singlestore.md),可通过--prebuilt singlestore启动,只需设置以下环境变量:

  • SINGLESTORE_HOST:SingleStore 服务器主机名或 IP
  • SINGLESTORE_PORT:端口号
  • SINGLESTORE_DATABASE:数据库名
  • SINGLESTORE_USER:数据库用户名
  • SINGLESTORE_PASSWORD:数据库用户密码

预构建配置默认暴露execute_sql(执行 SQL)与list_tables(列出用户建表的结构信息)两个工具。需要更精确、更安全的行为时,则按本文方式自定义singlestore-sql工具。

总结

singlestore-sql把「SQL 语句 + 参数声明 + 向量嵌入」三者以声明式 YAML 的方式绑定为一个安全的 MCP 工具:默认的参数化查询保证 Agent 输入不会破坏 SQL 结构;templateParameters在必要时提供结构级灵活性但需谨慎使用;embeddedBy+valueFromParam+JSON_ARRAY_PACK()/DOT_PRODUCT()的组合则让 SingleStore 的向量能力以「自然语言进、语义结果出」的形式无缝暴露给 LLM。结合 source 配置 与 tools 通用参数规范,开发者可以快速搭建出面向 SingleStore 的安全查询与语义检索 Agent 工作流。

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

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 13:02:47

三调图斑尖锐角与小缝隙的FME自动化检测修复实战

前几年做三调数据入库和质检的时候,最磨人的不是地类认定,也不是权属争议,反而是看起来特别不起眼的图形质量问题。尖锐角、小缝隙这两个词,干过三调的兄弟应该都不陌生——你辛辛苦苦把图斑矢量化完,一跑质检软件&…

作者头像 李华
网站建设 2026/9/15 13:02:22

EPS中用DOM与DSM创建垂直模型全流程解析

上周一个做测绘的朋友给我打电话,说手上接了个城市更新项目,甲方给的数据很朴素——一套0.2米分辨率的DOM加一套1米分辨率的DSM,要求在一个月内把核心区域的建筑垂直模型拉起来,用于方案比选和指标量算。他问我:在EPS里…

作者头像 李华