superbi-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@superbi-mcp open Sales.pbix and rename Total to Total Sales everywhere"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Super BI MCP
An MCP server that gives AI agents full local Power BI authoring - the semantic model, the report, and Power Query M - by editing .pbix and PBIP/PBIR files directly. 490 tools, backed by ~1,800 automated tests.
Point Claude (or any MCP client) at it and the agent can build a model, write the DAX, lay out the report pages and visuals, transform the Power Query, lint and auto-fix best-practice violations, prove the RLS actually filters, rename a column across the model and every report binding in one atomic call, screenshot the rendered result out of a running Power BI Desktop, evaluate DAX and read table rows out of a closed .pbix with no Fabric, edit a closed .pbit template's model with no Desktop at all, and hand you back a finished .pbix - all on your machine.
Why this instead of the other Power BI MCP servers
Super BI MCP | Microsoft Power BI Modeling MCP + agent skills | Community servers | |
Semantic model authoring (TOM) | Yes, with write transactions + rollback | Yes | Partial |
Report authoring (pages, visuals, filters, bookmarks) | Yes - legacy Layout and PBIR, deterministic tools | Skill-guided raw JSON editing by the LLM (separate skill pack) | Report-only or preview |
Direct | Yes | No - PBIP files only | Rare |
Power Query M authoring | Yes - 60+ transform/generator tools | Analyze/refactor only | Rare |
Propagating renames (model rename rewrites DAX, M, and every report binding, atomically) | Yes | No | One server, PBIP-only |
Model-to-report cross-analysis (usage, unused fields incl. conditional-formatting bindings, broken-reference repair) | Yes | No | Partial |
RLS execution testing (run any query as any role, per-role matrix) | Yes | No | Partial |
DAX benchmark + Analysis Services trace (FE/SE split, cache hits) | Yes | Benchmark yes | Partial |
Offline DAX linter (incl. catching hallucinated function names before they hit the engine) | Yes | No | One server |
Visual formatting | Deterministic property registry for 52 visual types, validated against the theme schema | n/a | Raw JSON edits |
Best Practice Analyzer | 89 rules, 28 with automatic fixes, Tabular Editor ruleset import | Loose | Rare |
Desktop feedback loop (page screenshots + hot-reload from a running Desktop) | Yes - via the Desktop Bridge | Yes - same bridge, separate CLI | No |
Layout, star-schema, theme-compliance, naming and file-integrity audits | Yes | No | Partial |
DAX generators (time-intelligence, ranking, segmentation, calc groups, dynamic RLS, custom calendars) | Yes, live or straight to TMDL offline | n/a | Partial |
Works offline, no Fabric account | Yes | Yes (local mode) | Varies |
Ships as | One integrated server | A server + a skills pack + two CLIs | Single-purpose servers |
The short version: Microsoft's official server stops at the semantic model, and its report story is a separate skill pack that has the LLM hand-write layout JSON. This is one server that authors the whole artifact - model, report, and Power Query - with deterministic, validated tools, treats model and report as one cross-referenced thing (renames propagate, broken bindings are found and fixed, unused fields are provable), and works on the .pbix files you actually have, not just PBIP folders.
Related MCP server: Fabric MCP Server - PowerBI Report Creator
Requirements
Windows x64 (the engine drives the Analysis Services client libraries and, for live-model work, Power BI Desktop)
Power BI Desktop - needed for live model editing, bulk refresh, bake, and the engine-backed offline
.pbixtools; report-layer and file-level tools work without itNode.js 16+ to install via
npx(below), or the .NET 8 SDK to build from source
Install
One command (recommended) - no .NET SDK needed. Add this to your MCP client's config (Claude Code / Claude Desktop .mcp.json, Cursor, etc.):
{
"mcpServers": {
"super-bi": {
"command": "npx",
"args": ["-y", "powerbi-pbix-mcp"]
}
}
}The first launch downloads the self-contained engine SuperBiMcp.exe (~109 MB) from the latest release, verifies its SHA-256, and caches it under ~/.powerbi-pbix-mcp/; later launches reuse the cache. Set SUPERBI_MCP_EXE to an existing SuperBiMcp.exe to skip the download.
Prefer a plain binary? Download SuperBiMcp-win-x64.zip from the release, extract, and point your client's command straight at SuperBiMcp.exe.
Build from source (needs the .NET 8 SDK):
git clone https://github.com/cyphonica/powerbi-pbix-mcp
cd powerbi-pbix-mcp
dotnet build src/SuperBiMcp.csproj -c Releasethen register the built DLL with "command": "dotnet", "args": ["<absolute path>/src/bin/Release/net8.0/SuperBiMcp.dll"].
Then ask your agent to open a .pbix and get to work. docs/automation-capabilities/GENERATED-TOOL-INDEX.md lists every tool; regenerate it any time with SuperBiMcp capability-map.
CLI modes
The same binary is also a headless factory:
Command | What it does |
| Headless report build from a declarative manifest (single file or batch/glob) |
| Bulk-refresh |
| In-memory model build to a complete PBIP (TMDL) - no Desktop needed |
| Deploy + refresh a scaffolded model and produce the populated binary DataModel |
| Turn a solution spec + sample data into a starter |
| CI integrity gate over two model snapshots |
| Docs drift gate - fails when the committed tool index no longer matches the code |
| Inspect the durable job queue used to serialise heavy Desktop work |
| Dump the 300 built-in starting-point templates |
Testing
dotnet test tests/SuperBiMcp.Tests/SuperBiMcp.Tests.csproj -c ReleaseA handful of live-connector smoke tests skip unless you provide credentials via DAXTEST_* environment variables. Set SUPERBI_TEST_SCRATCH to move test scratch space off your system drive.
Environment variables
Variable | Purpose |
|
|
| Scratch root for the test suite (defaults to the system temp dir) |
| Command template that turns a refreshed PBIP into a populated |
| Analysis Services instance for |
| Power BI Service / XMLA connectivity for the service-side tools |
License
Source-available under the Functional Source License, FSL-1.1-ALv2 (see LICENSE.md).
Use it freely for anything internal, personal, educational, or for client/consulting work. You may not offer it, or a product substantially built on it, as a competing commercial product or hosted service. Each release automatically becomes Apache 2.0 two years after publication.
This is a curated public mirror of a private development tree; history starts at the first public release and updates land as versioned drops.
Acknowledgements
See NOTICE.md for bundled third-party assets and rule-set attributions.
Available Tools
490 toolsadd_abc_classificationA
Generate ABC (Pareto) classification: a dynamic class measure plus a calculated class table. aThreshold / bThreshold are cumulative-share cut-offs (e.g. 0.7 and 0.9); the rest fall into C.
Inputs: key (required), sessionId (required), entityTable (required), valueMeasure (required), +3 more.
add_action_buttonA
Add a button bound to a BOOKMARK (the view-switch pattern): clicking it applies the bookmark (e.g. swap which visuals show). Writes the exact visualLink {type='Bookmark', bookmark=} shape the live product uses, plus the button label. bookmarkName = a bookmark from list_bookmarks/add_bookmark. Returns the new visual id.
Inputs: page (required), text (required), bookmarkName (required), reportSessionId (required), +4 more.
add_advanced_filterA
Add an ADVANCED multi-condition filter (the And/Or advanced filter card) at a scope=visual|page|report: up to two conditions on the same field joined by And or Or. conditions = JSON array of {op,value} where op=gt|gte|lt|lte|eq|ne|isblank|isnotblank|contains|startswith. combine=and|or. fieldKind=column|measure, valueType=int|decimal|string. For scope=visual pass page+visual; scope=page pass page.
Inputs: field (required), scope (required), table (required), conditions (required), +6 more.
add_analytics_lineA
Add an ANALYTICS reference line to a chart. kind = constant | min | max | average | median | trend | forecast. constant needs value; min/max/average/median compute from measureTable+measure; trend/forecast need no value. Optional label (data-label text on the line) and color (hex). Structure matched to the legacy analytics shape - verify the render in Desktop.
Inputs: kind (required), page (required), visual (required), reportSessionId (required), +5 more.
add_anomaly_detectionA
Add ANOMALY DETECTION to a line chart (the anomalyDetection object). sensitivity 0-100 optional (higher = more anomalies). explainBy = comma-separated fields the explanation groups by. Verify the render in Desktop.
Inputs: page (required), visual (required), reportSessionId (required), explainBy, +1 more.
add_auto_aggregationsA
Build an auto-aggregation scaffold: a hidden {Table}_Agg GROUPBY table over the group-by columns, hidden _Agg measures for each mapping, and IF-routing rewrites of the base measures so they answer from the small agg table when possible. groupByColumns is comma-separated Table[Column]. measureMappings is comma-separated aggMeasureName=baseMeasure. Extends set_aggregation. FLAG: the IF-routing is a best-known scaffold - review before production.
Inputs: sessionId (required), detailTable (required), groupByColumns (required), measureMappings (required).
add_between_filterA
Add a BETWEEN filter (lo <= field <= hi) at a scope=visual|page|report: two Comparisons (GTE + LTE) joined by And. valueType picks the literal encoding (int|long|decimal|double|datetime|...). fieldKind=column|measure. For scope=visual pass page+visual; scope=page pass page.
Inputs: hi (required), lo (required), field (required), scope (required), +6 more.
add_bookmarkA
Add a report-level bookmark that captures a page's visualContainers with the listed visuals HIDDEN and the rest shown (the view-state pattern). Names it 'Bookmark'+16 hex. hiddenVisuals = comma-separated visual ids (from list_visuals). Returns the new bookmark name. Wire it to a button with add_action_button.
Inputs: page (required), displayName (required), reportSessionId (required), captureData, +1 more.
add_buttonA
Add a BUTTON with any action: actionType = bookmark | back | pageNavigation | drillthrough | qna | webUrl | clearAllSlicers | applyAllSlicers. bookmark needs bookmarkName; pageNavigation/drillthrough need a destination page (in destinationOrUrl); webUrl needs a url (in destinationOrUrl); back/qna/clearAllSlicers/applyAllSlicers need neither (clearAllSlicers/applyAllSlicers act on the page's slicers, e.g. a native Clear-all-slicers button). Writes the actionButton visualLink the product uses. Returns the new visual id.
Inputs: page (required), text (required), reportSessionId (required), x, +6 more.
add_calc_group_formatA
Build a calc group whose items OVERRIDE the displayed format (a currency / % / scale switcher): each item keeps the value (SELECTEDMEASURE()) but reformats it via its own format string. items = JSON array of {name,formatString}. Creates the calc group on table if absent.
Inputs: items (required), table (required), sessionId (required), precedence.
add_calculated_columnC
Add a DAX calculated column to a table.
Inputs: dax (required), name (required), table (required), sessionId (required).
add_calculated_tableB
Create a new calculated table from a DAX table expression (e.g. a Calendar via CALENDAR()).
Inputs: dax (required), name (required), sessionId (required).
add_calculation_groupA
Turn a (single-column) table into a calculation group - the engine for reusable selectors like Time Intelligence (Current/YTD/PY/YoY) applied to ANY measure. After this, add items with add_calculation_item. Lower precedence is applied first when groups are nested. target=pbip: pass pbipFolder instead of sessionId to apply the edit OFFLINE to a PBIP semantic model's TMDL (no engine; a missing table is created whole and DiscourageImplicitMeasures is switched on).
Inputs: table, sessionId, pbipFolder, precedence.
add_calculation_itemA
Add a calculation item to a calculation group. The DAX usually wraps SELECTEDMEASURE(), e.g. "CALCULATE(SELECTEDMEASURE(), DATESYTD('Calendar'[Date]))" for a YTD item. ordinal sets display order; formatStringExpression sets a dynamic format for that item.
Inputs: name (required), table (required), sessionId (required), daxExpression (required), +2 more.
add_calendar_based_time_intelligenceA
Add native (non-Gregorian) calendar-based time intelligence: a calendar object on the calendar table's primary date column with a calendarColumnGroup over the associated period columns. associatedColumns is comma-separated. FLAG: the calendar / calendarColumnGroup objects are very new and absent from this build, so this is stamped as a PBI_Calendar table annotation - confirm in Desktop.
Inputs: sessionId (required), calendarTable (required), primaryColumn (required), associatedColumns (required).
add_cardC
Add a KPI card showing one measure.
Inputs: table (required), measure (required), pageName (required), reportSessionId (required), +5 more.
add_chartB
Add a chart. chartType = clusteredColumnChart | clusteredBarChart | lineChart | pieChart | donutChart | areaChart. Category is the axis, value is the measure.
Inputs: pageName (required), chartType (required), valueTable (required), valueMeasure (required), +10 more.
add_conditional_columnA
Power Query Add Conditional Column: add a column from an ordered if/then/else rule chain (the structured Conditional Column builder). Appends Table.AddColumn with a nested if-chain to the table's M query. rules is comma-separated as column:op:value:result, e.g. "Score:ge:90:A,Score:ge:80:B". op = eq | ne | gt | ge | lt | le | contains | startswith | endswith. valueType types the compared values; resultType types the results (text | number | logical | null).
Inputs: name (required), rules (required), table (required), sessionId (required), +4 more.
add_coverage_flagA
Close the loop on blank-on-select (the partner to audit_robustness). Adds a boolean calculated column to a dimension flagging whether each member has rows in a fact table. Filter slicers or add a report-level filter on it = users can no longer select a dead value (e.g. a brand with no sales). Returns how many members have data vs are dead. Idempotent + auto-recalcs.
Inputs: table (required), factTable (required), sessionId (required), columnName.
add_cultureA
Add a culture (locale, e.g. fr-FR or mi-NZ) so the model can carry translated captions, descriptions and display folders for that language. Add the actual translations with set_translation.
Inputs: locale (required), sessionId (required).
add_currency_conversion_calc_groupA
Create a currency-conversion calculation group: an Original Value item and a Converted item that applies the daily exchange rate (SUMX over Date * rate).
Inputs: table (required), rateTable (required), sessionId (required), rateColumn (required), +2 more.
add_custom_calendar_time_intelligenceA
Generate integer-index time intelligence for a custom (445/454/544/weekly/13-period) calendar - the case where built-in TI breaks. Builds *TD/PY/PYTD/prev-week/MAT(364) measures off DayIndex/MonthIndex/Year/PeriodIndex columns on the calendar table. kind = 445 | 454 | 544 | weekly | 13period.
Inputs: kind (required), table (required), sessionId (required), baseMeasure (required), +1 more.
add_custom_columnA
Power Query Add Custom Column: add a column from an M expression. Appends Table.AddColumn(prev, name, each ) to the table's M query. The expression references other columns as [Col], e.g. "[Qty] * [Price]".
Inputs: name (required), table (required), sessionId (required), mExpression (required), +1 more.
add_data_columnA
Add a data column's metadata to an import (M) table so relationships and bindings resolve. Needed after add_table_from_m because TOM does not auto-infer columns. Refresh afterwards to populate values.
Inputs: name (required), table (required), dataType (required), sessionId (required), +1 more.
add_deneb_visualA
Add a DENEB (Vega / Vega-Lite) custom visual to a page: registers the Deneb guid, adds the visual, binds dataRoles into Deneb's 'values' data role, and writes objects.vega[0].properties (jsonSpec one-lined + single-quoted in a literal, jsonConfig, provider=vega|vegaLite, renderMode=svg|canvas, enable* booleans). spec/config = JSON strings. dataRoles = JSON array of {table,field,kind}. FLAG: visualGuid defaults to the published Deneb guid - confirm in Desktop.
Inputs: name (required), page (required), spec (required), reportSessionId (required), +12 more.
add_does_not_contain_filterA
Add a DOES-NOT-CONTAIN filter (Not(Contains)) on a text column at a scope=visual|page|report. For scope=visual pass page+visual; scope=page pass page.
Inputs: field (required), scope (required), table (required), value (required), +3 more.
add_drillthroughB
Make a page a DRILL-THROUGH target on a column: right-clicking a data point of that column on any other page offers 'Drill through' to this page, filtered to that value. Adds the drill-through page filter + the Back button. Ground-truthed from a real report.
Inputs: pageName (required), drillTable (required), drillColumn (required), reportSessionId (required).
add_dynamic_rlsA
Generate dynamic row-level security: create the role (if absent) and set a USERPRINCIPALNAME()-driven filter on the SECURED table. shape = direct | bridge | hierarchy | lookup. Never targets the user/mapping table (refused - it would break the lookup).
Inputs: role (required), shape (required), sessionId (required), userTable (required), +6 more.
add_dynamic_segmentationA
Generate a dynamic-segmentation measure that classifies an entity by a measure value against a disconnected band table (left-closed, right-open bounds). Returns the count of entities in the selected segment.
Inputs: measure (required), sessionId (required), entityTable (required), lowerColumn (required), +4 more.
add_dynamic_title_measureA
Author a DYNAMIC TITLE text measure: SELECTEDVALUE over a column with an All/multiple fallback, optionally wrapped in a template ({value} is the placeholder). e.g. column Dim_Product[Category], template "Sales - {value}". Then bind it to a visual title with bind_dynamic_title (report side).
Inputs: column (required), homeTable (required), sessionId (required), measureName (required), +2 more.
add_dynamic_topnA
Generate a dynamic Top N: a what-if N slider, a UNION+Others dimension table, and a rank-or-others measure that buckets everything below rank N into an Others row.
Inputs: measure (required), dimension (required), homeTable (required), sessionId (required), +6 more.
add_error_barsA
Add ERROR BARS to a chart (the errorBars object). kind=byField: upperField (+ lowerField unless symmetrical) measures bound from measureTable. kind=byPercentage: percent of the value. relation = Absolute|Relative. symmetrical optional. band = Fill|Line|Both. Verify the render in Desktop.
Inputs: kind (required), page (required), visual (required), reportSessionId (required), +7 more.
add_field_parameterA
Create a FIELD PARAMETER - a small calculated table that lets a user swap which field a visual shows. Pass the fields as Table[Column] references; the first generated column drops onto a slicer to switch between them. Builds the {("Display", NAMEOF('T'[Col]), order), ...} table with the parameter metadata the report layer recognises.
Inputs: name (required), fields (required), sessionId (required).
add_fixed_anchor_relative_date_filterA
Add a FIXED-ANCHOR relative-date window (UI-impossible): Last/Next N units measured from a LITERAL anchor date instead of Now. Encoded as a GTE + LT pair of datetime Comparisons. mode=Last|Next, unit=Days|Weeks|Months|Years. anchorDate=ISO date (e.g. 2024-06-30). For scope=visual pass page+visual; scope=page pass page.
Inputs: mode (required), unit (required), count (required), field (required), +6 more.
add_hierarchyA
Create a drill-down hierarchy on a table from an ordered, comma-separated list of existing columns (e.g. "Year,Quarter,Month" or "Segment,Subsegment,ItemDesc"). target=pbip: pass pbipFolder instead of sessionId to apply the same edit OFFLINE to a PBIP semantic model's TMDL (no engine).
Inputs: name, table, levels, sessionId, +1 more.
add_hierarchy_levelA
Add a level to an existing hierarchy from a column on the same table. ordinal positions it (0 = top; omitted = appended at the bottom); remaining levels are renumbered densely.
Inputs: table (required), column (required), hierarchy (required), sessionId (required), +2 more.
add_html_content_blockA
Add the HTML Content (lite) custom visual bound to a DAX measure that returns HTML/CSS: registers the visual type, adds the visual, and binds the measure to its content (values) role. daxHtmlMeasure = "Table[Measure]" (the measure must already exist and return an HTML string). visualGuid overrides the visual type id (confirm the certified guid in Desktop).
Inputs: h (required), w (required), x (required), y (required), +5 more.
add_ibcs_variance_measureA
Author IBCS variance measure(s) for an actual measure vs a comparison base (PY|PL|FC). kind=abs (AC - base, leading-sign format) or rel (DIVIDE(AC - base, ABS(base)) %). The base is expected as a measure ' ' unless comparisonMeasure is given. applyIbcsFormat applies an IBCS number format (+/- leading sign).
Inputs: table (required), sessionId (required), actualMeasure (required), kind, +3 more.
add_imageA
Place an image (e.g. a brand LOGO) on a page - embeds the file into the .pbix as a resource and adds an image visual. Completes the brand kit (logo IN the report, not just the palette). scaling = Fit | Fill | Normal.
Inputs: pageName (required), imagePath (required), reportSessionId (required), x, +4 more.
add_include_exclude_filterA
Add an INCLUDE or EXCLUDE filter (the right-click include/exclude these values) at a scope=visual|page|report. values = comma-separated or JSON array. exclude=true excludes them (Not In), false includes them (In). valueType=int|decimal|string. For scope=visual pass page+visual; scope=page pass page.
Inputs: field (required), scope (required), table (required), values (required), +5 more.
add_index_columnB
Power Query Add Index Column: add a sequential index. Appends Table.AddIndexColumn to the table's M query.
Inputs: table (required), sessionId (required), name, step, +2 more.
add_kpi_cardA
Add a PREMIUM KPI card: a white rounded panel (shadow) with an uppercase label, a big value, an optional coloured delta ('vs LY') and an optional sparkline - composed from proven primitives so it always renders. Far richer than add_card. Pass deltaMeasure for the comparison, and trendMeasure + dateTable/dateColumn for the sparkline.
Inputs: label (required), table (required), pageName (required), valueMeasure (required), +12 more.
add_matrixC
Add a matrix. rows/columns/values = JSON arrays of {table,field,kind}. Rows/columns are typically columns; values are measures.
Inputs: rows (required), values (required), pageName (required), reportSessionId (required), +6 more.
add_measureA
Add a DAX measure to a table. Commits to the live model (persist with File > Save in Desktop). target=pbip: pass pbipFolder instead of sessionId to write the measure OFFLINE into a PBIP semantic model's TMDL (no engine; collision-checked, /// doc comments preserved).
Inputs: dax, name, table, sessionId, +4 more.
add_moving_averageA
Generate a rolling moving-average measure over the last N periods. unit = day | month (default day).
Inputs: table (required), periods (required), dateTable (required), sessionId (required), +3 more.
add_m_parameterA
Create (or update) a Power Query parameter (the Manage Parameters entry) as a shared expression carrying the IsParameterQuery metadata. type = Text | Number | Logical | DateTime. Pass allowedValues (comma-separated) to restrict the parameter to a fixed list.
Inputs: name (required), sessionId (required), type, defaultValue, +1 more.
add_narrative_measureA
Auto-narrative: create a dynamic DAX text measure like 'Grated, Sliced drove +2.1% growth'. Names the top-N dimension members by contribution to the change (current - prior) and states the overall growth. Display it in a card (it updates live with slicers). Insight text without the native smart-narrative visual.
Inputs: dimTable (required), dimColumn (required), homeTable (required), sessionId (required), +5 more.
add_pageB
Add a report page. Returns its internal pageName (use that for adding visuals).
Inputs: displayName (required), reportSessionId (required), width, height.
add_page_filterA
Add a PAGE-level filter (filters every visual on that page). kind=categorical writes an 'is one of' values filter (pass values, comma-separated or a JSON array); any other kind writes a comparison/blank filter (op = gt|gte|lt|lte|eq|ne|isblank|isnotblank) on a column or measure (fieldKind=column|measure). valueType=int|decimal|string for the values.
Inputs: page (required), field (required), table (required), reportSessionId (required), +5 more.
add_partitionA
Add an M partition to an existing table (e.g. to split a fact by year). mode = Import | DirectQuery | Dual | DirectLake (optional; engine default when omitted). The new partition has never refreshed - refresh before saving the .pbix.
Inputs: m (required), name (required), table (required), sessionId (required), +1 more.
add_pbir_bookmarkA
Add a bookmark to a PBIR report: a definition/bookmarks/.bookmark.json (explorationState with each visual's display.mode) plus a bookmarks.json index entry. hiddenVisuals = JSON array of the visual GUID names to hide; every other visual on the page is shown.
Inputs: page (required), displayName (required), pbirSessionId (required), hiddenVisuals.
add_pbir_filterA
Add a filter to a PBIR report at scope = report | page | visual, written into the PBIR filterConfig.filters array via the shared filter builders. kind=categorical|in|values -> an is-one-of values list (pass values); else a comparison/blank filter (op=gt|gte|lt|lte|eq|ne|isblank|isnotblank). fieldKind=column|measure. valueType=string|int|double|decimal|bool|datetime|color drives the literal type suffix.
Inputs: field (required), scope (required), table (required), pbirSessionId (required), +7 more.
add_pbir_visualA
Add a visual to a PBIR page: a fresh GUID folder definition/pages//visuals//visual.json. The query (projections + prototypeQuery) is built by the shared query builder. fields = JSON array of {role,table,field,kind} (kind=column|measure; role=Category|Y|Values|Rows|Columns|...). Returns the new visual GUID name.
Inputs: page (required), visualType (required), pbirSessionId (required), x, +5 more.
add_percent_of_parentA
Generate a percent-of-parent measure over a hierarchy. hierarchyColumns is a comma-separated list of Table[Column] from top level to leaf, e.g. Product[Category], Product[Subcategory], Product[Product].
Inputs: table (required), sessionId (required), baseMeasure (required), hierarchyColumns (required).
add_percent_of_totalB
Generate a percent-of-total measure for a base measure over a dimension. scope = ALL | ALLSELECTED | ALLEXCEPT (default ALLSELECTED).
Inputs: table (required), dimension (required), sessionId (required), baseMeasure (required), +1 more.
add_perspectiveA
Create a perspective - a named, focused view that shows only a chosen subset of tables/columns/measures (e.g. a 'Finance' or 'Sales' lens over a large model). Add members with add_to_perspective.
Inputs: name (required), sessionId (required).
add_query_groupA
Create a query group - a display folder for queries (shared expressions / partitions) in the Power Query Queries pane, e.g. 'Staging' or 'Parameters'. Assign objects to it with set_object_query_group.
Inputs: folder (required), sessionId (required).
add_rank_measureA
Generate a RANKX measure with ISINSCOPE + ALLSELECTED + blank guard. order = ASC | DESC (default DESC); ties = SKIP | DENSE (default SKIP). withinGroup (Table[Column]) ranks inside each group.
Inputs: table (required), dimension (required), sessionId (required), baseMeasure (required), +3 more.
add_relationshipA
Create a relationship between two columns. Defaults to a star-schema Many->One (from = many/fact side, to = one/dimension side), but the cardinality is overridable to support 1:1, M:1, 1:M and M:M. fromCardinality/toCardinality = One | Many. crossFilteringBehavior = OneDirection | BothDirections | Automatic (overrides the bothDirections flag). securityFilteringBehavior = OneDirection | BothDirections | None. joinOnDateBehavior = DateAndTime | DatePartOnly.
Inputs: toTable (required), toColumn (required), fromTable (required), sessionId (required), +8 more.
add_relative_date_filterA
Add a RELATIVE DATE filter at a scope=visual|page|report on a date column: mode=Last|Next|This, count units of unit=Days|Weeks|Months|Years. includeCurrent includes the current period; calendar=true aligns to calendar boundaries (vs a rolling window). For scope=visual pass page+visual; scope=page pass page.
Inputs: mode (required), unit (required), count (required), field (required), +7 more.
add_relative_time_filterA
Add a RELATIVE TIME filter at a scope=visual|page|report on a datetime column: mode=Last|Next|This, count units of unit=Hours|Minutes|Seconds. includeCurrent includes the current period. For scope=visual pass page+visual; scope=page pass page.
Inputs: mode (required), unit (required), count (required), field (required), +6 more.
add_report_filterA
Add a REPORT-level filter (filters every page in the report). kind=categorical writes an 'is one of' values filter (pass values, comma-separated or a JSON array); any other kind writes a comparison/blank filter (op = gt|gte|lt|lte|eq|ne|isblank|isnotblank) on a column or measure (fieldKind=column|measure). valueType=int|decimal|string.
Inputs: field (required), table (required), reportSessionId (required), op, +4 more.
add_report_measureA
Add a REPORT-LEVEL measure (a DAX measure stored in the report, not the model - handy when you cannot edit the model). table = the host table it attaches to. Written into layout.config.modelExtensions (legacy best-known shape; confirm in Desktop). Re-adding the same name updates it.
Inputs: name (required), table (required), daxExpression (required), reportSessionId (required), +2 more.
add_roleA
Create a security role. modelPermission controls what the role can do model-wide: Read (query only), ReadRefresh (query + refresh), Refresh (refresh only), Administrator (full control), or None. Then attach row-level filters with set_rls and members with add_role_member.
Inputs: name (required), sessionId (required), modelPermission.
add_role_memberA
Add a member to a role. By default a Windows member (e.g. DOMAIN\\user or user@org.com); pass provider (e.g. AzureAD) to add an external/cloud identity member instead.
Inputs: role (required), sessionId (required), memberName (required), provider.
add_running_totalA
Generate a running-total measure. Provide dateTable+dateColumn for a date cumulative, OR sortColumn (Table[Column]) for a generic / Pareto running total.
Inputs: table (required), sessionId (required), baseMeasure (required), dateTable, +2 more.
add_semiadditive_measuresA
Generate semi-additive balance measures (opening/closing balance, last/first non-blank) over a value column and date column - the standard inventory / account-balance pattern.
Inputs: table (required), sessionId (required), dateColumn (required), valueColumn (required).
add_shapeA
Add a decorative rounded rectangle panel. Place it BEHIND a group of visuals (lower z) to visually group them and add depth - the panel technique for sectioning a report.
Inputs: x (required), y (required), width (required), height (required), +6 more.
add_slicerA
Add a slicer for one column or measure. Defaults to a compact Dropdown (what users almost always want); pass mode=List for the classic vertical list, Between/Single for numeric/date ranges.
Inputs: field (required), table (required), pageName (required), reportSessionId (required), +7 more.
add_source_stepA
Seed or replace a table's data-source step with a generated connector expression (downstream steps preserved). connector = sql | oracle | mysql | postgresql | db2 | web | odata | excel | csv | json | xml | pdf | html | analysisservices | odbc | oledb | folder | sharepoint | azureblob | azuretable | datalake | deltalake | cdm. params is comma-separated key=value pairs; required keys per connector: sql/oracle/mysql/postgresql/db2 -> server, database (optional query); analysisservices -> server, database (optional query = MDX/DAX); web -> url (optional relativePath, query as a raw M record e.g. [#"$top"="10"], headers as a raw M record, content for a POST binary, apiKeyName, manualStatusHandling e.g. 404,500); odata -> url (optional filter/select/top/orderby folded into $filter/$select/$top/$orderby); excel/pdf -> path; csv -> path (optional delimiter, columns); json/xml/html -> path OR url; odbc -> connectionString or dsn (optional query); oledb -> connectionString (optional query); folder -> path; sharepoint -> url; azureblob/azuretable -> account; datalake/deltalake/cdm -> url. Static base URL + relativePath/query is the refresh-safe web pattern.
Inputs: table (required), params (required), connector (required), sessionId (required), +1 more.
add_sparklineA
Add a NATIVE SPARKLINE column to a table/matrix: a per-row mini line driven by a value measure across a category (e.g. trend over month). Writes objects.sparkline with the line measure + category bindings. valueTable/valueMeasure = the line measure; categoryTable/categoryField = the axis.
Inputs: page (required), visual (required), valueTable (required), valueMeasure (required), +4 more.
add_svg_chipA
Author an SVG CHIP/PILL measure (DataCategory=ImageUrl): an auto-sizing rounded label whose width fits the text. textMeasure supplies the label; colorMeasure (optional, returns a hex) supplies the fill, else defaultFill.
Inputs: name (required), table (required), sessionId (required), textMeasure (required), +3 more.
add_svg_databarA
Author an SVG DATA BAR measure (DataCategory=ImageUrl) that renders an in-cell bar scaled to value/max. Drop it into a table/matrix/card. valueMeasure/maxMeasure are measure names; pass maxMeasure for a comparable scale. negativeFill colours bars below zero; align=left|right.
Inputs: name (required), table (required), sessionId (required), valueMeasure (required), +6 more.
add_svg_gaugeA
Author an SVG ARC GAUGE measure (DataCategory=ImageUrl): a semicircular gauge mapping the value onto min..max, rendered in-cell. thresholds (optional JSON array of {at,color}, ascending) tint the value arc by the highest band the value clears.
Inputs: max (required), min (required), name (required), table (required), +5 more.
add_svg_iconA
Author an SVG THRESHOLD ICON measure (DataCategory=ImageUrl): renders a unicode glyph in a colour chosen by which [min,max) band the value falls into. rules = JSON array of {min,max,glyph,color}, e.g. [{"min":-1e9,"max":0,"glyph":"▼","color":"#D7263D"},{"min":0,"max":1e9,"glyph":"▲","color":"#2E7D32"}].
Inputs: name (required), rules (required), table (required), sessionId (required), +2 more.
add_svg_progress_barA
Author an SVG PROGRESS BAR / BULLET measure (DataCategory=ImageUrl): a track + a fill scaled to value/target, rendered in-cell. kind=bar|bullet (bullet adds a target tick). trackColor is the rail; fillColor the achieved portion.
Inputs: name (required), table (required), sessionId (required), valueMeasure (required), +6 more.
add_svg_sparklineA
Author an SVG SPARKLINE measure (DataCategory=ImageUrl): a min-max scaled line/area over a category column, rendered in-cell. kind=line|area|gradient-area. showLastPoint adds a terminal marker; intercept draws a zero baseline. categoryColumn = Table[Column].
Inputs: name (required), table (required), sessionId (required), valueMeasure (required), +7 more.
add_table_from_mA
Create a new import table from a Power Query (M) expression. Run refresh_table afterwards to populate columns.
Inputs: m (required), name (required), sessionId (required).
add_table_view_foldingA
ADVANCED: scaffold a Table.View that implements custom query folding over a non-foldable source. Emits Table.View(null, [handlers]). handlers is comma-separated from GetType, GetRows, OnTake, OnSkip, OnSelectColumns, OnSelectRows, GetRowCount. GetType+GetRows are the mandatory baseline (added automatically); OnTake is the cheapest win (bounded preview). FLAG: the handler bodies are TEMPLATES that defer to the table and must be specialised to actually fold into the native source.
Inputs: table (required), handlers (required), sessionId (required), partitionName.
add_table_visualB
Add a table visual. fields = JSON array of {table,field,kind} (kind=column|measure), shown left-to-right.
Inputs: fields (required), pageName (required), reportSessionId (required), x, +4 more.
add_template_measureA
Add a measure to a table in a closed .pbit template's model, editing the DataModelSchema JSON on disk with no Power BI Desktop. Collision-checked: fails if a measure of that name already exists on the table. The .pbit is written back in place (the original is copied to a .bak beside it first).
Inputs: name (required), table (required), pbitPath (required), expression (required), +2 more.
add_template_relationshipA
Add a relationship to a closed .pbit template's model, editing the DataModelSchema JSON on disk with no Power BI Desktop. Both endpoints must exist (the tables and columns are validated). A fresh GUID name is generated. Collision-checked: fails if an identical from/to relationship already exists. Written back in place (with a .bak guard).
Inputs: toTable (required), pbitPath (required), toColumn (required), fromTable (required), +3 more.
add_textboxB
Add a formatted text box - use for page headers, section titles and captions.
Inputs: text (required), pageName (required), reportSessionId (required), x, +7 more.
add_theme_visual_style_presetA
Add a NAMED visual-style PRESET to the theme so a visual can opt into a look (theme.visualStyles[visualType][presetName]). cardProperties = JSON object of cardName -> property map or array, e.g. {"title":{"fontSize":14,"bold":true},"background":{"show":true,"color":{"solid":{"color":"#FFFFFF"}}}}. Run generate_theme first.
Inputs: presetName (required), visualType (required), cardProperties (required), reportSessionId (required).
add_time_intelligenceB
Generate the standard time-intelligence measure set for a base measure: YTD, QTD, MTD, PY (prior year), and YoY %. Needs a date table column (e.g. Calendar[Date]).
Inputs: sessionId (required), dateColumn (required), baseMeasure (required), homeTable.
add_time_intelligence_calc_groupA
Create a time-intelligence calculation group on a table: Current/MTD/QTD/YTD/PY/PYTD/YoY/YoY% items with ordinals, a format-string on YoY%, and DiscourageImplicitMeasures set at model level.
Inputs: table (required), dateTable (required), sessionId (required), dateColumn (required), +1 more.
add_time_intelligence_measuresA
Generate the full time-intelligence measure set off a base measure: YTD/QTD/MTD, PY/PM, MoM/YoY (+%), PYTD/YOYTD (+%). fiscalYearEnd (MM-DD, e.g. 06-30) drives fiscal *TD. target=pbip: pass pbipFolder instead of sessionId to write the SAME measures OFFLINE into a PBIP semantic model's TMDL (no engine; collision-checked appends).
Inputs: table, dateTable, sessionId, dateColumn, +3 more.
add_tooltip_fieldsA
Add EXTRA FIELDS to a visual's DEFAULT (data) tooltip (the Tooltips field-well), so they show on hover. fields = JSON array of {table,field,kind} (kind=measure|column). Adds the projections + query Select entries. Distinct from set_visual_tooltip_page (which swaps the whole tooltip for a report page).
Inputs: page (required), fields (required), visual (required), reportSessionId (required).
add_to_perspectiveA
Add a table - or a specific column / measure / hierarchy on it - to a perspective. Omit childObject to include the whole table. Run add_perspective first.
Inputs: table (required), sessionId (required), perspective (required), childObject.
add_topn_filterA
Add a TOP-N (or bottom-N) filter at a scope=visual|page|report: keep the top/bottom n of table[field] ranked by byTable[byMeasure]. direction=top|bottom. For scope=visual pass page+visual; scope=page pass page.
Inputs: n (required), field (required), scope (required), table (required), +6 more.
add_variationA
Add a date-navigation Variation to a column: when the column is used in a visual, the model navigates through the named relationship to a default hierarchy on the related (date) table. isDefault makes it the column's default variation.
Inputs: table (required), column (required), sessionId (required), relationship (required), +2 more.
add_view_switcherA
THE premium pattern from pro reports: one page, a button bar that swaps between VIEWS - each view shows its own visuals and hides the rest. Builds the Display-only bookmarks + the buttons + sets the initial state to the first view. views = JSON array of {name, visuals:[visualName,...]} (visual names from list_visuals/add_* results). Ground-truthed from a real report.
Inputs: views (required), pageName (required), reportSessionId (required), x, +7 more.
add_visualA
Add any visual type with explicit role bindings. bindings = JSON array of {role,table,field,kind}. Roles depend on visualType (e.g. Category/Y for charts, Rows/Columns/Values for pivotTable, Values for card/slicer/tableEx).
Inputs: bindings (required), pageName (required), visualType (required), reportSessionId (required), +5 more.
add_visual_calculationA
Author a VISUAL CALCULATION on a visual: an in-visual DAX expression over the visual's own result matrix (e.g. RUNNINGSUM([Sales]), MOVINGAVERAGE([Sales],3), PERCENTOFTOTAL([Sales])) - distinct from a model measure. Written to singleVisual.visualCalculations[] and projected as a Values column so it renders. Re-adding the same name updates it.
Inputs: name (required), page (required), visual (required), daxExpression (required), +1 more.
add_visual_filterA
Add a VISUAL-LEVEL filter to an existing visual. op = gt|gte|lt|lte|eq|ne|isblank|isnotblank. kind=column|measure. The classic use: exclude discontinued/zero rows from a ranking table, e.g. op=isnotblank on 'Sales 52W TY' (or op=gt value=0), so -100%/blank-rank SKUs stop cluttering the top. valueType=int|decimal|string (default decimal) for comparison values.
Inputs: field (required), table (required), pageName (required), visualName (required), +5 more.
add_visual_topnA
Add a VISUAL-LEVEL Top N: rank rankTable[rankField] by byTable[byMeasure], keep the top/bottom n, with the ranking applied in the visual's own query (a Top node in prototypeQuery.Where). direction=Top|Bottom. Distinct from add_topn_filter (which writes a filter card).
Inputs: n (required), page (required), visual (required), byTable (required), +5 more.
add_whatif_parameterA
Create a WHAT-IF parameter: a disconnected GENERATESERIES calculated table plus a SELECTEDVALUE measure ([ Value]) that picks up the slider selection. Drop the table's column on a slider slicer and reference the value measure in your DAX. The standard Modeling > New parameter pattern.
Inputs: max (required), min (required), name (required), increment (required), +2 more.
align_visualsA
Align, distribute or match-size a set of visuals: mode = left|right|top|bottom|centerx|centery|samewidth|sameheight|distributeh|distributev. visualNames = comma-separated visual names (from list_visuals). Precise tidy-up on top of auto_arrange.
Inputs: mode (required), pageName (required), visualNames (required), reportSessionId (required).
analyze_dependenciesA
Analyse measure/column dependencies and impact. Returns the live INFO.CALCDEPENDENCY lineage plus, when an object is named ([Measure] or Table[Column]), the direct dependants (which measures reference it) from the model tree. Read-only.
Inputs: sessionId (required), object.
analyze_modelB
Read-only best-practices scan: measures/columns missing format strings, tables in no relationship, etc. Returns a list of findings to fix.
Inputs: sessionId (required).
append_queriesA
Power Query Append: stack the rows of one or more other queries onto this table (union). Appends Table.Combine to the table's M query. otherTables is comma-separated.
Inputs: table (required), sessionId (required), otherTables (required), partitionName.
apply_rename_planA
APPLY an audit_naming rename plan through the propagating rename machinery: planJson = audit_naming's renamePlan ({renames:[{objectType, table, oldName, newName}]}, a bare array also accepted). Rows that cannot apply (missing object, collision, malformed) are skipped WITH the reason; the survivors run as ONE atomic batch - TOM renames plus every DAX/M reference rewrite in a single SaveChanges, report bindings rewritten too when reportSource is given. One result row per rename.
Inputs: planJson (required), sessionId (required), reportSource.
apply_report_templateA
Apply a reusable REPORT TEMPLATE in one call: a bundle of theme + wallpaper + canvas-preset + nav settings. template = JSON { theme?:{...}, wallpaper?:{color,transparency}, canvas?:{preset,width,height}, nav?:{} }. page targets the wallpaper + canvas (defaults to the first page). Round-trips with save_report_template.
Inputs: template (required), reportSessionId (required), page.
apply_report_themeA
Apply a report theme (palette + fonts + structural colours) - the single biggest lever for a professional look. preset = executive|vibrant|slate|sunset|forest, OR pass a full Power BI theme JSON in themeJson to override.
Inputs: reportSessionId (required), preset, themeJson.
assert_measureA
Evaluate a scalar DAX expression (EVALUATE ROW) and compare the result to an expected value: numeric-vs-numeric within tolerance, otherwise ordinal string compare of the invariant-culture rendering. A mismatch returns pass:false (not an error) - the single-assert form of run_golden_set.
Inputs: dax (required), expected (required), sessionId (required), tolerance.
audit_datamashup_credentialsA
READ-ONLY credential audit of a .pbix's DataMashup: reports whether the embedded M carries credential material (connection strings with Password=/pwd=/AccountKey=/SAS tokens/etc) and whether a PermissionBindings blob is present. Reports PRESENCE and LOCATION only (indicator, query, line number) - secret values are NEVER echoed.
Inputs: pbixPath (required).
audit_namingA
READ-ONLY naming audit over table/column/measure names (technical DIM_/FACT_/TBL_ prefixes, snake_case, camelCase, leading/trailing/doubled spaces, lowercase initials) returning an applyable RENAME PLAN json {renames:[{objectType, table, oldName, newName, reason}]}. PLAN ONLY - nothing is renamed by this tool; a propagating apply (rewriting DAX/M references to renamed objects) lands in a later wave. Collisions are skipped and reported.
Inputs: sessionId (required).
audit_robustnessA
The complete 'select a value and the visuals fall over' detector - the pre-delivery reliability gate. For every low-cardinality slicer-style column it catches BOTH failure modes: (1) ERROR-on-select - a measure throws in that filter context, breaking the canvas (e.g. 'Brand=a given brand breaks [Margin %]'); and (2) BLANK-on-select - a value that empties every visual because it has no underlying data (the empty-brand class - a member with no rows). Pinpoints the offending values. Run before shipping. Tune with maxColumns/maxValuesPerColumn/maxMeasures; set anchorMeasure to choose the measure used for the blank test (defaults to the first model measure).
Inputs: sessionId (required), maxColumns, maxMeasures, anchorMeasure, +1 more.
audit_star_schemaA
READ-ONLY star-schema audit: classify every table (fact / dimension / date / bridge / disconnected) from the relationship topology + column types, then flag the schema smells - snowflaking, bidirectional filters, many-to-many, fact-to-fact relationships, a missing/unmarked date table, and descriptive text columns on fact tables. Returns a scored report (0-100) with a per-issue recommendation naming the fixing tool.
Inputs: sessionId (required).
audit_theme_complianceA
READ-ONLY theme lint: walk every visual's objects/vcObjects formatting trees against the report's custom theme (read_theme's defaults) and report hard-coded overrides that fight it - off-palette colour literals, on-palette colours that FREEZE the palette so a theme swap will not restyle them, title font family/size overrides of the theme text classes, and per-visual card-style overrides where the theme's visualStyles already set the look.
Inputs: reportSessionId (required).
auto_arrangeA
Auto-arrange a page into a clean professional grid in ONE call: header textboxes full-width at top, then a slicer filter-bar, then a KPI-card row, then the data visuals (charts/tables) in a balanced grid that fills the page - consistent margins, gutters and alignment. Add visuals roughly, then call this to snap them into a designed layout. Decorative shapes/images stay put.
Inputs: pageName (required), reportSessionId (required), gutter, margin, +6 more.
auto_mobile_layoutA
Auto-generate a phone (mobile) layout for a page: stacks the significant visuals (slicers, KPI value cards, tables, main charts) vertically on the 320-wide phone canvas; skips decorative shapes, tiny deltas and sparklines. A sensible mobile view in one call. Ground-truthed (layouts id 1).
Inputs: pageName (required), reportSessionId (required).
begin_model_transactionA
Open a write-transaction on the session's model: subsequent model tools accumulate TOM changes WITHOUT SaveChanges until commit_model_transaction applies them all in one SaveChanges (rollback_model_transaction discards them). Refreshes requested inside the transaction run at commit. One transaction per session; queries against the engine see the pre-transaction state until commit.
Inputs: sessionId (required).
bind_dynamic_titleA
Bind a visual's TITLE to a text MEASURE (expression-based title): the measure (e.g. a SELECTEDVALUE narrative with an All/multiple fallback) becomes the title text and title show is forced on. Author the text measure first with add_dynamic_title_measure (model side). titleMeasure = "Table[Measure]" (or pass titleMeasureTable). page/visual resolve by name or displayName.
Inputs: page (required), visual (required), titleMeasure (required), reportSessionId (required), +1 more.
bind_field_parameterA
Bind a FIELD PARAMETER to a visual so it actually swaps fields when opened in Desktop - the visual-side piece the model-side add_field_parameter cannot write. The chosen role's projection becomes the parameter COLUMN with active=true (the dynamic-projection marker) and the prototypeQuery Select swaps to the parameter column; the four model-side pieces (the NAMEOF calculated table, ParameterMetadata, SortByColumn, GroupByColumns) come from add_field_parameter - run it first. role defaults to the visual's measure well (Y, else Values).
Inputs: page (required), visual (required), parameterTable (required), reportSessionId (required), +2 more.
bridge_reloadA
UNSAFE-FOR-PIPELINE (interactive attach only): hot-reload the on-disk PBIP/PBIR definition into the open Power BI Desktop (file.reload/v1) without close/reopen - the composition step after save_pbir edits the tree on disk. Refuses while the Desktop reports unsaved changes (or cannot report at all) unless force=true, because a reload discards the in-memory state.
Inputs: pid (required), force, timeoutSec, reloadModelDefinition.
bridge_screenshotA
UNSAFE-FOR-PIPELINE (interactive attach only): capture pixel-accurate PNG renders of report pages from a RUNNING Power BI Desktop (report.snapshot.capture/v1) and write them to outDir - the render-verification half of the edit/see loop. Pass pageName (page GUID or displayName) for one page, or allPages=true for the whole report (needs an on-disk PBIR definition to enumerate). Returns per-page paths + status.
Inputs: pid (required), outDir (required), scale, allPages, +2 more.
bridge_statusA
UNSAFE-FOR-PIPELINE (interactive attach only): report every Power BI Desktop instance on this machine through the Desktop Bridge named pipe: bridge availability + manifest methods, the open file path, the unsaved-changes flag, the on-disk PBIR pages and the AS engine ports list_open_models discovers. A Desktop without the bridge (older build, or the 'external tool access through secure local APIs' preview switch off) degrades to a clear entry, never an error.
Inputs: connectTimeoutSec.
bring_to_frontA
Bring a visual to the FRONT of the page (z = current max + 1) so it renders on top of everything else.
Inputs: page (required), visual (required), reportSessionId (required).
build_category_reportA
RECIPE 2: a beautified multi-page CATEGORY REVIEW (the standard FMCG scan template) in ONE call - Performance, Price & Volume, Share and Distribution pages, branded + themed + nav-linked. Conditionally-formatted Brand matrices, a volume/price combo chart and a segment share breakdown. config = JSON with: title, subtitle, headline, headlineLabel, brandColor, accentColor, logoPath, canvasWidth/canvasHeight, factTable, brandTable, brandColumn, segmentTable, segmentColumn, dateTable, dateColumn, slicers:[{table,column,title}], measures:{sales,volume,price,distribution,growth,usw,salesTrend}.
Inputs: config (required), reportSessionId (required).
build_crossretailer_compareA
RECIPE: a Total-Market compare page across two retailers/panels (pairs with conform_dimension). Config: compareTable/compareColumn (the conformed dimension), retailerA/retailerB ({label,table,measure}), optional totalMeasure, slicers, and the additive options clearPages/pagePrefix. Builds banner + slicer bar + a KPI row (Total Market / Retailer A / Retailer B) + a by-entity table + an A-vs-B grouped bar. The pbix must be CLOSED. Verify the render in Desktop after.
Inputs: config (required), reportSessionId (required).
build_executive_reportA
RECIPE: build a complete premium 'Executive' dashboard page in ONE call from a JSON config. Composes a brand theme, a navy banner + gold seam, a slicer filter-bar, a row of premium KPI cards (value + delta + sparkline), a hero trend line, and a 'by segment' bar chart whose colour encodes growth. Point it at any client model by mapping the config fields. config = JSON with: title, subtitle, headline, headlineLabel, brandColor, accentColor, logoPath (brand kit - palette + logo in banner), canvasWidth/canvasHeight (default 1280x720; use 1920x1080 for a Full-HD pro report), factTable, dateTable, dateColumn, trendMeasure, segmentTable, segmentColumn, segmentValueMeasure, growthMeasure, slicers:[{table,column,title}], kpis:[{measure,label,delta,trend}].
Inputs: config (required), reportSessionId (required).
build_grid_reportA
RECIPE: a flexible GRID dashboard - compose ANY visuals in one call. config.visuals is an array of {type, title, span(1-12), rows, category:{table,column}, series:{table,column}, values:[{table,measure}]}; they flow into a 12-column grid that fills the canvas. Supports the full palette: column/bar/line/area/pie/donut/funnel/ribbon/combo + scatter/treemap + tables/cards. The open-ended composer behind the template library. clearPages/pagePrefix to append.
Inputs: config (required), reportSessionId (required).
bulk_bind_visualsA
BATCH set_visual_fields: rebind MANY visuals in one call instead of one round-trip each. items = JSON array of {page, visual, bindings:[{role,table,field,kind}, ...]}. One result row per target; a failing item never aborts the rest (partial failure is reported per item, never silently all-or-nothing).
Inputs: items (required), reportSessionId (required).
bulk_delete_visualsA
BATCH delete_visual: delete MANY visuals in one call. items = JSON array of {page, visual}. One result row per target; a missing visual fails its own row only, the rest still delete.
Inputs: items (required), reportSessionId (required).
bulk_set_visual_formatA
BATCH set_visual_format: apply formatting to MANY visuals in one call. items = JSON array of {page, visual, format:{vcObjects:{card:{prop:value}}, objects:{card:{prop:value}}}} (format takes the exact set_visual_format formatJson shape). One result row per target; per-item failures reported, the rest still apply.
Inputs: items (required), reportSessionId (required).
change_column_typeA
Power Query Change Type: set the data type of one or more columns. Appends Table.TransformColumnTypes to the table's M query. types is comma-separated as column:type, e.g. "Amount:number,OrderDate:date,Qty:int". type = text | int | number | date | datetime | bool | currency. Pass culture (e.g. "en-US", "en-NZ") to parse text against that locale's date/number conventions - the fix for silent type-conversion corruption on mixed-locale sources.
Inputs: table (required), types (required), sessionId (required), culture, +1 more.
change_visual_typeA
Change a visual's TYPE preserving its data bindings, position and applicable formatting. A deprecated target is modernised automatically (card -> cardVisual, table -> tableEx, matrix -> pivotTable). Projection roles are remapped through the curated data-role registry (list_visual_data_roles): same-named roles carry straight over, the rest fall to the first compatible role by kind, and per-role caps drop overflow (reported, never silent). Data-formatting cards the new type does not declare are dropped and reported; chrome (title/background/border) always survives. Sort is cleared - re-apply with set_visual_sort.
Inputs: page (required), visual (required), newType (required), reportSessionId (required).
check_directlake_fallbackA
Diagnose Direct Lake DirectQuery fallbacks: read the fallback-reason DMV and list model objects (calculated columns / calculated tables) that are unsupported in Direct Lake and force a fallback. Read-only.
Inputs: sessionId (required).
check_relationshipsA
Diagnose 'the visual is blank' issues: for every Fact->Dim relationship, count dimension members that have NO matching fact rows (these render BLANK when a user selects them in a slicer - the #1 cause of an apparently-broken visual) and fact keys with no dimension match. Run this whenever a visual is empty but the model 'looks fine'.
Inputs: sessionId (required).
clear_pagesA
Remove ALL pages from the report (e.g. to replace a stale report with a fresh one).
Inputs: reportSessionId (required).
clear_visual_stylingA
FLATTEN visuals to a plain 'non-premium' look the SAFE way. Removes the decorative chrome (border, dropShadow, stylePreset, visualHeader/visualHeaderTooltip and plain opaque backgrounds) from each visual's vcObjects. PRESERVES deliberate formatting by default: a custom-text or explicit-show title (e.g. a custom heading, or a title hidden on an overlay chart) and a transparent (overlay) background are kept. NEVER touches a button's navigation action (visualLink), bookmark/page-navigation actions, or the data + conditional formatting (singleVisual.objects). actionButton visuals are skipped entirely. This replaces the buggy 'delete the whole vcObjects bucket' flatten that destroyed meaningful titles/overlays and broke nav buttons. pageName omitted = all pages; visualName omitted = all visuals on the page. Set removeTitles=true to also strip deliberate titles (the old aggressive behaviour). Returns visuals touched, decorative keys removed, and a count of action/visualLink keys PRESERVED.
Inputs: reportSessionId (required), pageName, visualName, removeTitles, +1 more.
clone_pageA
Deep-clone a report page: copies the whole section, assigns a fresh unique section name and a new ordinal at the end, sets newDisplayName, and regenerates EVERY visual's id so ids stay globally unique across the report. Returns the new page name.
Inputs: sourcePage (required), newDisplayName (required), reportSessionId (required).
clone_visualA
Deep-clone one visual (with a fresh unique id) onto its page or onto targetPage. On the same page the copy is nudged so it is visible. Returns the new visual id.
Inputs: page (required), visual (required), reportSessionId (required), targetPage.
column_statisticsB
Run EVALUATE COLUMNSTATISTICS() - per-column Min / Max / Cardinality / MaxLength profiling for the whole model in one call.
Inputs: sessionId (required), maxRows.
combine_folder_filesA
Generate a robust combine-files-from-folder query as a new query: Folder.Files -> filter by extension -> per-file parse -> Table.Combine. Schema-drift safe: it does NOT use Power Query's default 'expand with a sample file' (which silently drops columns only present in later files). fileType = csv | excel. keepFilename adds Source.Name and Source.Folder Path columns; skipErrors wraps each file in try..otherwise so one bad file does not break the refresh. Refresh afterwards.
Inputs: name (required), sessionId (required), folderPath (required), fileType, +5 more.
commit_model_transactionA
Commit the open model transaction: one real SaveChanges applies every accumulated change (and any deferred refresh requests). If SaveChanges fails the transaction stays open so you can fix the model or roll back - nothing is half-committed.
Inputs: sessionId (required).
concatenate_with_group_byA
Concatenate text within groups: Table.Group + Text.Combine (the inverse of split-to-rows). Collapses each group's textColumn values into one delimited string. keys is comma-separated; delimiter defaults to ", ". Appends one step to the table's M query.
Inputs: keys (required), table (required), sessionId (required), textColumn (required), +3 more.
conform_dimensionA
Cross-retailer / total-market builder. Two separate fact islands (e.g. a grocery-retailer fact and a second-retailer fact) can't be filtered by one slicer because they share no dimension. This creates a CONFORMED dimension (a calculated table of the distinct union of a column from each side) and relates it to both, so one slicer filters both retailers and combined measures ([Total Market] = [retailer A] + [retailer B]) compute correctly. Auto-materialises + recalcs. Turns two side-by-side islands into a true total-market view (the Phase-2 join).
Inputs: table1 (required), table2 (required), column1 (required), column2 (required), +3 more.
connect_modelA
UNSAFE-FOR-PIPELINE (interactive attach only): connects to a Power BI Desktop model a human already has open and returns a sessionId used by all model tools. Omitting port attaches to the most recently written workspace port, which is a guess, not a guarantee. Unattended jobs must launch their own Desktop instead of attaching.
Inputs: port.
connect_xmlaA
Connect to a Fabric/Premium XMLA endpoint (powerbi://...) instead of local Power BI Desktop. Returns a sessionId that every session-based tool (run_dax, validate_dax, export_tmdl, run_bpa...) accepts unchanged - DAX runs against the Service, no Desktop needed. Endpoint/catalog/token default from DAXOPS_XMLA_ENDPOINT / DAXOPS_XMLA_CATALOG / DAXOPS_PBI_TOKEN; the token is held in memory only and never echoed.
Inputs: catalog, endpoint, accessToken.
convert_legacy_to_pbirA
BEST-EFFORT explode a legacy Report/Layout (.pbix or a raw Layout JSON file) into a PBIR definition tree written to a target folder (default .Report next to the source): pages -> page.json, visualContainers -> visual.json, generating GUID names. Returns a pbirSessionId over the new tree. FLAG: best-effort - open in Power BI Desktop to validate/upgrade. pbir->legacy is not implemented.
Inputs: legacyPath (required), targetFolder.
create_csv_tableA
Create a fully-typed import table from a (staged) CSV in ONE call: reads the header + samples rows to infer each column's type (Int64/Double/String), builds the Csv.Document M, declares EVERY column automatically, and refreshes. Removes the add_data_column-per-column grind. Pairs with stage_excel_to_csv / unpivot_weekly_csv. Pass pathExpression to control how the M references the file (e.g. 'DataFolder & "file.csv"'); omit to embed the absolute path.
Inputs: table (required), csvPath (required), sessionId (required), sampleRows, +1 more.
create_date_tableA
Create a fully-formed date table in ONE call: Date, Year, Quarter, Month, MonthYear + sort-by columns + a Year>Quarter>Month hierarchy. Then relate your fact's date column to [Date]. Pass dateColumnRef (e.g. "Fact[Date]") to size the range to your data, else CALENDARAUTO() is used. target=pbip: pass pbipFolder instead of sessionId to write the SAME table as Desktop-faithful TMDL into a PBIP semantic model with NO engine (columns authored explicitly; data materialises on the first Desktop refresh).
Inputs: name, hierarchy, sessionId, pbipFolder, +1 more.
create_pbir_pageA
Add a new page to a PBIR report: a fresh GUID folder definition/pages//page.json plus an update to pages.json (append to pageOrder). Returns the new page GUID name (use it for adding visuals).
Inputs: displayName (required), pbirSessionId (required), width, height.
dax_benchmarkA
Benchmark a DAX query: optionally clear the engine cache (XMLA ClearCache on the session database), then run the query N times returning {coldMs, warmMs[], rowCount}. Timings are client wall-clock per run (execution + full row drain) - honest about what is measured; pair with start_dax_trace/stop_dax_trace for the FE/SE split and cache hits.
Inputs: query (required), sessionId (required), runs, clearCache.
dax_lintA
PURE OFFLINE DAX static linter - no live session needed for a raw expression (the gap run_bpa cannot cover: linting a CANDIDATE expression before it is applied). Pass expression for offline lint; or sessionId to lint live measures (all, one table's, or one measure via table+measure). Rules with line numbers, severity and a rewrite hint: FILTER(wholeTable) inside CALCULATE, nested CALCULATE, '/' where DIVIDE belongs, IFERROR wrapping, '+ 0' blank suppression, EARLIER usage, SUMMARIZE used for aggregation, and UNKNOWN_FUNCTION - the AI-hallucinated-function catcher, checked against a maintained static catalogue (model UDFs auto-admitted in session mode; admit new engine functions via extraFunctions, comma-separated).
Inputs: table, measure, sessionId, expression, +1 more.
dax_suggest_rewriteA
Concrete BEFORE/AFTER rewrites for a DAX expression's lint findings - pure offline, no session. Mechanical fixes are applied: 'a / b' -> DIVIDE(a, b), IFERROR(x / y, alt) -> DIVIDE(x, y, alt), a trailing '+ 0' removed, and FILTER(Table, single-column predicate) inside CALCULATE collapsed to the bare predicate. Findings with no safe mechanical fix (EARLIER, SUMMARIZE aggregations, nested CALCULATE, ...) come back as hint-only notes. Also returns the full suggested expression with every non-overlapping rewrite applied.
Inputs: expression (required), extraFunctions.
declare_changed_propertyA
Mark a property as locally CHANGED so a schema sync does not wipe your override on a composite / Direct Lake object (name, isHidden, formatString, summarizeBy etc. are otherwise treated as source-owned and reset on refresh). objectType = model | table | column | measure | hierarchy | partition | relationship; pass the object's table where needed.
Inputs: name (required), property (required), sessionId (required), objectType (required), +1 more.
define_udfA
Define a DAX User-Defined Function (a net-new model object). The body carries its own typed parameters and return type. params is a comma-separated name:type list (type = Scalar | Table | ColumnRef | MeasureRef | AnyRef | Numeric | String; omit a type for an untyped param). UDFs need compatibility level 1702+, which is auto-bumped if lower. Inspect existing UDFs with list_udfs.
Inputs: name (required), bodyDax (required), sessionId (required), params, +2 more.
delete_bookmarkB
Delete a report-level bookmark by name or displayName.
Inputs: name (required), reportSessionId (required).
delete_calculation_itemB
Delete a calculation item from a calculation group.
Inputs: name (required), table (required), sessionId (required).
delete_calendarB
Delete a table's calendar definition (removes the PBI_Calendar annotation - the Wave R convention while the native calendar TOM objects are absent from this build).
Inputs: table (required), sessionId (required).
delete_cultureA
Delete a culture (locale) and all its translations and linguistic metadata from the model.
Inputs: locale (required), sessionId (required).
delete_hierarchyC
Delete a hierarchy from a table.
Inputs: table (required), hierarchy (required), sessionId (required).
delete_measureC
Delete a measure from a table.
Inputs: name (required), table (required), sessionId (required).
delete_pageB
Delete a report page by name or displayName.
Inputs: pageName (required), reportSessionId (required).
delete_partitionA
Delete a partition from a table (and its data on the next save). Refuses to delete the table's ONLY partition - use delete_table for that.
Inputs: name (required), table (required), sessionId (required).
delete_perspectiveC
Delete a perspective from the model.
Inputs: sessionId (required), perspective (required).
delete_relationshipA
Delete a relationship. Identify it by name, or by all four of fromTable/fromColumn/toTable/toColumn (order-insensitive).
Inputs: sessionId (required), name, toTable, toColumn, +2 more.
delete_roleB
Delete a security role (and its row-level/object-level rules and members) from the model.
Inputs: name (required), sessionId (required).
delete_tableA
Delete a table from the model (and any relationships that touch it). Use to remove stale/broken tables before a clean rebuild.
Inputs: name (required), sessionId (required).
delete_template_measureA
Delete a measure from a table in a closed .pbit template's model, editing the DataModelSchema JSON on disk with no Power BI Desktop. Fails if the measure does not exist. Written back in place (with a .bak guard).
Inputs: name (required), table (required), pbitPath (required).
delete_template_relationshipA
Delete the relationship whose endpoints match from/to from a closed .pbit template's model, editing the DataModelSchema JSON on disk with no Power BI Desktop. Fails if no such relationship exists. Written back in place (with a .bak guard).
Inputs: toTable (required), pbitPath (required), toColumn (required), fromTable (required), +1 more.
delete_translationA
Delete ONE object translation: the translated Caption / Description / DisplayFolder of a model object in a culture. objectType = table | column | measure | hierarchy | model (column/measure/hierarchy need the table).
Inputs: culture (required), property (required), sessionId (required), objectName (required), +2 more.
delete_variationB
Delete a date-navigation variation from a column (by variation name).
Inputs: table (required), column (required), sessionId (required), variation (required).
delete_visualC
Delete a visual from a page by its visual name.
Inputs: pageName (required), visualName (required), reportSessionId (required).
demote_headersA
Power Query Use Headers as First Row: push the current column names back down into a data row. Appends Table.DemoteHeaders to the table's M query.
Inputs: table (required), sessionId (required), partitionName.
detect_column_typesA
Power Query Detect Data Type: auto-detect and apply each column's type from its data. Appends a self-contained Table.TransformColumnTypes whose {column, type} pairs are inferred from the first non-null value of every column - no schema needs to be supplied.
Inputs: table (required), sessionId (required), partitionName.
detect_report_formatA
Classify a report source as legacy | pbir | pbip. Robust on both a .pbix (a ZIP: Report/Layout = legacy, Report/definition/ = pbir) and a PBIP project folder (a *.pbir pointer or a definition/ folder). Returns the classification plus the evidence.
Inputs: path (required).
disable_auto_date_timeA
Turn OFF Auto date/time: sets the model's __PBI_TimeIntelligenceEnabled annotation to 0 (so Power BI Desktop stops auto-generating a hidden LocalDateTable per date column) and removes any auto date/time tables already in the model. Slims the model and stops auto-date bloat.
Inputs: sessionId (required).
document_reportA
One-call Markdown documentation artifact for a report: pages, every visual (type, position, size, title, field bindings), page/report filter counts, bookmarks and the theme - rendered purely from the existing readers. When outPath is given the Markdown is also written to disk.
Inputs: reportSessionId (required), outPath.
duplicate_columnA
Power Query Duplicate Column: copy a column under a new name. Appends Table.DuplicateColumn to the table's M query.
Inputs: table (required), column (required), newName (required), sessionId (required), +1 more.
dynamic_unpivot_other_columnsA
Dynamic Unpivot Other Columns: unpivot every column NOT in keepColumns, deriving the unpivot set from Table.ColumnNames at evaluation time so NEW attribute columns added later auto-unpivot. keepColumns is comma-separated. Appends one step to the table's M query.
Inputs: table (required), sessionId (required), keepColumns (required), partitionName.
edit_measure_offlineA
Add or edit a measure on a CLOSED .pbix and save it back to disk. Briefly opens the file in the local Power BI Desktop (a Desktop window appears), adds/updates the measure via TOM, then drives Desktop's own File > Save (scripted Ctrl+S) so the change lands in the .pbix, and closes Desktop. An existing measure is updated (omit a field to keep it); a new one needs expression. Reports the before/after expression, format string and display folder, and whether the disk save was confirmed.
Inputs: name (required), table (required), pbixPath (required), expression, +4 more.
edit_model_offlineA
STRUCTURE-ONLY offline model edit (NO Power BI Desktop, NO live engine): deserialize a TMDL model (a definition/ folder or a PBIP .SemanticModel - the model half export_tmdl / generate_pbip / unpack_to_source produce), apply the edits to the object tree, and re-serialize edited TMDL to outputFolder. The model STRUCTURE (measures, relationships, calc columns, tables, partition definitions) round-trips exactly. DATA IS NOT PRESERVED: TMDL carries no compressed VertiPaq data, so import (M) tables come back empty until a refresh. Use this for template / thin-model edits and source-control workflows. For a DATA-preserving edit of a loaded report use persist_model_edit (offline, M-free) or persist_open_model (Desktop). NOTE: a cold data .pbix that imports via M cannot be read offline - first export its model with export_tmdl from a live session, then edit that folder here.
Inputs: edits (required), tmdlFolder (required), outputFolder (required).
edit_visual_aggregationA
Change the AGGREGATION applied to a field projected on a visual: wraps the Select node's Column/Measure in an Aggregation { Function }. aggregation=Sum|Avg|Min|Max|Count|CountNonNull|Median|StdDev|Var (index 0..8). field='Table.Field' (the queryRef). scopedEvalBaseline=true wraps it in a context-free ScopedEval/AllRolesRef baseline (FLAG: confirm shape in Desktop).
Inputs: page (required), field (required), visual (required), aggregation (required), +2 more.
eval_dax_offlineA
Evaluate a DAX query against a CLOSED .pbix and return the result rows (columns + rows). Briefly opens the file in the local Power BI Desktop (a Desktop window appears), runs the query against its engine, then closes Desktop. Accepts a full 'EVALUATE ...' query or a bare table expression (EVALUATE is prepended). Same result shape as run_dax, but no session / no manually-open Desktop.
Inputs: dax (required), pbixPath (required), timeoutSec.
execute_service_queryA
Run a DAX query against a PUBLISHED dataset over REST (POST .../executeQueries) - no Desktop, no live model session. Needs an AAD access token with the Power BI scopes (accessToken param or DAXOPS_PBI_TOKEN); never echoed.
Inputs: dax (required), datasetId (required), workspaceId (required), accessToken.
expand_columnA
Power Query Expand Column: surface inner fields of a structured column. Appends Table.ExpandRecordColumn / Table.ExpandTableColumn / Table.ExpandListColumn to the table's M query. kind = record | table | list (default record). fields (comma-separated) selects which inner fields to surface for record/table; ignored for list.
Inputs: table (required), column (required), sessionId (required), kind, +2 more.
export_data_dictionaryB
Export the model's data dictionary (tables, columns, measures with descriptions/types/format strings/DAX, plus relationships) rendered as Markdown or HTML, with a description COVERAGE score - the fraction of visible objects carrying a description (the missing-descriptions gap). Rendered from the TOM tree only; no queries are run.
Inputs: sessionId (required), format.
export_dataflow_modeljsonA
Export a Power BI dataflow model.json to disk from a set of entity definitions. entities is a JSON array of {name, m, attributes:[{name,dataType}]} where m is the entity's full M query and dataType = string|int64|double|decimal|date|dateTime|time|boolean|guid. The query mashup is embedded at the root pbi:mashup.document. FLAG: the inner pbi:mashup layout is best-known, NOT verified against a real export.
Inputs: entities (required), sessionId (required), outputPath (required), dataflowName (required), +1 more.
export_tmdlA
Serialize the live model to TMDL text files (Microsoft's official serializer) - the model half of a PBIP project, fully text and source-control-friendly. The foundation for generating projects without a live Power BI Desktop.
Inputs: sessionId (required), outputFolder (required).
extract_power_queryA
Extract the full Section1.m (the plain-text Power Query M for every query) from a .pbix's DataMashup part, plus the declared query names. READ-ONLY. If there is no DataMashup part, the M is in the DataModel/TMDL - use get_table_m.
Inputs: pbixPath (required).
extract_report_colorsA
READ-ONLY report-wide colour inventory: every hardcoded colour literal across all visuals AND the theme, with the exact locations of each occurrence (theme.dataColors[2], page/visual objects paths). The scouting pass before recolor_report.
Inputs: reportSessionId (required).
extract_report_level_measuresA
Promote report-level measures into the model as real measures: read the report definition's config.modelExtensions[].entities[].measures[] from a .pbix on disk and add each to its host table (keeping format/folder), skipping any name that already exists. Returns the measures promoted.
Inputs: pbixPath (required), sessionId (required).
fill_downA
Power Query Fill Down: replace nulls in a column with the most recent non-null value above. Appends Table.FillDown to the table's M query. columns is comma-separated.
Inputs: table (required), columns (required), sessionId (required), partitionName.
fill_upA
Power Query Fill Up: replace nulls in a column with the most recent non-null value below. Appends Table.FillUp to the table's M query. columns is comma-separated.
Inputs: table (required), columns (required), sessionId (required), partitionName.
filter_rowsA
Power Query Filter Rows: keep only the rows matching a condition. Appends Table.SelectRows(prev, each ) to the table's M query. Provide the condition referencing the row as _, e.g. "[Amount] > 0 and [Region] = "NZ"" (the 'each' is added if you omit it).
Inputs: table (required), sessionId (required), mCondition (required), partitionName.
find_attribution_gapsA
The 'your report is silently incomplete' detector. A single dimension member with no fact rows can be normal; a WHOLE GROUP of members under one attribute value (an entire supplier, a whole category) with zero data almost never is - it signals a systematic exclusion (mis-attribution / over-scoped fact), the empty-brand / supplier-group class. Finds those clusters automatically - no brand list or domain knowledge needed - so a human can review them. Read-only. The high-value data-integrity guarantee.
Inputs: sessionId (required), maxColumns, anchorMeasure, maxValuesPerColumn.
find_unusedA
Find columns and measures never referenced inside the model - not by a relationship, sort-by, hierarchy level, RLS filter, or any measure / calculated-column / calculated-table DAX. (Visual usage lives in the report layer and is not scanned here.) Read-only - the cleanup shortlist.
Inputs: sessionId (required).
fix_bpaA
Apply a BPA rule's autofix - it sets the precise TOM property the rule names (e.g. Column.IsHidden, Column.IsAvailableInMDX, Measure.FormatString, strip EVALUATEANDLOG). With no objectName every matching object is fixed; with objectName only that one. dryRun=true (the default) lists exactly what WOULD change without modifying anything - run again with dryRun=false to apply. Rules with no safe automatic fix (e.g. DAX_USE_DIVIDE, AVOID_FLOATING_POINT_DATA_TYPES) are refused with guidance.
Inputs: ruleId (required), sessionId (required), dryRun, objectName.
fix_broken_visualsA
Repair visual bindings that point at RENAMED or MOVED model fields (found by scan_broken_refs). repairMap = JSON {"Old Table[Old Field]":"New Table[New Field]", ...}. Rewrites the same binding paths set_visual_fields writes - prototypeQuery From/Select (aliases repointed when the table changed), projections queryRefs, sorts, visual filters, and the conditional-formatting / chrome bindings - plus page and report filters. Returns one row per changed target and lists any repair key that never matched.
Inputs: repairMap (required), reportSessionId (required).
fix_case_sensitive_daxA
Rewrite every measure's table / column / measure references to the model's EXACT casing - the fix for DirectQuery / Direct Lake against case-sensitive sources where 'sales'[amount] and 'Sales'[Amount] are different objects. Returns the measures rewritten.
Inputs: sessionId (required).
fix_slicer_single_selectA
ONE-CALL flat-line fix for a field-parameter-axis chart. Give ONLY the .pbix path and the page name (both are in a request like 'fix the flat line in Category vs Brand Share of ') - no slicer name, no boolean, no multi-step. Opens the CLOSED .pbix, finds the slicer bound to the page's FIELD PARAMETER (auto-detected: a slicer whose bound field is a field parameter - table==column, or the single-column-table field plotted on a chart axis), makes it SINGLE-SELECT (writes the ground-truth objects.selection[0].properties.strictSingleSelect=true), then writes the .pbix back (DataModel byte-preserved). THAT is the whole fix: a field-parameter-bound chart flat-lines because every option renders at once; single-select forces one option AND auto-picks the field parameter's first option (e.g. MonthYear) on open. If several field-parameter slicers exist, pass the optional 'chart' (its title/name/bound field) to disambiguate; if you already know a specific value, pass 'default_value' to pin the opening option (otherwise single-select auto-picks the first). Returns {ok, page, slicer, fieldParameter, strictSingleSelect, default_applied, before, after}. The .pbix must NOT be open in Power BI Desktop.
Inputs: page (required), pbix (required), chart, default_value.
format_columnB
Set a column's format string (e.g. "#,0", "$#,0.00", "0.0%", "dd mmm yyyy") and/or data category (e.g. "City", "WebUrl", "ImageUrl").
Inputs: table (required), column (required), sessionId (required), dataCategory, +1 more.
format_titleB
Format a visual's title: text, colour, font size, alignment (left|center|right), show/hide.
Inputs: pageName (required), visualName (required), reportSessionId (required), show, +4 more.
fuzzy_cluster_columnA
Power Query Fuzzy Cluster: add a column giving each row the canonical cluster representative of a text column (groups near-identical values, e.g. 'Acme' / 'acme inc' / 'ACME'). Appends Table.AddFuzzyClusterColumn to the table's M query. threshold is the optional 0..1 similarity cut-off.
Inputs: table (required), column (required), newColumn (required), sessionId (required), +2 more.
fuzzy_groupA
Power Query Fuzzy Group By: collapse rows whose key values are APPROXIMATELY equal (typos/casing) into one group with aggregates. Appends Table.FuzzyGroup to the table's M query. keyColumns is comma-separated. aggregations is comma-separated as name:op[:column] (op = Sum | Count | Average | Min | Max | CountDistinct | All). threshold is the optional 0..1 similarity cut-off.
Inputs: table (required), sessionId (required), keyColumns (required), aggregations (required), +2 more.
fuzzy_mergeA
Power Query Fuzzy Merge: join another query on APPROXIMATE key matches (typos, casing, spacing). Appends Table.FuzzyNestedJoin (+ optional Table.ExpandTableColumn) to the table's M query. leftKeys/rightKeys are comma-separated equal-length lists. joinKind = Inner | LeftOuter | RightOuter | FullOuter | LeftAnti | RightAnti. threshold is the 0..1 similarity cut-off (default 0.8). transformationTable is an optional {From,To} mapping query name.
Inputs: table (required), leftKeys (required), rightKeys (required), sessionId (required), +8 more.
generate_445_calendar_mA
Generate a retail 4-4-5 / 4-5-4 / 5-4-4 calendar table as a new query, one row per week with RetailYear, PeriodOfYear, WeekOfPeriod, WeekOfYear, WeekIndex, WeekStart, WeekEnd. startDate is raw M, e.g. #date(2024,1,29). weeksPattern = 445 | 454 | 544. periodsPerYear = 12 (standard) or 13 (every period 4 weeks). Refresh afterwards.
Inputs: name (required), sessionId (required), startDate (required), weeksPattern, +2 more.
generate_calendar_table_mA
Generate a full date/calendar table as a new query: List.Dates over [startExpr..endExpr] with ~20 part columns (Year, Quarter, QuarterName, MonthNo, MonthName, MonthShort, YearMonthNo, YearMonth, ISOWeek, ISOYear, WeekdayNo, DayName, DayNo, DayOfYear, StartOfMonth, EndOfMonth, IsWeekend). startExpr/endExpr are RAW M, e.g. "#date(2020,1,1)" or a parameter reference. Pass fiscalYearEndMonth (1..12) to add FiscalYear/FiscalMonthNo/FiscalQuarter. Pass locale (e.g. en-NZ) to render month/day names in that culture. Refresh afterwards.
Inputs: name (required), endExpr (required), sessionId (required), startExpr (required), +2 more.
generate_embed_tokenA
Mint a Power BI EMBED token (POST /GenerateToken) for the given datasets / reports / target workspaces - the scoped, short-lived token an embedding app hands to the browser. Needs an AAD access token with the Power BI scopes (accessToken param or DAXOPS_PBI_TOKEN); the AAD token itself is never echoed.
Inputs: reportIds, datasetIds, accessToken, workspaceIds.
generate_paletteA
Compute a palette and write it into the theme: dataColors[] + good/neutral/bad + CF min/center/max. mode=harmonic (hue-wheel off baseColor) | monochrome (lightness ramp of baseColor) | gradient (interpolate baseColor->... actually gradientFrom->gradientTo). For gradient pass gradientFrom + gradientTo; otherwise pass baseColor.
Inputs: reportSessionId (required), n, mode, baseColor, +2 more.
generate_pbipA
Generate a complete text-based PBIP project from the live model + a source pbix's report: .SemanticModel (TMDL via the official serializer) + .Report (legacy report.json + definition.pbir + StaticResources) + .pbip. Pure files - Power BI Desktop / Fabric open it directly, NO live engine needed to author. This is the spine that gets the whole tool off the live-Desktop dependency.
Inputs: name (required), sessionId (required), outputFolder (required), sourcePbixPath (required), +1 more.
generate_themeA
Generate AND (by default) apply a complete professional theme: an 8-colour palette derived from a primaryColor (hex), an explicit colors list, or a named style (executive|vibrant|slate|sunset|forest); structural colours + fonts; AND visualStyle defaults so EVERY visual automatically gets the card look - rounded corners, drop shadow, consistent title font, header hidden. This is the theme-driven 'looks pro' layer; pair it with auto_arrange. Set cardStyle=false for flat visuals, dark=true for a dark theme.
Inputs: reportSessionId (required), dark, name, apply, +8 more.
get_datamashup_infoA
Report whether a .pbix has a DataMashup (Power Query M) part and the query names it declares. READ-ONLY. If absent, the M lives in the DataModel/TMDL (enhanced-metadata PBI_V3) - use get_table_m / set_partition_m instead.
Inputs: pbixPath (required).
get_model_offlineA
Read the model of a CLOSED .pbix: tables, columns with data types, measures with their DAX, relationships and named M expressions. Briefly opens the file in the local Power BI Desktop (a Desktop window appears), reads the model via TOM, then closes Desktop. The offline form of get_model_summary - no session / no manually-open Desktop.
Inputs: pbixPath (required), timeoutSec.
get_model_summaryA
Return the model schema: tables, columns, measures, relationships and named M expressions. Use this to get exact names before binding visuals.
Inputs: sessionId (required).
get_pbir_pageB
Get one PBIR page's page.json plus the names/types of its visuals. page = the GUID name or the displayName.
Inputs: page (required), pbirSessionId (required).
get_pbir_visualA
Get one PBIR visual's visual.json (position + visual{visualType,query,objects,...} + filterConfig), verbatim.
Inputs: page (required), visual (required), pbirSessionId (required).
get_refresh_statusA
Read the recent refresh history of a published dataset (GET .../refreshes?$top=N) - status, start/end times and any service error. Needs an AAD access token with the Power BI scopes (accessToken param or DAXOPS_PBI_TOKEN); never echoed.
Inputs: datasetId (required), workspaceId (required), top, accessToken.
get_report_filtersA
READ-ONLY read-back of the report's filter surface: every report / page / visual-level filter parsed to structured form - scope, table[field], filter type, lock/hide flags, and the decoded condition (values list, comparison op + value, topN, relative date/time, and/or chains). The read partner of the add_*_filter tools.
Inputs: reportSessionId (required).
get_report_settingsA
READ-ONLY read-back of the report-level behaviour toggles (config.settings) that set_report_settings writes, decoded to plain values, plus the custom-theme name when one is applied. The read partner of set_report_settings.
Inputs: reportSessionId (required).
get_slicer_defaultsA
READ-ONLY read-back of every slicer's selection state: bound field, strictSingleSelect / singleSelect flags, display mode, and any default selection values written as Categorical filters in the slicer's own container. The read partner of set_slicer_selection / fix_slicer_single_select. Scope to one page or omit for all pages.
Inputs: reportSessionId (required), page.
get_transaction_statusA
Report whether a model transaction is open on the session, when it opened, and how many gated saves it has deferred so far. Read-only.
Inputs: sessionId (required).
get_visual_formatA
Read the DECODED, simplified current formatting of one visual (READ-ONLY). Returns its type, position {x,y,w,h}, the decoded vcObjects {object:{property:value}} (container: title, background, border, ...), the decoded objects {object:{property:value}} (visual-specific: labels, legend, categoryAxis, ...) and its field bindings. Use this to inspect before set_visual_format. page/visual resolve by name or displayName.
Inputs: page (required), visual (required), reportSessionId (required).
get_visual_schemaA
Get the formatting schema for one visualType as a compact structured object - the same cards -> properties -> {type, enum, min, max} as list_visual_properties, optionally scoped to a single card (e.g. legend, valueAxis, title). Omit card for the full schema.
Inputs: visualType (required), card.
group_byA
Power Query Group By: collapse rows to one per key-column combination with aggregates. Appends Table.Group to the table's M query. keyColumns is comma-separated. aggregations is comma-separated as name:op[:column], e.g. "Total:Sum:Amount,Lines:Count,Distinct Customers:CountDistinct:CustomerId". op = Sum | Count | Average | Min | Max | CountDistinct | All (column required except for Count/All).
Inputs: table (required), sessionId (required), keyColumns (required), aggregations (required), +1 more.
group_keep_all_columnsA
Group By keeping ALL columns: Table.Group with {each _} then expand the grouped table over its non-key columns - the workaround for the editor's Group By dropping non-aggregated columns. The expanded set is derived at evaluation time so it survives schema drift. keys is comma-separated. Appends two steps to the table's M query.
Inputs: keys (required), table (required), sessionId (required), partitionName.
group_visualsA
GROUP a set of visuals into a single group (like Desktop's right-click > Group). Creates a group container and stamps each child visual with parentGroupName. visualNames = comma-separated visual names (from list_visuals) - at least two. groupName is the optional display name shown in the selection pane. Returns the new group name.
Inputs: page (required), visualNames (required), reportSessionId (required), groupName.
hide_filterA
HIDE a filter in view mode (still applied to the report but not shown in the filter pane to viewers). scope=visual|page|report (visual needs page+visual; page needs page). Matches the filter on table[field]. Sets the filter's isHiddenInViewMode flag.
Inputs: field (required), scope (required), table (required), reportSessionId (required), +3 more.
impact_analysisA
BLAST RADIUS of one model object (a measure name or Table[Field]): every model dependant that transitively references it through DAX, plus - when reportSource is given - every report visual touching the object or any dependant measure (page/visual/context). The pre-rename / pre-delete safety check. Read-only.
Inputs: sessionId (required), objectName (required), reportSource.
import_bpa_rulesetA
Import a Tabular Editor BPARules.json document and reconcile it with the built-in catalogue: rules whose ID matches a built-in are mapped to our evaluable check; rules whose logic is a Tabular Editor dynamic C#/LINQ expression we cannot safely evaluate are registered as descriptive-only (id/severity/description surfaced) and FLAGGED. The arbitrary TE expression string is never executed.
Inputs: json (required), sessionId (required).
import_tmdlA
Import a TMDL folder (the official deserializer) into the live model. DEFAULTS TO A DRY RUN that returns the table/measure diff and changes NOTHING. Applying TMDL REPLACES the live model metadata (createOrReplace semantics), so the actual apply is gated behind applyToLiveModel:true. The folder may be a model TMDL folder or a PBIP SemanticModel (the nested 'definition' subfolder is auto-detected).
Inputs: sessionId (required), folderPath (required), applyToLiveModel.
infer_relationshipsA
Auto-detect missing relationships from the DATA, not just names: finds columns matching by name + type across tables, then proves each one - which side is the unique key (cardinality + direction) and what fraction of the many-side keys exist on the one side (coverage). Returns ranked proposals with confidence; with autoCreate:true it creates the high-confidence many-to-one matches (as inactive if an active path already exists). Run this instead of guessing add_relationship calls.
Inputs: sessionId (required), autoCreate, minCoverage.
info_viewB
Run EVALUATE INFO.VIEW.() (or INFO.()) and return shaped rows - the model's documentation/lineage surface. view = TABLES | COLUMNS | MEASURES | RELATIONSHIPS | CALCDEPENDENCY | etc.
Inputs: view (required), sessionId (required), maxRows.
inject_evaluateandlogA
Wrap a measure's DAX in EVALUATEANDLOG so its value is captured in Server Timings / DAX Studio traces during debugging. Idempotent. Remember to strip_evaluateandlog afterwards.
Inputs: table (required), measure (required), sessionId (required), label.
keep_bottom_rowsB
Power Query Keep Bottom Rows: keep only the last N rows. Appends Table.LastN to the table's M query.
Inputs: count (required), table (required), sessionId (required), partitionName.
keep_errorsA
Power Query Keep Errors: keep ONLY rows that carry an error value (to inspect bad data). Appends Table.SelectRowsWithErrors to the table's M query. Pass columns (comma-separated) to test only those columns; omit for the whole row.
Inputs: table (required), sessionId (required), columns, partitionName.
keep_range_rowsA
Power Query Keep Range of Rows: skip offset rows then keep count rows. Appends Table.Range to the table's M query.
Inputs: count (required), table (required), offset (required), sessionId (required), +1 more.
keep_top_rowsA
Power Query Keep Top Rows: keep only the first N rows. Appends Table.FirstN to the table's M query.
Inputs: count (required), table (required), sessionId (required), partitionName.
list_bookmarksA
List the report's bookmarks: each one's name, displayName, active page, and the visual ids it hides.
Inputs: reportSessionId (required).
list_bpa_rulesA
List the BPA rule catalogue so you can see coverage: id, category, severity, scope, fixable flag, the exact TOM property each autofix sets, and the description. Optionally filter to one category. Use the IDs with run_bpa (ruleIds) and fix_bpa (ruleId).
Inputs: sessionId (required), category.
list_calendarsA
List the model's calendar-based time-intelligence definitions: table, primary column and column groups. FLAG: read from PBI_Calendar table annotations (the Wave R convention) because the native calendar/calendarColumnGroup TOM objects are absent from this build. Read-only.
Inputs: sessionId (required).
list_culturesA
List the model's cultures (locales): name, translation count, and whether linguistic (Q&A) metadata is attached. Read-only.
Inputs: sessionId (required).
list_excel_sheetsA
List the worksheet names in an .xlsx/.xlsm file (so you can pick the one to stage).
Inputs: xlsxPath (required).
list_mA
List every Power Query (M) partition expression and shared expression in the model.
Inputs: sessionId (required).
list_measuresA
List measures (with DAX) for the whole model or one table.
Inputs: sessionId (required), table.
list_open_modelsA
UNSAFE-FOR-PIPELINE (interactive attach only): lists the Power BI Desktop models a human currently has open on this machine, opening a probe connection into every one of them. Open the .pbix in Power BI Desktop first. Never call this from an unattended job.
Inputs: no named parameters.
list_pagesB
List the report pages (name, displayName, size, visual count).
Inputs: reportSessionId (required).
list_partitionsA
List partitions - {table, partition, sourceType, mode, state, refreshedTime} - for the whole model or one table. Read-only.
Inputs: sessionId (required), table.
list_pbir_pagesA
List the pages of an open PBIR report (GUID name, displayName, size, displayOption, visual count), in page order.
Inputs: pbirSessionId (required).
list_recipesA
The recipe CATALOG: lists every report template, what it produces, and the config fields that map it to a model. Call this first to pick a template, then call that recipe's tool with a JSON config.
Inputs: no named parameters.
list_rolesA
List every security role with its model permission, members, and per-table row-level filters (RLS) and object-level metadata permissions (OLS).
Inputs: sessionId (required).
list_service_datasetsA
List the datasets and reports in a Power BI Service workspace (GET .../datasets + .../reports) - the ids feed refresh_dataset, execute_service_query and generate_embed_token. Needs an AAD access token with the Power BI scopes (accessToken param or DAXOPS_PBI_TOKEN); never echoed.
Inputs: workspaceId (required), accessToken.
list_translationsA
List object translations - {culture, objectType, objectName, table, property, value} - for every culture or one. Read-only.
Inputs: sessionId (required), culture.
list_udfsA
List the model's DAX User-Defined Functions (name, expression, description).
Inputs: sessionId (required).
list_variationsA
List the date-navigation variations on a column (name, relationship, default hierarchy, isDefault). Read-only.
Inputs: table (required), column (required), sessionId (required).
list_visual_data_rolesA
The QUERY data roles a visual type takes (Category / Y / Series / Values / Rows / ...), each with what it accepts (Grouping | Measure | GroupingOrMeasure), its per-role field cap, and the deprecated -> modern type mapping (card -> cardVisual, table -> tableEx, matrix -> pivotTable). Role metadata is HAND-CURATED for the mainstream visual types because the bundled theme schema only describes formatting cards, not query roles - coverage is reported honestly (curated | none). The role half of the discovery surface; list_visual_properties is the formatting half.
Inputs: visualType (required).
list_visual_propertiesA
List ALL formatting cards and their properties for one visualType (commonCards like title/background/border PLUS the visual-specific cards). Each property reports its type (bool|number|text|color|enum|object), enum values where applicable, and numeric min/max where declared. The complete discovery surface for what set_visual_format can set on a visual.
Inputs: visualType (required).
list_visualsA
List the visuals on a page (name, type, position).
Inputs: pageName (required), reportSessionId (required).
list_visual_typesA
List every canonical Power BI visualType key the formatting registry knows (52 types), each tagged data | container, with its card count. Use these keys with list_visual_properties / get_visual_schema and as a visual's type when adding visuals.
Inputs: no named parameters.
list_workspacesA
List the Power BI Service workspaces the caller can reach (GET /groups). Needs an AAD access token with the Power BI scopes (accessToken param or the DAXOPS_PBI_TOKEN env var); the token is used as a Bearer header only and never echoed.
Inputs: accessToken.
lock_filterA
LOCK a filter in view mode (shown in the filter pane but cannot be changed by viewers). scope=visual|page|report (visual needs page+visual; page needs page). Matches the filter on table[field]. Sets the filter's isLockedInViewMode flag.
Inputs: field (required), scope (required), table (required), reportSessionId (required), +3 more.
mark_as_date_tableA
Mark a table as the model's date table (the TOM equivalent of 'Mark as date table'): sets the table's data category to Time and flags the given DateTime column as the date key. Use this so built-in time intelligence works reliably against your own calendar table.
Inputs: table (required), sessionId (required), dateColumn (required).
mark_removed_childrenA
Stamp the model/table annotation PBI_RemovedChildren so a schema sync keeps tables/columns you deleted removed (otherwise they reappear on the next refresh). removedSourceLineageTags is a comma-separated list of the SOURCE lineage tags/names of the removed children. Merges into any existing list.
Inputs: table (required), sessionId (required), removedSourceLineageTags (required).
match_slicer_layoutA
Learn the slicer ROW STRUCTURE (row count, per-row y, height, left start, horizontal gap) from hand-fixed REFERENCE pages, then re-lay the slicers on TARGET pages onto that structure. Median-based inference tolerates reference noise (a slicer nudged off-canvas, a top row whose y drifts a few px between pages) - structure is INFERRED, never copied pixel-for-pixel. Slicers only: non-slicer visuals are never touched; widths are preserved (they shrink proportionally only when a row physically cannot fit the canvas). Writes the .pbix back offline (Report/Layout patched, DataModel byte-preserved). The .pbix must NOT be open in Power BI Desktop. Returns { ok, learned{referencePages,rows:[{row,y,height,leftStart,gap,samples}],rowPitch}, pagesMatched, totalMoves, pages:[{page,rowsDetected,moves:[{slicer,row,before,after}]}], persistedToDisk }.
Inputs: pbix (required), reference_pages (required), targets.
merge_columnsA
Power Query Merge Columns: concatenate two or more columns into one new column with a separator. Appends Table.CombineColumns (+ Combiner.CombineTextByDelimiter) to the table's M query. columns is comma-separated (the source columns are consumed).
Inputs: table (required), columns (required), separator (required), sessionId (required), +2 more.
merge_queriesA
Power Query Merge: join another query into this table on matching key columns, then optionally expand chosen columns. Appends Table.NestedJoin (+ Table.ExpandTableColumn) to the table's M query. leftKeys/rightKeys are comma-separated and must be equal length. joinKind = Inner | LeftOuter | RightOuter | FullOuter | LeftAnti | RightAnti.
Inputs: table (required), leftKeys (required), rightKeys (required), sessionId (required), +4 more.
model_healthA
Model-health report: object counts (tables/columns/measures/relationships) plus VertiPaq per-column storage (size + cardinality) read from the storage DMVs through the model connection - surfaces the largest columns so you can find bloat / unused high-cardinality columns. Read-only.
Inputs: sessionId (required).
model_report_usageA
CROSS-LAYER usage analysis: join the live semantic model (sessionId) with the report (reportSource = a reportSessionId from open_report, a pbirSessionId from read_pbir, or a path to a PBIR .pbix/PBIP folder) and classify EVERY model field three ways. DIRECT = bound in the report - a visual projection, filter, slicer, tooltip, sparkline, sort, or a conditional-formatting/chrome binding (colour measures, icon rules, image URLs, dynamic titles - the bindings naive scanners miss). INDIRECT = reached via a direct measure's DAX lineage, a relationship path between in-play tables, a sort-by column, or a model-internal reference. UNUSED = neither - the safe-to-remove shortlist that find_unused (model-only) cannot produce. Read-only.
Inputs: sessionId (required), reportSource (required).
modify_themeA
Tweak the report's current custom theme in place: change the palette (primaryColor or colors list), background/foreground, or the card defaults (cornerRadius/shadow/font). Run generate_theme or apply_report_theme first.
Inputs: reportSessionId (required), colors, shadow, background, +4 more.
move_columnB
Power Query Move Column: reposition a column. Appends Table.ReorderColumns with the computed order to the table's M query. position = start | end | before | after. For before/after, refColumn is required.
Inputs: table (required), column (required), position (required), sessionId (required), +2 more.
move_measureA
Move a measure to another table (its home table changes; DAX references to it are unaffected because measures are referenced as [Name]). KPI, format string, display folder, description, annotations, lineage tag and culture translations all travel with it (a deep clone is re-homed and translations are re-pointed - TOM forbids re-attaching a removed object).
Inputs: measure (required), sessionId (required), targetTable (required).
move_visualB
Move an existing visual to new x/y (and optional z order).
Inputs: pageName (required), visualName (required), reportSessionId (required), x, +2 more.
open_desktopA
UNSAFE-FOR-PIPELINE (interactive attach only): launch Power BI Desktop on a .pbix/.pbip (standard MSI install, the WindowsApps Store layout or the Store execution alias; spawn is console-window-free - Desktop shows its own window) and wait until its Desktop Bridge answers or waitForBridgeSec lapses. Returns pid + bridge availability + manifest; no bridge by the deadline degrades to a clear entry (the Desktop itself may still be healthy). Unattended pipelines must keep using their own queue-managed launch.
Inputs: path (required), exePath, waitForBridgeSec.
open_reportA
Open a .pbix's report for editing (pages/visuals). The .pbix must be CLOSED in Power BI Desktop. Returns a reportSessionId.
Inputs: pbixPath (required).
open_template_modelA
Read the model of a closed .pbit template's DataModelSchema on disk, with no Power BI Desktop and no engine: returns each table with its columns (name + data type + key properties) and measures (name + DAX expression + display folder), plus the relationships (from/to). A .pbit that has no DataModelSchema part (a live-connection or PBIR-only template) comes back ok:false with a clear note.
Inputs: pbitPath (required).
paginated_rest_sourceA
Generate a paginated REST source as a new query: a List.Generate page loop that accumulates pages then Table.Combine. mode = offset (uses pageParam+sizeParam, stops on an empty page) or cursor (reads the next token from nextField, stops when null). The base URL stays STATIC and the page key folds through Web.Contents [Query=...]; each page is List.Buffer-ed. dataPath is the JSON field holding the records array (e.g. "value" or "data"; empty = the body IS the array). Refresh afterwards.
Inputs: name (required), baseUrl (required), sessionId (required), mode, +6 more.
pbix_diffA
Semantic diff between two .pbix files or two unpacked source trees (from unpack_to_source): files added/removed/changed, TMDL tables + measures (trees only), report pages + visual counts, and Power Query M queries (.pbix only). The 'semantic git diff' for client models - read-only.
Inputs: pathA (required), pathB (required).
pbix_doctorA
READ-ONLY 17-point file-level container scan of a CLOSED .pbix: zip part inventory vs expected parts, Version/DataModel/DataMashup presence and sizes, stale SecurityBindings and DataMashup PermissionBindings, sensitivity-label parts, zero-byte / truncated / duplicate parts, and whether the report part is legacy or PBIR. Never writes.
Inputs: pbixPath (required).
persist_model_editA
THE single entry to fix a measure / relationship / calculated column in a model AND persist it to the .pbix. Picks the best route for target and reports what it did plus what is / isn't preserved. target = an open model sessionId (from connect_model) -> live edit + scripted Power BI Desktop File>Save; DATA PRESERVED for ANY model (needs the .pbix open in Desktop). target = a cold .pbix PATH -> offline engine edit (ImageLoad->edit->ImageSave->repack); DATA PRESERVED, no Desktop, but ONLY for M-free / engine-native models. If the .pbix imports via Power Query (M) - a normal data report - the offline route cannot host it and the result explains to open it in Desktop and pass the sessionId instead. edits = a JSON array of edit objects (see the tool-type summary). A .bak backup is taken and the write is atomic.
Inputs: edits (required), target (required), pbixPath, saveRetries.
persist_open_modelA
DATA-PRESERVING persist for a report OPEN in Power BI Desktop (the loop for a loaded report like a live dashboard): apply the model edits to the connected LIVE model (SaveChanges + a Calculate when a calc column/relationship changed), then drive Desktop's own File>Save (scripted Ctrl+S, located by the session's engine port) so Desktop writes its full model+DATA image back to the .pbix. Works for ANY model including Power Query (M) import models. PREREQUISITE (manual): the .pbix must be OPEN in Power BI Desktop and connected via connect_model - Desktop is the only host that can persist a data-loaded, M-based model to disk. Pass pbixPath so the tool can confirm the save landed.
Inputs: edits (required), sessionId (required), pbixPath, saveRetries.
pivot_columnA
Power Query Pivot Column: turn the distinct values of an attribute column into new columns, aggregating a value column. Appends Table.Pivot to the table's M query. aggregation = Sum | Count | Average | Min | Max (default Sum).
Inputs: table (required), sessionId (required), valueColumn (required), attributeColumn (required), +2 more.
pivot_text_valuesA
Pivot TEXT values: Table.Pivot with a Text.Combine aggregation (the default pivot errors on text values). Colliding values in a cell are joined with delimiter (default ", "). Appends one step to the table's M query.
Inputs: table (required), sessionId (required), valueColumn (required), attributeColumn (required), +2 more.
preview_tableA
Return the first N rows of a table (TOPN) to inspect the actual data after a refresh.
Inputs: table (required), sessionId (required), rows.
promote_headersB
Power Query Use First Row as Headers: promote the first data row to column names. Appends Table.PromoteHeaders to the table's M query.
Inputs: table (required), sessionId (required), partitionName.
publish_to_serviceA
Publish a built artifact to the Power BI Service: a .pbix path goes through the Import API (nameConflict CreateOrOverwrite by default); a PBIP folder (the tree generate_pbip/scaffold emit) is published at definition level via the Fabric items API - SemanticModel first, then Report, each created or updated in place. Needs an AAD access token with the Power BI scopes (accessToken param or DAXOPS_PBI_TOKEN); never echoed.
Inputs: path (required), workspaceId (required), accessToken, nameConflict, +1 more.
quality_gateA
PRE-DELIVERY QUALITY GATE: a comprehensive best-practices lint with a pass/review/fail verdict - unformatted measures/columns, tables out of relationships, visible key columns, missing date table, auto-date bloat, inactive relationships, and live relationship-integrity (orphan keys via DAX). Run before shipping a report so nothing goes out broken or untidy.
Inputs: sessionId (required).
read_pbirA
Open an enhanced (PBIR) report from a .pbix or a PBIP folder, parse the whole definition tree into memory, and return a structured summary (pages + visual counts, bookmarks, dataset reference). Returns a pbirSessionId reused by the other pbir tools. The source must be CLOSED in Power BI Desktop.
Inputs: path (required).
read_table_offlineA
Read up to topN rows of one table from a CLOSED .pbix (EVALUATE TOPN(topN, 'table')). Briefly opens the file in the local Power BI Desktop (a Desktop window appears), reads the rows, then closes Desktop. Returns columns + rows; when the row cap is hit the result flags truncated:true.
Inputs: table (required), pbixPath (required), topN.
read_themeA
Read the report's current custom theme: name, palette, structural colours, whether it sets visualStyle defaults, plus the full theme JSON to inspect or re-apply.
Inputs: reportSessionId (required).
recolor_reportA
Find/replace colour literals across ALL visuals and the theme in one call: colorMap = JSON {"#OLD":"#NEW", ...}. Handles both the plain theme spelling (#RRGGBB) and the quoted expr spelling ('#RRGGBB') inside visual objects, preserving each occurrence's form. Returns per-colour replacement counts; run save_report to persist.
Inputs: colorMap (required), reportSessionId (required).
refresh_datasetA
Trigger a refresh of a published dataset (POST .../refreshes, notifyOption NoNotification). Returns the requestId to correlate in get_refresh_status. Needs an AAD access token with the Power BI scopes (accessToken param or DAXOPS_PBI_TOKEN); never echoed.
Inputs: datasetId (required), workspaceId (required), type, accessToken.
refresh_partitionA
Refresh ONE partition (RefreshType.Full) - cheaper than refresh_table when only one slice changed. Inside an open model transaction the refresh is deferred to commit.
Inputs: name (required), table (required), sessionId (required).
refresh_tableA
Refresh one table (or the whole model if table omitted). Required after add_table_from_m / set_partition_m for data and columns to appear.
Inputs: sessionId (required), full, table.
register_custom_visualA
Register an imported CUSTOM VISUAL into the report so its visualType is usable: adds the guid to layout.config.publicCustomVisuals, and when a .pbiviz path is given, stages the file into resourcePackages. name = the visual's visualType/guid; guid defaults to name.
Inputs: name (required), reportSessionId (required), guid, path.
register_org_custom_visualA
Register an ORGANIZATION-store custom visual into the report so its visualType is usable: adds the guid to layout.config.organizationCustomVisuals (the tenant's org store, vs the public AppSource store register_custom_visual uses). name = the visual's visualType/guid; guid defaults to name. A .pbiviz path is rarely needed for org visuals but is staged when given.
Inputs: name (required), reportSessionId (required), guid, path.
remove_alternate_rowsA
Power Query Remove Alternate Rows: keep the first firstKept rows, then repeatedly take and skip in a pattern. Appends Table.AlternateRows to the table's M query.
Inputs: table (required), taken (required), skipped (required), firstKept (required), +2 more.
remove_blank_rowsB
Power Query Remove Blank Rows: drop rows where every field is blank (empty or null). Appends Table.SelectRows with the all-fields-non-blank predicate to the table's M query.
Inputs: table (required), sessionId (required), partitionName.
remove_bottom_rowsA
Power Query Remove Bottom Rows: drop the last N rows. Appends Table.RemoveLastN to the table's M query.
Inputs: count (required), table (required), sessionId (required), partitionName.
remove_columnsB
Power Query Remove Columns: drop columns. Appends Table.RemoveColumns to the table's M query. columns is comma-separated.
Inputs: table (required), columns (required), sessionId (required), partitionName.
remove_duplicatesA
Power Query Remove Duplicates: keep one row per distinct combination. Appends Table.Distinct to the table's M query. Pass columns (comma-separated) to dedupe on those columns only; omit to dedupe whole rows.
Inputs: table (required), sessionId (required), columns, partitionName.
remove_errorsA
Power Query Remove Errors: drop rows that carry an error value. Appends Table.RemoveRowsWithErrors to the table's M query. Pass columns (comma-separated) to test only those columns; omit to test the whole row.
Inputs: table (required), sessionId (required), columns, partitionName.
remove_filterA
Remove a matching filter (by table[field]) at a given scope = visual|page|report. For scope=visual pass page+visual; for scope=page pass page; scope=report needs neither. Returns how many filters were removed.
Inputs: field (required), scope (required), table (required), reportSessionId (required), +2 more.
remove_from_perspectiveA
Remove an object from a perspective. objectType = table | column | measure | hierarchy. For column/measure/hierarchy, pass the object's table. Removing a table removes it (and its members) from the perspective.
Inputs: name (required), sessionId (required), objectType (required), perspective (required), +1 more.
remove_hierarchy_levelA
Remove a level from a hierarchy (remaining levels are renumbered densely). Refuses to remove the LAST level - a hierarchy cannot be empty; use delete_hierarchy instead.
Inputs: level (required), table (required), hierarchy (required), sessionId (required).
remove_role_memberA
Remove a member from a security role (by member identity). Returns removed=false if the member was not on the role.
Inputs: role (required), member (required), sessionId (required).
rename_columnA
Rename a column. With propagate=true (the default) every DAX reference model-wide is rewritten too - measures, calculated columns/tables, RLS filters, calc items, format-string/detail-rows/KPI expressions - atomically (one SaveChanges; any failure rolls everything back), and when reportSource is given the report's bindings (projections, queryRefs, filters at all scopes, sorts, conditional-formatting/chrome, on both legacy Layout and PBIR) are rewritten as well. propagate=false renames the object only, leaving references by the old name in M/DAX untouched.
Inputs: table (required), column (required), newName (required), sessionId (required), +2 more.
rename_columnsA
Power Query Rename Columns: rename columns in the query. Appends Table.RenameColumns to the table's M query. renames is comma-separated as from:to, e.g. "col1:Amount,col2:Region".
Inputs: table (required), renames (required), sessionId (required), partitionName.
rename_columns_from_mappingA
Rename columns from a CONTROL TABLE: Table.RenameColumns(prev, Table.ToRows(...), MissingField.Ignore). Drives renames from a maintained {oldCol, newCol} mapping query; MissingField.Ignore skips columns that are absent. Appends one step to the table's M query.
Inputs: table (required), newCol (required), oldCol (required), sessionId (required), +2 more.
rename_pageA
Rename a report page (set its tab title / displayName). The internal page name is unchanged so bookmarks and navigation keep working.
Inputs: page (required), newName (required), reportSessionId (required).
rename_tableA
Rename a table. With propagate=true (the default) every reference model-wide is rewritten too - quoted 'Table'[Col] and bare Table[Col] DAX forms across measures/calc columns/calc tables/RLS/calc items/KPIs, plus M query-name references (#"Old" and bare identifiers in partition M and shared expressions, the partition name kept in step) - atomically (one SaveChanges; any failure rolls everything back). When reportSource is given the report's bindings (From entities, projections, queryRefs, filters at all scopes, conditional-formatting/chrome, legacy Layout and PBIR) follow as well. propagate=false renames the object only. Sort-bys, hierarchies, relationships and translations carry over automatically in TOM either way.
Inputs: table (required), newName (required), sessionId (required), propagate, +1 more.
reorder_columnsA
Power Query Reorder Columns: move the listed columns to the front in the given order (remaining columns keep their relative order). Appends Table.ReorderColumns to the table's M query. order is comma-separated.
Inputs: order (required), table (required), sessionId (required), partitionName.
reorder_pagesA
Reorder the report's pages. orderedNames = comma-separated page names/displayNames in the desired left-to-right order; each gets a fresh ordinal in that order. Pages not listed keep their relative order and are appended after.
Inputs: orderedNames (required), reportSessionId (required).
replace_errorsA
Power Query Replace Errors: substitute a value for error cells in specific columns. Appends Table.ReplaceErrorValues to the table's M query. replacements is comma-separated as column:value, e.g. "Amount:0,Region:Unknown". valueType (text | number | logical | null) applies to all replacement values; for an all-columns replacement, list every column with the same value.
Inputs: table (required), sessionId (required), replacements (required), valueType, +1 more.
replace_valueA
Power Query Replace Value (whole-cell): swap the entire cell value in a column - unlike replace_values which replaces a text substring. Appends Table.ReplaceValue (Replacer.ReplaceValue) to the table's M query, supporting null<->value and numeric replacements (e.g. null->0, 0->null, -1->0). valueType (text | number | logical | null) applies to BOTH oldValue and newValue.
Inputs: table (required), column (required), sessionId (required), newValue, +3 more.
replace_valuesB
Power Query Replace Values: replace every occurrence of a text value in a column. Appends Table.ReplaceValue (Replacer.ReplaceText) to the table's M query.
Inputs: find (required), table (required), column (required), replace (required), +2 more.
resize_pageA
Resize a page's canvas to an explicit width x height (pixels). Writes the section size + the pageSize object so it sticks in Desktop. For named presets use set_canvas_preset.
Inputs: page (required), width (required), height (required), reportSessionId (required).
resize_visualB
Resize an existing visual to new width/height.
Inputs: pageName (required), visualName (required), reportSessionId (required), width, +1 more.
rewrite_connection_stringA
Find/replace a literal substring (a server/db name, file path, URL, ...) across Section1.m inside a .pbix's DataMashup, clearing PermissionBindings. Returns how many occurrences were replaced. RISKY - work on a COPY; the .pbix must be CLOSED in Desktop; refuses protected client paths.
Inputs: find (required), replace (required), pbixPath (required).
rls_test_harnessA
Prove the model's security filters: evaluate one DAX query under EVERY role in the model plus an unfiltered baseline, returning a per-role matrix of {role, rowCount, sampleRows, error}. A role whose rowCount equals the baseline is not filtering that query - the classic silent-RLS-gap detector. Read-only.
Inputs: query (required), sessionId (required), sampleRows.
rollback_model_transactionA
Roll back the open model transaction: discards every accumulated TOM change via Model.UndoLocalChanges - the engine never sees them.
Inputs: sessionId (required).
run_bpaA
Run the Best Practice Analyzer: a catalogue of ~90 lint rules (merging the Tabular Editor and semantic-link-labs rulesets) across Performance, DAXExpressions, ErrorPrevention, Maintenance, NamingConventions, Formatting, Metadata and RelationshipsLayout. Read-only. Returns every finding (ruleId, category, severity 1 info/2 warning/3 error, objectType, objectName, message, fixable) plus a summary count by category and severity. Filter with categories / severities / ruleIds (comma-separated) and scope (Model|Table|Column|Measure|Relationship|Partition|Hierarchy). Use fix_bpa to auto-remedy fixable findings.
Inputs: sessionId (required), scope, ruleIds, categories, +1 more.
run_daxA
Run a DAX query against the live model and RETURN the result rows (columns + rows). Accepts a full 'EVALUATE ...' query or a bare table expression (EVALUATE is prepended). Use to verify a refresh, get row counts, check date ranges, or preview data.
Inputs: dax (required), sessionId (required), maxRows.
run_dax_as_roleA
Run a DAX query AS a security role: opens a second connection to the session's engine with Roles= (and optionally EffectiveUserName= for dynamic USERPRINCIPALNAME-driven RLS) so the engine applies the role's row-level filters, and returns the rows. Role names are validated against the model so a typo can never silently run unfiltered. Read-only.
Inputs: query (required), roles (required), sessionId (required), maxRows, +1 more.
run_golden_setA
Replay a golden-set file against the live model: every golden is re-evaluated and compared to its baseline (numeric tolerance 1e-6, error-state matching). Returns total/passed/failed plus per-failure expected vs actual - the numbers gate for verifying a measure change in CI.
Inputs: path (required), sessionId (required).
running_total_mA
Add a FAST running total of valueColumn ordered by orderColumn, optionally restarting within each groupColumn. Uses List.Buffer + a single accumulation pass (O(n)) rather than a per-row re-scan (O(n^2)). Appends sort + index + running-total steps to the table's M query.
Inputs: table (required), sessionId (required), orderColumn (required), valueColumn (required), +2 more.
save_golden_setA
Capture a measure-regression baseline: evaluate every model measure (or a comma-separated subset) via EVALUATE ROW and write a deterministic, git-friendly golden-set JSON file (sorted by name, no timestamps). A measure that errors is recorded as an error-state golden so regressions to/from errors are caught. Replay with run_golden_set.
Inputs: path (required), sessionId (required), measures.
save_open_pbixA
Persist an OPEN Power BI Desktop model to its .pbix by driving Desktop's own File>Save (scripted Ctrl+S), located by the session's engine port. This is the model-side 'save' the toolkit otherwise lacks: after any live model edit (add_measure, add_relationship, ...) call this to write the change - WITH data - back to disk without a manual click. Requires the .pbix open in Power BI Desktop. Pass pbixPath so the tool can confirm the save landed (LastWriteTime advanced). On an XMLA (Fabric/Service) session there is no local .pbix: the dataset persists server-side, so a pending M change is flushed by a full server-side refresh instead (ok:true, persisted:'xmla-refresh', saveDispatched:false; no Desktop is touched).
Inputs: sessionId (required), pbixPath, saveRetries.
save_pbirA
Persist the open PBIR report, re-emitting ONLY changed files and preserving every other entry byte-for-byte, GUID names intact, the DataModel untouched, and SecurityBindings stripped. For a .pbix this repacks the zip; for a PBIP folder it writes the changed files. The source must NOT be open in Power BI Desktop.
Inputs: pbirSessionId (required).
save_reportA
Write all report edits back into the .pbix (patches Report/Layout in the ZIP). The .pbix must be CLOSED in Power BI Desktop.
Inputs: reportSessionId (required).
save_report_templateA
Save the report's current look as a reusable TEMPLATE bundle (inverse of apply_report_template): captures the live theme, the page's wallpaper + canvas size, and the report nav settings into one templateJson to re-apply later. page defaults to the first page.
Inputs: name (required), reportSessionId (required), page.
save_template_modelA
Rewrite a closed .pbit template's ZIP with the current DataModelSchema, preserving every other part (Report/Layout, [Content_Types].xml, SecurityBindings, Version, etc.) byte-for-byte - no Power BI Desktop. With no outPath it re-packs in place (the original is copied to a .bak first); with an outPath it writes an edited copy there and leaves the source untouched. The edit tools already persist on each call, so this is the explicit save-as (or an integrity re-pack).
Inputs: pbitPath (required), outPath.
scan_broken_refsA
Flag report bindings that point at MISSING model fields (renamed/deleted tables, columns or measures): every projection, filter, sort and conditional-formatting binding is resolved against the live model, and each broken ref reports where it is bound plus repair suggestions (same field on another table, closest name on the same table). reportSource = a reportSessionId, a pbirSessionId, or a PBIR path. Repair legacy sessions with fix_broken_visuals. Read-only.
Inputs: sessionId (required), reportSource (required).
select_columnsA
Power Query Choose Columns: keep ONLY the listed columns (in that order) and drop the rest. Appends Table.SelectColumns to the table's M query. columns is comma-separated.
Inputs: table (required), columns (required), sessionId (required), partitionName.
send_to_backA
Send a visual to the BACK of the page (z = current min - 1) - e.g. push a decorative panel behind the data visuals.
Inputs: page (required), visual (required), reportSessionId (required).
sentinel_diffA
Sentinel: compare two integrity snapshots (before vs after a refresh) and raise ranked alerts on any regression - a whole category dropped to zero, a table's rows collapsed, the grand total fell, a measure started erroring. Explains the likely cause and proposes the fix. status=fail means a report is now WRONG - do not trust the refresh. Pure/headless (two snapshot files).
Inputs: afterPath (required), beforePath (required).
sentinel_snapshotA
Sentinel (the trust layer): take a model integrity snapshot - grand total, per-table row counts, per-group totals, and per-measure health - and optionally write it to a file. Take one before and one after a refresh (or any change), then sentinel_diff them to catch a regression - a vanished category, collapsed rows, a newly-broken measure - the instant it happens. CI/observability for BI.
Inputs: sessionId (required), outPath, maxGroups, anchorMeasure, +1 more.
set_aggregationA
Define a user-defined AGGREGATION: mark a column on a (typically pre-aggregated) detail table as the aggregate of a base column or table, so the engine can transparently answer queries from the smaller table. summarization = GroupBy | Sum | Count | Min | Max. For GroupBy, baseColumnOrTable is a Table[Column]; for the aggregate functions it's the base table name (or a Table[Column]).
Inputs: table (required), sessionId (required), detailColumn (required), summarization (required), +1 more.
set_alt_textA
Set a visual's ACCESSIBILITY ALT TEXT (read by screen readers): written to singleVisual.objects.general.altText.
Inputs: page (required), text (required), visual (required), reportSessionId (required).
set_annotationA
Set a name/value annotation on any model object: objectType = model | table | column | measure | hierarchy | partition. Pass the object's table for column/measure/hierarchy/partition. Replaces a same-named annotation. Annotations are free-form metadata that survive serialization (used by tooling like Tabular Editor).
Inputs: name (required), value (required), sessionId (required), objectName (required), +2 more.
set_axisB
Configure a chart axis. axis = x (category) or y (value): toggle the axis and its title, set the value-axis start/end, display units (None|Thousands|Millions|Billions|Auto), and gridlines.
Inputs: pageName (required), visualName (required), reportSessionId (required), end, +6 more.
set_azuremap_layer_sourceA
Set an azureMap data layer source. layer=reference: a reference layer from a local .json/.geojson file (embedded), an http(s) URL, or an inline GeoJSON string. layer=tile: a custom tile-layer URL TEMPLATE (e.g. https://.../{z}/{x}/{y}.png). Verify the render in Desktop.
Inputs: page (required), layer (required), source (required), visual (required), +1 more.
set_bookmark_data_stateA
Re-capture an existing bookmark's DATA state from the page's CURRENT live state: filter/slicer values, saved sort, drill position and cross-highlight (not just which visuals are shown). This is the 'update bookmark with current data' action. Keeps the bookmark's hidden/shown visuals. page (optional) re-anchors which page is captured (defaults to the bookmark's active page).
Inputs: bookmark (required), reportSessionId (required), page.
set_bookmark_optionsA
Set a bookmark's OPTIONS - the Data / Display / Current-page / Selected-visuals toggles. suppressData=true turns DATA off, suppressDisplay=true turns DISPLAY off, suppressActiveSection=true turns CURRENT-PAGE off. targetVisuals = JSON array of visual names to scope the bookmark to those visuals (empty array clears the scope). Only the supplied options change.
Inputs: bookmark (required), reportSessionId (required), suppressData, targetVisuals, +2 more.
set_button_state_cfB
Measure-driven per-STATE button formatting: a measure returning a hex colour drives a button's fill/text/icon colour for a given state. state=default|hover|pressed|selected; target=fill|text|icon. button is the actionButton's visual name. colorMeasure = "Table[Measure]".
Inputs: page (required), button (required), colorMeasure (required), reportSessionId (required), +3 more.
set_calc_group_precedenceA
Set a calculation group's Precedence - when multiple calculation groups apply, the HIGHER precedence is evaluated last (outermost). Run on a table that is already a calculation group.
Inputs: table (required), sessionId (required), precedence (required).
set_calc_group_selection_expressionsA
Set a calculation group's NoSelectionExpression and/or MultipleOrEmptySelectionExpression - the DAX returned when no / multiple calc items are selected - with optional dynamic format strings. Needs compatibility level 1605+ (auto-bumped, reported back).
Inputs: table (required), sessionId (required), noSelectionExpression, noSelectionFormatString, +2 more.
set_calc_item_ordinalA
Set a calculation item's Ordinal - its display/sort order within the calculation group (lower shows first).
Inputs: table (required), ordinal (required), itemName (required), sessionId (required).
set_canvas_presetA
Set a page's canvas to a named PRESET: 16:9 (1280x720), 4:3 (1024x768), letter (816x1056), tooltip (320x240) or mobile (320x568). preset=custom needs width+height. Writes the section size + pageSize object.
Inputs: page (required), preset (required), reportSessionId (required), width, +1 more.
set_card_imageA
Set a hero/callout IMAGE on a cardVisual (the new card's image element). imageUrlOrPath = a local file (embedded) or an http(s)/data URL. fit = Fit|Fill|Normal. Verify the render in Desktop.
Inputs: page (required), visual (required), imageUrlOrPath (required), reportSessionId (required), +1 more.
set_color_scaleA
Apply a GRADIENT colour scale to a visual property driven by a measure - the signature enterprise feature. e.g. colour a table value's background light->dark by [Total Sales]. objectName/propertyName presets: dataPoint/fill (chart bars/columns), values/backColor (table/matrix cell background), values/fontColor (text colour). Pass a centerColor for a 3-colour (diverging) scale. Data min/max is auto-computed. For DISCRETE colour bands by value range instead, use set_conditional_formatting.
Inputs: measure (required), pageName (required), visualName (required), measureTable (required), +10 more.
set_column_data_categoryA
Set a column's data category so the report layer treats it specially, e.g. Address, City, Continent, Country, County, Latitude, Longitude, Place, PostalCode, StateOrProvince, WebUrl, ImageUrl, BarcodeText. (For format + category in one call use format_column.)
Inputs: table (required), column (required), category (required), sessionId (required).
set_column_data_typeB
Set a column's data type. dataType = String | Int64 | Double | Decimal | DateTime | Boolean | Binary. A refresh is required for the change to take effect on imported data.
Inputs: table (required), column (required), dataType (required), sessionId (required).
set_column_flagsA
Set a column's modelling flags (any subset; omitted flags are left unchanged): isKey (the table's key column), isNullable, isUnique, alignment (Left | Center | Right | Default), encodingHint (Hash | Value | Default - the VertiPaq encoding preference).
Inputs: table (required), column (required), sessionId (required), isKey, +4 more.
set_column_olsA
Object-level security: set whether a role can SEE a column. permission = None (column hidden + inaccessible to the role), Read (visible), or Default (inherit).
Inputs: role (required), table (required), column (required), sessionId (required), +1 more.
set_column_visibilityA
Hide or show a column in the field list. Hidden columns still work in DAX and relationships - use to hide keys/sort columns.
Inputs: table (required), column (required), hidden (required), sessionId (required).
set_conditional_formattingA
Apply DISCRETE rule-based BACKGROUND colour bands to a measure column in a table/matrix: each value in [min, max) renders its band colour. rules = JSON array of {min, max, color} (e.g. positive band #C6EFCE, negative band #e68f96). Writes the standard Power BI rule-based conditional-formatting structure (RuleDefinition rules with a >=min AND <max condition per band), NOT a gradient. For a smooth colour scale instead, use set_color_scale.
Inputs: page (required), rules (required), visual (required), measure (required), +4 more.
set_cross_report_drillthroughA
Enable (or disable) CROSS-REPORT drill-through on a drill-through page so it can be a target from OTHER reports in the workspace. Writes the page pageBinding.referenceScope=CrossReport + flips the report useCrossReportDrillthrough setting. The page should already be set_page_type drillthrough with carried fields. Verify in Desktop.
Inputs: page (required), reportSessionId (required), enable.
set_custom_format_stringA
Set a measure's STATIC custom format string: a 3/4-section pattern positive;negative;zero;"text" with optional [Colour] codes and UNICHAR arrows (distinct from set_dynamic_format_string, the DAX-driven one). e.g. "[Green]▲ #,0;[Red]▼ #,0;0".
Inputs: table (required), measure (required), pattern (required), sessionId (required).
set_data_access_optionsA
Set Model.DataAccessOptions (any subset; omitted unchanged): fastCombine (ignore privacy levels for query folding IN this file - the in-file equivalent of disabling Privacy), legacyRedirects, returnErrorValuesAsNull. Needs compatibility level 1400+.
Inputs: sessionId (required), fastCombine, legacyRedirects, returnErrorValuesAsNull.
set_data_barsA
Add DATA BARS to a measure column in a table/matrix: an in-cell bar whose length tracks the measure, with a positive colour and an optional negative colour. reverseDirection draws bars right-to-left; hideText shows the bar only (no value text); axisColor sets the zero-axis colour; minValue/maxValue pin the bar scale (omit for auto - the default fixes the old min==max bug where bars never rendered). Verify the render in Desktop.
Inputs: page (required), visual (required), measure (required), measureTable (required), +8 more.
set_data_colorA
Set a chart's data colour (the default series fill). For a branded single-measure chart, point this at a theme colour.
Inputs: color (required), pageName (required), visualName (required), reportSessionId (required).
set_data_coverageA
Set a partition's data coverage definition (DataCoverageDefinition) - a DAX boolean telling the engine which data a DirectQuery partition covers, so a hybrid Import+DirectQuery table can answer in-range queries from the cheaper imported partition. Defaults to the table's first partition.
Inputs: table (required), sessionId (required), daxExpression (required), partition.
set_data_labelsA
Show/hide data labels on a chart, with optional display units (None|Thousands|Millions|Billions|Auto) and decimal places.
Inputs: pageName (required), visualName (required), reportSessionId (required), show, +2 more.
set_data_sourceA
Create or update a first-class DataSource object (separate from raw M partitions). kind = Structured (modern Power Query - connectionDetails and credential are each a flat JSON object of key/value pairs, e.g. connectionDetails={"protocol":"tds","server":"srv","database":"db"}) or Provider (legacy - connectionString + provider + impersonation = Default | ImpersonateAccount | ImpersonateAnonymous | ImpersonateCurrentUser | ImpersonateServiceAccount | ImpersonateUnattendedAccount). Replaces a same-named data source in place.
Inputs: kind (required), name (required), sessionId (required), provider, +4 more.
set_detail_rowsA
Define drillthrough detail rows - the DAX table returned when a user drills into a measure value (or the table's default). Set measure for a per-measure definition, or omit it to set the table's default detail rows. daxTableExpression is a DAX table expression, e.g. "SELECTCOLUMNS('Sales', ...)".
Inputs: table (required), measure (required), sessionId (required), daxTableExpression (required).
set_display_folderA
Set the display folder for a measure or a column - groups fields into folders in the field list (e.g. 'Key Measures', 'Time Intelligence'). Use a backslash for nested folders, e.g. 'Sales\\Margins'.
Inputs: table (required), folder (required), target (required), sessionId (required).
set_drilldownA
Set DRILL-DOWN behaviour on a visual with a drillable (hierarchy/multi-level) axis: expandToNextLevel (a click expands to the next level rather than drilling) and drillOnClick (single-click drills). Seeds the saved drill state (expansionStates). Set at least one toggle.
Inputs: page (required), visual (required), reportSessionId (required), drillOnClick, +1 more.
set_drillthrough_fieldsA
Wire the CARRIED FIELDS of a DRILL-THROUGH page: fields = JSON array of {table,field}. Each becomes a drill-through page filter (so right-clicking that field elsewhere drills through to this page filtered to the value). keepAllFilters toggles the 'keep all filters' switch. Replaces any existing drill-through fields. Pair with set_page_type drillthrough / add_drillthrough.
Inputs: page (required), fields (required), reportSessionId (required), keepAllFilters.
set_dynamic_format_stringA
Set a dynamic (DAX-driven) format string on a measure OR a calculation item, so the displayed format changes with context (e.g. currency vs percent, or scaling units). Provide measure for a measure, or calculationItem (with its calculation-group table) for an item.
Inputs: table (required), measure (required), sessionId (required), daxExpression (required), +1 more.
set_extended_propertyA
Set a typed extended property on any model object: type = String | Json. objectType = model | table | column | measure | hierarchy | partition. Pass the object's table for column/measure/hierarchy/partition. Replaces a same-named property. Extended properties are structured metadata (e.g. the ParameterMetadata tag on field-parameter columns).
Inputs: name (required), value (required), sessionId (required), objectName (required), +3 more.
set_field_value_cfA
FORMAT BY FIELD VALUE conditional formatting on a table/matrix column: a measure that returns a hex/CSS colour drives the column's background, font or icon colour DIRECTLY (not a rule/gradient - the measure's returned colour IS the colour). target=background|font|icon. colorMeasure = "Table[Measure]" (or pass colorMeasureTable). column = the column's queryRef e.g. 'Dim_Product.Brand'.
Inputs: page (required), column (required), target (required), visual (required), +3 more.
set_filter_paneA
Show/hide and expand/collapse the FILTER PANE. Omit page to set it report-wide; pass page to override one page. visible=false hides the pane entirely; expanded=false collapses it. Set at least one.
Inputs: reportSessionId (required), page, visible, expanded.
set_filter_restatementA
Set a filter card's RESTATEMENT (custom display label) and/or its lock/hide flags on a matching filter (by table[field]) at a scope=visual|page|report. displayName overrides the card's auto label; isHiddenInViewMode / isLockedInViewMode toggle hide/lock. For scope=visual pass page+visual; scope=page pass page.
Inputs: field (required), scope (required), table (required), reportSessionId (required), +5 more.
set_font_color_rulesA
Apply DISCRETE rule-based FONT-COLOUR bands to a measure column in a table/matrix: each value in [min, max) renders its band text colour. Same rule structure as set_conditional_formatting, applied to the text colour instead of the background. rules = JSON array of {min, max, color}.
Inputs: page (required), rules (required), visual (required), measure (required), +2 more.
set_forecastA
Set a FULL forecast on a line chart (the forecast object: length/units/ignore-last/confidence/seasonality) - more complete than add_analytics_line forecast, which only sets the band. units = Point|Day|Month|Year. confidenceInterval e.g. 0.95. Verify the render in Desktop.
Inputs: page (required), length (required), visual (required), reportSessionId (required), +4 more.
set_global_wildcard_defaultsA
Set the theme's GLOBAL WILDCARD defaults ("":{"":[...]}) - house-style formatting for every card of every visual in one shot. props = JSON { cardName: {prop:value} | [{prop:value}] }, merged into any existing defaults. The card card uses a "$id":"default" quirk - supply such a body verbatim to target it.
Inputs: props (required), reportSessionId (required).
set_gradient_colorA
Set a measure-driven GRADIENT-STOP saturation colour on a card that set_color_scale does not target (treemap/funnel/map dataPoint fill). minColor/maxColor (and optional centerColor for a 3-stop ramp) drive the fill by the measure; min/center/max set explicit stop values. card defaults to dataPoint.
Inputs: page (required), visual (required), measure (required), maxColor (required), +8 more.
set_hierarchy_propertiesA
Set hierarchy-level properties (any subset): displayFolder, hidden (show/hide the hierarchy), hideMembers = Default | HideBlankMembers (hide blank members of the hierarchy).
Inputs: table (required), hierarchy (required), sessionId (required), hidden, +2 more.
set_icon_rulesA
Apply DISCRETE rule-based ICONS to a measure column in a table/matrix: each value in [min, max) maps to an icon. rules = JSON array of {min, max, color}. glyphs = optional comma-separated icon glyph names (one per band, e.g. ArrowDown,ArrowSideways,ArrowUp) - when given, each band uses that glyph instead of being colour-keyed. iconSet picks the glyph family (e.g. ThreeArrowsColored, ThreeFlags, ThreeTrafficLights1). layout = left|right|icon-only (where the icon sits relative to the value). Verify in Desktop.
Inputs: page (required), rules (required), visual (required), measure (required), +5 more.
set_image_sourceA
Re-source an EXISTING image visual: rewrite its sourceFile to a new image (add_image only creates new ones). imageUrlOrPath = a local file (embedded) or an http(s)/data URL. Preserves the visual's current scaling.
Inputs: page (required), visual (required), imageUrlOrPath (required), reportSessionId (required).
set_incremental_refreshA
Attach a basic incremental-refresh policy to a table: keep a rolling window of data and only refresh the most recent increment. Needs RangeStart/RangeEnd M parameters - this creates them if absent (then point the table's M partition at them to bind the date range). Granularity = Day | Month | Quarter | Year.
Inputs: table (required), sessionId (required), incrementalPeriods (required), rollingWindowPeriods (required), +3 more.
set_isavailableinmdxA
Set Column.IsAvailableInMDX. Setting it false on high-cardinality, non-attribute columns saves memory and processing. GUARD: it is kept TRUE on any SortByColumn target (flipping it false breaks the sort with 'invalid column ID'). Pass table+column for one column; pass table alone to set a whole table; or bulkHeuristic=hiddenAndKeys (with no table/column) for a safe model-wide pass over hidden/key columns.
Inputs: value (required), sessionId (required), table, column, +1 more.
set_kpiA
Attach a KPI to a measure: a target to compare against and a status expression (typically returns -1/0/1 for bad/neutral/good) that drives a traffic-light indicator. statusGraphic picks the indicator set (default 'Three Circles Colored').
Inputs: table (required), measure (required), sessionId (required), statusExpression (required), +2 more.
set_legendB
Show/hide a chart legend and set its position (Top|Bottom|Left|Right|TopCenter|... ).
Inputs: pageName (required), visualName (required), reportSessionId (required), show, +1 more.
set_level_propertiesA
Set a hierarchy LEVEL's properties (any subset): ordinal (its order within the hierarchy), description, and/or newName (rename the level). NOTE: hide-blank-members and display folder are hierarchy-wide - set those with set_hierarchy_properties.
Inputs: level (required), table (required), hierarchy (required), sessionId (required), +3 more.
set_lineage_tagA
Set the LineageTag (a stable identity that survives schema sync / git merge across renames) on a model object. objectType = model | table | column | measure | hierarchy | partition | relationship; pass the object's table for column/measure/hierarchy/partition. Needs compatibility level 1540+ (auto-bumped, reported back).
Inputs: tag (required), name (required), sessionId (required), objectType (required), +1 more.
set_list_bufferA
Perf heuristic: wrap a referenced list/table in List.Buffer / Table.Buffer to cache it for repeated reads (complements set_query_buffer). kind = list | table. referenceExpr is the raw M reference to buffer. Appends one step to the table's M query.
Inputs: table (required), sessionId (required), referenceExpr (required), kind, +1 more.
set_map_conditional_formattingA
Set measure-driven conditional FILL on a filledMap/azureMap filled layer (dataPoint fillColor). Pass rules = JSON array of {min,max,color} bands for discrete CF, OR minColor+maxColor (and optional centerColor) for a gradient. target defaults to fill. Verify the render in Desktop.
Inputs: page (required), visual (required), measure (required), measureTable (required), +6 more.
set_measure_propertiesA
Set a measure's metadata that update_measure does not cover: hide/show it (hidden), set its description, and/or rename it (newName). Any omitted property is left unchanged. Use update_measure for the DAX / format string / display folder. A rename with propagate=true (the default) rewrites every [Measure] reference model-wide - other measures, calc columns/tables, RLS filters, calc items, KPI/format-string/detail-rows expressions - atomically, and the report's bindings too when reportSource is given. propagate=false renames the object only.
Inputs: table (required), measure (required), sessionId (required), hidden, +4 more.
set_mobile_positionA
Place one visual on the phone (mobile) layout at x,y,width,height on the 320-wide phone canvas (a second layouts entry). Use for precise mobile control. mobileFormat (optional) is a set_visual_format-shaped JSON { vcObjects/objects } of MOBILE-SPECIFIC formatting overrides (e.g. a smaller title or hidden legend on phone) stamped onto the mobile layout entry.
Inputs: x (required), y (required), width (required), height (required), +4 more.
set_mobile_visibilityA
Show or HIDE a visual on the PHONE (mobile) layout only - its desktop visibility is unchanged. visible=false hides it from the phone view. Seeds a mobile layout entry mirroring the desktop position if none exists.
Inputs: page (required), visual (required), visible (required), reportSessionId (required).
set_model_settingsA
Set model-level settings (any subset; omitted settings unchanged): discourageImplicitMeasures (force explicit measures - a best practice), defaultMode = Import | DirectQuery | Dual | DirectLake | Push | Default, directLakeBehavior = Automatic | DirectLakeOnly | DirectQueryOnly, culture (model locale, e.g. en-US).
Inputs: sessionId (required), culture, defaultMode, directLakeBehavior, +1 more.
set_object_query_groupA
Put a shared expression or a table partition into a query group (display folder). objectType = expression | partition. For a partition, name is the table name (uses its first partition) or 'Table/Partition'. Creates the query group if it does not exist.
Inputs: name (required), sessionId (required), objectType (required), queryGroupFolder (required).
set_page_backgroundC
Set a page's background colour for a clean, professional canvas.
Inputs: color (required), pageName (required), reportSessionId (required), transparency.
set_page_displayA
Set a page's DISPLAY OPTION (how the canvas fits the screen: FitToPage|FitToWidth|ActualSize) and/or its VISIBILITY (AlwaysVisible|HiddenInViewMode - hide the page from viewers). Both optional; set at least one.
Inputs: page (required), reportSessionId (required), visibility, displayOption.
set_page_tab_orderA
Set a page's KEYBOARD TAB ORDER with explicit HIDE: orderedVisuals (comma-separated) get sequential tab order; hidden (comma-separated) get tabOrder -1 (removed from the tab sequence). Visuals in neither list keep their order. Set at least one list.
Inputs: page (required), reportSessionId (required), hidden, orderedVisuals.
set_page_typeA
Set a page's TYPE: standard | tooltip | drillthrough. tooltip sets the small tooltip canvas (320x240) and flags the page as a report-page tooltip; drillthrough flags it as a drill-through target. Pair tooltip with set_visual_tooltip_page. Verify the render in Desktop.
Inputs: page (required), reportSessionId (required), type.
set_page_visibilityA
Hide or show a report page (the tab). A hidden page stays in the file and keeps working, but viewers in the Power BI Service do not see its tab - use it to keep a page out of a published report. hidden=false shows it again.
Inputs: pageName (required), reportSessionId (required), hidden.
set_page_wallpaperA
Set the page WALLPAPER (the grey margin OUTSIDE the canvas), distinct from set_page_background (which colours the canvas area). color = hex, transparency = 0-100. Writes the page outspace object.
Inputs: page (required), reportSessionId (required), color, transparency.
set_partition_mA
Replace a table's Power Query (M) partition expression - e.g. to repoint a table at new source data.
Inputs: m (required), table (required), sessionId (required), partitionName.
set_partition_modeA
Set a partition's storage mode: Import | DirectQuery | Dual | DirectLake. Defaults to the table's first partition. Use Dual + a DirectQuery partition with set_data_coverage to build a hybrid (Import + DirectQuery) table. (Switching to DirectLake/DirectQuery may also need the matching partition source kind; this flips the Mode flag.)
Inputs: mode (required), table (required), sessionId (required), partition.
set_pbir_bookmarkA
Overwrite an existing PBIR bookmark's explorationState in place (keeps its GUID name). hiddenVisuals = JSON array of the visual GUID names to hide on the bookmark's page.
Inputs: name (required), page (required), displayName (required), pbirSessionId (required), +1 more.
set_pbir_visual_formatA
Set ONE formatting property on a PBIR visual, merged into its objects tree via the shared encoder. card = the formatting object (e.g. legend, dataLabels, title, background). bucket = objects (data cards) | visualContainerObjects (chrome). value is a SCALAR (true/false, a number, 'text', '#RRGGBB') encoded by property kind, OR (when valueIsJson=true) a pre-shaped structured PBI JSON value written verbatim (a measure-bound expr {"measure":"T[M]"}, a FillRule, an image, gradient stops).
Inputs: card (required), page (required), value (required), visual (required), +4 more.
set_personalizationA
Turn PERSONALISATION (inline exploration) on/off. scope=report sets the report-level allowInlineExploration setting (viewers can re-jig visuals for themselves). scope=page sets the per-page personalizeVisual toggle (perVisualPersonalize).
Inputs: reportSessionId (required), page, scope, perVisualPersonalize, +1 more.
set_play_axisA
Bind a field to a scatter chart's PLAY AXIS (a data binding: the Play projection role). field = "Table.Column". Animates the scatter over the field's values. Verify the render in Desktop.
Inputs: page (required), field (required), visual (required), reportSessionId (required).
set_plot_area_imageA
Set a chart's PLOT-AREA background image (the plotArea image object). imageUrlOrPath = a local file (embedded into the report) or an http(s)/data URL. scaling = Fit|Fill|Normal. transparency 0-100 optional. Verify the render in Desktop.
Inputs: page (required), visual (required), imageUrlOrPath (required), reportSessionId (required), +2 more.
set_qna_phrasingA
Author an LSDL Q&A phrasing into the model's linguistic metadata - the way to teach Q&A a concept like 'happy customers'. phrasingType = Verb | Adjective | Noun | PreModifier | Preposition | Attribute | Name | DynamicNoun. phrasingJson is the LSDL phrasing definition as a JSON object. FLAG: the linguistic phrasing schema is large and is stored verbatim, not validated.
Inputs: sessionId (required), phrasingJson (required), phrasingName (required), phrasingType (required), +1 more.
set_query_bufferA
Power Query folding hint: wrap the table in Table.Buffer so it loads once into memory (stops re-evaluation and downstream folding). Appends Table.Buffer to the table's M query.
Inputs: table (required), sessionId (required), partitionName.
set_refresh_scheduleA
Set a published dataset's scheduled-refresh plan (PATCH .../refreshSchedule): enable/disable, the days, the local times and the time zone. Needs an AAD access token with the Power BI scopes (accessToken param or DAXOPS_PBI_TOKEN); never echoed.
Inputs: enabled (required), datasetId (required), workspaceId (required), days, +3 more.
set_report_settingsA
Set REPORT-LEVEL behaviour toggles (ExplorationSettings). settings = a JSON object of toggle->value. Booleans: useStylableVisualContainerHeader, hideVisualContainerHeader, defaultFilterActionIsDataFilter (filter vs highlight on click), defaultDrillFilterOtherVisuals, useCrossReportDrillthrough, allowChangeFilterTypes, allowInlineExploration (personalise visuals), useEnhancedTooltips, useScaledTooltips. Enums: exportDataMode (AllowSummarized|AllowSummarizedAndUnderlying|None), pagesPosition (PagesPane|Bottom). Merges - untouched toggles are kept.
Inputs: settings (required), reportSessionId (required).
set_rlsA
Set or update the row-level security (RLS) filter for a role on a table. The DAX boolean expression keeps only the rows it returns true for, e.g. "[Region] = USERPRINCIPALNAME()" or "'Sales'[Country] = "NZ"". Creates the table permission if absent.
Inputs: role (required), table (required), sessionId (required), daxFilterExpression (required).
set_role_permissionB
Change a role's model-wide permission: Read | ReadRefresh | Refresh | Administrator | None.
Inputs: role (required), sessionId (required), modelPermission (required).
set_selection_expression_behaviorA
Set the model-wide selection-expression behavior controlling which clients honour calc-group selection expressions: automatic | nonvisual | visual. Needs compatibility level 1605+ (auto-bumped, reported back). FLAG: stamped as a PBI_SelectionExpressionBehavior model annotation - the strongly-typed property is absent from this build.
Inputs: behavior (required), sessionId (required).
set_shapemap_custom_mapA
Set a custom TopoJSON/GeoJSON map on a shapeMap (the custom-map upload). topojsonOrGeojson = a local .json file (embedded), an http(s) URL, or an inline JSON string. Verify the render in Desktop.
Inputs: page (required), visual (required), reportSessionId (required), topojsonOrGeojson (required).
set_show_items_no_dataA
Toggle 'Show items with no data' for one field in a visual: categories with no rows still appear (e.g. all months even with zero sales). The field must already be projected on the visual. Writes the projection's showAll flag.
Inputs: page (required), field (required), table (required), visual (required), +2 more.
set_slicer_conditional_formattingA
Apply measure-driven conditional formatting to a SLICER or button-slicer (generalises the table/matrix FillRule builders). target = fill|font|callout. rules = JSON array of {min,max,color} bands driven by the measure. Verify the render in Desktop.
Inputs: page (required), rules (required), target (required), visual (required), +3 more.
set_slicer_selectionA
TARGETED offline slicer fix: open a CLOSED .pbix, make a slicer SINGLE-SELECT (and optionally pre-select a default value), then write the .pbix back (DataModel preserved). Single-select writes the ground-truth objects.selection[0].properties.strictSingleSelect = true - Power BI's 'Single select', which forces exactly one item AND auto-picks the first available option when none is selected. THIS is the fix for a field-parameter axis that flat-lines: a field-parameter-bound chart only renders when its slicer is filtered to ONE option. Locate the slicer by its title (e.g. 'Chart Period'), config name, or its bound field (e.g. 'Brand Chart Axis'). default_value (optional) is written as a Categorical selection filter in the slicer's container so it opens on that specific value. The .pbix must NOT be open in Power BI Desktop.
Inputs: page (required), pbix (required), slicer (required), default_value, +1 more.
set_source_lineage_tagA
Set the SourceLineageTag (the SOURCE-side name a Direct Lake / composite model re-binds to after a schema refresh) on a model object. objectType = model | table | column | measure | hierarchy | partition | relationship; pass the object's table where needed. value = the source object's name. Needs compatibility level 1550+ (auto-bumped, reported back).
Inputs: name (required), value (required), sessionId (required), objectType (required), +1 more.
set_stop_foldingB
Power Query folding hint: append Table.StopFolding to prevent the M engine folding any further operations into the data source's native query. Appends Table.StopFolding to the table's M query.
Inputs: table (required), sessionId (required), partitionName.
set_summarize_byA
Set a column's default summarization (the implicit aggregation used when the column is dropped on a visual). summarizeBy = Default | None | Sum | Min | Max | Count | Average | DistinctCount. Set None on key/ID columns so they are not silently summed.
Inputs: table (required), column (required), sessionId (required), summarizeBy (required).
set_synonymsA
Add Q&A natural-language synonyms for a model object (so 'revenue'/'turnover' map to a 'Sales' measure). objectType = table | column | measure | hierarchy; pass the object's table for column/measure/hierarchy. synonyms is a comma-separated list. culture defaults to the model culture. NOTE: the Q&A linguistic schema is large and complex - this authors a flat per-entity synonyms list and merges into any existing schema; richer phrasings/relationships need a hand-authored schema.
Inputs: synonyms (required), sessionId (required), objectName (required), objectType (required), +2 more.
set_synonym_stateA
Author Q&A synonyms with an explicit State (Authored to make terms stick, Deleted to suppress an auto-generated term, Generated, Suggested) and optional Weight 0..1. objectType = table | column | measure | hierarchy; pass the object's table where needed. Extends set_synonyms (which only adds bare terms). NOTE: the Q&A linguistic schema is large; only flat per-entity terms with State/Weight are authored.
Inputs: name (required), synonyms (required), sessionId (required), objectType (required), +4 more.
set_table_detail_rowsA
Set a TABLE's default detail rows (Table.DefaultDetailRowsDefinition) - the DAX table returned when a user drills into a value of this table that has no per-measure detail rows. Distinct from the measure-level set_detail_rows. daxTableExpression is a DAX table expression.
Inputs: table (required), sessionId (required), daxTableExpression (required).
set_table_olsA
Object-level security: set whether a role can SEE a whole table. permission = None (table hidden + inaccessible to the role), Read (visible), or Default (inherit). Creates the table permission if absent.
Inputs: role (required), table (required), sessionId (required), permission (required).
set_table_privateA
Set Table.IsPrivate - a private table is hidden from ALL clients (stronger than hide), the right setting for internal helper / staging tables.
Inputs: table (required), isPrivate (required), sessionId (required).
set_table_visibilityA
Hide or show a whole table in the field list (e.g. hide a bridge/parameter table).
Inputs: table (required), hidden (required), sessionId (required).
set_tab_orderA
Set the KEYBOARD TAB ORDER of a page's visuals: visualOrder = comma-separated visual names in the order a keyboard user tabs through them. Writes each visual's layouts[0].position.tabOrder. Visuals not listed keep their order.
Inputs: page (required), visualOrder (required), reportSessionId (required).
set_template_columnA
Patch properties of an existing column in a closed .pbit template's model - data type, format string, hidden flag, sort-by column and default summarisation - editing the DataModelSchema JSON on disk with no Power BI Desktop. Any omitted property is left unchanged. Fails if the column does not exist. Written back in place (with a .bak guard).
Inputs: table (required), column (required), pbitPath (required), dataType, +4 more.
set_textbox_contentA
Set RICH multi-run text on a textbox (add_textbox is single-run). runs = JSON array of {text, fontFamily?, fontSize?, color?, bold?, italic?, url?} - each becomes a styled run on one paragraph; url makes a run a hyperlink. bulleted=true renders the paragraph as a bullet. Replaces the textbox's current content.
Inputs: page (required), runs (required), visual (required), reportSessionId (required), +1 more.
set_theme_cf_colorsA
Set the report theme's CONDITIONAL-FORMATTING gradient stops: min / center / max / null. Each is a hex colour; supply at least one. Run generate_theme first.
Inputs: reportSessionId (required), max, min, nul, +1 more.
set_theme_data_colorsA
Set the report theme's DATA COLOURS (the categorical palette). colors = comma-separated hex. Run generate_theme / apply_report_theme first.
Inputs: colors (required), reportSessionId (required).
set_theme_sentiment_colorsA
Set the report theme's SENTIMENT colours: good / neutral / bad (the KPI sentiment ramp). Each is a hex colour; supply at least one. Run generate_theme first.
Inputs: reportSessionId (required), bad, good, neutral.
set_theme_structural_colorsA
Set the report theme's STRUCTURAL colours. colors = JSON object with any of: firstLevelElements, secondLevelElements, thirdLevelElements, fourthLevelElements, background, secondaryBackground, tableAccent (foreground is an alias of firstLevelElements). Each value is a hex colour; only supplied keys change. Run generate_theme first.
Inputs: colors (required), reportSessionId (required).
set_theme_text_classA
Set/merge one theme TEXT CLASS: class = callout|title|header|label or a secondary class (largeTitle|semiboldLabel|largeLabel|smallLabel|lightLabel|boldLabel|largeLightLabel|smallLightLabel). Any subset of fontFace / fontSize / color. Merges - untouched props are kept. Run generate_theme first.
Inputs: textClass (required), reportSessionId (required), color, fontFace, +1 more.
set_tooltip_field_bindingA
Bind a TOOLTIP PAGE to specific fields so it only shows when hovering those fields. fields = JSON array of {table,field}. Writes the tooltip page's pageBinding {type=Tooltip, parameters}. The page should already be set_page_type tooltip. Verify in Desktop.
Inputs: fields (required), tooltipPage (required), reportSessionId (required).
set_totalsB
Show/hide totals on a table and subtotals on a matrix.
Inputs: pageName (required), visualName (required), reportSessionId (required), show.
set_translationA
Set a translated Caption, Description or DisplayFolder for a model object in a culture. objectType = table | column | measure | hierarchy | model. For a column/measure/hierarchy, also pass its table. Run add_culture first.
Inputs: value (required), culture (required), property (required), sessionId (required), +3 more.
set_visual_backgroundA
Set a visual's BACKGROUND (typed convenience over set_visual_format). show/color/transparency all optional. transparency 0 = opaque, 100 = fully transparent (an OVERLAY background, which clear_visual_styling preserves).
Inputs: page (required), visual (required), reportSessionId (required), show, +2 more.
set_visual_borderA
Set a visual's BORDER (typed convenience over set_visual_format). show/color/radius all optional.
Inputs: page (required), visual (required), reportSessionId (required), show, +2 more.
set_visual_display_modeA
Set a visual's DISPLAY STATE on the page: normal (default), hidden, spotlight (dim everything else), maximize, or focus. Writes singleVisual.display.mode. Note: spotlight/focus are live states that may need a bookmark to persist in Desktop; normal removes the override.
Inputs: mode (required), page (required), visual (required), reportSessionId (required).
set_visual_fieldsA
Replace the field bindings of an EXISTING visual - change which columns/measures a table/matrix/chart shows WITHOUT deleting it (preserves position, formatting, conditional formatting). bindings = JSON array of {role,table,field,kind}. Roles: tableEx/card=Values; matrix/pivotTable=Rows/Columns/Values; charts=Category/Y/Y2/Series/X/Size. Clears the sort - re-apply with set_visual_sort.
Inputs: bindings (required), pageName (required), visualName (required), reportSessionId (required).
set_visual_formatA
Set ANY formatting on a visual (TOTAL customizability) - the universal styling engine. formatJson e.g. { "vcObjects": { "title": {"show":true,"text":"My Title"}, "background": {"show":true,"color":"#FFFFFF","transparency":100} }, "objects": { "legend": {"show":false} } }. Each property is encoded by kind (show->bool, text->text, transparency/fontSize->number, color/fontColor->colour, alignment/position->enum; otherwise inferred: boolean->bool, number->number, #RRGGBB->colour, else text) and MERGED in - untouched objects/properties and any selector are preserved. Returns the objects/properties changed.
Inputs: page (required), visual (required), formatJson (required), reportSessionId (required), +1 more.
set_visual_format_selectorA
Set a SELECTOR-SCOPED formatting entry on a visual so a card targets a data scope: a single series, a category, the grand total/subtotal, or a wildcard/conditional scope. Unlocks per-series colours, per-category formatting and total/subtotal formatting. bucket=objects|vcObjects. properties = JSON {prop:value} (encoded like set_visual_format). selector = JSON: {"data":[{"scopeId":...},{"roles":["Series"]},{"dataViewWildcard":{"matchingOption":0}}]} | {"metadata":"Table.Field"} | {"total":true}. Updates the matching selector entry in place without clobbering the default card.
Inputs: page (required), bucket (required), object (required), visual (required), +4 more.
set_visual_interactionsA
Set how a SOURCE visual affects a TARGET visual when a data point is selected (edit interactions). interaction = filter | highlight | none. sourceVisual/targetVisual are visual names (from list_visuals). Writes a { source, target, type } override in the page config (type: 1=filter, 2=highlight, 3=none). Verify the render in Desktop.
Inputs: page (required), interaction (required), sourceVisual (required), targetVisual (required), +1 more.
set_visual_positionA
Set a visual's POSITION/size. Updates BOTH the visualContainer x/y/width/height AND the config layouts[0].position so the move sticks. All of x/y/width/height optional.
Inputs: page (required), visual (required), reportSessionId (required), x, +3 more.
set_visual_propertyA
Set ANY visual formatting property (the universal escape hatch). objectName/propertyName are Power BI formatting ids e.g. labels/show, legend/position, categoryAxis/showAxisTitle, valueAxis/start, dataPoint/fill. kind = text|number|bool|color|raw. target = objects (data formatting) or vcObjects (container: title, background, border).
Inputs: value (required), pageName (required), objectName (required), visualName (required), +4 more.
set_visual_sortA
Set the SORT ORDER of an EXISTING visual (table/matrix/chart): order its query by a field, asc or desc. kind=column|measure. Use descending=true to sort a ranking by sales/value so the top performers lead and blank-rank/zero rows fall to the bottom (the fix for 'blanks at the top'). The field should be one already shown in the visual.
Inputs: field (required), table (required), pageName (required), visualName (required), +3 more.
set_visual_titleA
Set a visual's TITLE (typed convenience over set_visual_format). All params after page/visual are optional - set only what you want. Preserve a custom title by passing show=false on an overlay, or set custom text. Use this to restore a title clear_visual_styling must never destroy.
Inputs: page (required), visual (required), reportSessionId (required), show, +4 more.
set_visual_tooltip_pageA
Point a visual's hover TOOLTIP at a report-page tooltip (instead of the default data tooltip). Writes the visualTooltip {type='ReportPage', section=} on the visual. The tooltip page should already be flagged with set_page_type tooltip. Verify the render in Desktop.
Inputs: page (required), visual (required), tooltipPage (required), reportSessionId (required).
set_visual_visibilityA
Show or hide a visual in the base layout (display.mode). Use list_visuals to get names.
Inputs: hidden (required), pageName (required), visualName (required), reportSessionId (required).
set_visual_z_orderA
Set a visual's z (stack) order explicitly. Updates BOTH the container z and the config layouts position so the order sticks. Higher z renders on top.
Inputs: z (required), page (required), visual (required), reportSessionId (required).
set_web_url_cfA
WEB URL conditional formatting on a table/matrix column: a measure that returns a URL string makes the cell a clickable link. urlMeasure = "Table[Measure]" (or pass urlMeasureTable). column = the column's queryRef.
Inputs: page (required), column (required), visual (required), urlMeasure (required), +2 more.
skip_rowsA
Power Query Remove Top Rows: drop the first N rows. Appends Table.Skip to the table's M query.
Inputs: count (required), table (required), sessionId (required), partitionName.
sort_column_byA
Sort a column by another column (e.g. Month by MonthSort) so visuals order chronologically/logically instead of alphabetically.
Inputs: table (required), column (required), sessionId (required), sortByColumn (required).
sort_rowsA
Power Query Sort Rows: sort by one or more columns. Appends Table.Sort to the table's M query. sorts is comma-separated as column[:direction], e.g. "Region:Ascending,Sales:Descending". direction = Ascending | Descending (default Ascending).
Inputs: sorts (required), table (required), sessionId (required), partitionName.
split_columnA
Power Query Split Column: split a text column into N new columns. Appends Table.SplitColumn (+ the matching Splitter.*) to the table's M query, emitting parts output columns named .1 .. .N. by = delimiter (arg is the delimiter, e.g. ","), positions (arg is comma-separated zero-based positions, e.g. "0,5"), or lengths (arg is comma-separated repeated lengths, e.g. "3,3"). parts is the number of output columns (default 2).
Inputs: by (required), arg (required), table (required), column (required), +3 more.
split_column_to_rowsA
Power Query Split Column into Rows: split a text column on a delimiter so each part becomes its own row. Appends Table.SplitColumn (into a list) + Table.ExpandListColumn to the table's M query.
Inputs: table (required), column (required), delimiter (required), sessionId (required), +1 more.
stage_excel_to_csvA
Stream a large Excel worksheet to a CSV on disk (memory-bounded - does NOT load the workbook into RAM). ALWAYS use this for big Excel files (tens of MB / 100k+ rows) and then load the CSV with Csv.Document(), because Power Query's Excel.Workbook() parses the whole workbook into memory and crashes the mashup engine. Returns row/column counts and the output path.
Inputs: xlsxPath (required), sheetName, outCsvPath.
stamp_vertipaq_statsA
Read the storage DMVs and write each column's VertiPaq stats as Vertipaq_* annotations (Vertipaq_TotalSize / Vertipaq_DictionarySize / Vertipaq_Cardinality - the semantic-link-labs scheme) so the numbers persist in the model definition for offline review. Read of the live engine; writes annotations.
Inputs: sessionId (required).
start_dax_traceA
Start an Analysis Services server trace on the session's engine capturing QueryEnd, VertiPaq SE QueryEnd, VertiPaq SE CacheMatch and DAXEvaluationLog events (DAXEvaluationLog is dropped automatically on engines that reject it). Run the queries to profile, then stop_dax_trace to collect. One trace per session.
Inputs: sessionId (required).
stop_dax_traceA
Stop the session's DAX trace and return the structured events plus the Server Timings arithmetic: total query ms, storage-engine ms (sum of subclass-0 VertiPaq scans), formula-engine ms (query minus SE, floored at 0 because SE threads run in parallel), SE query count and cache matches.
Inputs: sessionId (required).
strip_evaluateandlogA
Remove EVALUATEANDLOG wrappers. Pass table+measure for one measure, or omit both to strip every measure in the model (clean-up after debugging).
Inputs: sessionId (required), table, measure.
style_pageA
One-shot 'make it beautiful' pass: apply a consistent card style (fill, rounded corners, shadow, header) to every DATA visual on a page (skips textboxes/shapes). Pair with set_page_background for a clean canvas.
Inputs: pageName (required), reportSessionId (required), shadow, background, +3 more.
style_visualA
Give one visual the modern 'floating card' look: background fill, rounded corners, drop shadow, and hide the header. e.g. background=#FFFFFF, cornerRadius=8, shadow=true, showHeader=false, borderColor=#E6E9EF.
Inputs: pageName (required), visualName (required), reportSessionId (required), shadow, +4 more.
sync_slicerA
Add a slicer to a SYNC GROUP so its field stays in sync across pages (slicers sharing a groupName sync). groupName defaults to the slicer's bound field. fieldChanges/filterChanges control what syncs (both default true). The slicer must also be PLACED on each page (use clone_visual) for it to appear there - this wires the sync, not the placement.
Inputs: page (required), slicerVisual (required), reportSessionId (required), groupName, +2 more.
tidy_slicer_layoutA
ONE-CALL conservative slicer cleanup for a CLOSED .pbix. Give ONLY the .pbix path (tidies EVERY page) or the .pbix + a page name (tidies that page). It (1) DE-OVERLAPS: any slicer whose bounding box overlaps another slicer is nudged by the SMALLEST clean move that clears the collision - kept near its original spot, on-canvas, aligned to its neighbours, no new overlap; and (2) SNAP-ALIGNS: a slicer whose left or top edge sits a few px off a shared edge is snapped onto it. CONSERVATIVE by design for client reports: only SLICERS ever move, sizes are NEVER changed, and any nudge/snap that would create fresh overlap is rejected. Slicer-over-NON-slicer overlaps (e.g. a State slicer deliberately layered over a wide date-label card) are FLAGGED, not moved, unless deOverlapNonSlicers=true. Writes the .pbix back offline (Report/Layout patched, DataModel byte-preserved). The .pbix must NOT be open in Power BI Desktop. Returns { ok, pagesScanned, pagesTidied, moveCount, moves:[{page,slicer,reason,before{x,y,w,h},after{x,y,w,h}}], flaggedCount, flagged, persistedToDisk }.
Inputs: pbix (required), page, deOverlapNonSlicers.
tidy_slicer_layout_v2A
Row-aware slicer tidy (v2): cluster a page's slicers into ROWS, top-align each row onto one shared baseline y (the row median), pull off-canvas slicers back onto the canvas, and re-pack each row with EVEN-GAP spacing (one uniform gap = the median of the row's existing gaps, squeezed only as needed to stay on-canvas), which also clears within-row overlaps. Positions only (sizes NEVER change), slicers only (non-slicer visuals never move); a row wider than the canvas even packed flush is FLAGGED, not forced. Writes the .pbix back offline (Report/Layout patched, DataModel byte-preserved). The .pbix must NOT be open in Power BI Desktop. Returns { ok, rows:[{page,row,y,members,aligned}], moveCount, moves:[{page,slicer,row,reason,before,after}], flaggedCount, flagged, persistedToDisk }.
Inputs: pbix (required), page.
transform_all_column_namesA
Bulk-transform every column NAME with Table.TransformColumnNames (schema-agnostic). transform = snakeToSpace | toUpper | toLower | trim | prefix (needs arg) | camelSplit (insert a space before each interior capital). Appends one step to the table's M query.
Inputs: table (required), sessionId (required), transform (required), arg, +1 more.
transform_columnA
Power Query single-column transform: apply a scalar function to a column in place. Appends Table.TransformColumns to the table's M query. operation = (text) upper, lower, trim, clean, proper, length; (number) round, abs, floor, ceiling, sign, sqrt; (date) year, month, day, quarter, weekofyear, dayofweek, startofmonth, endofmonth, startofyear, endofyear, monthname, dayname.
Inputs: table (required), column (required), operation (required), sessionId (required), +1 more.
transposeA
Power Query Transpose: flip rows into columns and columns into rows. Appends Table.Transpose to the table's M query.
Inputs: table (required), sessionId (required), partitionName.
ungroup_visualsA
UNGROUP a group: clears parentGroupName from every child and removes the group container. groupName = the group name returned by group_visuals.
Inputs: page (required), groupName (required), reportSessionId (required).
unpack_to_sourceA
Unpack a .pbix into a deterministic, text-only, git-committable source tree: Model/definition (TMDL from the live session model) + Report/ (legacy Layout canonicalised to Layout.json, or the full PBIR definition tree). Same inputs always produce byte-identical output, so the tree diffs cleanly under git. Refuses to overwrite a folder that is not empty or a previous unpack.
Inputs: pbixPath (required), sessionId (required), outputFolder (required).
unpivot_columnsB
Power Query Unpivot Columns: turn the listed columns into Attribute/Value row pairs. Appends Table.Unpivot to the table's M query. columns is comma-separated.
Inputs: table (required), columns (required), sessionId (required), partitionName.
unpivot_keep_nullsA
Unpivot keeping NULL rows: replace nulls with a sentinel, UnpivotOtherColumns, then restore the sentinel to null - because plain unpivot silently DROPS null-valued rows. keepColumns (the columns NOT unpivoted) is comma-separated. Appends three steps to the table's M query.
Inputs: table (required), sessionId (required), keepColumns (required), partitionName.
unpivot_other_columnsA
Power Query Unpivot Other Columns: keep the listed columns and unpivot every OTHER column into Attribute/Value pairs (robust to new columns appearing). Appends Table.UnpivotOtherColumns to the table's M query. keepColumns is comma-separated.
Inputs: table (required), sessionId (required), keepColumns (required), partitionName.
unpivot_weekly_csvA
Stream-unpivot a WIDE CSV (one column per week, e.g. '23/06/2024_SALES','23/06/2024_VOLUME') into a TALL CSV (keys + WeekKey + one column per measure), one row at a time. USE THIS when a CSV has hundreds of period columns and Power Query's Table.UnpivotOtherColumns runs the mashup OUT OF MEMORY on big files - the tall CSV then loads with Csv.Document() and no transform. Optional 2-pass scope filter keeps only rows whose scopeColumn value appears for filterColumn=filterValue (e.g. 'the categories the supplier sells in'). Empty weeks are skipped.
Inputs: inCsv (required), measures (required), keyColumns (required), outCsv, +3 more.
update_bookmarkA
Re-set which visuals a bookmark hides: listed visuals become hidden, all other recorded visuals become shown. hiddenVisuals = comma-separated visual ids.
Inputs: name (required), reportSessionId (required), captureData, hiddenVisuals.
update_calculation_itemA
Update an existing calculation item on a calculation group: DAX expression, ordinal, dynamic format string (empty string clears it) and/or rename it. Omitted properties are left unchanged.
Inputs: name (required), table (required), sessionId (required), newName, +3 more.
update_calendarA
Update a table's calendar definition: change the primary date column and/or replace the associated period-column group (columns are validated against the table). FLAG: stamped as the PBI_Calendar table annotation (the Wave R convention) because the native calendar TOM objects are absent from this build.
Inputs: table (required), sessionId (required), primaryColumn, associatedColumns.
update_kpiA
Extend a measure's KPI beyond set_kpi: set the trend expression, a target format string, and the status/trend/target descriptions. Creates the KPI if the measure has none. Any omitted property is left unchanged.
Inputs: table (required), measure (required), sessionId (required), trendExpression, +4 more.
update_measureC
Update an existing measure's DAX, format string or display folder.
Inputs: name (required), table (required), sessionId (required), dax, +2 more.
update_power_queryA
Replace the ENTIRE Section1.m (the full 'section Section1; shared Query = ...;' document) inside a .pbix's DataMashup, clearing PermissionBindings (Desktop recomputes the SHA-256 on open). RISKY - work on a COPY; the .pbix must be CLOSED in Desktop; refuses protected client paths.
Inputs: newM (required), pbixPath (required).
update_relationshipA
Update an existing relationship's cardinality, filtering behaviour, active flag or join-on-date behaviour. Identify it by name, or by all four of fromTable/fromColumn/toTable/toColumn (order-insensitive). fromCardinality/toCardinality = One | Many (to switch 1:1 / M:1 / 1:M / M:M). crossFilteringBehavior = OneDirection | BothDirections | Automatic. securityFilteringBehavior = OneDirection | BothDirections | None. joinOnDateBehavior = DateAndTime | DatePartOnly. Any omitted property is left unchanged.
Inputs: sessionId (required), name, toTable, isActive, +8 more.
update_template_measureA
Update an existing measure's DAX expression, format string and/or display folder in a closed .pbit template's model, editing the DataModelSchema JSON on disk with no Power BI Desktop. Any omitted field is left unchanged. Fails if the measure does not exist. Written back in place (with a .bak guard).
Inputs: name (required), table (required), pbitPath (required), expression, +2 more.
update_visual_propertyA
GENERAL offline report-visual editor: open a CLOSED .pbix, set ANY property at a JSON path UNDER a visual's singleVisual config, then write the .pbix back (DataModel preserved). Locate the visual by its config name, displayName, its visible TITLE (e.g. 'Chart Period'), or a bound field (Table.Field / table / field). property_path navigates under singleVisual and creates missing objects/arrays, e.g. 'objects.selection[0].properties.strictSingleSelect', 'drillFilterOtherVisuals', 'display.mode'. valueKind: auto (default = JSON if it parses, else string) | raw | json | string | literal | bool | number | color | text - literal/bool/number/color/text wrap the value as a Power BI formatting literal expr so a formatting-card property can be set by path. Returns the before/after value at that path. The .pbix must NOT be open in Power BI Desktop.
Inputs: page (required), pbix (required), value (required), propertyPath (required), +2 more.
validate_daxA
Validate a DAX expression against the live model without changing anything (runs EVALUATE ROW).
Inputs: dax (required), sessionId (required).
validate_visual_formatA
Validate a formatJson against the registry for a given visualType WITHOUT applying it. formatJson is the set_visual_format shape ({vcObjects:{card:{prop:val}}, objects:{card:{prop:val}}}) or a bare {card:{prop:val}} map. Returns non-fatal warnings: unknown cards, unknown properties, and type/enum/range mismatches. Custom visuals and newer properties legitimately fall outside the catalogue, so warnings are advisory, not errors.
Inputs: formatJson (required), visualType (required).
validate_wireframeA
READ-ONLY layout lint over visual positions + page size (no fixes applied): visual OVERLAP pairs, OFF-CANVAS placement (negative or beyond the page bounds), tiny/zero-size visuals, z-order anomalies (a data visual rendering ABOVE an overlapping slicer), plus margin/gap statistics per page. Every violation names the existing fixer tool (auto_arrange / align_visuals / tidy_slicer_layout_v2 / move_visual / resize_visual / set_visual_z_order). Accepts a LEGACY reportSessionId (from open_report) OR a PBIR pbirSessionId (from read_pbir) - the same shared geometry checker runs over both readers.
Inputs: reportSessionId (required), pageName.
value_nativequery_foldingA
Run a native query against a source and KEEP downstream folding alive: Value.NativeQuery(sourceExpr, nativeQuery, params, [EnableFolding=true]). sourceExpr is raw M (e.g. a Sql.Database(...) reference). paramsExpr is an optional raw M parameter record/list. Appends one step to the table's M query.
Inputs: table (required), sessionId (required), sourceExpr (required), nativeQuery (required), +2 more.
warm_directlake_cacheA
Warm the Direct Lake cache: run EVALUATE TOPN(1, SELECTCOLUMNS(...)) over the listed columns (or every column on the table) to force them resident, removing the first-query latency. columns is comma-separated (omit for all). Returns the query and result.
Inputs: table (required), sessionId (required), columns.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 490 tools
With 490 tools, many have overlapping boundaries. For example, set_visual_format and set_visual_property both set formatting on a visual, and there are numerous add_*_filter tools at different scopes that could be confused. While descriptions are detailed, the sheer volume makes misselection likely.
Tool names mostly follow a verb_noun snake_case pattern (add_measure, delete_visual, set_axis). Deviations exist such as model_health, dax_lint, impact_analysis, and sentinel_diff, which start with nouns, but the pattern is still coherent and readable.
At 490 tools, this is an extreme mismatch for any server. Even for a comprehensive Power BI automation toolkit, this far exceeds the typical well-scoped count and will overwhelm agents attempting to select the right tool.
The tool surface is remarkably complete, covering model editing, report design, Power Query transformations, PBIR handling, security, service operations, and more. It includes create/read/update/delete operations across virtually every domain, with few if any obvious gaps for the stated purpose.
Maintenance
Related MCP Connectors
Convert, create and edit Word, PowerPoint, Excel and PDF documents from any AI agent.
PDF and image tools for AI agents: compress, merge, split, OCR, sign. Runs locally, never uploads.
Productivity toolbox for Personal Agents: create PPTs, covers, websites, music and process files.
File tools for your AI chat: PDF tables to Excel, merge PDFs, images to PDF, fill PDF forms.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables LLM clients to analyze and interact with Power BI (.pbix) files, providing access to data models, DAX measures, Power Query code, table relationships, and data contents through natural language.MIT
- FlicenseNot gradedqualityDmaintenanceEnables AI agents to deploy Power BI reports to Microsoft Fabric by automating data loading from CSV, creating semantic models, and generating report visuals.1-
- FlicenseNot gradedqualityBmaintenanceEnables AI assistants to read and modify Power BI Desktop files programmatically, including querying models, creating measures, and managing relationships through natural language.255-
- AlicenseAqualityBmaintenanceEnables local Power BI project (.pbip) automation, including model (TMDL) and report (PBIR) layer manipulation, without cloud dependencies. Provides 56 tools for building, editing, and validating reports and measures through natural language prompts.13MIT