Skip to content

feat: Support dashboard variables in MCP server - #2951

Draft
pulpdrew wants to merge 3 commits into
mainfrom
drew/vars-mcp
Draft

feat: Support dashboard variables in MCP server#2951
pulpdrew wants to merge 3 commits into
mainfrom
drew/vars-mcp

Conversation

@pulpdrew

@pulpdrew pulpdrew commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR updates the MCP tools and prompts to include support for the new dashboard variables feature.

  • Dashboard filters can now be set to enable/disable variable and broadcast modes
  • Prompts and schema descriptions have been updated to describe how variables work and where they can be used
  • Dashboard create/save/patch have been updated to surface various warnings when variables are used incorrectly within tiles or dependent filters
  • Query Tile(s) tools have been updated to allow the user to specify values for variables that should be substituted when evaluating tiles, to allow the agent to test that variable substitution works as expected

This is to be merged only after removing the toggles guarding the dashboard variables feature.

Screenshots or video

How to test locally

Fire up your agent and ask it to build a dashboard that makes use of dashboard variables.

References

  • Linear Issue: Closes HDX-5062
  • Related PRs:

@changeset-bot

changeset-bot Bot commented Aug 20, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 5b32a11

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
@hyperdx/api Patch
@hyperdx/common-utils Patch
@hyperdx/app Patch
@hyperdx/otel-collector Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Aug 20, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hyperdx-oss Ready Ready Preview Aug 27, 2026 12:44pm
hyperdx-storybook Ready Ready Preview Aug 27, 2026 12:44pm

Request Review

@github-actions github-actions Bot added the review/tier-3 Standard — full human review required label Aug 20, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🟡 Tier 3 — Standard

Introduces new logic, modifies core functionality, or touches areas with non-trivial risk.

Why this tier:

  • Diff size: 829 production lines changed (Tier 2 max: < 250)
  • Cross-layer change: touches backend (packages/api) + shared utils (packages/common-utils)

Review process: Full human review — logic, architecture, edge cases.
SLA: First-pass feedback within 1 business day.

Stats
  • Production files changed: 16
  • Production lines changed: 829 (+ 2148 in test files, excluded from tier calculation)
  • Branch: drew/vars-mcp
  • Author: pulpdrew

To override this classification, remove the review/tier-3 label and apply a different review/tier-* label. Manual overrides are preserved on subsequent pushes.

@greptile-apps

greptile-apps Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds dashboard-variable support to MCP dashboard persistence, validation, and tile-query tools.

  • Preserves variable-enabled filter fields through dashboard create, read, update, and patch flows.
  • Resolves supplied variable selections before executing individual or batched tiles.
  • Adds variable-aware expansion, diagnostics, prompts, schemas, and focused query coverage.

Confidence Score: 3/5

The PR is not yet safe to merge because the outstanding aggregate-condition language mismatch can generate malformed or incorrectly filtered ClickHouse queries.

Variable-bearing aggregate conditions still default to Lucene during substitution while the aggregate WHERE-pushdown path defaults the same field to SQL, leaving both previously reported query failures unresolved.

Files Needing Attention: packages/common-utils/src/variables.ts, packages/common-utils/src/core/renderChartConfig.ts

Important Files Changed

Filename Overview
packages/common-utils/src/variables.ts Extends language-aware variable expansion, but the previously reported aggregate-condition default mismatch remains in the current query path.
packages/api/src/mcp/tools/dashboards/variables.ts Resolves declared dashboard variables, defaults selections to empty, and rejects unknown supplied names.
packages/api/src/mcp/tools/dashboards/queryTile.ts Adds variable selections and variable diagnostics to single-tile execution.
packages/api/src/mcp/tools/dashboards/queryTiles.ts Threads resolved variables through bounded concurrent tile execution.
packages/api/src/mcp/tools/query/helpers.ts Passes variables into builder, raw-SQL, and event-pattern query paths and improves unknown-variable diagnostics.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[MCP dashboard tool] --> B[Load team-scoped dashboard]
  B --> C[Read variable-enabled filters]
  C --> D[Resolve supplied variable values]
  D --> E[Expand tile expressions and macros]
  E --> F[Render ClickHouse query]
  F --> G[Return result and warnings]
