Skip to content

feat: Support dashboard variables in MCP server - #2951

Draft
pulpdrew wants to merge 1 commit into
mainfrom
drew/vars-mcp
Draft

feat: Support dashboard variables in MCP server#2951
pulpdrew wants to merge 1 commit 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: 7a41daf

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 20, 2026 3:33pm
hyperdx-storybook Ready Ready Preview Aug 20, 2026 3:33pm

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 extends MCP dashboard tools with variable-aware filter schemas, validation, substitution, and tile-query inputs.

  • Preserves variable-enabled dashboard filters across get, save, and patch operations.
  • Adds variable selections to individual and batch tile queries.
  • Adds agent guidance, warnings, macro errors, and focused variable tests.

Confidence Score: 4/5

The PR is not yet safe to merge because omitted aggregate-condition languages can still generate malformed SQL for variable-driven builder tiles.

Variable substitution defaults an omitted aggregate-condition language to Lucene, while the all-select-condition WHERE pushdown defaults it to SQL and passes the expanded expression through unchanged, so reachable MCP tile queries can fail in ClickHouse.

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

Important Files Changed

Filename Overview
packages/common-utils/src/variables.ts Adds dashboard-variable extraction and substitution, but omitted aggregate-condition languages remain inconsistent with the renderer's WHERE pushdown.
packages/api/src/mcp/tools/dashboards/variables.ts Resolves declared dashboard variables and validates caller-supplied selections before tile execution.
packages/api/src/mcp/tools/dashboards/queryTile.ts Threads resolved variable values into individual dashboard tile queries.
packages/api/src/mcp/tools/dashboards/queryTiles.ts Applies the same variable-resolution contract to bounded batch tile execution.
packages/api/src/mcp/tools/dashboards/validation.ts Adds non-blocking warnings for unknown, bare, and dependent variable references.
packages/common-utils/src/filters.ts Extends shared dashboard-filter behavior and variable-name handling used by MCP validation and rendering.

Sequence Diagram

sequenceDiagram
  participant Agent as MCP agent
  participant Tool as Dashboard query tool
  participant Vars as Variable resolver
  participant Render as Chart renderer
  participant CH as ClickHouse
  Agent->>Tool: query tile + variableValues
  Tool->>Vars: resolve dashboard variables
  Vars-->>Tool: names, expressions, selected values
  Tool->>Render: chart config + variables
  Render->>Render: substitute variable macros
  Render->>CH: rendered ClickHouse query
  CH-->>Tool: tile result
  Tool-->>Agent: result and warnings
Loading

Comments Outside Diff (1)

  1. packages/common-utils/src/variables.ts, line 544 (link)

    P1 Conflicting aggregate language defaults

    When every builder select item has a variable-bearing aggregate condition and omits aggConditionLanguage, substitution expands the condition as Lucene while the WHERE pushdown consumes it as raw SQL, producing malformed ClickHouse syntax such as ServiceName:("api" OR "web") and causing the tile query to fail.

    Knowledge Base Used:

    Fix in Claude Code Fix in Conductor Fix in Cursor Fix in Codex

Fix all with Greploop Fix All in Claude Code Fix All in Conductor Fix All in Cursor Fix All in Codex

Reviews (2): Last reviewed commit: "feat: Support dashboard variables in MCP..." | 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 • 307 passed • 1 skipped • 1186s

Status Count
✅ Passed 307
❌ Failed 0
⚠️ Flaky 0
⏭️ 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