MCP Toolbox 中 cloud-sql-list-databases 工具的完整配置与源码级实现解析
【免费下载链接】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 仓库中的cloud-sql-list-databases工具文档为核心,系统讲解该工具在tools.yaml中的配置方法、参数规则与底层实现。读完后,你将能够独立完成该工具的配置与调用,并理解其参数解析、Cloud SQL Admin API 调用链、输出结构与错误处理机制,从而在 Agent 工作流中可靠地列举指定 Cloud SQL 实例下的所有数据库。
工具概述
cloud-sql-list-databases是 MCP Toolbox 中面向 Cloud SQL 管理场景的只读工具,用于列举指定 Google Cloud 项目和 Cloud SQL 实例中的所有数据库。它归属于cloud-sql-adminsource 生态:工具本身不直接持有凭证或 API 客户端,而是通过配置中的source字段绑定一个cloud-sql-adminsource,由 source 统一负责与 Google Cloud SQL Admin API 的认证与通信。
关于cloud-sql-adminsource 的完整参数说明(如defaultProject、useClientOAuth、readOnly),参见仓库内的 Cloud SQL Admin Source 文档。
兼容 Source 与认证方式
该工具仅兼容cloud-sql-admin类型的 source。source 的认证支持两种方式:
- Application Default Credentials(ADC):默认行为。source 使用 ADC 与 Cloud SQL Admin API 交互,适合本地开发机、CI 环境(已配置
gcloud auth application-default login或 metadata 凭证)。 - 客户端 OAuth(Client-side OAuth):当 source 配置
useClientOAuth: true时,source 不再自行获取凭证,而是期望由客户端(例如 Web 浏览器中的 Agent 前端)在每次请求时提供 OAuth 2.0 access token。
source 的最小配置示例如下:
kind: source name: my-cloud-sql-admin type: cloud-sql-admintools.yaml 配置示例
下面是官方文档给出的完整配置示例:先声明一个cloud-sql-adminsource,再声明一个类型为cloud-sql-list-databases的 tool,并通过source字段将其绑定:
kind: source name: my-cloud-sql-admin-source type: cloud-sql-admin --- kind: tool name: list_my_databases type: cloud-sql-list-databases source: my-cloud-sql-admin-source description: Use this tool to list all Cloud SQL databases in an instance.几点说明:
name是该 tool 在本服务器中的唯一标识,Agent 通过它发起调用;type必须是cloud-sql-list-databases,这是工具类型注册名;source必须指向一个已声明的cloud-sql-adminsource,否则服务器启动阶段即会校验失败(见下文“启动期校验”);description是可选字段,它会被直接传递给 Agent 作为工具说明。若不配置,源码会注入默认描述(见下节)。
配置参考(Reference)
cloud-sql-list-databases工具支持以下配置字段:
| field | type | required | description |
|---|---|---|---|
| name | string | true | 工具名称,服务器内唯一。 |
| type | string | true | 必须为cloud-sql-list-databases。 |
| source | string | true | 要使用的cloud-sql-adminsource 的名称。 |
| description | string | false | 传递给 Agent 的工具描述。 |
| annotations | object | false | MCP 工具注解,例如读写语义声明(见下文)。 |
从源码 cloudsqllistdatabases.go 可以看到Config结构体的实际字段定义:
type Config struct { tools.ConfigBase `yaml:",inline"` Type string `yaml:"type" validate:"required"` Source string `yaml:"source" validate:"required"` Annotations *tools.ToolAnnotations `yaml:"annotations,omitempty"` }其中ConfigBase内联了name、description、authRequired等公共字段;Type与Source带有validate:"required"标签,即配置解析阶段就强制校验必填。
工具调用参数
cloud-sql-list-databases有两个必填参数:
| field | type | required | description |
|---|---|---|---|
| project | string | true | Google Cloud 项目 ID。 |
| instance | string | true | Cloud SQL 实例 ID。 |
这里有一个文档未展开、但对 Agent 使用体验很关键的细节——source 的defaultProject会“烘焙”进 project 参数。从 buildParams 的实现 可以看出:
func buildParams(project string) parameters.Parameters { projectParam := parameters.NewStringParameter("project", "The project ID") if project != "" { projectParam = parameters.NewStringParameter("project", "The GCP project ID. This is pre-configured; do not ask for it unless the user explicitly provides a different one.", parameters.WithStringDefault(project)) } return parameters.Parameters{ projectParam, parameters.NewStringParameter("instance", "The instance ID"), } }- 若 source 配置了
defaultProject,project参数会携带该默认值,且参数描述明确提示 Agent“无需再向用户索要项目 ID,除非用户显式提供另一个”; - 若未配置,
project仍是必填参数,Agent 需要向用户询问。
这种设计在仓库的预构建配置中可以印证,例如 cloud-sql-mysql-admin.yaml:
kind: source name: cloud-sql-admin-source type: cloud-sql-admin defaultProject: ${CLOUD_SQL_MYSQL_PROJECT:} readOnly: ${CLOUD_SQL_MYSQL_READONLY:false} --- kind: tool name: list_databases type: cloud-sql-list-databases source: cloud-sql-admin-source源码级执行流程
工具的实现位于 internal/tools/cloudsql/cloudsqllistdatabases/,整体链路可分为注册、校验、调用三步。
类型注册
工具类型在包初始化时通过init()注册到全局工具注册表:
const resourceType string = "cloud-sql-list-databases" func init() { if !tools.Register(resourceType, newConfig) { panic(fmt.Sprintf("tool type %q already registered", resourceType)) } }因此tools.yaml中type: cloud-sql-list-databases能被发现并解析,依赖的就是这一注册机制。
启动期 Source 兼容性校验
工具声明了一个“兼容 source”接口,用于在服务启动时验证所绑定的 source 是否具备所需能力:
type compatibleSource interface { GetDefaultProject() string UseClientAuthorization() bool ListDatabase(context.Context, string, string, string) (any, error) }ValidateSource会对配置中的 source 做类型断言,不满足接口则直接报错:invalid source for "cloud-sql-list-databases" tool: source "..." is not a compatible type。也就是说,把cloud-sql-admin之外的 source(例如普通cloud-sql-mysql数据源)绑定到该工具上,会在启动阶段失败而不是运行期失败。
Invoke 调用链
Invoke 方法 是工具被 Agent 调用时的入口:
func (t Tool) Invoke(ctx context.Context, s sources.Source, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) { source, ok := s.(compatibleSource) if !ok { return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, nil) } paramsMap := params.AsMap() project, ok := paramsMap["project"].(string) if !ok { return nil, util.NewAgentError("missing 'project' parameter", nil) } instance, ok := paramsMap["instance"].(string) if !ok { return nil, util.NewAgentError("missing 'instance' parameter", nil) } resp, err := source.ListDatabase(ctx, project, instance, string(accessToken)) if err != nil { return nil, util.ProcessGcpError(err) } return resp, nil }几个值得注意的行为:
- 参数缺失被归类为 AgentError。MCP Toolbox 区分了面向客户端的错误(ClientServerError)与面向 Agent 的错误(AgentError)。缺少
project/instance属于“Agent 本可以提供却未提供”的情况,返回 AgentError 可让 Agent 据此向用户追问,而不是把失败当成服务器故障; - GCP 错误统一经
util.ProcessGcpError转换。API 侧返回的权限错误、配额错误等会被规整为 Toolbox 标准错误格式,便于上层统一呈现; - accessToken 透传。
accessToken参数对应useClientOAuth: true场景下的客户端 OAuth token,由 source 的GetService消费。
Source 侧的 API 调用与输出裁剪
真正的 API 调用发生在 cloud-sql-admin source 的 ListDatabase 方法:
func (s *Source) ListDatabase(ctx context.Context, project, instance, accessToken string) (any, error) { service, err := s.GetService(ctx, accessToken) if err != nil { return nil, err } resp, err := service.Databases.List(project, instance).Do() if err != nil { return nil, fmt.Errorf("error listing databases: %w", err) } if resp.Items == nil { return []any{}, nil } type databaseInfo struct { Name string `json:"name"` Charset string `json:"charset"` Collation string `json:"collation"` } var databases []databaseInfo for _, item := range resp.Items { databases = append(databases, databaseInfo{ Name: item.Name, Charset: item.Charset, Collation: item.Collation, }) } return databases, nil }这里有两个影响实际使用行为的设计:
- 只返回精简字段。Cloud SQL Admin API 的原始
Database对象包含kind、state、instance等冗余字段,source 层将其裁剪为name、charset、collation三个字段,降低传给 LLM 的 token 噪音; - 空实例返回空数组而非 null。当实例下没有任何数据库(
resp.Items == nil)时,返回[]any{},保证输出始终是 JSON 数组,Agent 无需处理 null 分支。
输出格式
调用成功后,工具返回一个 JSON 数组,每个元素对应一个数据库。集成测试 tests/cloudsql/cloud_sql_list_databases_test.go 中的期望结果直观展示了这一格式:
[ {"name": "db1", "charset": "utf8", "collation": "utf8_general_ci"}, {"name": "db2", "charset": "utf8mb4", "collation": "utf8mb4_unicode_ci"} ]测试验证
仓库中该工具有两层测试覆盖,可作为行为依据:
- 配置解析单元测试:cloudsqllistdatabases_test.go 通过
server.UnmarshalPrimitiveConfig验证 YAML 到Config结构体的解析,确认name、type、source、description字段正确落位; - 端到端集成测试:cloud_sql_list_databases_test.go 启动真实 toolbox 服务器(
--enable-api),并用httptest假服务器拦截发往https://sqladmin.googleapis.com的请求,模拟 Admin API 响应。该测试同时断言了两类行为:- 正常调用(
{"project": "p1", "instance": "i1"})返回上述双数据库 JSON 数组; - 缺少
instance参数时返回{"error":"parameter \"instance\" is required"}——即参数必填性在参数校验层强制执行; - 还校验了出站请求的
User-Agent携带genai-toolbox/前缀(见 测试 handler)。
- 正常调用(
默认只读注解与预构建工具集
该工具在初始化时默认打上只读注解。从 Initialize 方法 可以看到:
tools.GetAnnotationsOrDefault(cfg.Annotations, tools.NewReadOnlyAnnotations)即若用户未在annotations中显式声明,工具会默认获得readOnlyHint: true语义,向支持 MCP 注解的客户端表明这是一个只读查询操作;若用户确需覆盖,可通过annotations字段自定义。
在仓库的预构建配置中,cloud-sql-list-databases是 MySQL、PostgreSQL、SQL Server 三套 Cloud SQL Admin 预构建(如 cloud-sql-mysql-admin.yaml)的标配工具之一,与cloud-sql-create-database、cloud-sql-list-instances、cloud-sql-create-users等组合成完整的实例管理工具集。使用时可通过环境变量注入defaultProject(如CLOUD_SQL_MYSQL_PROJECT),并配合readOnly开关在 source 层面抑制写操作类工具——需要说明的是,readOnly抑制的是写能力管理工具,cloud-sql-list-databases本身是只读的,不受该开关移除。
小结
cloud-sql-list-databases以极小的配置面(type+source)提供了对 Cloud SQL 实例数据库清单的标准查询能力。其设计上有三个对集成方重要的点:一是在 source 配置defaultProject后,project参数自动获得默认值,减少 Agent 的交互式追问;二是 source 层将 API 响应裁剪为name/charset/collation三字段并保持“空实例返回空数组”的稳定输出;三是参数缺失返回 AgentError、API 失败经ProcessGcpError规整,使错误在 Agent 工作流中可解释、可恢复。以上行为均有对应源码与测试(工具实现、source 实现、集成测试)可直接核验。
【免费下载链接】mcp-toolboxMCP Toolbox for Databases is an open source MCP server for databases.项目地址: https://gitcode.com/GitHub_Trending/ge/mcp-toolbox
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考