Loading

Reviews (5): Last reviewed commit: "fix: Fix tests after merge" | Re-trigger Greptile

Comment thread packages/api/src/mcp/__tests__/dashboards/queryTile.int.test.ts
@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

E2E Test Results

All tests passed • 320 passed • 1 skipped • 1356s

Status Count
✅ Passed 320
❌ Failed 0
⚠️ Flaky 1
⏭️ Skipped 1

Tests ran across 4 shards in parallel.

View full report →

@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Deep Review

✅ No P0/P1 issues found. The change is well-tested (large additions across patchDashboard, queryTile(s), saveDashboard, validation, and variables test suites) and the SQL-expansion path reuses the existing escapeSqlString/format machinery rather than introducing new interpolation. One contract-level gap and a couple of nits are worth addressing before merge.

🟡 P2 — recommended

  • packages/api/src/mcp/tools/dashboards/schemas.ts:1183 — The mcpDashboardFilterSchema description states variableName is "Rejected when isVariableEnabled is not true" and (schemas.ts:1148) that a non-empty appliesToSourceIds "is rejected when isBroadcastEnabled is false", but neither mcpDashboardFilterSchema nor the underlying DashboardFilterSchema in packages/common-utils/src/types.ts:1682 has a superRefine enforcing either — the common-utils schema comment even says variableName is merely "Ignored". An agent trusting the description sends variableName without isVariableEnabled, the field is silently accepted, and the mistake only surfaces later as an "unknown variable" at tile-query time instead of a clear save-time rejection.
    • Fix: Add a superRefine to mcpDashboardFilterSchema that rejects variableName when isVariableEnabled !== true and rejects a non-empty appliesToSourceIds when isBroadcastEnabled === false, or soften both descriptions to say the fields are ignored rather than rejected.
🔵 P3 nitpicks (2)
  • packages/api/src/mcp/tools/dashboards/validation.ts:445 — In getFilterVariableWarnings, filtersByUnpublishedVarName is keyed by lower-cased variable names and looked up via name.toLowerCase(), but variable resolution elsewhere (requireVariable in packages/common-utils/src/variables.ts and declaredNames) is case-sensitive, so the "not published as a variable" hint can misfire or suggest a variableName that still would not resolve at runtime.
    • Fix: Key and compare filtersByUnpublishedVarName case-sensitively to match runtime variable matching.
  • packages/api/src/mcp/tools/dashboards/variables.ts:65byName.get(name)!.values = values relies on a non-null assertion; it is safe today because unknown names are rejected just above, but the invariant is implicit.
    • Fix: Destructure the map lookup with an explicit guard (or a comment) so the non-null assumption is self-documenting for future edits.

Reviewers (10): correctness, testing, maintainability, project-standards, api-contract, security, adversarial, kieran-typescript, agent-native, learnings-researcher.

Coverage note: The dispatched persona-reviewer sub-agents had not returned their findings at synthesis time, so the findings above come from direct analysis of the diff and the surrounding schema/expansion code; they were verified against the code paths cited. The new behavior is otherwise accompanied by substantial test coverage, and the CSV-format non-escaping in formatVariableValues is pre-existing (not introduced by this diff) and reachable only by a caller who already has arbitrary-SQL access via the sql tool.

Testing gaps: No test asserts the documented "Rejected when isVariableEnabled is not true" / "rejected when isBroadcastEnabled is false" filter constraints — consistent with those constraints not being enforced.

@brandon-pereira

Copy link
Copy Markdown
Member

Are we planning to merge this only after we remove the feature flags? I am concerned agents might start using this feature before its allowed.

@pulpdrew

Copy link
Copy Markdown
Contributor Author

Are we planning to merge this only after we remove the feature flags? I am concerned agents might start using this feature before its allowed.

Correct, we will merge after enabling the feature. Sorry, should have written that in the description. I'll put this in draft mode but would appreciate your review still, so I can get started on addressing any feedback you may have.

I expect we can remove the toggle early next week.

@pulpdrew
pulpdrew marked this pull request as draft August 21, 2026 16:05
@brandon-pereira

Copy link
Copy Markdown
Member

PR LGTM otherwise! Thanks for clarifying

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review/tier-3 Standard — full human review required

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants