DAX Lab
Author and run DAX, see where the time goes (Formula Engine versus Storage Engine), benchmark cold against warm, and prove a rewrite returns identical numbers before you keep it. DAX Lab is the measure workbench, and every button here is an MCP tool your Claude can drive.
#In the Studio

Write a query and run it against the connected model, results in a grid. Build a visual from field wells and hover any point to read its exact filter context, so you can see why a number is what it is.
Benchmark a query cold versus warm to expose the worst case, and profile it to see the Formula Engine versus Storage Engine split, the storage-engine scan count and CPU, and the heaviest scans. When a query is Formula-Engine-bound, capture its query plan to find the costly operators.
The optimise-and-prove loop is the headline. Give two or more candidate rewrites, and the engine verifies each returns identical values to the current measure across a group-by matrix you choose, benchmarks only the ones that matched, and surfaces the fastest that genuinely beats the original. Correctness always gates speed, so a faster-but-wrong candidate can never win. Auto-applying the winner is a Pro feature; on the free tier the same run returns the full evidence, paused, so you apply the winner yourself.
#Over MCP
The whole suite is dual-drive. Grouped by what they do:
- Query and read:
run_daxruns anEVALUATEquery,run_dmvruns a DMV,preview_tablepulls the first N rows, andpivot_measureevaluates a measure across a row-by-column matrix so you can sanity-check its values by category and date. - Author offline:
validate_daxchecks syntax and references before you write (no connection needed), andlint_daxruns about fifteen deterministic best-practice rules over an expression. - Measure and profile:
profile_daxreturns the FE/SE timings and heaviest scans,capture_query_planreturns the logical and physical plans,benchmark_daxgives first-run, warm-min and warm-median, andbenchmark_dax_coldwarmmeasures cold and warm with the SE split.clear_cacheevicts the VertiPaq cache so a cold measurement is meaningful, andevaluate_and_logruns a query withEVALUATEANDLOGand returns every logged intermediate. - Prove and optimise:
verify_dax_equivalenceproves a candidate rewrite matches the original across a filter-context matrix;probe_measureruns a measure across many contexts (grand total, single, multi, empty, boundary) to catch context-dependence bugs; andoptimize_measureruns the whole race (validate, verify, benchmark, apply the proven winner) and records the evidence.
# the optimise-and-prove loop
benchmark_dax "EVALUATE ROW(\"v\", [Total Sales])" # measure the baseline
verify_dax_equivalence exprA=<current> exprB=<rewrite> groupBy=[Date[Year], Product[Category]]
optimize_measure measure:Sales/Total Sales candidates=[<rewriteA>, <rewriteB>] verifyGroupBy=[...]
#What needs a live connection
Running, benchmarking, profiling, capturing plans, probing and proving equivalence all execute DAX,
so they need a live connection: a local Power BI Desktop instance or an XMLA endpoint. The
Formula/Storage split and the cold runs want a local Desktop or an admin XMLA endpoint, and degrade
gracefully to wall-clock only elsewhere. Authoring is different: validate_dax and
lint_dax are fully offline, so you can write and check measures with no connection at all.
A grand-total-only match is thin evidence, and Semanticus downgrades it to unverified rather than accept it. Pass representative group-by columns so "identical results" means identical everywhere it matters, not just at the total.
Semanticus