@luutuankiet/looker mcp垫片
一台MCP服务器。AI代理的Looker开发人员完全自主。
逐一检查仪表板。创建、修改和删除互动程序和过滤器。使用编译的SQL运行查询。编辑LookML、推送、验证。通过SDK方法发现执行Looker的469个API端点中的任何一个。所有这些都是通过一个stdio服务器完成的——没有人为干预机械步骤。
npx -y @luutuankiet/looker-mcp-shim安装技能文档 对于Claude Code代理(工作流程指南、API模式、配方):
npx -y @luutuankiet/looker-mcp-shim install-skill # current project
npx -y @luutuankiet/looker-mcp-shim install-skill --global # all projects______________________________________________________________________
这有什么作用
使用此服务器的AI代理可以完成Looker开发人员所做的一切,包括LookML仪表板生命周期(导入、迭代、导出):
graph LR
A[Inspect
dashboards + tiles] --> B[Query
data + compiled SQL]
B --> C[Mutate
create/update/delete
tiles + filters]
C --> D[Edit LookML
push + validate]
D --> E[Verify
re-inspect + re-query]
E --> A
F[LookML Dashboard
import → iterate → export] --> C
A --> F
style F fill:#9C27B0,color:#fff
style A fill:#4285F4,color:#fff
style B fill:#34A853,color:#fff
style C fill:#FBBC04,color:#000
style D fill:#EA4335,color:#fff
style E fill:#4285F4,color:#fff57工具 来自一台服务器:17个自定义填充工具+41个从谷歌上游Looker MCP动态桥接。
______________________________________________________________________
建筑
graph TD
subgraph "AI Agent"
A["Claude Code / Cursor / etc"]
end
subgraph "looker-mcp-shim — single stdio server"
direction TB
D["core.ts
Session + Safety Layer"]
subgraph "Read Tools"
E["inspect"]
F["run_tile / run_query"]
end
subgraph "Mutation Tools"
G["create_tile / update_tile / delete_tile"]
H["create_filter / update_filter / delete_filter"]
end
subgraph "Dev Tools"
I["switch_mode / reset_to_remote / validate"]
end
subgraph "Escape Hatch"
J["retrieve_sdk_methods"]
K["describe_sdk_method"]
L["execute_sdk_code"]
end
U["upstream.ts
MCP Client Bridge"]
end
subgraph "Google Looker MCP"
V["@toolbox-sdk/server
41 tools"]
end
subgraph "Looker"
W["REST API 4.0"]
X["swagger.json
469 methods"]
end
A -->|stdio| D
D --> E & F & G & H & I & J & K & L
D --> U
U -->|stdio| V
V --> W
D --> W
J & K -.->|loads at startup| X
style D fill:#4285F4,color:#fff
style U fill:#34A853,color:#fff
style V fill:#EA4335,color:#fff______________________________________________________________________
快速入门
1.配置
# .env (or pass as env vars in MCP config)
LOOKER_BASE_URL=https://your-instance.cloud.looker.com
LOOKER_CLIENT_ID=your_client_id
LOOKER_CLIENT_SECRET=your_client_secret
LOOKER_PROJECT_ID=your-lookml-project
# Branch auto-detected from Looker. Optional overrides:
# LOOKER_ALLOWED_BRANCHES=* # default: any branch
# LOOKER_RESET_BRANCHES=feat/my-branch,tmp/sandbox # default: none2.注册
克劳德代码/光标 --添加到 .mcp.json:
{
"mcpServers": {
"looker": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@luutuankiet/looker-mcp-shim"],
"env": {
"LOOKER_BASE_URL": "https://your-instance.cloud.looker.com",
"LOOKER_CLIENT_ID": "...",
"LOOKER_CLIENT_SECRET": "...",
"LOOKER_PROJECT_ID": "your-project",
"LOOKER_RESET_BRANCHES": "feat/your-branch"
}
}
}
}3.未注册的测试
npx @luutuankiet/mcp-proxy-shim passthru -- npx @luutuankiet/looker-mcp-shim
# From another terminal:
curl http://localhost:3456/tools # list all 56 tools
curl -X POST http://localhost:3456/call/inspect -d '{"args":{"target":"151"}}'禁用上游桥: SKIP_UPSTREAM=1 npx @luutuankiet/looker-mcp-shim
4.安装技能文档(推荐)
npx -y @luutuankiet/looker-mcp-shim install-skill将工作流指南安装到 .claude/skills/looker-mcp-shim/:
| 文件 | 它教了什么 |
|---|---|
SKILL.md | 入口点+工具索引+决策树 |
rules/workflow.md | 完整的开发循环 |
rules/inspect.md | 仪表板/瓷砖检查 |
rules/query.md | 使用过滤器自动连接运行查询 |
rules/mutate.md | Tile+过滤器CRUD,通过SDK连接过滤器 |
rules/git-ops.md | 开发模式、git同步、LookML验证 |
rules/sdk-escape.md | SDK方法发现+代码执行 |
rules/patterns.md | 迁移QA、仪表板克隆、批量操作 |
只有触摸 looker-mcp-shim/ 命名空间。不干扰其他技能。
______________________________________________________________________
分行安全模型
Looker开发模式在git分支上运行。垫片分离 切换 (安全)从 重置 (破坏性):
graph TD
A[Agent wants to work
on a branch] --> B{switch_mode}
B -->|LOOKER_ALLOWED_BRANCHES=*| C[Switch to ANY branch]
B -->|explicit list| D[Only listed branches]
C --> E{Agent calls
reset_to_remote?}
D --> E
E -->|Branch in
LOOKER_RESET_BRANCHES| F[Reset allowed
Wipes uncommitted changes]
E -->|Branch NOT in
LOOKER_RESET_BRANCHES| G[BLOCKED
Other people's work protected]
style F fill:#34A853,color:#fff
style G fill:#EA4335,color:#fff设置
# .env — branch is auto-detected from Looker, no config needed
LOOKER_ALLOWED_BRANCHES=* # switch to any branch (default)
LOOKER_RESET_BRANCHES=feat/dev_tools,tmp/sandbox # ONLY these can be reset运作原理
| 动作 | 门 | 示例 |
|---|---|---|
switch_mode({mode: "dev", branch: "feat/alice"}) | ALLOWED_BRANCHES | ✅ 随着 *,任何分支工程 |
switch_mode({mode: "dev", branch: "main"}) | ALLOWED_BRANCHES | ✅ 安全--每次会话只读检查 |
reset_to_remote({}) 上 feat/dev_tools | RESET_BRANCHES | ✅ 在列表中--允许重置 |
reset_to_remote({}) 上 feat/alice | RESET_BRANCHES | ❌ 已阻止--不在列表中 |
reset_to_remote({}) 上 main | RESET_BRANCHES | ❌ 已阻止--不在列表中 |
典型分支工作流程
sequenceDiagram
participant Agent
participant Shim
participant Looker
Note over Agent: Start on default dev branch
Agent->>Shim: switch_mode({mode: "dev",
branch: "feat/dev_tools"})
Shim-->>Agent: {mode: "dev", branch: "feat/dev_tools"}
Note over Agent: Inspect another team member's branch
Agent->>Shim: switch_mode({mode: "dev",
branch: "feat/alice-dashboard"})
Shim-->>Agent: {mode: "dev", branch: "feat/alice-dashboard"}
Agent->>Shim: inspect({target: "152"})
Shim-->>Agent: Dashboard state on Alice's branch
Note over Agent: Try to reset — BLOCKED
Agent->>Shim: reset_to_remote({})
Shim-->>Agent: ERROR: Branch "feat/alice-dashboard"
not in LOOKER_RESET_BRANCHES
Note over Agent: Switch to safe branch, edit, reset
Agent->>Shim: switch_mode({mode: "dev",
branch: "feat/dev_tools"})
Note over Agent: Edit LookML, git push
Agent->>Shim: reset_to_remote({})
Shim-->>Agent: {success: true}
Agent->>Shim: validate({})
Shim-->>Agent: {status: "ok"}为什么这很重要: reset_to_remote 为API用户清除当前分支上所有未提交的更改。如果没有安全门,代理切换到同事的分支并重置可能会破坏正在进行的工作。
______________________________________________________________________
代理工作流
1.仪表板检查
代理从两个层面探索仪表板——首先是概述,然后深入到特定的图块。
sequenceDiagram
participant Agent
participant Shim
participant Looker
Agent->>Shim: inspect({target: "152"})
Shim->>Looker: GET /dashboard_elements + /dashboard_filters
Shim-->>Agent: 12 tiles, 14 filters
(~50 tokens/tile)
Note over Agent: Agent picks tile to investigate
Agent->>Shim: inspect({target: "tile:1486"})
Shim->>Looker: GET /dashboard_elements/1486
Shim-->>Agent: fields, filters, sorts, vis_config,
filter wiring, query_id (~200 tokens)
Agent->>Shim: run_tile({element_id: "1486", format: "sql"})
Shim->>Looker: GET /queries/{id}/run/sql
Shim-->>Agent: Compiled BigQuery SQL (33K chars)
Agent->>Shim: run_tile({element_id: "1486", format: "json", limit: 5})
Shim->>Looker: GET /queries/{id}/run/json
Shim-->>Agent: 5 data rowsURL智能输入 --所有这些工作:
| 输入 | 解析到 |
|---|---|
"152" | 仪表板152 |
"tile:1486" | 瓷砖细节 |
"https://host/dashboards/152" | 仪表板152 |
"https://host/explore/common/transactions?fields=..." | 探索 |
______________________________________________________________________
2.仪表板突变——构建和修改磁贴
代理创建图块,修改它们,并验证——在不接触Looker UI的情况下进行完整的CRUD。
sequenceDiagram
participant Agent
participant Shim
participant Looker
Note over Agent: Create a revenue tile
Agent->>Shim: create_tile({dashboard_id: "152",
title: "Revenue by Region",
query: {model: "common",
view: "transactions",
fields: ["transactions.region",
"transactions.total_revenue"],
vis_config: {type: "looker_bar"}}})
Note over Shim: Two-step: create_query() -> query_id
then create_dashboard_element()
Shim->>Looker: POST /queries + POST /dashboard_elements
Shim-->>Agent: {element_id: "1503"}
Note over Agent: Change chart type to pie
Agent->>Shim: update_tile({element_id: "1503",
query: {vis_config: {type: "looker_pie"}}})
Note over Shim: Reads existing query, merges changes,
creates new query, updates element
Shim->>Looker: GET element -> POST /queries -> PATCH element
Shim-->>Agent: {fields preserved, vis updated}
Note over Agent: Add a filter
Agent->>Shim: create_filter({dashboard_id: "152",
name: "region_filter",
title: "Region",
type: "field_filter",
dimension: "transactions.region",
model: "common",
explore: "transactions"})
Shim->>Looker: POST /dashboard_filters
Shim-->>Agent: {filter_id: "1141"}
Note over Agent: Verify everything
Agent->>Shim: inspect({target: "152"})
Shim-->>Agent: Tile 1503 + Filter 1141 confirmed关键见解: Looker的API拒绝内联 query 元素上的对象创建/更新。垫片自动处理两步舞-- create_query() 首先,然后通过引用 query_id特工们不需要知道这些。
部分更新: 更新互动程序时 vis_config,填充程序读取现有查询,合并您的更改,并保留其他所有内容(字段、过滤器、排序)。你只发送更改的内容。
______________________________________________________________________
3.LookML编辑→ 验证→ 验证循环
完整的开发人员循环:编辑LookML、同步Looker、验证、检查结果。
sequenceDiagram
participant Agent
participant Git as Local Git
participant Shim
participant Looker
participant BQ as BigQuery
Note over Agent: Agent edits LookML locally
Agent->>Git: Edit .lkml files
Agent->>Git: git push origin feat/branch
Note over Agent: Sync Looker to latest code
Agent->>Shim: reset_to_remote({})
Shim->>Looker: POST /projects/{id}/reset_to_remote
Shim-->>Agent: {success: true}
Note over Agent: Validate LookML syntax
Agent->>Shim: validate({})
Shim->>Looker: POST /projects/{id}/lookml_validation
Shim-->>Agent: {status: "ok", errors: []}
Note over Agent: Verify data still correct
Agent->>Shim: run_tile({element_id: "1486",
format: "json", limit: 5})
Shim->>Looker: GET /queries/{id}/run/json
Looker->>BQ: Execute compiled SQL
BQ-->>Looker: Result rows
Shim-->>Agent: [{region: "SG", revenue: 45000}, ...]
Note over Agent: Compare with expected values
Agent->>Shim: run_tile({element_id: "1486",
format: "json", limit: 5,
force_production: true})
Shim-->>Agent: Production data for parity checkforce_production --从开发模式对生产LookML运行查询。非常适合在不切换模式的情况下将开发更改与生产基线进行比较。
长时间运行的查询 --复杂探索(例如,具有33K char编译SQL的BigQuery)默认超时120秒。如果过期,填充程序会自动回退到Looker的异步查询任务机制(与Looker UI相同),轮询完成情况并返回结果。
______________________________________________________________________
4.SDK方法发现——Escape Hatch
对于15个专用工具未涵盖的任何内容,代理将发现并执行Looker的469个API方法中的任何一个。
sequenceDiagram
participant Agent
participant Shim
participant Swagger as swagger.json
Note over Agent: "I need to find scheduled plans"
Step 1: Search
Agent->>Shim: retrieve_sdk_methods({query: "schedule plan"})
Shim->>Shim: Search catalog (loaded from swagger.json)
Shim-->>Agent: 15 matches:
scheduled_plans_for_dashboard,
create_scheduled_plan, ...
Note over Agent: Step 2: Get details
Agent->>Shim: describe_sdk_method({
method: "scheduled_plans_for_dashboard"})
Shim-->>Agent: Parameters: dashboard_id (required),
user_id, all_users, fields
Code example: sdk.ok(sdk.scheduled_plans_for_dashboard({
dashboard_id: "152" }))
Note over Agent: Step 3: Execute
Agent->>Shim: execute_sdk_code({code: "
const plans = await sdk.ok(
sdk.scheduled_plans_for_dashboard({
dashboard_id: '152', all_users: true
})
)
return plans.map(p => ({
name: p.name, cron: p.crontab
}))"})
Shim-->>Agent: [{name: "Weekly Revenue",
cron: "0 9 * * 1"}, ...]目录是从Looker实例自己的目录加载的 swagger.json 在启动时——对于您的特定Looker版本总是准确的。
______________________________________________________________________
5.迁移QA——Tableau到Looker
驱动此工具的用例:代理接收Tableau屏幕截图,并逐块验证Looker中的数据奇偶性。
sequenceDiagram
participant Human
participant Agent
participant Shim
participant Looker
Human->>Agent: "Verify dashboard 152 matches
this Tableau screenshot"
Agent->>Shim: switch_mode({mode: "dev",
branch: "feat/migration"})
Shim-->>Agent: {mode: "dev", branch: "feat/migration"}
Agent->>Shim: inspect({target: "152"})
Shim-->>Agent: 12 tiles, 14 filters
loop For each tile
Agent->>Shim: inspect({target: "tile:{id}"})
Shim-->>Agent: fields, model, explore, filters
Agent->>Shim: run_tile({element_id: "{id}",
format: "json", limit: 20})
Shim-->>Agent: Data rows
Note over Agent: Compare data vs Tableau screenshot
alt Data mismatch found
Agent->>Shim: run_tile({element_id: "{id}",
format: "sql"})
Shim-->>Agent: Compiled SQL
Note over Agent: Agent identifies join/filter issue,
edits LookML, pushes to git
Agent->>Shim: reset_to_remote({})
Agent->>Shim: validate({})
Agent->>Shim: run_tile({element_id: "{id}",
format: "json"})
Note over Agent: Data matches now
end
end
Agent->>Human: "All 12 tiles verified.
3 had issues, fixed in LookML."______________________________________________________________________
6.LookML仪表板生命周期——导入、迭代、导出
LookML仪表板是代码定义的-瓦片不能通过API进行变异。垫片提供了一个快速的迭代路径:导入为UDD,使用变异工具迭代(无git提交),然后导出回LookML。
sequenceDiagram
participant Agent
participant Shim
participant Looker
participant Git
Note over Agent: Inspect the LookML dashboard
Agent->>Shim: inspect({target: "model::dashboard_name"})
Shim->>Looker: GET /dashboards/model::dashboard_name
Shim-->>Agent: 4 tiles, 14 filters, type: lookml_dashboard
hint: use import_lookml_dashboard
Note over Agent: Import as editable UDD
Agent->>Shim: import_lookml_dashboard({
lookml_dashboard_id: "model::dashboard_name",
folder_id: "85"})
Shim->>Looker: validate_project + dashboard() + import_lookml_dashboard()
Shim-->>Agent: {id: "173", verification: {tiles_match: true}}
Note over Agent: Fast iteration loop (no git!)
loop Iterate on UDD
Agent->>Shim: update_tile / create_tile / update_filter
Agent->>Shim: run_tile({dashboard_id: "173", tile: "#1"})
Agent->>Shim: inspect({target: "173"})
end
Note over Agent: Export final state as LookML
Agent->>Shim: export_dashboard_lookml({dashboard_id: "173"})
Shim->>Looker: GET /dashboards/173/lookml
Shim-->>Agent: {lookml: "---\n- dashboard: ..."}
Note over Agent: Commit to code
Agent->>Git: Write .dashboard.lookml + git push
Agent->>Shim: reset_to_remote({})
Agent->>Shim: validate({})
Agent->>Shim: inspect({target: "model::dashboard_name"})
Note over Agent: Compiled result matches intent ✔两个环路,一个桥:
- 快速循环(UDD): 突变工具,即时,无git
- 慢循环(LookML): git推送+重置+验证
- 导入 进入快速循环, 出口 退出它
______________________________________________________________________
工具参考
检查
| 工具 | 它的作用 | 关键参数 |
|---|---|---|
inspect | 仪表板概述或互动程序详细信息 | target:URL、ID或 tile:NNN |
LookML仪表板生命周期
| 工具 | 它的作用 | 关键参数 |
|---|---|---|
inspect | 检查LookML仪表板(瓷砖、过滤器) | target: "model::dashboard_name" |
import_lookml_dashboard | 将LookML仪表板克隆为可编辑的UDD | lookml_dashboard_id, folder_id |
export_dashboard_lookml | 将任何仪表板导出为LookML YAML | dashboard_id |
查询执行
| 工具 | 它的作用 | 关键参数 |
|---|---|---|
run_tile | 执行磁贴的查询 | element_id, format (json/sql/csv), limit, force_production, timeout |
run_query | 特别探索查询 | model, explore, fields, filters, sorts, limit, force_production, timeout |
这两个工具都自动处理长时间运行的BigQuery查询——120秒超时,异步查询任务回退。
仪表板突变
| 工具 | 它的作用 | 关键参数 |
|---|---|---|
create_tile | 将互动程序添加到仪表板 | dashboard_id, title, query (内联)或 query_id |
update_tile | 修改互动程序(部分) | element_id, title, query (部分合并) |
delete_tile | 移除瓷砖 | element_id |
create_filter | 添加仪表板筛选器 | dashboard_id, name, title, type, dimension, model, explore |
update_filter | 修改筛选器 | filter_id, title, default_value, ... |
delete_filter | 拆下过滤器 | filter_id |
部分查询更新: update_tile 将您的更改与现有查询合并。仅发送已更改的内容——字段、vis_config、排序和过滤器将保留。
{"element_id": "1486", "query": {"vis_config": {"type": "looker_pie"}}}垫片读取当前查询,合并您的 vis_config 更改、创建新查询并更新元素。字段、过滤器、排序——全部保留。
开发操作
| 工具 | 它做什么 |
|---|---|
switch_mode | 通过分支选择切换dev/prod模式 |
reset_to_remote | 将Looker项目同步到git HEAD |
validate | LookML语法验证中存在文件行错误 |
SDK逃生舱
| 工具 | 它做什么 |
|---|---|
retrieve_sdk_methods | 按关键字/标签搜索469种SDK方法 |
describe_sdk_method | 获取方法的完整参数+代码示例 |
execute_sdk_code | 使用预认证会话运行任意SDK代码 |
工作流程: 搜索->描述->执行。永远不要猜测方法签名。
retrieve_sdk_methods({query: "render png"}) # find the method
describe_sdk_method({method: "create_dashboard_element_render_task"}) # get params
execute_sdk_code({code: "..."}) # run it上游Looker MCP(41个工具,自动桥接)
所有工具来自 @toolbox-sdk/server --prebuilt=looker,looker-dev 自动可用:
get_project_files, update_project_file, create_project_file, delete_project_file, get_explores, get_dimensions, get_measures, get_filters, get_models, get_connections, run_dashboard, run_look, query_sql, query, make_dashboard, make_look, dev_mode, validate_project, get_dashboards, get_looks以及更多。
这些前缀为 [upstream] 在描述中。我们的垫片工具优先考虑名称冲突。
______________________________________________________________________
安全层
被阻止的SDK方法(硬编码,不可配置)
| 类别 | 方法 |
|---|---|
| 生产部署 | deploy_ref_to_production, deploy_to_production |
| 用户模拟 | login_user |
| 破坏性管理员 | delete_group, create_group, update_group, delete_user_attribute, delete_role, delete_folder, delete_dashboard, delete_look, update_user |
| 计划操纵 | delete_scheduled_plan, update_scheduled_plan, create_scheduled_plan |
可配置护栏
| 设置 | 目的 |
|---|---|
LOOKER_ALLOWED_BRANCHES | 分支机构满负荷运行 switch_mode.Set * 对于任何分支 |
LOOKER_RESET_BRANCHES | 分支机构在哪里 reset_to_remote 允许(默认为无) |
LOOKER_SANDBOX_FOLDER_ID | 将仪表板保存限制到文件夹 |
______________________________________________________________________
配置
| 变量 | 必填 | 默认 | 描述 |
|---|---|---|---|
LOOKER_BASE_URL | 是 | -- | 查找器实例URL |
LOOKER_CLIENT_ID | 是 | - | API客户端ID |
LOOKER_CLIENT_SECRET | 是 | - | API客户端机密 |
LOOKER_PROJECT_ID | 没有 | '' | LookML项目ID |
LOOKER_ALLOWED_BRANCHES | 没有 | * | switch_mode的分支列表。 * =任何分支 |
LOOKER_RESET_BRANCHES | 没有 | '' (无) | 分支机构 reset_to_remote 是允许的。必须明确 |
LOOKER_SANDBOX_FOLDER_ID | 否 | -- | import_lookml_dashboard的默认文件夹 |
SKIP_UPSTREAM | 否 | -- | 设置为 1 禁用上游桥梁 |
______________________________________________________________________
如何比较
| 功能 | 谷歌Looker MCP | 这个Shim |
|---|---|---|
| LookML文件CRUD | \\u2705 | \\u2505(通过上游网桥) |
| 运行仪表板(满) | \\u2705 | \\u2505(通过上游网桥) |
| 逐块检查 | \\u274c | \\u2705字段、过滤器、vis_config、过滤器接线 |
| 每块编译的SQL | \\u274c | \\u2705运行文件格式=SQL |
| 使用部分合并创建/更新/删除磁贴 | \\u274c | \\u2705 |
| 创建/更新/删除筛选器 | \\u274c | \\u2705 |
| 重置到远程 | \\u274c | \\u2705 |
| 开发/生产模式+分支 | \\u274c原子 | \\u2705原子开关 |
| SDK方法发现 | \\u274c | \\u2705从swagger中检索+描述 |
| 使用安全代理任意执行SDK | \\u274c | \\u2705 |
| 长查询处理 | \\u274c | \\u2705 120秒超时+异步回退 |
| 工具总数 | 41 | 57 (17个垫片+41个桥接,1个共享名称) |
您只注册了一台服务器。它自动连接上游。
______________________________________________________________________
技术栈
| 组件 | 包装 | 用途 |
|---|---|---|
| 运行时 | Node.js>=20(ESM) | 现代JavaScript |
| 语言 | TypeScript ^5.7 | 类型安全 |
| Looker SDK | @looker/sdk-node | Auth,会话,API |
| MCP服务器 | @modelcontextprotocol/sdk | 服务器+客户端(用于网桥) |
| 上游 | @toolbox-sdk/server | 谷歌的Looker MCP(桥接) |
| 测试 | @luutuankiet/mcp-proxy-shim | Passthrough REST测试 |
许可证
麻省理工学院
