MCP Toolbox for Databases 的 Couchbase 数据源配置详解:从连接串到参数化 SQL 工具
【免费下载链接】mcp-toolboxMCP Toolbox for Databases is an open source MCP server for databases.项目地址: https://gitcode.com/GitHub_Trending/ge/mcp-toolbox
在 mcp-toolbox 中接入 Couchbase 集群的核心,是声明一个type: couchbase的 source,再配合couchbase-sql工具执行参数化 SQL 查询。本文完整梳理 Couchbase Source 官方文档 中的连接配置、参考字段与注意事项,并结合 internal/sources/couchbase/couchbase.go 与 internal/tools/couchbase/couchbase.go 的源码实现,讲解每个配置项在底层如何生效,帮助你从零写出可运行的 Couchbase 接入配置并理解其安全与一致性行为。
Couchbase Source 的定位
couchbasesource 建立与 Couchbase 集群的连接,使挂载在其上的工具能够针对该集群执行 SQL 查询(Couchbase 的 N1QL 查询服务,默认作用域为 bucket 内的 scope)。从源码看,source 注册入口在 couchbase.go#L37-L41,通过sources.Register(SourceType, newConfig)以"couchbase"类型名注册配置解析器;解析成功后,Initialize方法完成两件事:
- 调用
createCouchbaseOptions()根据 YAML 配置构造gocb.ClusterOptions(认证、TLS、连接 profile); - 执行
gocb.Connect(r.ConnectionString, opts)建立集群连接,并通过cluster.Bucket(r.Bucket).Scope(r.Scope)定位到目标 scope(见 couchbase.go#L73-L90)。
Source结构体最终只暴露一个*gocb.Scope字段(外加配置本身),所有工具查询都收敛到该 scope 上——这也解释了为什么bucket与scope都是必填项:Couchbase 的 N1QL 查询以scope.collection为命名空间,不指定它们就无法定位数据。
最小可用配置示例
官方文档给出的标准示例如下,使用 Couchbase 官方 sample buckettravel-sample中的inventoryscope:
kind: source name: my-couchbase-instance type: couchbase connectionString: couchbase://localhost bucket: travel-sample scope: inventory username: Administrator password: password各字段的必填性与源码中的校验一一对应:Config结构体上Name、Type、ConnectionString、Bucket、Scope都带有validate:"required"标签(见 couchbase.go#L51-L67)。单元测试 couchbase_test.go#L106-L152 验证了两类解析失败场景:
- 缺失必填字段(如省略
connectionString)会触发Field validation for 'ConnectionString' failed on the 'required' tag错误; - 出现未定义字段(如
foo: bar)会因 YAML 严格模式报unknown field "foo",配置解析失败。
这意味着 mcp-toolbox 对 source 配置是"零容忍"的:写错字段名会直接让服务启动失败,而不是静默忽略。
完整字段参考表
以下参考表继承自 source.md,并补充了源码层面的行为说明:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | true | 必须为"couchbase"。 |
connectionString | string | true | Couchbase 集群连接串,如couchbase://localhost、couchbases://host1:18018,host2:18018。 |
bucket | string | true | 要连接的 bucket 名称。 |
scope | string | true | bucket 内的 scope 名称(如_default)。 |
username | string | false | 认证用户名。 |
password | string | false | 认证密码。 |
clientCert | string | false | 客户端证书文件路径(TLS 双向认证)。 |
clientCertPassword | string | false | 客户端证书密码。 |
clientKey | string | false | 客户端密钥文件路径。 |
clientKeyPassword | string | false | 客户端密钥密码。 |
caCert | string | false | CA 证书文件路径。 |
noSslVerify | boolean | false | 为 true 时跳过服务端证书校验。警告:仅可用于开发/测试环境,生产环境禁用,否则连接存在中间人攻击风险。 |
profile | string | false | 要应用的连接 profile 名称(如serverless)。 |
queryScanConsistency | integer | false | 索引扫描一致性级别。1=not_bounded(最快,但结果可能不含最新写入);2=request_plus(最高一致性,包含查询开始前的所有已提交操作,但有性能开销)。不指定时使用 Couchbase Go SDK 的默认值。 |
TLS 与认证配置在源码中的实现
createCouchbaseOptions()(couchbase.go#L140-L211)展示了各 TLS 字段的组装逻辑,理解它有助于正确使用证书相关字段:
- 用户名/密码认证:只要
username非空,就构造gocb.PasswordAuthenticator并设为cbOpts.Authenticator。 - 证书认证:
clientCert、clientKey、caCert三个路径会被os.ReadFile读入内存(任一文件读取失败都会使 source 初始化失败),随后交给tlsutil.NewConfig生成 TLS 配置;若clientCert已设置,认证器替换为gocb.CertificateAuthenticator(X.509 证书认证)。 - 信任锚:
caCert提供后,SecurityConfig.TLSRootCAs指向该 CA 池;noSslVerify为 true 时则设置TLSSkipVerify。注意源码中仅当clientCert或caCert至少有一个非空时,才走 TLS 解析分支(couchbase.go#L172-L203)。 - 证书/密钥密码:
getCertKeyPassword的取舍规则是——clientKeyPassword非空时优先使用它,否则回退到clientCertPassword(couchbase.go#L213-L220)。因此当证书与密钥共用同一密码时,只填clientCertPassword即可。
一个完整的 TLS 配置示例(取自 couchbase_test.go#L58-L91 的测试用例):
kind: source name: my-couchbase-instance type: couchbase connectionString: couchbases://localhost bucket: travel-sample scope: inventory clientCert: /path/to/cert.pem clientKey: /path/to/key.pem clientCertPassword: password clientKeyPassword: password caCert: /path/to/ca.pem noSslVerify: false queryScanConsistency: 2关于连接串中的多节点备选地址与自定义端口,官方文档提示可参考 Couchbase Go SDK 的 Managing Connections 指南(Couchbase 官方文档,此处不附外链);mcp-toolbox 侧直接将connectionString原样透传给gocb.Connect,因此 SDK 支持的一切地址格式(多主机、备地址、自定义端口)在此均适用。
profile:连接性能档位
profile字段最终调用cbOpts.ApplyProfile(gocb.ClusterConfigProfile(r.Profile))(couchbase.go#L204-L209)。这是 Go SDK 提供的连接配置档位(如serverless),用于按部署环境(本地开发、云、Serverless)调整重连、连接池等参数;不指定时使用 SDK 默认。
queryScanConsistency:一致性换性能
该字段在RunSQL中直接映射为gocb.QueryOptions.ScanConsistency(couchbase.go#L119-L123):
results, err := s.CouchbaseScope().Query(statement, &gocb.QueryOptions{ ScanConsistency: gocb.QueryScanConsistency(s.CouchbaseQueryScanConsistency()), NamedParameters: params.AsMap(), })- 设为
1(not_bounded):允许索引扫描读取未提交/未同步的条目,最快,适合对实时性不敏感的探索性查询; - 设为
2(request_plus):保证扫描到查询发起前已提交且已向主节点请求过的所有操作,适合要求"读到最近写入"的场景; - 不设置:透传 Go SDK 默认值(SDK 默认为 request_plus 语义的自动级别)。
仓库的集成测试在testcontainers启动的 Couchbase 容器上固定使用queryScanConsistency: 2(见 tests/couchbase/couchbase_integration_test.go 的getCouchbaseVars),可以作为可复现的参考配置。
与 Source 配套的工具:couchbase-sql
source 声明连接,工具声明"能做什么"。mcp-toolbox 中面向 Couchbase 的工具是couchbase-sql,完整文档见 couchbase-sql.md。它执行一条预定义的 SQL 语句,且以参数化语句方式运行:语句中的$name占位符会被同名参数替换。
工具配置参考表(来自 couchbase-sql.md):
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | true | 必须为"couchbase-sql"。 |
source | string | true | 工具所执行的 source 名称。 |
description | string | true | 传递给 LLM 的工具描述。 |
statement | string | true | 要执行的 SQL 语句。 |
parameters | 参数列表 | false | 与 SQL 语句配合使用的命名参数。 |
templateParameters | 参数列表 | false | 在执行前直接插入 SQL 语句的模板参数。 |
authRequired | array[string] | false | 使用该工具所需的服务端认证服务列表。 |
基础参数示例(来自官方文档):
kind: tool name: search_products_by_category type: couchbase-sql source: my-couchbase-instance statement: | SELECT p.name, p.price, p.description FROM products p WHERE p.category = $category AND p.price < $max_price ORDER BY p.price DESC LIMIT 10 description: | Use this tool to get a list of products for a specific category under a maximum price. Takes a category name, e.g. "Electronics" and a maximum price e.g 500 and returns a list of product names, prices, and descriptions. Do NOT use this tool with invalid category names. Do NOT guess a category name, Do NOT guess a price. Example: { "category": "Electronics", "max_price": 500 } parameters: - name: category type: string description: Product category name - name: max_price type: integer description: Maximum price (positive integer)注意description的写法:它同时面向 LLM 说明参数边界("不要猜 category 或 price"),这种"约束性描述"能显著降低模型生成越界调用的概率,值得在自定义工具时借鉴。
源码视角:参数化查询如何防注入
工具侧的执行链路在 internal/tools/couchbase/couchbase.go#L109-L130 的Invoke方法中,分三步:
parameters.ResolveTemplateParams(...):先对statement做 Go template 渲染,处理templateParameters;parameters.GetParams(...):从 LLM 传入的参数值中提取parameters声明的命名参数;source.RunSQL(newStatement, newParams):将最终语句与NamedParameters一并交给 Couchbase 查询引擎,由引擎完成参数绑定。
由于parameters走的是数据库侧的命名参数绑定(gocb.QueryOptions.NamedParameters),参数值永远不会被拼进 SQL 文本,这是防注入的根本保证。而templateParameters则相反——它允许把值直接插入语句文本(包括表名、列名等标识符位置),官方工具文档 明确警告这会使语句更易受 SQL 注入影响,"出于性能与安全考虑,推荐只使用基础 parameters"。相关参数机制的完整定义(含escape等字段)见 工具配置文档。
工具还会在ValidateSource中校验 source 是否实现了compatibleSource接口(要求提供CouchbaseScope()与RunSQL,见 couchbase.go#L46-L49),因此只有couchbase类型的 source 能被couchbase-sql工具使用,配置错配会在启动阶段报错而非运行期才暴露。
结果如何返回
RunSQL(couchbase.go#L119-L138)将每行结果以json.RawMessage原样收集为[]any返回,即工具输出是一个 JSON 数组,每个元素是一行 Couchbase 查询结果。这意味着 MCP 客户端(如 Gemini CLI、Claude)拿到的就是与 N1QL 查询服务一致的 JSON 行集,无需二次转换。
端到端验证方式
仓库为这条链路提供了两级测试可作参考:
- 配置解析单测:internal/sources/couchbase/couchbase_test.go 验证基础配置与 TLS 配置的 YAML 解析,以及未知字段、缺失必填字段的报错信息;internal/tools/couchbase/couchbase_test.go 验证
couchbase-sql工具(含 templateParameters 混合场景)的解析结果; - 集成测试:tests/couchbase/couchbase_integration_test.go 通过 testcontainers 拉起真实 Couchbase 集群(默认
_defaultscope、test-bucket、Administrator账号),跑通 source +couchbase-sql工具的实际查询。
阅读这两个测试文件,可以快速复制一份"最小验证配置":connectionString指向容器地址、scope: _default、queryScanConsistency: 2。
小结
- 一个
type: couchbase的 source 由connectionString+bucket+scope三要素定位数据,认证支持用户名/密码与 X.509 证书两种方式,noSslVerify仅限开发环境使用; queryScanConsistency是显式的一致性/性能权衡开关,1 =not_bounded,2 =request_plus,缺省交给 Go SDK 默认值;- 工具侧统一使用
couchbase-sql:parameters走引擎侧命名参数绑定(防注入),templateParameters直接改写语句文本(灵活但有注入风险),生产配置优先只用前者; - 所有字段行为均可在 internal/sources/couchbase/couchbase.go 与 internal/tools/couchbase/couchbase.go 中逐行核对,出错时结合 couchbase_test.go 中的报错样例可快速定位配置问题。
【免费下载链接】mcp-toolboxMCP Toolbox for Databases is an open source MCP server for databases.项目地址: https://gitcode.com/GitHub_Trending/ge/mcp-toolbox
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考