MCP Toolbox 中的 looker-get-project-files 工具:基于 Looker SDK 枚举 LookML 项目文件

原创2026-09-14 12:16:541,388 阅读
文章标签:MCP 服务数据库后端AI 应用

MCP Toolbox 中的 looker-get-project-files 工具:基于 Looker SDK 枚举 LookML 项目文件

导读

looker-get-project-files 是 MCP Toolbox(MCP Toolbox for Databases)为 Looker 集成提供的一个只读工具,它接收一个 project_id 参数,返回该 LookML 项目中全部文件(如 .model.lkml、.view.lkml、.explore.lkml 等)的元数据列表,是 Agent 感知 LookML 项目结构、进而深入读取与修改 LookML 的起点。读完本文,你将掌握该工具的完整配置方式、与 looker-get-projects、looker-get-project-file 的组合用法,以及它在仓库源码中的调用链路与返回字段的真实构成。

工具是什么

根据官方文档 looker-get-project-files.md 的定义:

A looker-get-project-files tool returns all the LookML files in a project in the source.

该工具不接受其他过滤条件,唯一必需的入参是 project_id,用于定位 LookML 项目。它的典型输出是“一个 JSON 数组,数组元素是代表单个 LookML 文件的对象,包含 path、id、type、git_status 等详情”。

从语义上讲,它是一条**枚举型(List)**查询:只做读取、不做任何写操作,因此在源码实现中被标注为只读工具(详见下文“源码级实现”)。

在 LookML 工具链中的位置

looker-get-project-files 不是孤立存在的,它处在 Looker 集成工具链的中间环节,与相邻两个工具配合构成“先找项目 → 再列文件 → 再读内容”的典型流程:

工具 入参 作用 文档
looker-get-projects 无 返回源上所有 LookML 项目,输出 project_id 与 project_name looker-get-projects.md
looker-get-project-files project_id(必填) 返回指定项目内的所有 LookML 文件列表 looker-get-project-files.md
looker-get-project-file project_id、file_path(均必填) 返回指定文件的原始文本内容 looker-get-project-file.md

三者协作时,project_id 由 get_projects 获得,file_path 通常由 get_project_files 的输出提供。预构建配置 looker-dev.yaml 中同时装配了这三个工具(其中 get_project_files 定义在第 117–129 行),说明它们被设计为配套使用的开发工具集。

在 Toolbox 配置文件中启用

在 MCP Toolbox 的配置文件中,工具以 kind: tool 的 YAML 文档形式声明。官方文档给出的完整示例如下:

kind: tool
name: get_project_files
type: looker-get-project-files
source: looker-source
description: |
  This tool retrieves a list of all LookML files within a specified project,
  providing details about each file.

  Parameters:
  - project_id (required): The unique ID of the LookML project, obtained from `get_projects`.

  Output:
  A JSON array of objects, each representing a LookML file and containing
  details such as `path`, `id`, `type`, and `git_status`.

字段参考

字段 类型 必填 说明
type string 是 必须为 "looker-get-project-files",工具注册标识,不可改动
source string 是 指向 Looker 源实例的名称,须与 kind: source 中定义的源名一致
description string 是 工具描述,会原样传递给 LLM,作为模型理解工具用途与参数的依据
name string 是 工具在 MCP 命名空间中的调用名(如 get_project_files),来自所有工具共用的 ConfigBase
annotations 对象 否 可选的 MCP Tool Annotations,如 readOnlyHint、idempotentHint 等

其中 name 与可选的 annotations 字段来自通用工具框架 tools.go 中定义的 ConfigBase,对所有类型工具统一生效。

必填与严格校验

从测试用例可以确认,配置解析是严格的:在 lookergetprojectfiles_test.go 中,TestFailParseFromYamlLookerGetProjectFiles 验证了在 looker-get-project-files 配置里加入不存在的 method: GOT 字段会直接报错 unknown field "method"。因此配置时只需、也只能使用上表列出的字段。同时,Initialize 中规定 description 为空时会返回错误 description is required for tool(见 lookergetprojectfiles.go),这与文档中 description 标为必填一致。

前置条件:Looker Source 的配置

该工具依赖 source 字段指向的 Looker 源。Source 的配置方式见 Looker 源文档,核心要点如下:

kind: 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}
  • base_url:Looker 服务器地址,不要带尾部斜杠;本地部署时可能需要追加 API 端口,如 https://looker.example.com:19999。
  • verify_ssl:除非使用自签名证书,否则应保持 true;任何非 true 的值都会被解释为 false。
  • client_id / client_secret:Looker 服务器分配的随机字符序列;若使用 Looker OAuth 或客户端授权转发则无需填写。
  • use_client_oauth:设为 'true' 时转发客户端 OAuth 访问令牌;为空字符串或 'false' 时禁用(默认禁用)。该配置与下文“客户端授权转发”直接相关。
  • 敏感信息建议使用 ${ENV_NAME} 环境变量替换而非硬编码。

源码级实现:一条从 YAML 到 Looker API 的完整链路

该工具的完整实现位于 lookergetprojectfiles.go,从注册到执行共四步,每一环都能在仓库源码中找到对应证据。

1. 类型注册

resourceType 常量被定义为 "looker-get-project-files",在包的 init() 中通过 tools.Register(resourceType, newConfig) 注册到全局工具注册表(tools.go)。如果该类型已被注册,Register 返回 false 并触发 panic,避免重复注册。配置解析时,框架按 type 在注册表中查找到 newConfig,用 YAML 解码器填充 Config 结构体。

