Skip to content

fix(mcp): align Jinja context across query preview and compile paths … - #43176

Open
AmoghAtreya wants to merge 24 commits into
apache:masterfrom
AmoghAtreya:fix/43174-mcp-jinja-context-preview-compile
Open

AmoghAtreya wants to merge 24 commits into
apache:masterfrom
AmoghAtreya:fix/43174-mcp-jinja-context-preview-compile

Conversation

@AmoghAtreya

@AmoghAtreya AmoghAtreya commented Aug 14, 2026 •

Copy link
Copy Markdown
Contributor

SUMMARY

Follow-up to #42822 / #43174. Chart execution could resolve request-dependent Jinja (filter_values, get_filters, url_param, get_time_filter, implicit metric() dataset lookup) while sibling MCP paths (get_chart_sql, preview, compile, query_dataset, get_table) still rendered fallbacks such as No filter, so displayed SQL could diverge from executed SQL.

This extracts a shared helper that serializes a real QueryObject/QueryContext onto g.form_data in the chart-data API shape, and applies it immediately before every MCP ChartDataCommand construction. For query_dataset and get_table, execute_tabular_query passes the resolved time_range alongside the query dict so get_time_filter() sees the same value as SQL execution, without putting it on QueryObject.time_range itself (keeps the sc-120967 cache-key fix intact). Guest authorize_query still runs first. Non-MCP ChartDataCommand sites are unchanged.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

N/A

TESTING INSTRUCTIONS

  1. Create a virtual dataset whose SQL uses {{ filter_values('region') }}, {{ url_param('tenant') }}, and {{ get_time_filter().time_range }}.
  2. Build a chart on that dataset with a region filter, url_params.tenant, and a time range.
  3. Call get_chart_data and confirm the macros resolve (not No filter / empty).
  4. Call get_chart_sql and get_chart_preview on the same chart and confirm the rendered SQL matches the executed query.
  5. Repeat with an unsaved chart via form_data_key.
  6. Call query_dataset / get_table with filters and time_range and confirm get_time_filter() matches the request.
  7. Confirm an embedded guest still cannot query a chart outside the guest dashboard scope.
pytest -q \
  tests/unit_tests/charts/data/form_data_test.py \
  tests/unit_tests/mcp_service/chart/tool/test_get_chart_data.py \
  tests/unit_tests/mcp_service/dataset/tool/test_query_dataset.py \
  tests/unit_tests/mcp_service/chart/tool/test_get_chart_sql.py \
  tests/unit_tests/mcp_service/chart/tool/test_get_chart_preview.py \
  tests/unit_tests/mcp_service/chart/test_preview_utils.py \
  tests/unit_tests/mcp_service/chart/test_compile.py \
  tests/unit_tests/mcp_service/semantic_layer/tool/test_get_table.py \
  tests/unit_tests/mcp_service/chart/tool/test_generate_chart.py \
  tests/unit_tests/common/test_tabular_query.py

ADDITIONAL INFORMATION

  • Has associated issue: Fixes fix(mcp): align Jinja context across query preview and compile paths #43174
  • Required feature flags:
  • Changes UI
  • Includes DB Migration (follow approval process in SIP-59)
    • Migration is atomic, supports rollback & is backwards-compatible
    • Confirm DB migration upgrade and downgrade tested
    • Runtime estimates and downtime expectations provided
  • Introduces new feature or API
  • Removes existing feature or API

@dosubot dosubot Bot added api Related to the REST API change:backend Requires changing the backend global:jinja Related to Jinja templating labels Aug 14, 2026
@bito-code-review

bito-code-review Bot commented Aug 14, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #a1a3d1

Actionable Suggestions - 0
Filtered by Review Rules

Bito filtered these suggestions based on rules created automatically for your feedback. Manage rules.

  • tests/unit_tests/mcp_service/semantic_layer/tool/test_get_table.py - 2
    • Test doubles must expose required attributes · Line 143-143
    • Test doubles must expose required attributes · Line 475-475
