looker mcp服务器
](https://pypi.org/project/looker-mcp-server/) ](https://pypi.org/project/looker-mcp-server/)   
功能齐全 模型上下文协议 (MCP)服务器 Looker API。让AI助手直接访问您的Looker实例——查询语义模型、管理内容、编辑LookML和管理用户——所有这些都可以通过标准MCP界面完成。
特性
- 160工具 覆盖整个Looker API表面的15组
- 语义层查询 --通过LookML模型查询,而不是原始SQL
- OAuth传递 --从上游网关或MCP OAuth流转发用户令牌
- 用户模拟 --admin sudo在自托管的Looker上,OAuth在Google Cloud核心上
- 双重运输 --stdio用于本地/CLI使用,可流式传输http用于生产部署
- 选择性工具加载 --通过仅启用所需的工具组
--groups - 可插拔身份 --通过交换自定义身份验证
IdentityProvider协议 - 健康终点 —
/healthz和/readyz用于容器编排
快速开始
安装
pip install looker-mcp-server
# or
uv add looker-mcp-server环境变量
至少,设置您的Looker实例URL和API3凭据:
export LOOKER_BASE_URL="https://mycompany.looker.com"
export LOOKER_CLIENT_ID="your-api3-client-id"
export LOOKER_CLIENT_SECRET="your-api3-client-secret"使用stdio运行(适用于Claude Code、Claude Desktop等)
looker-mcp-server --groups explore,query,schema使用HTTP运行(用于生产部署)
LOOKER_TRANSPORT=streamable-http looker-mcp-server --groups all --port 8080MCP客户端配置
克劳德代码
添加到您的Claude Code MCP设置中:
{
"mcpServers": {
"looker": {
"command": "looker-mcp-server",
"args": ["--groups", "explore,query,schema,content"],
"env": {
"LOOKER_BASE_URL": "https://mycompany.looker.com",
"LOOKER_CLIENT_ID": "your-client-id",
"LOOKER_CLIENT_SECRET": "your-client-secret"
}
}
}
}克劳德桌面版
添加 ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"looker": {
"command": "looker-mcp-server",
"args": ["--groups", "explore,query,schema,content"],
"env": {
"LOOKER_BASE_URL": "https://mycompany.looker.com",
"LOOKER_CLIENT_ID": "your-client-id",
"LOOKER_CLIENT_SECRET": "your-client-secret"
}
}
}
}工具组
工具被组织成可以选择性启用的组。默认组标记为 \*.
| 组 | 工具 | 描述 |
|---|---|---|
| 探索\* | list_models, get_model, get_explore, list_dimensions, list_measures, list_connections | 浏览LookML模型、探索和字段 |
| 查询\* | query, query_sql, run_query, run_look, run_dashboard, query_url, search_content | 通过语义层运行查询 |
| 模式\* | list_databases, list_schemas, list_tables, list_columns | 检查底层数据库架构 |
| 内容\* | list_looks, create_look, update_look, delete_look, list_dashboards, create_dashboard, update_dashboard, delete_dashboard, add_dashboard_element, add_dashboard_filter, generate_embed_url, validate_content | 管理外观和仪表板 |
| 板 | list_boards, get_board, create_board, update_board, delete_board, get_board_section, create_board_section, update_board_section, delete_board_section, get_board_item, create_board_item, update_board_item, delete_board_item | 用图板、章节和项目管理内容 |
| 文件夹 | list_folders, get_folder, create_folder, update_folder, delete_folder, get_folder_children, get_folder_ancestors, get_folder_looks, get_folder_dashboards | 导航和管理文件夹层次结构 |
| 健康\* | health_pulse, health_analyze, health_vacuum | 实例健康检查和使用情况分析 |
| 建模 | list_projects, get_project, create_project, update_project, delete_project, get_project_manifest, get_project_deploy_key, create_project_deploy_key, list_project_files, get_file, create_file, update_file, delete_file, validate_project, list_datagroups, get_datagroup, reset_datagroup, trigger_datagroup, start_pdt_build, check_pdt_build, stop_pdt_build, graph_derived_tables_for_view, graph_derived_tables_for_model | LookML项目生命周期、文件编辑、语法验证、数据组缓存+触发器管理和PDT构建管理 |
| 版本控制系统 | get_git_branch, list_git_branches, get_git_branch_by_name, create_git_branch, switch_git_branch, delete_git_branch, deploy_to_production, reset_to_production, get_git_deploy_key, create_git_deploy_key, list_git_connection_tests, run_git_connection_test | Git分支生命周期、生产部署、SSH部署密钥轮换和Git连接诊断 |
| 管理员 | list_users, get_user, create_user, update_user, delete_user, create_credentials_email, send_password_reset, list_roles, get_role, create_role, update_role, delete_role, get_role_groups, get_role_users, list_permissions, list_permission_sets, create_permission_set, update_permission_set, delete_permission_set, list_model_sets, create_model_set, update_model_set, delete_model_set, list_groups, create_group, delete_group, add_group_user, remove_group_user, set_role_groups, set_role_users, set_user_roles, get_user_roles, list_schedules, create_schedule, update_schedule, delete_schedule, run_schedule_once | 用户、角色、RBAC、组和日程管理 |
| 连接 | get_connection, list_connection_dialects, create_connection, update_connection, delete_connection, test_connection | 数据库连接CRUD和健康检查 |
| 用户属性 | list_user_attributes, get_user_attribute, create_user_attribute, update_user_attribute, delete_user_attribute, list_user_attribute_group_values, set_user_attribute_group_values, delete_user_attribute_group_value, list_user_attribute_values_for_user, set_user_attribute_user_value, delete_user_attribute_user_value | 用户属性定义以及每个组和每个用户的值覆盖(行级安全性、每个开发人员凭据、过滤器默认值) |
| 资格 | list_credentials_api3, create_credentials_api3, get_credentials_api3, delete_credentials_api3, get_credentials_ldap, delete_credentials_ldap, get_credentials_saml, delete_credentials_saml, get_credentials_oidc, delete_credentials_oidc, get_credentials_google, delete_credentials_google | 非电子邮件凭据——LDAP、SAML、OIDC和Google SSO链接的API3密钥对轮换以及获取/删除 |
| 审计 | get_query_history, get_content_usage, get_pdt_build_log, get_schedule_history, get_user_activity_log, list_running_queries, kill_query, list_active_sessions, get_session, terminate_session, list_project_ci_runs, get_project_ci_run, trigger_project_ci_run | 通过system\_\_activity查询历史记录、内容使用情况、PDT构建+计划+事件日志,以及实时操作(运行查询、会话、CI运行) |
| 工作流 | provision_connection, bootstrap_lookml_project, deploy_lookml_changes, rollback_to_production, provision_user, grant_access, offboard_user, rotate_api_credentials, audit_query_activity, audit_instance_health, investigate_runaway_queries, find_stale_content, disable_stale_sessions | 面向任务的第2层组合——配置工作流(引导、部署、配置用户)加上操作/审计工作流(非机载、轮换凭据、审计、清理) |
选择组
# Default groups only (explore, query, schema, content, health)
looker-mcp-server
# Specific groups
looker-mcp-server --groups explore,query
# All groups (including board, folder, modeling, git, admin, connection, user_attributes, credentials, audit, workflows)
looker-mcp-server --groups all配置参考
所有设置都是通过环境变量配置的 LOOKER_ 前缀,或通过 .env 文件。
| 变量 | 默认值 | 描述 |
|---|---|---|
LOOKER_BASE_URL | *(必填)* | Looker实例的基本URL |
LOOKER_CLIENT_ID | 服务帐户的API3客户端ID | |
LOOKER_CLIENT_SECRET | 服务帐户的API3客户端密码 | |
LOOKER_API_VERSION | 4.0 | Looker API版本 |
LOOKER_DEPLOYMENT_TYPE | self_hosted | self_hosted 或 google_cloud_core |
LOOKER_TRANSPORT | stdio | stdio 或 streamable-http |
LOOKER_HOST | 0.0.0.0 | HTTP绑定地址 |
LOOKER_PORT | 8080 | HTTP端口 |
LOOKER_SUDO_AS_USER | true | 当存在身份标头时启用用户模拟 |
LOOKER_SUDO_ASSOCIATIVE | false | 将sudo activity属性设置为admin(true)或假冒用户(false) |
LOOKER_USER_EMAIL_HEADER | X-User-Email | HTTP标头携带用于模拟sudo的用户电子邮件 |
LOOKER_USER_TOKEN_HEADER | X-User-Token | 携带预先交换的OAuth令牌的HTTP标头 |
LOOKER_TIMEOUT | 60.0 | HTTP请求超时(秒) |
LOOKER_MAX_ROWS | 5000 | 查询工具的默认最大行数 |
LOOKER_VERIFY_SSL | true | 验证TLS证书 |
LOOKER_LOG_LEVEL | INFO | 日志记录级别 |
LOOKER_MCP_MODE | dev | dev (允许)或 public (OAuth 2.1资源服务器,MCP 2025-11-25)。看 MCP级别身份验证. |
LOOKER_MCP_JWKS_URI | 授权服务器JWK设置URL(RFC 7517)。 需要时 LOOKER_MCP_MODE=public. 必须是 https:// URL。 | |
LOOKER_MCP_ISSUER_URL | 预计 iss 声明(RFC 8414)。 需要时 LOOKER_MCP_MODE=public. 必须是 https:// URL。 | |
LOOKER_MCP_RESOURCE_URI | 此服务器用于RFC 8707受众绑定和RFC 9728 PRM的规范URI resource 现场。 需要时 LOOKER_MCP_MODE=public. 必须是 https:// 没有片段的URL。 | |
LOOKER_MCP_AUTH_TOKEN | 用于MCP级身份验证的静态承载令牌。 已弃用 --在中发出警告 dev 模式,彻底拒绝 public 模式(RFC 9068§2.1禁止OAuth 2.1访问令牌的对称静态承载)。计划在未来的主要版本中删除;迁移到 LOOKER_MCP_MODE=public. |
身份验证和模拟
服务器支持三种身份验证模式,根据配置和请求标头自动选择。
模式1:服务帐户(API密钥)
最简单的模式-所有API调用都使用配置的服务帐户凭据。
export LOOKER_CLIENT_ID="your-api3-client-id"
export LOOKER_CLIENT_SECRET="your-api3-client-secret"
export LOOKER_SUDO_AS_USER=false模式2:管理员Sudo(自托管Looker)
管理员服务帐户通过Looker模拟个人用户 login_user API用户由请求标头中的电子邮件地址标识(通常由上游网关设置)。
export LOOKER_CLIENT_ID="admin-api3-client-id"
export LOOKER_CLIENT_SECRET="admin-api3-client-secret"
export LOOKER_DEPLOYMENT_TYPE=self_hosted
export LOOKER_SUDO_AS_USER=true当请求到达时 X-User-Email: alice@company.com,服务器:
- 使用管理员凭据登录
- 通过电子邮件查找Alice的Looker用户ID
- 以Alice的身份创建sudo会话
login_user - 以Alice的身份执行工具调用
- 注销两个会话
注: 在Looker(谷歌云核心)上, login_user 仅适用于嵌入类型的用户。普通用户需要OAuth模式。模式3:OAuth传递(谷歌云核心)
对于Looker(谷歌云核心)部署,普通用户无法通过sudo模拟。上游网关执行OAuth令牌交换,并在标头中传递用户的令牌。
export LOOKER_CLIENT_ID="fallback-api3-client-id"
export LOOKER_CLIENT_SECRET="fallback-api3-client-secret"
export LOOKER_DEPLOYMENT_TYPE=google_cloud_core
export LOOKER_SUDO_AS_USER=true当请求到达时 X-User-Token: ,服务器直接使用该令牌,不需要登录/注销周期。
如果不存在令牌标头,服务器将回退到服务帐户模式。
自动模式选择
当 LOOKER_SUDO_AS_USER=true (默认),服务器使用 DualModeIdentityProvider 自动路由:
- 自托管 → sudo(通过
X-User-Email头球 - 谷歌云核心 → OAuth(通过
X-User-Token头球 - 无身份标头 → 服务帐户回退
每次呼叫管理员模拟(act_as_user)
Looker开发模式(workspace_id=dev)是 按用户设计隔离每个用户都有自己的开发工作区;未提交的LookML更改、活动分支和开发模式本地分支都位于调用用户的工作区中。这意味着管理员正在运行 delete_git_branch 反对 *管理员* devworkspace对中卡住的分支不做任何处理 *其他用户的* 开发工作区。
git工具接受可选 act_as_user 这样管理员就可以以不同的用户身份执行调用——通常是为了清理其他人卡住的开发工作区状态,而无需将MCP留给原始HTTP。接受数字用户ID或电子邮件地址(通过Looker的user-search API解析为ID)。
// Example: admin sweeping a stale CI branch out of ci-bot's dev workspace
{
"tool": "delete_git_branch",
"arguments": {
"project_id": "acme_analytics",
"branch_name": "tmp_ci_5bd8888773",
"act_as_user": "ci-bot@example.com"
}
}配置。 每次呼叫的管理员模拟由以下因素控制 LOOKER_SUDO_AS_USER --该标志是OSS服务器中支持sudo行为的单个终止开关,以及 act_as_user 尊重它。设置 LOOKER_SUDO_AS_USER=true (配置管理员凭据时的默认设置)启用。随着 LOOKER_SUDO_AS_USER=false,通过 act_as_user 引发一个明显的验证错误,而不是在配置的身份下静默运行调用——在调用站点发现错误配置,而不是让它路由到错误的用户。
安全模型。 MCP转发功能——它不会对其进行门控。Sudo权限由Looker服务器端强制执行:如果配置了 LOOKER_CLIENT_ID 没有sudo功能, login_user 返回HTTP 403,工具失败。开源服务器中没有MCP方面的“谁可以冒充谁”政策;通过包裹将一层包裹进去 IdentityProvider 如果你需要它(见下一节)。
工具覆盖范围。 所有八个git/工作区范围的工具都接受 act_as_user: get_git_branch, list_git_branches, get_git_branch_by_name, create_git_branch, switch_git_branch, delete_git_branch, deploy_to_production, reset_to_production。五个查询工具也接受它-- query, query_sql, query_url, run_query, run_look --对于CI模式,对功能分支的查询必须在专用服务用户的开发工作区下运行,而不是在调用管理员的工作区下。项目级工具(部署密钥、连接诊断)故意不这样做——它们不依赖于每个用户的开发工作区状态。
审核日志。 每个参数驱动的sudo都会发出一个INFO级别的结构日志行:
{
"event": "looker.audit.act_as_user",
"tool": "delete_git_branch",
"target_user_id": "77",
"target_user_email": "ci-bot@example.com",
"triggered_by": "argument",
"configured_user": "admin-api3-client-id"
}这与跟踪级别无关 looker.session.sudo 调试线,是下游审计管道的右钩。标题驱动的sudo(网关模式)已标记 triggered_by="header" 在调试线上-- looker.audit.act_as_user 仅对显式的每次呼叫管理员模拟触发。
模式交互。 act_as_user 覆盖内部身份,包括OAuth和基于头的sudo。这是有意的——显式的管理员覆盖应该胜过隐式网关路由——但底层凭据仍必须具有sudo功能,Looker强制执行。在Google Cloud核心上,只能模拟嵌入类型的用户;对于常规GCC用户,请改用模式3(OAuth传递)。
故障模式。
act_as_user既不是全数字也不是电子邮件(否@) → 在任何Looker调用之前,验证错误被预先拒绝。避免将垃圾转发到/login/{value}在那里它将作为不透明的HTTP 400出现。- 电子邮件与任何Looker用户都不匹配→ 验证错误。大声失败是故意的;默默地回到配置的身份会让一封拼写错误的电子邮件在错误的用户下运行操作。
LOOKER_SUDO_AS_USER=false和act_as_user已过→ 解释如何修复的验证错误(启用sudo或删除参数)。- 配置的凭据缺少sudo功能→ Looker在上返回403
login_user,浮出水面Permission denied — the current user lacks access.
开发模式和分支验证
查询工具(query, query_sql, query_url, run_query, run_look)建模/git工具接受三个可选参数-- dev_mode, branch,以及 project_id --它们共同允许您在Looker开发工作区而不是生产环境中对LookML运行操作。这使得从MCP进行功能分支验证成为可能,而无需回到原始REST。
Looker如何确定工作区的范围。 工作区选择(生产与开发)是API会话令牌的属性,而不是调用。MCP问题 PATCH /session {"workspace_id": "dev"} 在身份验证后立即 dev_mode=True 已设置;这会影响通过同一会话路由的每个后续呼叫。该设置不会在登录后持续存在,因此每次MCP调用都会显式设置它。
服务器端的每个Looker用户都有分支状态。 每个Looker用户只有一个开发工作区,每个LookML项目都有一个当前签出的分支。分支签出在注销和并发调用之间持续存在——它是Looker服务器上可变的共享状态。针对同一用户的两个操作争夺这个单一的单元。
原子分支交换
集 branch="" 和 project_id="" 在查询工具上以原子方式:
- 将用户当前签出的分支保存在项目中。
- PUT目标分支。
- 运行查询。
- 在中还原已保存的分支
finally(即使提出质疑)。
branch 暗示 dev_mode=True。当开发工作区已位于目标分支上时,保存和还原操作不起作用。
规范工作流程
一次性CI:根据真实数据验证PR的LookML。 单一工具调用,原子。在此期间借用专用CI服务用户的开发工作区;在调用返回之前恢复保存的分支。
{
"tool": "query",
"arguments": {
"model": "ecommerce",
"view": "orders",
"fields": ["orders.region", "orders.total_revenue"],
"branch": "feature/new-aggregation",
"project_id": "ecommerce",
"act_as_user": "ci-bot@example.com"
}
}生产与公关比较。 两个调用——LLM在自己的上下文中对结果进行差异化。
{ "tool": "query", "arguments": { "model": "ecommerce", "view": "orders", "fields": [...] } }
{ "tool": "query", "arguments": { "model": "ecommerce", "view": "orders", "fields": [...],
"branch": "feature/new-aggregation", "project_id": "ecommerce",
"act_as_user": "ci-bot@example.com" } }迭代式人工调试。 分支状态在开发工作区中是粘性的,因此使用以下命令设置一次 switch_git_branch 并使用以下命令运行多个查询 dev_mode=True (没有 branch arg)。用另一个恢复用户的正常分支 switch_git_branch 当完成时。
{ "tool": "switch_git_branch", "arguments": { "project_id": "ecommerce", "branch_name": "feature/new-aggregation" } }
{ "tool": "query", "arguments": { "model": "ecommerce", "view": "orders", "fields": [...], "dev_mode": true } }
{ "tool": "update_lookml_file", "arguments": { ... } }
{ "tool": "query", "arguments": { "model": "ecommerce", "view": "orders", "fields": [...], "dev_mode": true } }
{ "tool": "switch_git_branch", "arguments": { "project_id": "ecommerce", "branch_name": "main" } }清理另一个用户卡住的开发工作区。 合并 act_as_user 使用git工具对其他人的每个用户状态进行操作。
{
"tool": "switch_git_branch",
"arguments": { "project_id": "ecommerce", "branch_name": "main", "act_as_user": "alice@example.com" }
}并发警告
Looker的每用户每项目分支签出是一个可变单元格。同一设备上的两个并发操作 act_as_user (或相同配置的管理员标识,当 act_as_user 省略)竞争。原子保存+还原可以防止意外的状态泄漏,但确实如此 不 序列化并发调用——如果您的CI在多个打开的PR中针对单个CI-bot用户扇出,您将看到不确定的结果。
对于并行PR验证,提供多个Looker用户(例如。 ci-bot-1, ci-bot-2,…),并让您的CI扇出逻辑通过以下方式在它们之间旋转 act_as_userMCP侧没有互斥体;这是部署人员做出的操作选择。
什么 dev_mode 做 *不* 封面(v1)
- 多项目清单导入。 如果您的LookML项目导入了另一个项目,则导入将保留在该导入项目的开发工作区中当前签出的任何分支上。原子交换是单个项目;递归清单感知交换是v2关注的问题。
- 跨呼叫会话连续性。 每个工具调用都有自己的短暂API会话(登录→ 操作→ 注销),所以
dev_mode=True仅在一次通话中生效。分支状态在调用之间持续存在,因为Looker在服务器端为每个用户存储它;工作区设置没有。
按工具组划分的覆盖范围
dev_mode, branch,以及 act_as_user 通过使用工作区范围的LookML状态的工具组传播。读取工作区无关元数据的工具不接受这些参数。
| 工具组 | 工作空间感知工具 | 仅生产工具 |
|---|---|---|
| 版本控制系统 | switch_git_branch, create_git_branch, delete_git_branch, reset_to_production (默认值 dev_mode=True) | get_git_branch, list_git_branches, get_git_branch_by_name, deploy_to_production (读取prod-git状态) |
| 查询 | query, query_sql, query_url, run_query, run_look (默认值 dev_mode=False;通过以下方式选择加入 branch= 或 dev_mode=True) | run_dashboard, search_content (生产内容) |
| 建模——文件操作 | list_project_files, get_file (默认值 dev_mode=True), create_file, update_file, delete_file (总是dev-Looker拒绝写入生产环境) | -- |
| 建模-验证 | validate_project (默认值 dev_mode=False;通过以下方式选择加入 branch= 用于PR验证) | -- |
| 建模--数据测试 | list_lookml_tests, run_lookml_tests (默认值 dev_mode=False;通过以下方式选择加入 branch= 用于PR数据回归检查) | -- |
| 建模--项目元数据 | — | list_projects, get_project, get_project_manifest, list_datagroups, reset_datagroup (与工作区无关的项目状态) |
run_lookml_tests --PR数据回归检查
run_lookml_tests(project_id="ecommerce", branch="feature-x", act_as_user="ci-bot@example.com") 是捕获PR引入的数据回归错误的主要原语。Looker编译每个测试的 explore_source 查询,对仓库运行它,并根据结果行计算断言表达式。失败会返回断言级别的详细信息(model_name, test_name, errors[]).
默认的每次调用超时为1800秒(30分钟),因为数据测试使用断言运行真实的仓库查询,并且在大型表上可能需要很长时间——与Spectacles的默认使用时间相同。
使用自定义身份提供程序进行扩展
这 IdentityProvider 协议是与自定义身份验证系统集成的主要扩展点。
from looker_mcp_server.identity import IdentityProvider, LookerIdentity, RequestContext
from looker_mcp_server.server import create_server
from looker_mcp_server.config import LookerConfig
class MyIdentityProvider:
"""Custom identity provider that integrates with your auth system."""
async def resolve(self, context: RequestContext) -> LookerIdentity:
# Extract identity from headers, tokens, etc.
token = context.headers.get("authorization", "").removeprefix("Bearer ")
if token:
# Exchange for a Looker-scoped token via your auth system
looker_token = await my_token_exchange(token)
return LookerIdentity(mode="oauth", access_token=looker_token)
# Fall back to service account
return LookerIdentity(
mode="api_key",
client_id="your-client-id",
client_secret="your-client-secret",
)
# Wire it up
config = LookerConfig()
mcp, client = create_server(config, identity_provider=MyIdentityProvider())这 RequestContext 提供:
headers--HTTP请求标头(stdio模式下为空)tool_name--正在调用的MCP工具的名称tool_group--该工具属于哪个组arguments--传递给工具的参数
MCP级别身份验证
MCP级身份验证(谁可以连接到服务器)有两种模式,由选择 LOOKER_MCP_MODE.
LOOKER_MCP_MODE=dev (默认)--允许
适用于本地开发、stdio部署和上游网关后的信任网络场景。两个子选项:
- 无MCP级别的身份验证 (默认)--任何可以访问传输的客户端都可以连接。
- 静态承载令牌 (已弃用)--set
LOOKER_MCP_AUTH_TOKEN客户必须出示DeprecationWarning因为RFC 9068§2.1禁止OAuth 2.1访问令牌的对称静态承载,并且因为静态承载不携带每个用户的身份或到期时间。计划在未来的主要版本中删除--迁移到LOOKER_MCP_MODE=public.
LOOKER_MCP_MODE=public --OAuth 2.1资源服务器(MCP 2025-11-25)
互联网暴露/合规性门控部署。服务器:
- 验证每个请求
Authorization: Bearer标头作为OAuth 2.1访问令牌。 - 仅接受
RS256和ES256签名(RFC 9068§2.1)。HS256在头部检查时被硬拒绝,以关闭算法融合攻击向量(CVE-2015-9235)。 - 使用1小时的TTL缓存授权服务器的JWKS(RFC 7517),并限制孩子错过刷新(每5分钟≤1次强制刷新)。
- 强制执行
iss(RFC 8414)以及aud(RFC 8707)声明绑定。 - 为客户端自动发现提供RFC 9728受保护资源元数据文档。规范规范URL遵循RFC 9728§3的构造:
/.well-known/oauth-protected-resource当LOOKER_MCP_RESOURCE_URI是仅限来源的标识符,或/.well-known/oauth-protected-resource当它携带一条路径时。源根路径也被用作防御回退。 - 发射领域轴承
WWW-Authenticate401(RFC 7235第4.1节+RFC 9728第5.1节)的挑战,将客户端指向PRM URL。 - 拒绝URL查询承载令牌(
?access_token=,?authorization=)400invalid_request根据OAuth 2.1§5.1.1——无论目标是什么,URL绑定的令牌都会泄漏到引用者标头、代理日志和浏览器历史记录中。 - 拒绝
LOOKER_MCP_AUTH_TOKEN完全 --如果旁边设置了静态承载env varLOOKER_MCP_MODE=public,服务器无法启动。
所需配置:
export LOOKER_MCP_MODE=public
export LOOKER_MCP_JWKS_URI="https://auth.example.com/.well-known/jwks.json"
export LOOKER_MCP_ISSUER_URL="https://auth.example.com"
export LOOKER_MCP_RESOURCE_URI="https://looker-mcp.example.com/mcp"所有三个URI都必须是绝对的 https:// URL;服务器在启动时失败关闭,并键入 DeploymentPostureError 如果有缺失、格式错误或使用 http://The LOOKER_MCP_RESOURCE_URI 不得携带片段(RFC 9728§3)。
弃用时间表 LOOKER_MCP_AUTH_TOKEN
- 此版本(0.13.0) --已弃用
dev模式(发出警告),在中被拒绝public模式(启动失败)。 - 未来主要版本 --完全删除。
如果您目前依赖 LOOKER_MCP_AUTH_TOKEN 对于网关级MCP保护,现在就计划迁移:要么建立一个授权服务器,该服务器发出绑定到的OAuth 2.1访问令牌 aud=,或将服务器保持在 dev 受信任网络边界后面的模式。
PDT管理工作流
PDT(持久派生表)生命周期分为两个工具组: connection 集团的 update_connection 切换连接上的PDT控制和 modeling 集团的 start_pdt_build / check_pdt_build / stop_pdt_build (构建管理), trigger_datagroup (强制重建+缓存失效),以及 graph_derived_tables_for_* (依赖性检查)涵盖了每个PDT操作。
连接级工作流的两个有主见的配方:
禁用连接上的PDT工作流
当您需要暂停连接上的所有PDT构建时(仓库维护、成本飙升调查等):
// 1. Stop new builds at the source — Looker will reject any further enqueues
{ "tool": "update_connection", "args": { "name": "my_warehouse", "pdt_api_control_enabled": false } }
// 2. Inspect what's currently materialized so you know what's at risk
{ "tool": "graph_derived_tables_for_model", "args": { "model": "ecommerce", "color": true } }
// 3. (Optional) Stop any in-flight builds you have materialization_ids for
{ "tool": "stop_pdt_build", "args": { "materialization_id": "mat-abc" } }
// 4. Verify the connection is quiesced
{ "tool": "test_connection", "args": { "name": "my_warehouse", "tests": ["pdt"] } }在连接上启用PDT工作流
当您准备在维护后重新启用PDT构建时:
// 1. Re-enable PDT API control
{ "tool": "update_connection", "args": { "name": "my_warehouse", "pdt_api_control_enabled": true } }
// 2. Verify the connection is healthy for PDT builds
{ "tool": "test_connection", "args": { "name": "my_warehouse", "tests": ["pdt"] } }
// 3. (Optional) Force-rebuild gating datagroups so downstream PDTs catch up
{ "tool": "trigger_datagroup", "args": { "datagroup_id": "dg1" } }
// 4. (Optional) Pre-warm specific PDTs
{ "tool": "start_pdt_build", "args": { "model_name": "ecommerce", "view_name": "orders_pdt" } }
{ "tool": "check_pdt_build", "args": { "materialization_id": "mat-…" } } // poll until status == "complete"这些配方被有意地作为单独的基元而不是单个基元公开 disable_pdt_workflow(connection) 复合工具。每个调用在 looker.session.sudo 在下运行时的调试日志 act_as_user,这是合规性审查的正确粒度。复合工具将对作为操作员的LLM隐藏步骤,并使故障路径不那么清晰。
健康终点
在HTTP模式下运行时,服务器会公开:
GET /healthz--活性探测(如果服务器正在运行,则始终返回200)GET /readyz--准备就绪探测(通过登录/注销周期验证Looker连接)GET /.well-known/oauth-protected-resource--RFC 9728受保护资源元数据(仅当LOOKER_MCP_MODE=public).当LOOKER_MCP_RESOURCE_URI有路径,同一文档也会送达/.well-known/oauth-protected-resource--这是符合RFC 9728§3的规范规范URL,也是resource_metadata=...401WWW-Authenticate挑战。
发展
# Clone
git clone https://github.com/ultrathink-solutions/looker-mcp-server.git
cd looker-mcp-server
# Install dependencies
uv sync --locked --dev
# Run quality checks
uv run ruff check . # lint
uv run ruff format . # format
uv run pyright # type check
uv run pytest tests/ -v # tests看 贡献.md 关于贡献指南。
