
MCP Toolbox for Databases 中的 bigquery-execute-sqlGoogleSQL 动态执行工具与 writeMode、allowedDatasets 安全机制详解【免费下载链接】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下文简称 Toolbox的 BigQuery 集成中bigquery-execute-sql是最灵活的一类工具它允许 LLM 直接提交任意 GoogleSQL 语句而非受限于固定的预构建查询。本文以官方文档 bigquery-execute-sql 工具说明 为主体结合 工具实现源码、BigQuery 数据源实现 与 配套测试完整讲解该工具的配置方式、sql/dry_run参数、readOnly×writeMode行为矩阵、allowedDatasets数据集白名单的底层校验链路以及 MCP 工具注解的动态行为帮助你在 Agent 工作流中安全地启用 SQL 执行能力。工具概述与参数说明bigquery-execute-sql工具的作用是在 BigQuery 上执行一条 GoogleSQL 语句。它接受两个参数参数类型必填说明sqlstring是要执行的 GoogleSQL 语句。参数描述会根据 source 的writeMode与allowedDatasets动态变化见下文。dry_runboolean否设为true时查询只被校验而不实际运行返回关于该执行的元信息dry-run job 信息。默认false。从源码 buildParams 可以看到sql参数的描述文本是动态生成的当 source 处于blocked模式时描述会追加 In blocked mode, only SELECT statements are allowed; other statement types will fail.当 source 处于protected模式时描述会追加 Only SELECT statements and writes to the sessions temporary dataset are allowed (e.g.,CREATE TEMP TABLE ...).当配置了allowedDatasets时描述会追加约束说明仅一个数据集时会提示表必须用数据集限定名书写如my_dataset.my_table多个数据集时会列出全部允许的project.dataset列表。这意味着 LLM 在tools/list阶段看到的就是与其权限边界一致的参数说明而不是事后在tools/call时才被拒绝。配置示例与字段参考最小可用的工具配置如下继承自官方文档 Example 一节kind: tool name: execute_sql_tool type: bigquery-execute-sql source: my-bigquery-source description: Use this tool to execute sql statement.该工具引用一个type: bigquery的数据源。完整的 BigQuery source 配置含readOnly、writeMode、allowedDatasets、useClientOAuth、maximumBytesBilled等字段说明见 BigQuery Source 文档BigQuery 预置工具集配置可参考 bigquery 预置配置。工具的字段参考与官方文档 Reference 一节一致字段类型必填说明typestring是必须为bigquery-execute-sql。sourcestring是SQL 所执行的数据源名称必须是bigquery类型 source。descriptionstring是传给 LLM 的工具描述。另外从 Config 结构体 可以看到工具配置还支持可选的annotations字段MCP 工具注解覆盖项用于自定义readOnlyHint、destructiveHint等未显式指定时的默认行为见下文MCP 工具注解一节。readOnly × writeMode 行为矩阵官方文档给出的核心行为矩阵如下readOnlywriteMode工具行为MCP 工具注解false默认allowed默认允许所有 SQL 语句默认注解无特殊提示trueblockedreadOnly: true时的默认值只允许SELECT其他类型语句如INSERT、UPDATE、CREATE一律拒绝readOnlyHint: truetrueprotected启用基于会话session的执行所有表都可SELECT但写操作只允许落在该会话的临时数据集如CREATE TEMP TABLE ...readOnlyHint: true注意相互冲突的配置如readOnly: true搭配writeMode: allowed会在服务器启动阶段被直接拒绝。该矩阵在源码中可以得到完整印证默认值推导在 newConfig 中未显式设置writeMode时默认取allowed若同时声明readOnly: true则writeMode自动推导为blocked。启动期冲突校验在 Source.Initialize 中readOnly布尔值必须与writeMode的只读语义一致——readOnly: true只能搭配blocked或protectedreadOnly: false只能搭配allowed否则返回 conflicting source configuration 错误。运行时语句类型拦截在 Tool.Invoke 中blocked模式下 dry-run 得到的statementType若不是SELECT直接返回 write mode is blocked, only SELECT statements are allowedprotected模式下则检查 dry-run 返回的DestinationTable若写入目标不属于会话临时数据集session.DatasetID则拒绝。此外writeMode: protected有一个硬性限制它不能与useClientOAuth一起使用因为客户端 OAuth 场景下每次工具调用都会创建新客户端、无法维持跨调用的同一会话该约束同样在 Initialize 中校验。执行流程先 dry-run 校验再真实执行理解dry_run参数的关键是该工具内部永远先执行一次 BigQuery dry-run jobdry_run: true只是决定校验后是否继续真实执行。从 Invoke 调用链 看通过 source 的RetrieveClientAndService取得 BigQuery 客户端客户端 OAuth 模式下使用调用方 token 创建缓存客户端若 source 处于protected模式先取/建 BigQuery session并把session_id作为ConnectionProperty注入后续查询调用 bqutil.DryRunQuery 提交一个dryRun: true的 job同时透传 source 级maximumBytesBilled上限从返回的 job 中读出statementType与引用表信息依据 writeMode 与 allowedDatasets 执行权限判定见下两节若调用方传了dry_run: true把整个 dry-run job 以格式化 JSON 返回不执行查询否则经 source 的RunSQL真实执行并把mcp-toolbox-tool: bigquery-execute-sql作为 job label 附加配合 SQL Commenter 标签可在INFORMATION_SCHEMA.JOBS与账单导出中按工具归因见 source 文档 Advanced Usage。因此dry_run是一个零成本不扫描数据、不计费执行的预检开关Agent 可以借此先确认查询语法、预估扫描量statistics中的 estimated bytes再决定真实执行。执行结果的返回形态由 source 层的 RunSQL 决定结果行以列名 → 值的有序 map 数组返回行数受 source 的maxQueryResultRows限制默认 50SELECT查得 0 行时返回文本 The query returned 0 rows.DML/DDL 等无结果集语句返回 Query executed successfully and returned no content.。数值上NUMERIC/BIGNUMERIC底层*big.Rat会被规范化为最多 38 位精度、去尾零的十进制字符串BYTES保持 Base64。protected 模式下的会话管理writeMode: protected依赖 BigQuery 的会话能力会话由 newBigQuerySessionProvider 管理其生命周期策略值得注意会话通过一个带CreateSession: true的 dry-run job 创建拿到session_id与会话临时数据集 ID已有会话先做一次带session_id的SELECT 1校验 dry-run成功则复用并刷新LastUsed绝对寿命为 7 天距寿命终点 30 分钟内的会话会被主动换新源码注释说明假设单任务不超过 30 分钟避免任务中途失效按 source 文档 的说法会话在 24 小时不活跃或 7 天后被服务端终止下次请求会新建会话前一会话的临时数据随之丢失所有关联该 source 的工具共享同一个会话因此protected模式不推荐多用户共享的服务端部署。allowedDatasets数据集白名单的双重校验当 source 配置了allowedDatasets时bigquery-execute-sql在执行前会对查询做静态分析访问白名单外数据集的查询会被拒绝。官方文档指出被一并禁止的操作包括数据集级操作如CREATE SCHEMA、ALTER SCHEMA无法静态分析出访问表的操作如EXECUTE IMMEDIATE、CREATE PROCEDURE、CALL。源码中这一机制由两条互补的校验链路实现均发生在 dry-run 之后的权限判定段Invoke L173-L218链路一dry-run 元数据最可靠来源。从 dry-run job 的statistics.query中收集ReferencedTables、DdlTargetTable、DdlDestinationTable三处表引用汇总成project.dataset.table形式的去重集合。同时按statementType直接拦截无法静态分析的类型CREATE_SCHEMA/DROP_SCHEMA/ALTER_SCHEMACREATE_FUNCTION/CREATE_TABLE_FUNCTION/CREATE_PROCEDURE以及CALL——拒绝理由都是其内容无法被安全分析。链路二内置 SQL 词法解析器兜底。TableParser 是一个手写状态机能识别字符串/原始字符串含r、反引号、单行/多行注释、子查询括号嵌套等用于捕获 dry-run 可能绕过的表和视图引用。它还会额外拦截几类危险模式标识符中出现EXTERNAL_QUERY一律拒绝外部查询无法追踪目标INFORMATION_SCHEMA查询仅允许数据集级视图TABLES、COLUMNS、PARTITIONS等白名单见 datasetLevelInformationSchemaViews且必须带数据集前缀——SELECT * FROM region-us.INFORMATION_SCHEMA.SCHEMATA这类项目/区域级查询会被拒绝词法层面的CREATE/ALTER/DROP SCHEMA|DATASET、EXECUTE IMMEDIATE、CREATE [OR REPLACE] PROCEDURE|FUNCTION同样会被解析器直接报错。最终两条链路得到的所有表 ID 逐一调用 IsDatasetAllowed 比对白名单任一越界即返回类似 query accesses dataset project.dataset, which is not in the allowed list 的错误。白名单本身在 source 初始化时还会逐个通过 API 验证存在性见 Initialize L222-L254避免配置了不存在的白名单这类静默失效。集成测试 TestInvokeDatasetRestrictions 用模拟 BigQuery REST 服务覆盖了上述边界允许数据集内表、INFORMATION_SCHEMA.TABLES带前缀放行白名单外表、混合 JOIN 越权表、区域级INFORMATION_SCHEMA.SCHEMATA、EXTERNAL_QUERY全部被拒绝可作为实现行为的直接验证依据。MCP 工具注解的动态行为bigquery-execute-sql的 MCP 注解不是写死的而是根据 source 的只读状态动态生成。GetAnnotations 的逻辑是若 source 判定为只读writeMode为blocked或protected见 Source.IsReadOnly则在基础注解上强制覆盖readOnlyHint: true、destructiveHint: false且保留调用方显式指定的其他提示位如idempotentHint、openWorldHint。TestGetAnnotations 验证了全部组合allowed模式保持默认的 destructive 注解blocked/protected模式翻转为只读注解显式只读注解在只读 source 下不被改变。这让客户端IDE、Agent 框架能依据注解在 UI 上做风险分级与行为矩阵中MCP Tool Annotations一列一一对应。适用场景与使用限制官方文档对该工具的定位非常明确它面向带人工介入human-in-the-loop的开发者辅助工作流不应直接用于生产环境的无人值守 Agent。这一限制与该工具任意 SQL 可执行的本质相符——即便叠加blocked/protected模式与allowedDatasetsLLM 生成的 SQL 仍可能产生昂贵的全表扫描。落地时建议配合 source 层的其余安全阀maximumBytesBilled单查询扫描字节上限超限的查询在 dry-run 阶段即失败该值同时注入内部 dry-run 与真实执行见 RunSQL L625-L627maxQueryResultRows限制返回给 LLM 的行数默认 50控制上下文体积readOnly: true或writeMode: blocked把工具收敛为纯查询入口。小结bigquery-execute-sql通过配置期约束writeMode、allowedDatasets 调用期双重静态分析dry-run 元数据 内置解析器 动态 MCP 注解三层设计把自由 SQL 执行的风险收敛到可审计的范围dry_run提供零成本预检blocked/protected控制写权限allowedDatasets圈定数据边界而 job label 使每次执行都能在INFORMATION_SCHEMA.JOBS中归因到具体工具。相关实现集中在 internal/tools/bigquery/bigqueryexecutesql/bigqueryexecutesql.go、internal/sources/bigquery/bigquery.go 与 internal/tools/bigquery/bigquerycommon/table_name_parser.go可作为进一步深入阅读的入口。【免费下载链接】mcp-toolboxMCP Toolbox for Databases is an open source MCP server for databases.项目地址: https://gitcode.com/GitHub_Trending/ge/mcp-toolbox创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考