Review Details
  • Files reviewed - 19 · Commit Range: ff13ce0..ff13ce0
    • superset/charts/data/api.py
    • superset/charts/data/form_data.py
    • superset/mcp_service/chart/compile.py
    • superset/mcp_service/chart/preview_utils.py
    • superset/mcp_service/chart/tool/get_chart_data.py
    • superset/mcp_service/chart/tool/get_chart_preview.py
    • superset/mcp_service/chart/tool/get_chart_sql.py
    • superset/mcp_service/dataset/tool/query_dataset.py
    • superset/mcp_service/semantic_layer/tool/get_table.py
    • superset/tasks/async_queries.py
    • tests/unit_tests/charts/data/form_data_test.py
    • tests/unit_tests/mcp_service/chart/test_compile.py
    • tests/unit_tests/mcp_service/chart/test_preview_utils.py
    • tests/unit_tests/mcp_service/chart/tool/test_generate_chart.py
    • tests/unit_tests/mcp_service/chart/tool/test_get_chart_data.py
    • tests/unit_tests/mcp_service/chart/tool/test_get_chart_preview.py
    • tests/unit_tests/mcp_service/chart/tool/test_get_chart_sql.py
    • tests/unit_tests/mcp_service/dataset/tool/test_query_dataset.py
    • tests/unit_tests/mcp_service/semantic_layer/tool/test_get_table.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@codecov

codecov Bot commented Aug 14, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 87.69231% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.12%. Comparing base (2c275ed) to head (219895c).
⚠️ Report is 68 commits behind head on master.

Files with missing lines Patch % Lines
superset/common/tabular_query.py 57.14% 3 Missing and 3 partials ⚠️
...perset/mcp_service/chart/tool/get_chart_preview.py 89.47% 0 Missing and 2 partials ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##           master   #43176   +/-   ##
=======================================
  Coverage   84.12%   84.12%           
=======================================
  Files        3056     3056           
  Lines      201392   201394    +2     
  Branches    47090    47088    -2     
