
MCP Toolbox looker-query 工具详解基于 Looker 语义模型执行内联查询【免费下载链接】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 开源仓库中的looker-query工具文档docs/en/integrations/looker/tools/looker-query.md为主体结合 internal/tools/looker/lookerquery/lookerquery.go、internal/tools/looker/lookercommon/lookercommon.go 与预置配置 internal/prebuiltconfigs/tools/looker.yaml 展开。读完本文你将掌握looker-query的 10 个参数语义、LLM 场景下的 YAML 工具定义方式、Looker 过滤器表达式与动态字段的写法以及该工具在源码层面的执行链路能够直接在 MCP Toolbox 中配置并运行基于 LookML 模型的查询。looker-query 是什么looker-query是 MCP Toolbox 中用于运行内联查询的工具它接收一组描述查询意图的参数模型、探索视图、字段、过滤条件等直接调用 Looker 的run_inline_query类 API将查询结果以 JSON 数组形式返回给调用方LLM。它不需要预先保存一个 Look 或 Dashboard而是即写即查非常适合 Agent 在对话中临时探索数据先通过get_models、get_explores、get_dimensions等元数据工具摸清可用的模型与字段再通过looker-query落地实际的数据查询。从源码看looker-query在 internal/tools/looker/lookerquery/lookerquery.go 中注册了资源类型常量resourceType looker-query其Invoke方法依次完成三件事见 lookerquery.go#L112-L151通过lookercommon.ProcessQueryArgs把参数组装成v4.WriteQuery通过lookercommon.RunInlineQuery以json格式执行内联查询将响应json.Unmarshal成[]any后原样返回。十个核心参数looker-query共接收十个参数其中前三个为必填其余可选。其定义集中位于 internal/tools/looker/lookercommon/lookercommon.go#L116-L169 的GetQueryParameters()中#参数必填说明1model是包含该 explore 的 LookML 模型名来自get_models2explore是要查询的 explore来自get_explores3fields是查询要返回的字段列表维度、度量、过滤器字段或参数4filters否过滤器映射键为view.field全限定字段名值为 Looker 过滤器表达式5filter_expression否Looker 表达式过滤器字符串自定义过滤支持复杂逻辑与字段间比较6dynamic_fields否动态字段数组表计算、自定义度量、自定义维度以 JSON 对象定义7pivots否透视字段列表必须同时包含在fields中8sorts否排序字段列表可带方向如[view.field desc]9limit否行数上限默认 500传-1表示不限制10tz否查询时区如America/Los_Angeles不传时自动取运行环境本地时区几点值得注意的细节fields在源码中定义为数组参数每个元素对应parameters.NewStringParameter(field, ...)lookercommon.go#L119-L122limit的默认值 500 直接体现在参数定义里parameters.NewIntParameter(limit, The row limit., parameters.WithIntDefault(500))lookercommon.go#L147filters是 map 参数默认空映射pivots、sorts、dynamic_fields是数组参数默认空数组lookercommon.go#L123-L155tz若不显式给出ProcessQueryArgs会通过tzlocal.RuntimeTZ()读取运行环境本地时区失败时回退为Etc/UTClookercommon.go#L338-L348。filters 的写法约定filters的每个键必须是全限定的view_name.field_name且必须逐字取自get_dimensions、get_measures、get_filters或get_parameters的返回结果——视图前缀和点号不可省略。取值方面值按裸传处理不要额外包裹引号对 LookMLparameter字段使用原始allowed_value如first_touch而非first_touch判空用not null而不是-NULL若值本身包含逗号需用单引号包裹如New York, NY若字段suggestable为 true可先调用get_field_value_suggestions工具获取合法取值。在源码层面ProcessQueryArgs还会自动剥掉键和字符串值外层的单/双引号一层lookercommon.go#L306-L325并对 LookMLtype: unquoted参数做通配符元字符转义Looker 将_视为单字符通配符、%视为多字符通配符未转义的值如first_touch会被解析成first单字符通配符touch并触发 400 错误EscapeUnquotedParameterFilters会先拉取 explore 的 parameter 元数据再对命中 unquoted 类型的过滤器值做幂等转义lookercommon.go#L184-L290。filter_expression 表达式过滤器filter_expression是 Looker 的表达式过滤器自定义过滤用于表达普通过滤器难以描述的逻辑字段引用使用${view.field_name}语法支持逻辑运算符AND、OR、NOT与比较运算符支持 Looker 内置函数matches_filter、now、add_days、diff_days等。官方预置描述中给出的三个典型示例${orders.order_date} add_years(-1, now())${activity.email} ! ${activity_drive_facts.current_owner_email}matches_filter(${order.order_month}, 24 months) AND matches_filter(${order.order_month}, before 2024/07/01)dynamic_fields 动态字段dynamic_fields允许在查询中临时定义模型中没有的字段以 JSON 对象数组传入适合临时计算场景。三类常见形态取自 internal/prebuiltconfigs/tools/looker.yaml表计算Table Calculation[{table_calculation: test, label: test, expression: ${order_items.total_sale_price} * 0.8, _type_hint: number}]自定义维度Custom Dimension[{dimension: days_since_order, label: days since order, expression: diff_days(${order.order_date}, now()), _type_hint: number}]自定义度量Custom Measure[{measure: sum_of_revenue, label: Sum of Revenue, based_on: training.revenue, type: sum, _type_hint: number}]源码中dynamic_fields会在ProcessQueryArgs内被json.Marshal序列化为字符串后赋给WriteQuery.DynamicFieldslookercommon.go#L359-L369。兼容的 Source 类型looker-query只能运行在兼容的 Looker Source 上。源码通过compatibleSource接口lookerquery.go#L50-L55约束来源类型接口要求实现UseClientAuthorization() boolGetAuthTokenHeaderName() stringLookerApiSettings() *rtl.ApiSettingsGetLookerSDK(context.Context, string) (*v4.LookerSDK, error)ValidateSource会对配置阶段声明的source做类型断言不匹配即报错invalid source for looker-query toollookerquery.go#L104-L110。当前仓库中type: looker的 Sourceinternal/sources/looker/looker.go即满足该接口因此预置配置中默认使用名为looker-source的 Sourcekind: source name: looker-source type: looker base_url: ${LOOKER_BASE_URL} client_id: ${LOOKER_CLIENT_ID:} client_secret: ${LOOKER_CLIENT_SECRET:} verify_ssl: ${LOOKER_VERIFY_SSL:true} timeout: 600s use_client_oauth: ${LOOKER_USE_CLIENT_OAUTH:false} show_hidden_models: ${LOOKER_SHOW_HIDDEN_MODELS:true} show_hidden_explores: ${LOOKER_SHOW_HIDDEN_EXPLORES:true} show_hidden_fields: ${LOOKER_SHOW_HIDDEN_FIELDS:true}在 MCP Toolbox 中定义一个 looker-query 工具工具通过 YAML 声明式配置注册。官方文档给出的最小可运行示例如下摘自 looker-query.mdkind: tool name: query type: looker-query source: looker-source description: | This tool runs a query against a LookML model and returns the results in JSON format. Required Parameters: - model_name: The name of the LookML model (from get_models). - explore_name: The name of the explore (from get_explores). - fields: A list of field names (dimensions, measures, filters, or parameters) to include in the query. Optional Parameters: - pivots: A list of fields to pivot the results by. These fields must also be included in the fields list. - filters: A map of filter expressions, e.g., {view_name.field_name: value, view_name.date: 7 days}. - Each key must be a fully-scoped view_name.field_name, copied verbatim from get_dimensions, get_measures, get_filters, or get_parameters. The view prefix and the dot are required. - Each value is a Looker filter expression. Pass values bare: do not wrap them in extra quote characters. For LookML parameter fields, use the raw allowed_value (e.g. first_touch, not first_touch). - Use not null instead of -NULL. - If a value contains a comma, enclose it in single quotes (e.g., New York, NY). - filter_expression: A Looker expression filter string (custom filter). This allows complex logic and comparing fields. - Reference fields using ${view.field_name} syntax. - Supports logical operators (AND, OR, NOT) and comparison operators. - Supports Looker functions (e.g., matches_filter, now, add_days, diff_days). - Examples: - ${orders.order_date} add_years(-1, now()) - ${activity.email} ! ${activity_drive_facts.current_owner_email} - matches_filter(${order.order_month}, 24 months) AND matches_filter(${order.order_month}, before 2024/07/01) - dynamic_fields: An optional array of dynamic fields (table calculations, custom measures, custom dimensions) defined as JSON objects. - Useful for ad-hoc calculations that are not defined in the LookML model. - Reference fields using ${view.field_name} syntax. - Examples: - Table Calculation: [{table_calculation: test, label: test, expression: ${order_items.total_sale_price} * 0.8, _type_hint: number}] - Custom Dimension: [{dimension: days_since_order, label: days since order, expression: diff_days(${order.order_date}, now()), _type_hint: number}] - Custom Measure: [{measure: sum_of_revenue, label: Sum of Revenue, based_on: training.revenue, type: sum, _type_hint: number}] - sorts: A list of fields to sort by, optionally including direction (e.g., [view.field desc]). - limit: Row limit (default 500). Use -1 for unlimited. - query_timezone: specific timezone for the query (e.g. America/Los_Angeles). Note: Use get_dimensions, get_measures, get_filters, and get_parameters to find valid fields. The result of the query tool is JSON工具级配置字段仅三个见 looker-query.md 的 Reference 表fieldtyperequireddescriptiontypestringtrue必须为looker-querysourcestringtrue查询要执行于其上的 Source 名称。descriptionstringtrue传给 LLM 的工具描述。对应的 Go 结构体在 lookerquery.go#L57-L62 中定义Config内联了tools.ConfigBase并带type、source两个必填校验字段和可选的annotations。Initialize中若description为空会直接报错lookerquery.go#L71-L74并默认以只读注解NewReadOnlyAnnotations注册工具——这一点与查询类工具不应产生副作用的定位一致。测试用例 internal/tools/looker/lookerquery/lookerquery_test.go 也验证了标准 YAMLtype: looker-querysourcedescription可被正确解析而未知字段如method会导致解析失败。实际使用中无需手写上述冗长描述——仓库在 internal/prebuiltconfigs/tools/looker.yaml 中提供了完整的预置工具集含get_models、get_explores、get_dimensions、get_measures、get_filters、get_parameters、get_field_value_suggestions、query、query_sql、query_url等其中query工具即是本文主角looker-query的完整描述版本。这些元数据工具与looker-query形成标准协作流程先用前者枚举合法字段名再构造过滤器与动态字段最后执行查询。执行链路与结果格式一次looker-query调用的内部流程可以归纳为参数装配ProcessQueryArgs将十个参数转换为 Looker SDK 的v4.WriteQuery其中model映射到Model、explore映射到View、fields/pivots/sorts映射为字符串数组、filters映射为 map、limit转为字符串、filter_expression与dynamic_fields转为可选指针lookercommon.go#L292-L384获取 SDKsource.GetLookerSDK根据认证模式返回 SDK 实例——若use_client_oauth为 false使用预置的client_id/client_secret登录会话否则携带调用方传入的访问令牌构建带Authorization头的 SDKinternal/sources/looker/looker.go#L249-L281转义处理对命中type: unquoted参数的过滤器值做通配符转义失败仅告警不阻断保证无 explore 读权限的调用方其非参数查询仍能成功执行查询RunInlineQuery优先调用带query_api_client_context客户端名标记为MCP Toolbox的新版POST /queries/run_inline端点失败时回退到 SDK 原生RunInlineQuerylookercommon.go#L408-L432返回 JSON将字符串响应json.Unmarshal为[]any返回若底层响应含status401会转为401 Unauthorized错误lookerquery.go#L132-L138。因此工具的最终输出始终是一个 JSON 数组每行数据一个元素便于 LLM 直接解析为结构化结果。在 Looker System Activity 中识别查询自 Looker v25.18 起looker-query产生的查询可以在 Looker 的 System Activity系统活动中识别在 History explore 中使用字段API Client Name即可筛选出 MCP Toolbox 发起的查询。这一机制来自上述第 4 步中写入的QueryApiClientContext{Name: MCP Toolbox}lookercommon.go#L386-L405它让运维与审计人员能够将流量明确归因到 MCP Toolbox 客户端方便排查慢查询、权限与用量问题。若你的 Looker 版本低于 v25.18则该归属字段不可用。常见问题与注意事项字段名拼写fields与filters的键必须与get_dimensions/get_measures/get_filters/get_parameters返回的全限定名完全一致视图前缀不可省略过滤器值不要加引号裸值传递是硬性约定unquoted类型参数还会自动做_、%、,、^的转义无需手工处理逗号值加单引号如New York, NY避免被 Looker 解析为过滤器值分隔符limit 默认 500需要全量结果时显式传-1时区不传tz时使用运行环境本地时区跨时区分析建议显式指定如America/Los_Angeles认证模式use_client_oauth: false时必须在 Source 中配置client_id/client_secret否则初始化即报错internal/sources/looker/looker.go#L130-L139。总结looker-query是 MCP Toolbox Looker 集成中执行查询的核心工具它以 10 个参数完整映射 Looker 内联查询的能力与get_models、get_explores、get_dimensions等元数据工具配合让 LLM 能够安全、可追溯地直接查询 LookML 语义模型并以 JSON 获取结果。无论是临时探索、数据分析 Agent 工作流还是通过 System Activity 做查询审计本文覆盖的配置、参数与源码级执行细节都能直接指导你的落地实践。【免费下载链接】mcp-toolboxMCP Toolbox for Databases is an open source MCP server for databases.项目地址: https://gitcode.com/GitHub_Trending/ge/mcp-toolbox创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考