Skip to content

feat(tool/looker): add create_merge_query tool - #3758

Open
LacombeLouis wants to merge 1 commit into
googleapis:mainfrom
LacombeLouis:claude/looker-mcp-merge-query-2e181d
Open

feat(tool/looker): add create_merge_query tool#3758
LacombeLouis wants to merge 1 commit into
googleapis:mainfrom
LacombeLouis:claude/looker-mcp-merge-query-2e181d

Conversation

@LacombeLouis

Copy link
Copy Markdown
Contributor

Description

Adds a new Looker tool, looker-create-merge-query (registered as
create_merge_query), exposing Looker's
Merged Results through the
API (POST /merge_queries).

Impact: a query call can only target one explore, so today an agent that
needs fields from two explores has to run both queries and stitch the rows
together itself — losing Looker's join semantics and burning extra tool calls.
This tool performs the merge server-side, including across explores backed by
different databases.

Solution: the tool takes a source_queries array, one entry per explore.
Order is significant — the first entry is the primary query, and the results of
every later entry are joined onto it using that entry's merge_fields, matching
Looker's left-outer-join semantics. Each source query is created with
sdk.CreateQuery (idempotent, so an identical query is reused rather than
duplicated) and the resulting query ids are handed to sdk.CreateMergeQuery.
Merge-level pivots, sorts, limit, column_limit, total,
dynamic_fields and vis_config are supported.

Important API limitation

Looker has no endpoint that runs a merge query — only create and get. So the
tool returns the merge query id, its result_maker_id, the created source
queries (name, model, explore, query_id, slug) and a url that opens
the merged results in the Looker UI, rather than rows of data. This is stated
explicitly in the tool description and the docs page so the planner does not
expect data back and instead falls back to query per explore when it needs the
rows in-conversation.

Notable details

  • Strict source-query keys. An unknown key inside a source query is
    rejected rather than silently dropped, so a typo like explores surfaces as an
    error instead of a query quietly missing a filter.
  • Unquoted-parameter filters. Reuses
    lookercommon.EscapeUnquotedParameterFilters per source query, so LookML
    type: unquoted parameters behave exactly as they do in looker-query.
  • Discoverability. Adds a note to the prebuilt query tool description
    pointing at create_merge_query. The shared parameter descriptions in
    lookercommon are deliberately left untouched — changing them forces edits
    across five separate integration-test expectation blocks.
  • Annotations. Uses NewWriteAnnotations (non-destructive write), since the
    call does create objects in Looker but nothing user-visible or destructive.

Testing

  • Unit tests: YAML config parse (success + failure), processSourceQuery (happy
    path, every optional key, 10 error cases), processSourceQueries (arity guard),
    asRowLimit and mergeURL.
  • go test -race ./cmd/... ./internal/... passes.
  • go vet and gofmt clean, including tests/looker.
  • .ci/lint-docs-tool-page.sh passes (320 pages).
  • Integration tests: tool config plus a RunToolGetTestByName manifest
    assertion (verified byte-for-byte against the generated manifest) and a
    RunToolInvokeParametersTest invoke case.

Reviewer notes

  • The integration invoke test is unverified against a live instance. It
    merges two system__activity look queries joined on look.id and assumes
    look.id / look.title exist there. I had no Looker instance available, so
    this is the most likely thing to need adjusting.
  • golangci-lint is not installed in my environment and was not run; CI will be
    the first real check.
  • .ci/lint-docs-sample-filters.sh fails locally, but it reports every filter in
    every untouched file as invalid — a pre-existing local tooling problem, not
    something this branch causes.

PR Checklist

  • Make sure you reviewed
    CONTRIBUTING.md
  • Make sure to open an issue as a
    bug/issue
    before writing your code! That way we can discuss the change, evaluate
    designs, and agree on the general idea
  • Ensure the tests and linter pass
  • Code coverage does not decrease (if any source code was changed)
  • Appropriate docs were updated (if necessary)
  • Make sure to add ! if this involve a breaking change (not a breaking change)

🛠️ Fixes #3756 🦕

🤖 Generated with Claude Code

@google-cla

google-cla Bot commented Jul 31, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new tool, create_merge_query (type looker-create-merge-query), to the Looker integration. This tool enables merging query results from multiple explores, mimicking a SQL left outer join. The changes include the Go implementation of the tool, comprehensive unit and integration tests, updates to prebuilt configurations, and extensive documentation. No review comments were provided, so I have no feedback to offer on the review itself.

Adds `looker-create-merge-query`, exposing Looker's Merged Results
through the API (`POST /merge_queries`). This lets an agent combine
fields from two or more explores — even across different databases — in
a single result, which a plain `query` call cannot do since it targets
one explore.
The tool takes a `source_queries` array (one entry per explore) whose
order is significant: the first entry is the primary query and the
results of every later entry are joined onto it via that entry's
`merge_fields`, matching Looker's left-outer-join semantics. Each source
query is created with `sdk.CreateQuery` (idempotent, so identical
queries are reused) and the resulting ids are passed to
`sdk.CreateMergeQuery`.
Looker has no API endpoint that runs a merge query, so the tool returns
the merge query id, its result_maker_id, the created source queries and
a URL that opens the merged results in the Looker UI, rather than rows.
This is stated in the tool description and docs so the planner does not
expect data back.
Notable details:
- Unknown keys inside a source query are rejected rather than silently
  dropped, so a typo like `explores` surfaces as an error instead of a
  query missing a filter.
- Reuses `lookercommon.EscapeUnquotedParameterFilters` per source query,
  so `type: unquoted` parameter filters behave as they do in
  `looker-query`.
- Adds a note to the prebuilt `query` tool description pointing at this
  tool, so the planner can discover it. The shared parameter
  descriptions in `lookercommon` are deliberately untouched to avoid
  churn in the integration-test expectations.
@LacombeLouis
LacombeLouis force-pushed the claude/looker-mcp-merge-query-2e181d branch from a99c6c5 to 17737fa Compare July 31, 2026 16:12
@duwenxin99

Copy link
Copy Markdown
Contributor

Hi @drstrangelooker, this contributor is adding a new Looker tool. Could you take a look and see if this is what you want? Thank you!

@duwenxin99 duwenxin99 added the priority: p2 Moderately-important priority. Fix may not be included in next release. label Aug 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

priority: p2 Moderately-important priority. Fix may not be included in next release.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add create_merge_query to Looker MCP

3 participants