=======================================
+ Hits       169419   169424    +5     
+ Misses      28727    28722    -5     
- Partials     3246     3248    +2     
Flag Coverage Δ
hive 34.87% <12.30%> (-0.01%) ⬇️
mysql 52.81% <12.30%> (-0.02%) ⬇️
postgres 52.82% <12.30%> (-0.02%) ⬇️
presto 36.60% <12.30%> (-0.01%) ⬇️
python 87.36% <87.69%> (+0.01%) ⬆️
sqlite 52.58% <12.30%> (-0.02%) ⬇️
unit 81.74% <87.69%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment on lines +55 to +62
set_form_data(
{
"datasource": {"id": datasource_id, "type": datasource_type},
"queries": [
_serialize_query(query, form_data) for query in query_context.queries
],
"form_data": form_data,
}

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.

Suggestion: The synthetic global form data keeps the original chart fields only under the nested form_data key, while get_form_data() exposes the first serialized query as the top-level form data. Consequently, fields such as adhoc_filters and extra_form_data from query_context.form_data are invisible to Jinja macros that inspect top-level form data, notably get_time_filter(column), which can render a fallback or the wrong temporal range even though the executed query has the filter. Merge the relevant original form-data fields into the top level or serialize them into the query using the chart-data request shape. [api mismatch]

Severity Level: Major ⚠️
- ❌ MCP SQL output can diverge from executed chart SQL.
- ⚠️ Column-specific Jinja time filters are ignored.
- ⚠️ Virtual dataset previews can show incorrect temporal ranges.

Fix in Cursor Fix in VSCode Claude

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset/charts/data/form_data.py
**Line:** 55:62
**Comment:**
	*Api Mismatch: The synthetic global form data keeps the original chart fields only under the nested `form_data` key, while `get_form_data()` exposes the first serialized query as the top-level form data. Consequently, fields such as `adhoc_filters` and `extra_form_data` from `query_context.form_data` are invisible to Jinja macros that inspect top-level form data, notably `get_time_filter(column)`, which can render a fallback or the wrong temporal range even though the executed query has the filter. Merge the relevant original form-data fields into the top level or serialize them into the query using the chart-data request shape.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this is covered too, just less directly. _serialize_query still carries query.filter up as filters, and get_time_filter() runs convert_legacy_filters_into_adhoc() first, converting any TEMPORAL_RANGE entries into adhoc_filters before matching on column. No test covers the column-specific case though, so flagging before closing this out.

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.

Reopening this one briefly, @rusackas. On the dataset path I do not think it is covered: by the time _serialize_query runs, _apply_granularity has already deleted the TEMPORAL_RANGE entry from QueryObject.filter (it fires whenever granularity names the filter's column, which query_dataset always does when time_range is set), so there is nothing left for convert_legacy_filters_into_adhoc() to convert. I verified it on the head: after the real factory, queries[0].filter is [] and get_time_filter() returns No filter. Details and a suggested fix in my comment on query_dataset.py. Are the chart tool paths safe only because their form_data carries a top level time_range, or is there another mechanism I am missing for the column specific case there?

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.

You’re right—the dataset path is not covered by this helper as currently written.

_serialize_query() only sees the post-factory QueryObject. For query_dataset, _apply_granularity() removes the TEMPORAL_RANGE filter when the temporal column is used as granularity, so both:

query.filter == []
query.time_range is None

may be true by the time set_query_context_form_data() runs. The fallback hoisting logic therefore has nothing to serialize, and get_time_filter() can still return No filter.

The chart paths are safer when their original form_data includes a top-level time_range, but that does not fully solve column-specific get_time_filter("column") behavior. They should still rely on the serialized query’s filter payload where possible.

The minimal fix is to preserve the request’s temporal filter for the Jinja payload before the query factory mutates the QueryObject, without adding QueryObject.time_range (which would affect cache-key behavior). For example, pass the original filters/time range through the query context’s form data or attach a chart-data-shaped filter payload, then let _serialize_query() use that preserved value when the final query has no temporal filter.

So the concern is valid and should remain open until the dataset path has a regression test asserting get_time_filter().time_range after the real QueryContextFactory runs.

Comment thread superset/mcp_service/chart/tool/get_chart_sql.py

@gabotorresruiz gabotorresruiz 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.

Thanks @AmoghAtreya, this closes out the follow-up from #42822 nicely, and the approach is the right one: the synthesized payload mirrors the chart-data API body shape, so the g fallback in get_form_data() and convert_legacy_filters_into_adhoc() see the same inputs the executed QueryObject carries.

I verified this empirically. All 8 new regression tests fail on the parent commit and pass on this head, and the full mcp_service, charts and tasks unit suites pass locally (3,976 tests) except one, see below. I also ran it live: booted the MCP service from this branch over streamable HTTP, built a virtual dataset using {{ filter_values("region") }}, {{ url_param("tenant") }}, {{ get_time_filter().time_range }} and {{ get_time_filter("order_date").time_range }}, and called the tools end to end. On this branch get_chart_sql returns exactly the SQL get_chart_data executed, with the macros resolved (North, acme, Last month), and query_dataset/get_table resolve the time macros too. The same scenario on the parent commit renders none and No filter across all of them, so the fix does what it says.

Blocking items:

  1. tests/unit_tests/mcp_service/chart/tool/test_get_chart_data.py:1612 (in test_oauth2_redirect_on_form_data_key_path) still stubs build_query_context_from_form_data as a bare object(), and _query_from_form_data now dereferences query_context.form_data before running the command, so the OAuth error surfaces as InternalError and the unit-tests job fails. I verified the one-line fix locally, it matches your other stub updates:
monkeypatch.setattr(
    chart_data_module,
    "build_query_context_from_form_data",
    lambda *args, **kwargs: SimpleNamespace(queries=[], form_data={}),
)
  1. pre-commit: 5 mypy errors and one ruff-format reflow. I reproduced them with the repo's mypy hook and confirmed they clear with casts in the three test files (cast(Any, ...) for the SimpleNamespace chart and context doubles, dict[str, object] for the bare dict return at test_compile.py:609) plus ruff format on tests/unit_tests/charts/data/form_data_test.py.

  2. Rebase needed: #42822 merged about an hour after this PR opened, so master already has superset/charts/data/form_data.py, and this branch conflicts with it (add/add on the helper and its test file, content conflict in test_query_dataset.py). When rebasing, keep your datasource_id: int | str signature (master has int, but resolve_form_data_datasource can return a string id on the combined-datasource path). Your query_dataset/get_table time_range copy and all the sibling-path coverage are net new on top of master, so they survive the rebase.

One observation from the live run, not a blocker: with the modern saved-query shape where the temporal range only exists as a TEMPORAL_RANGE filter (no time_range key on the query), {{ get_time_filter().time_range }} without a column renders No filter on the chart paths, while the column-scoped {{ get_time_filter("order_date").time_range }} resolves. That matches chart-data API semantics (QueryObjectFactory.create keeps QueryObject.time_range as None and only derives from_dttm/to_dttm from the filter), and executed and displayed SQL stay identical, so it is consistent. Just worth knowing when running step 3 of your testing instructions, which only holds when the query carries an explicit time_range.

Happy to approve once CI is green on the rebased branch.

query_context,
chart.datasource_id,
chart.datasource_type,
)

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.

Not a blocker, a parity question: here the Jinja fallback gets chart.datasource_id, but the command executes the datasource encoded in the saved query_context. If a chart is repointed to another dataset while its saved query_context is stale, get_dataset_id_from_context() (and so an implicit metric() lookup) resolves a different dataset than the SQL we return. Since query_context is already loaded here, query_context.datasource.id and str(query_context.datasource.type) would make the template context and the execution target unable to diverge, matching the fallback you already added in _sql_from_form_data. Same question for the saved-context branch in get_chart_data (line 681), where merge_extra_form_data_filters_into_query a few lines up already uses query_context_json["datasource"]["id"]. Or is the chart-level datasource intentional there?

@rusackas

Copy link
Copy Markdown
Member

Heya @AmoghAtreya, @gabotorresruiz left a really thorough review above with the exact fixes needed (test stub, pre-commit, rebase off master). Once those land and CI's green, this should be quick to get merged. Holler if you get stuck on any of it, happy to push some commits.

@AmoghAtreya

Copy link
Copy Markdown
Contributor Author

Thanks @gabotorresruiz for the super thorough review and detailed feedback, and @rusackas for checking in! Sorry for the delay on my end—I was out of town for the past week and was unable to work on the fixes.

I'm getting to work on the requested fixes now (updating the test stub, fixing the pre-commit issues, and rebasing on master). I'll also address the comments from CodeAnt and update the stale datasource references in get_chart_sql.py so the template context and execution target stay strictly in sync.

I'll ping back as soon as the updated commits are pushed and CI is green!

@github-actions github-actions Bot added the requires:rebase Requires rebasing on top of current master label Sep 3, 2026
@AmoghAtreya
AmoghAtreya force-pushed the fix/43174-mcp-jinja-context-preview-compile branch from ff13ce0 to d3fe6a8 Compare September 9, 2026 00:10
@github-actions github-actions Bot removed api Related to the REST API requires:rebase Requires rebasing on top of current master labels Sep 9, 2026
@bito-code-review

Copy link
Copy Markdown
Contributor

AI Code Review is in progress (usually takes 3 to 15 minutes unless it's a very large PR).

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

@netlify

netlify Bot commented Sep 9, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for superset-docs-preview ready!

Name Link
🔨 Latest commit 89ae570
🔍 Latest deploy log https://app.netlify.com/projects/superset-docs-preview/deploys/6ada61fe2a01dd75397ad19b
😎 Deploy Preview https://deploy-preview-43176--superset-docs-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions github-actions Bot added the doc Namespace | Anything related to documentation label Sep 9, 2026
@AmoghAtreya

Copy link
Copy Markdown
Contributor Author

Thanks again @gabotorresruiz for the thorough review and detailed instructions on what to fix and @rusackas for following up. Sorry for the delay , but the blocking items from the last review are in.

Here's what I fixed:

  1. OAuth form_data_key stub now returns SimpleNamespace(queries=[], form_data={}) so _query_from_form_data doesn’t blow up
  2. mypy casts / ruff-format on the helper tests
  3. rebased/merged onto master, keeping datasource_id: int | str
  4. saved SQL / chart-data Jinja fallback now prefers the executed query_context datasource (with JSON, then chart, as a fallback so MagicMock doubles still work)

CI is green on the latest commits. The get_time_filter() no-column / TEMPORAL_RANGE-only note matches what I see as well — same as the chart-data API, so executed and displayed SQL stay in sync.

Please let me know if there's any other changes you would like me to implement. Happy to follow up on anything else!

@bito-code-review

bito-code-review Bot commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #e1ef8a

Actionable Suggestions - 0
Review Details
  • Files reviewed - 3 · Commit Range: 7802fbf..b98f43b
    • superset/mcp_service/chart/tool/get_chart_data.py
    • superset/mcp_service/chart/tool/get_chart_sql.py
    • tests/unit_tests/mcp_service/chart/tool/test_get_chart_data.py
  • Files skipped - 1
    • docs/static/resources/openapi.json - Reason: Filter setting
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@github-actions github-actions Bot added the requires:rebase Requires rebasing on top of current master label Sep 9, 2026
@rusackas

Copy link
Copy Markdown
Member

@gabotorresruiz the three blockers are in (OAuth stub, mypy/ruff, rebase) and CI's green now. Looks like your datasource parity question got fixed too, both get_chart_sql and get_chart_data now prefer query_context.datasource.id/type over chart.datasource_id, matching what you asked for. Worth another look when you get a chance?

@gabotorresruiz gabotorresruiz 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.

Thanks @AmoghAtreya for the careful follow-through, and @rusackas for shepherding. All three blockers from my last review are resolved. I verified each at b98f43b rather than taking the diff's word for it:

  • The OAuth form_data_key stub now returns SimpleNamespace(queries=[], form_data={}) and the routing tests pass.
  • The repo's mypy pre-commit hook passes locally on all changed files, ruff format is clean, and CI is green at the head.
  • The branch is synced over #42822 with datasource_id: int | str kept. Full local run of the mcp_service, charts and tabular_query unit suites: 4,050 passed, 2 xfailed, 0 failed.

The datasource parity question from my inline comment is addressed too: get_chart_sql and get_chart_data now prefer query_context.datasource over the chart row, so the template context cannot diverge from the execution target.

Since form_data.py, compile.py, preview_utils.py and the preview seed hunks are unchanged from the head I verified live in August (virtual dataset with filter_values, url_param and get_time_filter over the MCP HTTP transport, rendered SQL matching executed SQL on every path), that end-to-end evidence carries over to this head.

One mechanical item before merge: master moved again after your sync, and the branch now conflicts in three test files (test_compile.py, test_preview_utils.py, test_get_table.py, from #43943 and #44105). One more master sync should clear it; please re-run those suites afterwards since #44105 landed in the same tabular time-range territory. The openapi.json regen is fine to carry, it is the CI-enforced sync for the schema change already on master.

Approving. And thanks for consolidating #43711 into this PR, the compile and preview paths finally get the same Jinja context as every other ChartDataCommand site.

@rusackas

Copy link
Copy Markdown
Member

@AmoghAtreya master moved again since your last sync, GitHub shows conflicts now in the test files @gabotorresruiz flagged (test_compile.py, test_preview_utils.py, test_get_table.py, from #43943 and #44105). Rebase and re-run those suites and this should be ready, as @gabotorresruiz already approved the substance. Let us know if you need a hand.

@rusackas
rusackas force-pushed the fix/43174-mcp-jinja-context-preview-compile branch from b98f43b to 3d17c49 Compare September 12, 2026 19:13
@github-actions github-actions Bot removed the doc Namespace | Anything related to documentation label Sep 12, 2026
@AmoghAtreya

AmoghAtreya commented Sep 12, 2026 •

Copy link
Copy Markdown
Contributor Author

Thanks for the commit, @rusackas ! If you'd like, I can fix the failing tests and push my updates once the current test run finishes.

AmoghAtreya and others added 5 commits October 3, 2026 10:46
Harden set_query_context_form_data for incomplete query-context doubles and hoist TEMPORAL_RANGE into Jinja form data so MCP queries keep rollover cache behavior from apache#43914.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Granularity processing strips TEMPORAL_RANGE before the form-data helper runs, so read the raw query dicts in cache_values and reconstruct one-sided semantic-view comparisons.

Co-authored-by: Cursor <cursoragent@cursor.com>
Chart-like preview objects may omit datasource_id; skip the helper instead of raising so typed errors still surface.

Co-authored-by: Cursor <cursoragent@cursor.com>
Keep the shared serializer chart-API identical so async get_time_filter() is not invented from TEMPORAL_RANGE filters. Tabular callers pass the original range explicitly.

Co-authored-by: Cursor <cursoragent@cursor.com>
@AmoghAtreya
AmoghAtreya force-pushed the fix/43174-mcp-jinja-context-preview-compile branch from bd6d88f to 8de6b69 Compare October 3, 2026 17:47
AmoghAtreya and others added 6 commits October 3, 2026 10:48
The getattr guards only existed for test stubs; production always passes a QueryObject, so direct access is clearer and will fail loudly if those fields move.

Co-authored-by: Cursor <cursoragent@cursor.com>
getattr defaults only soft-failed for incomplete stubs; QueryContext defines both fields, so direct access matches the annotation and fails loudly on renames.

Co-authored-by: Cursor <cursoragent@cursor.com>
_time_range_from_filters and _time_range_filters were easy to confuse; rename the reader to _temporal_range_in_filters.

Co-authored-by: Cursor <cursoragent@cursor.com>
…compile

No circular dependency requires a deferred import; sibling chart tools already import it at the top of the module.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Direct QueryObject access stays; the QueryContext envelope again accepts unit-test stubs so preview/compile mocks without form_data or list queries do not crash.

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions github-actions Bot removed the requires:rebase Requires rebasing on top of current master label Oct 3, 2026
Co-authored-by: Cursor <cursoragent@cursor.com>
@AmoghAtreya

Copy link
Copy Markdown
Contributor Author

@rusackas just rebased the branch and got it updated with master! Please let me know if there are any other changes to make.

@bito-code-review bito-code-review 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 Agent Run #4f788a

Actionable Suggestions - 3
  • tests/unit_tests/mcp_service/chart/tool/test_get_chart_preview.py - 1
  • tests/unit_tests/mcp_service/chart/tool/test_get_chart_sql.py - 2
Additional Suggestions - 7
  • tests/unit_tests/common/test_tabular_query.py - 2
    • Helper missing docstring · Line 515-522
      `_factory_dataset` is the only new function in this file without a docstring, while sibling helpers like `_column` and every new test document their intent. A one-liner noting that every column is temporal except the literal `"region"` would also document the sentinel coupling noted separately. ([BITO.md](BITO.md))
    • Magic string sentinel · Line 518-521
      The literal `"region"` encodes the business rule 'this column is the non-temporal one' in three places: the `is_dttm` predicate (518), the `main_dttm_col` generator (521), and the call site `_factory_dataset("region", "order_date")` (561). Renaming the test column would silently flip every column's `is_dttm`. Hoist it into a named constant.
  • tests/unit_tests/mcp_service/chart/tool/test_get_chart_sql.py - 1
    • Duplicated test setup block · Line 265-295
      Both tests repeat identical setup: the `importlib.import_module` of `get_data_command`, the `QueryObject(filters=[...], time_range="Last week")` construction, and a near-identical `chart` SimpleNamespace (lines 319-329 and 346-353 mirror this block). A shared helper or fixture would keep each test focused on its differing patches.
  • superset/mcp_service/chart/tool/get_chart_preview.py - 3
    • New Jinja-context behavior untested · Line 224-247
      The new `_run_chart_data_command` behavior — publishing `g.form_data` via `set_query_context_form_data` before `ChartDataCommand.run` — has no test coverage: no test references the helper, and existing tests in test_get_chart_preview.py patch `ChartDataCommand` without asserting the Jinja-context publication. BITO.md rule 11730 asks for tests covering new feature behavior; please add one.
    • Inline import violates rule 12745 · Line 226-226
      BITO.md adaptive rule 12745 requires module-level imports unless a documented circular dependency exists. `superset.commands.chart.data.get_data_command` has no mcp_service back-import (verified), and this file already imports `superset.commands.exceptions` and `set_query_context_form_data` at module level, so the inline import in `_run_chart_data_command` is unnecessary; move it beside line 29.
    • Use specific type for query_context · Line 224-224
      The `query_context` parameter is typed as `Any`, which is disallowed by `ANN401`. Use a specific type like `QueryContext` from `superset.models.sql.types` to improve type safety.
  • tests/unit_tests/tasks/test_async_queries.py - 1
    • Missing local var type hint · Line 235-235
      The new local `query` (line 235) lacks a type annotation, contrary to the org-mandated BITO.md adaptive rule 13153/13347 requiring explicit annotations on all local variables in test files. Add `query: QueryObject = QueryObject(...)` for consistency with the repo's typing standard.
Review Details
  • Files reviewed - 21 · Commit Range: 7c49ba6..2bb5c98
    • superset/charts/data/form_data.py
    • superset/common/tabular_query.py
    • superset/datasource/api.py
    • superset/mcp_service/chart/compile.py
    • superset/mcp_service/chart/preview_utils.py
    • superset/mcp_service/chart/tool/get_chart_data.py
    • superset/mcp_service/chart/tool/get_chart_preview.py
    • superset/mcp_service/chart/tool/get_chart_sql.py
    • superset/mcp_service/dataset/tool/query_dataset.py
    • superset/mcp_service/semantic_layer/tool/get_table.py
    • tests/unit_tests/charts/data/form_data_test.py
    • tests/unit_tests/common/test_tabular_query.py
    • tests/unit_tests/mcp_service/chart/test_compile.py
    • tests/unit_tests/mcp_service/chart/test_preview_utils.py
    • tests/unit_tests/mcp_service/chart/tool/test_generate_chart.py
    • tests/unit_tests/mcp_service/chart/tool/test_get_chart_data.py
    • tests/unit_tests/mcp_service/chart/tool/test_get_chart_preview.py
    • tests/unit_tests/mcp_service/chart/tool/test_get_chart_sql.py
    • tests/unit_tests/mcp_service/dataset/tool/test_query_dataset.py
    • tests/unit_tests/mcp_service/semantic_layer/tool/test_get_table.py
    • tests/unit_tests/tasks/test_async_queries.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

Comment thread tests/unit_tests/mcp_service/chart/tool/test_get_chart_preview.py
Comment thread tests/unit_tests/mcp_service/chart/tool/test_get_chart_sql.py
Comment thread tests/unit_tests/mcp_service/chart/tool/test_get_chart_sql.py Outdated
@bito-code-review

bito-code-review Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #3d1718

Actionable Suggestions - 0
Review Details
  • Files reviewed - 2 · Commit Range: 2bb5c98..b5268cc
    • tests/unit_tests/mcp_service/chart/tool/test_get_chart_preview.py
    • tests/unit_tests/mcp_service/chart/tool/test_get_chart_sql.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@github-actions github-actions Bot added the requires:rebase Requires rebasing on top of current master label Oct 9, 2026
Co-authored-by: Cursor <cursoragent@cursor.com>
@codeant-ai-for-open-source

codeant-ai-for-open-source Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

CodeAnt PR Risk: Medium Risk

  • The PR needs attention before merging: the Jinja fallback keeps original form data nested, so macros relying on top-level adhoc_filters or extra_form_data may see different inputs.

Assessed commit: 89ae57057e8a

@github-actions github-actions Bot added requires:rebase Requires rebasing on top of current master and removed requires:rebase Requires rebasing on top of current master labels Oct 21, 2026
AmoghAtreya and others added 2 commits October 22, 2026 12:20
Co-authored-by: Cursor <cursoragent@cursor.com>
The master merge left a duplicate table seed call and a redefined import, which broke semantic-view compile and pre-commit ruff.

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions github-actions Bot removed the requires:rebase Requires rebasing on top of current master label Oct 22, 2026

This branch has not been deployed

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

Labels

api Related to the REST API change:backend Requires changing the backend global:jinja Related to Jinja templating size/XXL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(mcp): align Jinja context across query preview and compile paths

3 participants