使用 spanner-list-graphs 工具查询 Cloud Spanner 属性图 Schema 元数据:MCP Toolbox 完整实战指南
2026/9/15 14:47:45 网站建设 项目流程

使用 spanner-list-graphs 工具查询 Cloud Spanner 属性图 Schema 元数据:MCP Toolbox 完整实战指南

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

本文基于 MCP Toolbox 开源仓库(ge/mcp-toolbox)深入讲解spanner-list-graphs工具的完整用法:从 YAML 配置、参数语义、INFORMATION_SCHEMA.PROPERTY_GRAPHS底层查询实现,到 simple/detailed 两种输出格式的逐字段解析,以及将其接入 LLM Agent 的高级示例。读完本文,你将掌握如何通过 MCP 协议以只读方式获取 Spanner 数据库中属性图(Property Graph)的节点表、边表、标签与属性声明等完整元数据,并理解 GoogleSQL 方言限制背后的原因。

工具概览

spanner-list-graphs是 MCP Toolbox 中面向 Google Cloud Spanner 的内置工具,用于检索数据库中用户创建的属性图的完整 Schema 信息。它通过执行预定义的 SQL 查询,从INFORMATION_SCHEMA系统表中收集元数据,并返回结构化的 JSON,包含:

  • 节点表(node tables):图中作为节点的基表及其关键列、标签与属性定义;
  • 边表(edge tables):图中作为边的基表、源/目标节点表映射、键列与属性定义;
  • 标签(labels):节点与边对应的标签名称及其属性声明列表;
  • 属性声明(property declarations):图中各属性的名称与数据类型。

该工具由 spannerlistgraphs.go 实现。从源码结构看,它通过tools.Register("spanner-list-graphs", newConfig)注册到工具注册表(见resourceType常量与init()),属于标准的只读发现类工具,与同源族的spanner-list-tablesspanner-sqlspanner-search-catalog并列。

核心特性

  • 全面 Schema 信息:一次查询即可返回节点表、边表、标签和属性声明,覆盖属性图元数据的绝大部分维度;
  • 灵活过滤:支持列出全部图,也支持通过逗号分隔的图名列表精确过滤指定图;
  • 输出格式可选simple模式只返回图名列表,detailed模式返回完整 Schema 信息(默认值)。

典型使用场景

  1. 数据库文档生成:基于真实 Schema 自动生成数据库结构文档;
  2. Schema 校验:验证期望的图、节点表与边表是否真实存在;
  3. 迁移规划:在进行结构变更前完整了解当前 Schema 状态;
  4. 开发工具:构建需要感知数据库结构的辅助工具(如代码生成器、数据探查器);
  5. 审计与合规:跟踪 Schema 变更,满足数据治理策略的合规要求。

使用前提与关键限制

仅支持 GoogleSQL 方言

重要警告spanner-list-graphs仅适用于GoogleSQL方言的 Spanner 数据库,因为 Spanner Graph(属性图)功能在 PostgreSQL 方言中不可用。

这一限制不仅是文档声明,也在源码中被强制执行:工具在Invoke中通过source.DatabaseDialect()运行时检查方言,若返回值不等于googlesql,会直接返回 Agent 错误:

operation not supported: The 'spanner-list-graphs' tool is only available for GoogleSQL dialect databases. Your current database dialect is '...'

对应代码位于 spannerlistgraphs.go。注释明确说明检查放在运行时而非启动时,因此你可以在同一个配置文件中声明多个 Spanner source,只要 GoogleSQL 方言的 source 才会被该工具兼容。

IAM 权限

工具以只读方式执行查询,运行 MCP Toolbox 的 IAM 身份需要具备以下权限(来自 spanner-googlesql-dialect.md):

  • Cloud Spanner Database Readerroles/spanner.databaseReader):执行 DQL 查询与列出表/图所需的最小权限;
  • 若还需通过其他工具执行 DML,需要Cloud Spanner Database Userroles/spanner.databaseUser)。