2. 参数声明

Initialize 阶段声明了唯一的入参:

projectIdParameter := parameters.NewStringParameter("project_id", "The id of the project containing the files")

project_id 是必填字符串参数,其描述为“包含这些文件的项目 id”。随后该参数被打包进 parameters.Parameters,并生成工具 Manifest(含描述、参数定义与 authRequired),最终在 Invoke 中通过 params.AsMap() 取出:

projectId, ok := mapParams["project_id"].(string)
if !ok {
    return nil, util.NewAgentError(fmt.Sprintf("'project_id' must be a string, got %T", mapParams["project_id"]), nil)
}

如果模型传来的不是字符串类型,会返回 Agent 级错误。这是对文档“接受一个 project_id 参数”的代码级落实。

3. 调用 Looker SDK 的 AllProjectFiles

核心调用发生在 Invoke 中:

sdk, err := source.GetLookerSDK(ctx, string(accessToken))
...
resp, err := sdk.AllProjectFiles(projectId, "", source.LookerApiSettings())
  • GetLookerSDK 由 Looker 源实现(见 looker.go):若源启用了 use_client_oauth,则使用携带客户端访问令牌的传输层创建全新 SDK(并转发 X-Forwarded-For、X-Real-IP 等客户端 IP 头);否则复用源初始化时基于 client_id/client_secret 建立的共享客户端。
  • AllProjectFiles(projectId, "", apiSettings) 是 Looker SDK(looker-open-source/sdk-codegen/go 的 v4 版本)的 API 调用,第二个参数传空字符串表示不限制返回字段(fields)。

4. 响应整理与返回

AllProjectFiles 返回的是 Looker SDK 的 ProjectFile 对象列表,工具将其逐个转换为 map 并只保留非空字段:

vMap := make(map[string]any)
if v.Id != nil { vMap["id"] = *v.Id }
if v.Path != nil { vMap["path"] = *v.Path }
if v.Title != nil { vMap["title"] = *v.Title }
if v.Type != nil { vMap["type"] = *v.Type }
if v.Extension != nil { vMap["extension"] = *v.Extension }
if v.Editable != nil { vMap["editable"] = *v.Editable }
data = append(data, vMap)

因此,实际返回的每个文件对象可能包含 id、path、title、type、extension、editable 等键,空值键会被省略。文档示例描述中提到的 git_status 属于对 Looker SDK ProjectFile 完整模型的描述;从当前源码看,工具实际输出的键集为上述六个。这一点在依赖输出时值得留意——例如把 path 传给 looker-get-project-file 读取文件内容时,应以实际返回的非空键为准。

错误处理

  • 若 Looker API 返回 401(在错误信息中匹配 status=401),工具将其转换为 http.StatusUnauthorized 的客户端-服务器错误;
  • 其他错误统一交给 util.ProcessGeneralError 处理;
  • 若 source 类型与工具不兼容(未实现 compatibleSource 接口),会返回“invalid source for tool”错误。

只读语义与客户端授权转发

该工具在 Initialize 中使用了默认的只读注解:

tools.GetAnnotationsOrDefault(cfg.Annotations, tools.NewReadOnlyAnnotations)

NewReadOnlyAnnotations 会设置 ReadOnlyHint: true(见 tools.go),向 MCP 客户端声明这是一个无副作用的只读工具。

此外,该工具实现了 RequiresClientAuthorization 与 GetAuthTokenHeaderName 两个方法:当 Looker 源开启 use_client_oauth 时,工具会要求客户端授权,并把访问令牌连同 Authorization(或自定义的认证头)转发给 Looker SDK。这意味着在企业场景中,可以做到按最终用户的 OAuth 令牌去列举其有权限访问的项目文件,而不是统一使用服务账号凭据。

测试如何验证该工具

仓库为该工具提供了单元测试 lookergetprojectfiles_test.go:

  • TestParseFromYamlLookerGetProjectFiles:验证标准的 YAML 片段(type: looker-get-project-files、source: my-instance、description)能被正确解析为 lkr.Config,且 authRequired 默认为空切片;
  • TestFailParseFromYamlLookerGetProjectFiles:验证未知字段(如 method)会导致解析失败。

这两类测试说明:工具的配置面(YAML → Config)是严格受控的,任何超出文档字段表的键都会被拒绝,从侧面保障了“配置即契约”的可靠性。

典型使用流程小结

在 MCP Toolbox 中启用 Looker 开发工具集(可直接使用预构建配置 looker-dev.yaml,其中已包含 get_project_files 定义)后,一个完整的工作流是:

  1. 调用 get_projects 获取源上的所有 LookML 项目,记录目标 project_id;
  2. 调用 get_project_files,传入 project_id,得到项目内全部 LookML 文件的列表(含 path、type、extension 等);
  3. 对感兴趣的文件调用 get_project_file,传入 project_id 与 file_path,读取其原始内容;
  4. 如需修改,再进入 create_project_file、update_project_file 等开发模式工具。

在整个链路中,looker-get-project-files 承担着“项目目录索引”的角色——它本身不返回文件内容,却是模型了解项目构成、决定下一步读写动作的关键输入。配置时只需牢记三点:type 固定为 looker-get-project-files、source 指向已配置好的 Looker 源、description 写清参数与输出以引导 LLM 正确使用。

登录后查看全文
mcp-toolbox