Toolbox 使用 Application Default Credentials (ADC) 进行认证与授权,配置服务器时需先完成 ADC 设置,并为身份授予相应 IAM 角色。

配置 Source 与 Tool

定义 Spanner 数据源

首先在 YAML 配置中定义一个type: spanner的 source。字段说明(完整参考见 source.md):

字段类型必填说明
typestring必须为"spanner"
projectstringGCP 项目 ID(如"my-project-id"
instancestringSpanner 实例名称
databasestring实例上的数据库名称
dialectstring必须为googlesqlpostgresql,默认googlesql

在 spanner.go 中可以看到,newConfig会在解码前把Dialect默认值预置为googlesql,因此省略dialect字段的 source 天然满足本工具的要求。

基础用法——列出所有图

kind: source name: my-spanner-db type: spanner project: ${SPANNER_PROJECT} instance: ${SPANNER_INSTANCE} database: ${SPANNER_DATABASE} dialect: googlesql # wont work for postgresql --- kind: tool name: list_all_graphs type: spanner-list-graphs source: my-spanner-db description: Lists all graphs with their complete schema information

列出指定图

kind: tool name: list_specific_graphs type: spanner-list-graphs source: my-spanner-db description: | Lists schema information for specific graphs. Example usage: { "graph_names": "FinGraph,SocialGraph", "output_format": "detailed" }

工具字段参考(Reference)

字段类型必填说明
typestring必须为"spanner-list-graphs"
sourcestring要查询的 Spanner source 名称(方言必须为 GoogleSQL)
descriptionstring传给 LLM 的工具描述
authRequiredstring[]调用该工具所需的认证服务列表

spannerlistgraphs_test.go中的TestParseFromYamlListGraphs用例验证了三种配置形态的解析结果:最小配置(仅 name/type/source)、带description的常规配置,以及带authRequired的认证配置——这为上述字段提供了测试级佐证(见 spannerlistgraphs_test.go)。

参数详解

工具接受两个可选参数(定义见 spannerlistgraphs.go):

参数类型默认值说明
graph_namesstring""逗号分隔的图名列表,用于过滤;为空时列出用户可访问 Schema 中的所有图
output_formatstring"detailed"输出格式:simple仅返回图名,detailed返回完整 Schema 信息

源码层面的默认值处理逻辑:

  • graph_names通过parameters.NewStringParameter声明,默认空字符串;
  • output_format默认"detailed",在Invoke中还会再次兜底:if outputFormat == "" { outputFormat = "detailed" }(spannerlistgraphs.go),即使 LLM 传入空值也不会出现未定义格式。

两个参数连同查询语句一起作为参数绑定传入source.RunSQL

stmtParams := map[string]interface{}{ "graph_names": graphNames, "output_format": outputFormat, } resp, err := source.RunSQL(ctx, true, googleSQLStatement, stmtParams)

注意这里的readOnly=true,结合 spanner.go 中RunSQL的实现:只读路径使用s.SpannerClient().Single().Query(ctx, stmt)(单次只读快照事务)执行查询,从机制上保证该工具不会修改任何数据。

底层实现:INFORMATION_SCHEMA 查询剖析

工具的查询逻辑集中在一个 GoogleSQL 语句中(spannerlistgraphs.go),核心分为三部分:

1. 图名过滤 CTE

WITH FilterGraphNames AS ( SELECT DISTINCT TRIM(name) AS GRAPH_NAME FROM UNNEST(IF(@graph_names = '' OR @graph_names IS NULL, ['%'], SPLIT(@graph_names, ','))) AS name )

graph_names为空时,CTE 生成单个通配符'%';否则按逗号拆分并去除首尾空白,得到目标图名集合。

2. 从系统表读取元数据

FROM INFORMATION_SCHEMA.PROPERTY_GRAPHS PG

INFORMATION_SCHEMA.PROPERTY_GRAPHS是 Spanner 内置的属性图元数据视图,每一行代表一个属性图,PROPERTY_GRAPH_METADATA_JSON列保存了节点表(nodeTables)、边表(edgeTables)、标签(labels)与属性声明(propertyDeclarations)的 JSON 结构。

3. 按输出格式拼装 JSON

CASE WHEN @output_format = 'simple' THEN CONCAT('{"name":"', IFNULL(REPLACE(PG.PROPERTY_GRAPH_NAME, '"', '\"'), ''), '"}') ELSE CONCAT( '{', '"schema_name":"', IFNULL(PG.PROPERTY_GRAPH_SCHEMA, ''), '",', '"object_name":"', IFNULL(PG.PROPERTY_GRAPH_NAME, ''), '",', '"catalog":"', IFNULL(JSON_VALUE(PG.PROPERTY_GRAPH_METADATA_JSON,"$.catalog"), ''), '",', '"node_tables":', TO_JSON_STRING(PG.PROPERTY_GRAPH_METADATA_JSON.nodeTables), ',', '"edge_tables":', TO_JSON_STRING(PG.PROPERTY_GRAPH_METADATA_JSON.edgeTables), ',', '"labels":', TO_JSON_STRING(PG.PROPERTY_GRAPH_METADATA_JSON.labels), ',', '"property_declarations":', TO_JSON_STRING(PG.PROPERTY_GRAPH_METADATA_JSON.propertyDeclarations), '}' ) END AS object_details

schema_name/object_name直接取自系统表的PROPERTY_GRAPH_SCHEMAPROPERTY_GRAPH_NAME列;catalog通过JSON_VALUE从元数据 JSON 提取;而节点表、边表、标签与属性声明则通过TO_JSON_STRING序列化为 JSON 字符串。

4. 结果行的 JSON 反序列化

查询结果经RunSQL返回前,会经过 spanner.go 中processRows的特殊处理:当列名是object_details时,将字符串内容json.Unmarshalmap[string]any后再加入结果行。这样最终返回给调用方(LLM/Agent)的就是可直接消费的嵌套 JSON 对象,而不是一段需要二次解析的字符串。

输出格式详解

Simple 格式

output_format"simple"时,仅返回图的名称,JSON 结构最小化:

[ { "object_details": { "name": "FinGraph" }, "object_name": "FinGraph", "schema_name": "" }, { "object_details": { "name": "SocialGraph" }, "object_name": "SocialGraph", "schema_name": "" } ]

Detailed 格式(默认)

output_format"detailed"(默认值)时,返回完整 Schema 信息。以下示例展示了一个名为SocialGraph的属性图,包含一个节点表Person与一条边表Knows

[ { "object_details": { "catalog": "", "edge_tables": [ { "baseCatalogName": "", "baseSchemaName": "", "baseTableName": "Knows", "destinationNodeTable": { "edgeTableColumns": [ "DstId" ], "nodeTableColumns": [ "Id" ], "nodeTableName": "Person" }, "keyColumns": [ "SrcId", "DstId" ], "kind": "EDGE", "labelNames": [ "Knows" ], "name": "Knows", "propertyDefinitions": [ { "propertyDeclarationName": "DstId", "valueExpressionSql": "DstId" }, { "propertyDeclarationName": "SrcId", "valueExpressionSql": "SrcId" } ], "sourceNodeTable": { "edgeTableColumns": [ "SrcId" ], "nodeTableColumns": [ "Id" ], "nodeTableName": "Person" } } ], "labels": [ { "name": "Knows", "propertyDeclarationNames": [ "DstId", "SrcId" ] }, { "name": "Person", "propertyDeclarationNames": [ "Id", "Name" ] } ], "node_tables": [ { "baseCatalogName": "", "baseSchemaName": "", "baseTableName": "Person", "keyColumns": [ "Id" ], "kind": "NODE", "labelNames": [ "Person" ], "name": "Person", "propertyDefinitions": [ { "propertyDeclarationName": "Id", "valueExpressionSql": "Id" }, { "propertyDeclarationName": "Name", "valueExpressionSql": "Name" } ] } ], "object_name": "SocialGraph", "property_declarations": [ { "name": "DstId", "type": "INT64" }, { "name": "Id", "type": "INT64" }, { "name": "Name", "type": "STRING" }, { "name": "SrcId", "type": "INT64" } ], "schema_name": "" }, "object_name": "SocialGraph", "schema_name": "" } ]

对返回结构的关键字段解读:

字段含义
object_name/schema_name属性图名称及其所属 Schema(用户 Schema 时通常为空字符串)
node_tables[].kind表角色,节点表为NODE,边表为EDGE
node_tables[].keyColumns表的键列(如PersonId
edge_tables[].sourceNodeTable/destinationNodeTable边的源/目标节点表,包含节点表名及对应的节点表列与边表列映射(如KnowsSrcIdPerson.Id表示起点)
edge_tables[].keyColumns边的键列组合(如["SrcId", "DstId"]
labels[].propertyDeclarationNames该标签关联的属性声明列表
property_declarations[]图中所有属性的名称与类型(如INT64STRING

高级用法:接入 LLM Agent

spanner-list-graphs接入 Agent 时,description字段会作为 LLM 的工具说明被传递,因此编写清晰、带示例的 description 能显著提升模型正确调用工具的准确率:

kind: source name: spanner-db type: spanner project: my-project instance: my-instance database: my-database dialect: googlesql --- kind: tool name: schema_inspector type: spanner-list-graphs source: spanner-db description: | Use this tool to inspect database schema information. You can: - List all graphs by leaving graph_names empty - Get specific graph schemas by providing comma-separated graph names - Choose between simple (names only) or detailed (full schema) output Examples: 1. List all graphs with details: {"output_format": "detailed"} 2. Get specific graphs: {"graph_names": "FinGraph,SocialGraph", "output_format": "detailed"} 3. Just get graph names: {"output_format": "simple"}

description为空,源码会注入一段默认描述(spannerlistgraphs.go),确保 LLM 始终能理解工具用途:

"Lists detailed graph schema information (node tables, edge tables, labels and property declarations) as JSON for user-created graphs. Filters by a comma-separated list of graph names. If names are omitted, lists all graphs. The output can be 'simple' (graph names only) or 'detailed' (full schema)."

使用预构建配置快速接入

MCP Toolbox 提供了现成的预构建配置(--prebuilt spanner),其中已包含list_graphs工具(见 spanner.yaml),并声明了所需环境变量与权限:

  • 环境变量SPANNER_PROJECT(GCP 项目 ID)、SPANNER_INSTANCE(实例 ID)、SPANNER_DATABASE(数据库 ID)、SPANNER_DIALECT(默认googlesql);
  • 权限roles/spanner.databaseReader(执行 DQL 与列出表/图);
  • 工具集list_graphs与其他工具一同打包在data工具组与data_with_discovery工具集中,适合与execute_sql_readonlylist_tables组合实现"探索 + 查询"的完整 Agent 工作流。

完整说明见 spanner-googlesql-dialect.md。

验证与测试

仓库中针对该工具提供了解析级单元测试TestParseFromYamlListGraphs(spannerlistgraphs_test.go),覆盖三种配置输入:

  1. 基础示例kind: tool+type: spanner-list-graphs+source+description,验证解析出的Config各字段;
  2. 带认证authRequired列表被正确解析;
  3. 最小配置:仅name/type/sourcedescription为空、AuthRequired为空切片。

这些用例可作为自定义配置时的回归参考,也可用于理解server.UnmarshalPrimitiveConfig的解析链路。

故障排查

  • 只读保证:该工具是只读的,通过单次只读快照事务(Single().Query)执行,不会修改任何数据;
  • 方言限制:仅支持 GoogleSQL 方言,PostgreSQL 方言数据库会在运行时返回明确的操作不支持错误;
  • 查询性能:大型数据库中图数量较多时,查询耗时可能更长——detailed模式需要为每个图序列化完整的元数据 JSON,若仅需图名列表,优先使用simple模式以减少返回体量。

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

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

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

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

立即咨询