powerbi-mcp-local
This server connects MCP clients (LLMs) to a local Power BI Desktop engine to automate semantic model work, DAX, Power Query, Excel, and report layout tasks.
Model discovery & navigation: list tables, columns, measures, relationships, roles, calculation groups, instances, and full model snapshots
Model mutation: create/update/delete tables, columns, measures, relationships, roles, and RLS filters; rename objects; set formats and data types
DAX execution & validation: run DAX/DMV queries, execute as a role, trace timing, validate expressions, lint DAX, detect circular dependencies and name collisions
Measure automation: batch-create measures, generate time intelligence, variance, contribution, Top-N, and rolling average measures
Power Query / M: read, write, create import queries (Excel/CSV/folder), parameterize or relocate data sources, validate M step patterns
Excel integration: create/work with workbooks, sheets, cells, ranges, search, formatting, auto-width, and pre-import checks
Report layout automation: extract/compile PBIX, add 28 chart/visual types via a unified tool, edit bindings, lint layouts, compare report versions
Quality & validation workflows: audit model, score dashboards/rubrics, detect empty/missing visuals, generate validation and correction reports
PBIP/TMDL support: list/read/write/patch TMDL project files
Persistence & repair checks: validate PBIX persistence and reopened-file health, plus system health, operation history, and connection management
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., "@powerbi-mcp-local add a measure for total revenue"
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.

powerbi-mcp-local
MCP server for local Power BI Desktop automation
It exposes tools for semantic model changes, DAX, Power Query, Excel, and report layouts to MCP clients.
Quick Links
Start | Setup | Tools | Security |
Related MCP server: Power BI Report MCP Server
What It Does
Connects AI tools to a running local Power BI Desktop engine.
Automates tables, columns, measures, relationships, DAX, refreshes, and Power Query.
Reads/writes Excel files for local BI workflows.
Extracts, patches, validates, and compiles report layouts through
pbi-tools.
No Power BI Pro license is required for the local Desktop workflow.
Architecture
MCP Client --(stdio or sse)--> src/server.py
|
+-- src/mcp_core.py FastMCP instance, _run, lifecycle
+-- src/wrappers/ 14 thin wrappers/<domain>.py
+-- src/tools/ business logic (the *_tool fns)
+-- TOM/.NET ─────────> Power BI Desktop local SSAS
+-- ADOMD ────────────> DAX query execution
+-- openpyxl ─────────> Excel read/write/format
+-- pbi-tools ────────> report extract/compile + visuals
+-- src/security.py path, DAX, payload safeguardsFull module layering and the visuals/ submodule fan-out: see ARCHITECTURE.md.
Requirements
Requirement | Install |
Windows | Power BI Desktop local engine is Windows-only |
Power BI Desktop |
|
Python 3.11+ |
|
.NET 6+ Runtime |
|
pbi-tools |
|
ADOMD.NET ships with Power BI Desktop. If pbi-tools is not on PATH, set PBI_TOOLS_PATH.
Quick Start
git clone https://github.com/inerthel-agi/powerbi-mcp-local.git
cd powerbi-mcp-local
pip install -r requirements.txtOpen Power BI Desktop with a .pbix file, then verify connectivity:
python tests/test_connection.pyStart the MCP server:
python src/server.pyUseful launch modes:
python src/server.py --transport sse --port 8765
python src/server.py --readonly
python src/server.py --profile readonly # ~56 read tools
python src/server.py --profile write # readonly + writes (no destructive)
python src/server.py --profile grading # 25-tool surface for evaluation workflows
python src/server.py --profile all # default — every toolMultiple clients can run simultaneously. Each server uses a dedicated worker
for blocking operations; writes to the same model or file are serialized
across MCP processes. A conflicting write returns resource_busy after
10 seconds. pbi_system_health reports the active operation while it runs.
If a write returns write_outcome_unknown, check system health and inspect
the target before retrying. A client timeout does not release the resource
lock while native work is still running.
For SSE auth:
$env:PBI_MCP_AUTH_TOKEN = "your-secret-token"
python src/server.py --transport sse --port 8765Clients must send:
Authorization: Bearer your-secret-tokenMCP Client Setup
Standard stdio config:
{
"mcpServers": {
"powerbi": {
"command": "python",
"args": ["C:\\path\\to\\powerbi-mcp-local\\src\\server.py"]
}
}
}Google Antigravity (Gemini-based IDE) ships a stricter MCP client that
drops the connection at resources/list against the default FastMCP
1.27.x stdio server. Since v0.12.1 the project ships a dedicated entry
point — src/server_antigravity.py — that strips the capability
advertisement to tools only, forces UTF-8 / \n stdio, and routes
every log to stderr at ERROR level. The default src/server.py is left
untouched for Claude Desktop / Cursor / Anthropic CLI.
The PowerShell wrapper at tools/antigravity_mcp_launcher.ps1 pins the
working directory and exports PYTHONUTF8=1 / PYTHONIOENCODING=utf-8
before invoking the venv Python on server_antigravity.py, so the
encoding stays stable regardless of how Antigravity spawns the process.
%USERPROFILE%\.gemini\antigravity\mcp_config.json:
{
"mcpServers": {
"powerbi": {
"command": "powershell.exe",
"args": [
"-NoProfile",
"-ExecutionPolicy",
"Bypass",
"-File",
"D:\\Users\\stealthy\\Documents\\GitHub\\powerbi-mcp-local\\tools\\antigravity_mcp_launcher.ps1",
"--profile",
"readonly"
]
}
}
}Adjust the -File path to your clone. --profile readonly keeps
tools/list small while validating the client connection — switch to
--profile all (or omit the flag) once Antigravity lists tools
successfully. --readonly and --profile {readonly,write,all,grading}
are all forwarded through the wrapper to the entry point with the same
semantics as src/server.py.
Local compatibility probe:
$init = @(
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"antigravity-probe","version":"1.0"}}}',
'{"jsonrpc":"2.0","method":"notifications/initialized","params":{}}'
)
($init + '{"jsonrpc":"2.0","id":2,"method":"resources/list","params":{}}') -join "`n" |
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\tools\antigravity_mcp_launcher.ps1 --profile readonly
($init + '{"jsonrpc":"2.0","id":3,"method":"tools/list","params":{}}') -join "`n" |
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\tools\antigravity_mcp_launcher.ps1 --profile readonlySSE endpoint:
http://localhost:8765/sseSetup guides:
Example Prompts
Connect to Power BI and list all tables with columns.Create a measure called Total Sales in table Sales.Run this DAX query and show top 20 rows.Extract report, add a new page, place 3 visuals, then compile.
Tool Catalog
141 MCP tools are grouped into these areas. Visual creation is consolidated behind pbi_add_visual (28 chart types via visual_type) and pbi_add_visual_from_intent:
Area | Coverage |
Model discovery | instances, tables, measures, relationships, metadata, validation |
Model mutations | measures, columns, tables, relationships, formats, role-based DAX |
Query and import | DAX execution, traces, validation, refresh, model export |
Power Query (M) | read, write, create, import, bulk Excel/folder sources |
PBIP/TMDL | list, read, write, and patch TMDL project files |
Workflows | model audit, Excel import, measure workflow automation |
Quality gates | DAX linting, visual checks, persistence, scenarios, report validation |
RLS and calc groups | roles, filters, members, calculation groups |
Excel | workbook, sheet, cell/range, formatting, search, Power BI import checks |
Reports and visuals | extract, compile, pages, cards, charts, slicers, themes, dashboards |
Unified visual creation is available through:
pbi_add_visual(visual_type, config)In-place binding edits (no remove + recreate) via:
pbi_update_visual_bindings(extract_folder, page, visual_id,
projections={"Y": ["Total Sales"]})Force Power BI Desktop to flush in-memory TOM mutations to the PBIX file (opt-in UI automation):
$env:PBI_MCP_ALLOW_UI_AUTOMATION = "1" # set before launching the serverpbi_persist_now(pbix_path="C:\\reports\\sales.pbix", confirm=true)Automation Flow
Excel input -> Power Query -> model updates -> measures -> validation -> report layout -> compile PBIXCommon tool chain:
excel_write_range
pbi_create_import_query
pbi_create_relationship
pbi_create_measure
pbi_refresh
pbi_execute_dax
pbi_extract_report
pbi_build_dashboard
pbi_compile_reportTroubleshooting
Symptom | Fix |
| Install .NET 6+ runtime, then restart terminal |
| Open a |
| Add it to |
| Close Excel; workbook files are locked while open |
Path blocked by policy | Configure |
Security
Built-in safeguards include:
local path restrictions and traversal protection
DAX/DMV unsafe-query guards
Power Query SSRF protections (cloud DW + SaaS + reflection blocked by default)
export redaction controls
zip safety checks (Excel + PBIX)
response-size cap (16 MiB by default) + per-minute rate limit (600/min)
SSE Bearer auth + DNS-rebinding host/origin allowlist
tool-call auditing
Details: SECURITY.md
Environment variables (quick reference)
Variable | Default | Purpose |
| unset | SSE Bearer token (≥32 chars when set) |
| unset | Extra Host/Origin allowlist for SSE |
|
| Acknowledge non-loopback SSE without auth |
|
| Block all write/destructive tools |
|
| Allow |
|
| Bypass the M function blocklist |
|
| Required for |
|
| Fall back from PostMessage to SendInput |
|
|
|
|
| Native connection deadline (s) |
|
| Shared tool deadline, including probes and reconnects (s); explicit tool timeouts take priority |
| cwd |
|
| unset | Path or inline JSON for |
|
| Tool registry audit (CI) |
Development
pip install -e ".[dev]"
pytest -q
ruff check src tests
ruff format --check src testsCI runs pytest --cov=src --cov-fail-under=54 on Windows + an offline subset on Ubuntu, plus ruff lint + format check, on every PR. Strict registry audit (PBI_MCP_STRICT_REGISTRY=1) ensures every public pbi_*_tool has a matching @mcp.tool() wrapper.
Repository Layout
powerbi-mcp-local/
├── src/
│ ├── server.py CLI + transport launcher + @mcp.resource/@mcp.prompt (~320 L)
│ ├── mcp_core.py FastMCP instance + CONNECTION_MANAGER + lifecycle (~250 L)
│ ├── pbi_connection.py TOM + ADOMD bring-up, write helpers, op history
│ ├── security.py path / DAX / payload guards + tool category sets
│ ├── wrappers/ 14 domain modules — `register_tool(pbi_*_tool)` calls
│ └── tools/ business logic (*_tool functions)
│ └── visuals/ 17 focused submodules (layout, bindings, containers, charts, …)
├── tests/ 167 offline unit tests (live-only scripts gitignored)
├── .github/workflows/ci.yml pytest + coverage + ruff on Windows + Ubuntu, py3.11/3.12
├── docs/, specs/
├── ARCHITECTURE.md module layering, visuals/ tree, profiles, registry audit
├── CHANGELOG.md active changelog (last 3 releases)
├── CHANGELOG-archive.md historical changelog
├── SECURITY.md
├── pyproject.toml ruff, pytest, coverage config + dev deps
└── requirements.txtLicense
MIT
Available Tools
141 toolsexcel_auto_widthD
Inputs: sheet (required), file_path (required). Returns: result
excel_create_sheetD
Inputs: name (required), file_path (required), position. Returns: result
excel_create_workbookD
Inputs: file_path (required), sheets. Returns: result
excel_delete_sheetD
Inputs: name (required), file_path (required). Returns: result
excel_format_rangeD
Inputs: range (required), sheet (required), format (required), file_path (required). Returns: result
excel_list_sheetsD
Inputs: file_path (required). Returns: result
excel_read_cellD
Inputs: cell (required), sheet (required), file_path (required). Returns: result
excel_read_sheetD
Inputs: sheet (required), file_path (required), limit, range. Returns: result
excel_searchD
Inputs: query (required), file_path (required), sheet. Returns: result
excel_to_pbi_checkD
Inputs: file_path (required). Returns: result
excel_workbook_infoD
Inputs: file_path (required). Returns: result
excel_write_cellD
Inputs: cell (required), sheet (required), value (required), file_path (required), +1 more. Returns: result
excel_write_rangeD
Inputs: data (required), sheet (required), file_path (required), start_cell (required). Returns: result
pbi_add_conditional_formattingB
Add table / matrix conditional formatting (data bar, colour scale, icon set).
Power BI stores conditional formatting on table-style visuals under
singleVisual.objects.values (or columnFormatting on older
builds), keyed by a queryRef that matches the column / measure
bound to the visual's Values role. We write the canonical shape
Power BI Desktop emits in current builds.
Parameters
column_name:
The display name (Property) of the measure / column inside the
Values projection. Matched case-insensitively against the
prototypeQuery Select entries.
format_type:
One of dataBar, colorScale, iconSet.
min_color, mid_color, max_color:
Colour scale endpoints (and optional midpoint). Hex strings.
bar_color:
Data bar fill colour.
icon_set:
One of threeArrows, threeArrowsGray, threeTrafficLights,
threeSymbols, threeFlags, fiveArrows.
Inputs: page (required), visual_id (required), column_name (required), format_type (required), +6 more. Returns: result
pbi_add_role_memberA
Add (or update) a member (user/group) on a role.
member_type: 'external' (default, ExternalModelRoleMember — recommended for Power BI service) 'windows' (WindowsModelRoleMember — domain principal SID)
With overwrite=False (default), raises PowerBIDuplicateError if a
member with the same member_name already exists on the role. With
overwrite=True the existing member's identity_provider is refreshed
(when external) and the response carries action="updated".
Inputs: role (required), member_name (required), overwrite, member_type, +1 more. Returns: result
pbi_add_visualA
Add any visual to a report page — the single entry point for visual creation.
visual_type: card, labelled_card, multi_row_card, bar_chart,
stacked_bar_chart, stacked_column_chart, clustered_column_chart,
hundred_percent_stacked_bar_chart, hundred_percent_stacked_column_chart,
ribbon_chart, line_chart, area_chart, stacked_area_chart,
hundred_percent_stacked_area_chart, donut, pie_chart, treemap, funnel,
table, waterfall, scatter_chart, combo_chart, slicer, gauge, kpi,
matrix, map, text_box.
config: per-type keys — categorical charts: category_column +
value_measure (+ legend_column); axis charts: axis_column +
value_measures (list); card/gauge: measure; table: columns (list);
matrix: rows + values (lists); scatter: category_column + x_measure +
y_measure; combo: category_column + bar_measures + line_measures;
kpi: indicator_measure + trend_column; slicer: column (+ slicer_type);
map: location (+ measure); text_box: text. Error messages name any
missing key. Prefer pbi_add_visual_from_intent when you have a
business intent rather than an exact type.
dry_run: when True, run all validation and binding logic but skip the
layout disk write — response carries dry_run=True and a
write_log.
Inputs: x (required), y (required), page (required), visual_type (required), +6 more. Returns: result
pbi_add_visual_from_intentB
Plan a visual from a business-intent spec, then build it.
Same intent schema as pbi_plan_visual_tool. The chosen visual is
created through the generic dispatcher, so all field validation and
binding logic applies. dry_run=True plans and validates without
writing the layout.
Inputs: x (required), y (required), page (required), intent (required), +5 more. Returns: result
pbi_apply_designD
Inputs: extract_folder (required), preset, style_cards, page_background. Returns: result
pbi_apply_format_presetA
Apply a named format preset to a list of measures or columns.
Wraps pbi_set_format_tool so callers don't need to memorise the raw
format string. Supported preset families: currency_eur(_k|_m), currency_usd,
percent (0dp/1dp/2dp/4dp), thousands, millions, decimal_2, integer,
integer_no_sep, date_iso, date_short_fr, date_short_us, date_long_fr,
datetime_iso. Use pbi_list_format_presets_tool to inspect them.
Inputs: names (required), table (required), preset (required), object_type. Returns: result
pbi_apply_style_presetB
Apply a one-shot visual style preset to an existing .pbix.
wallpaper_fit (optional) overrides the preset's default canvas
image scaling. Must be one of Fit, Fill, Normal,
Stretch (Power BI's enum). When omitted the preset's
page.wallpaper.fit is used.
See module docstring for the full flow.
Inputs: preset (required), pbix_path (required), pages, custom_spec, +3 more. Returns: result
pbi_apply_themeD
Inputs: extract_folder (required), theme_json_path (required). Returns: result
pbi_audit_modelC
Detect missing, ambiguous, bidirectional, and orphaned model structures.
Inputs: include_hidden. Returns: result
pbi_auto_grid_layoutC
Compute non-overlapping (x, y, width, height) for visual specs on a column-based grid. Pure offline calculation.
Inputs: specs (required), gap, cols, start_x, +5 more. Returns: result
pbi_build_dashboardD
Inputs: page (required), layout (required), extract_folder (required). Returns: result
pbi_bulk_import_excelC
Bulk-create Excel import queries for multiple tables.
Inputs: excel_path (required), refresh_after, promote_headers, sheet_table_map. Returns: result
pbi_check_scaffold_spec_dbcc_risksA
Pre-build DBCC risk analysis on a tables spec.
Mirrors the input shape of pbi_create_persistent_report_tool and
pbi_scaffold_pbix_tool. Pass the same tables list before
calling the builder to catch empty-String-column risks up front.
Inputs: tables (required). Returns: result
pbi_compare_report_versionsC
Compare two extracted report versions by pages, visuals, and layout score.
Inputs: extract_folder_a (required), extract_folder_b (required), label_a, label_b. Returns: result
pbi_compile_reportD
Inputs: output_path (required), extract_folder (required), force. Returns: result
pbi_connectC
Connect to Power BI Desktop and report the active instance.
Inputs: preferred_port, force_reconnect. Returns: result
pbi_convert_visual_typeC
Migrate an existing visual to a different type while preserving compatible field bindings.
Inputs: page (required), new_type (required), visual_id (required), extract_folder (required). Returns: result
pbi_create_calc_groupB
Create a calculation group table with its Name column and optional calculation items.
items: list of {name, expression, format_string_expression?, ordinal?}.
Inputs: table_name (required), items, overwrite, precedence, +1 more. Returns: result
pbi_create_columnC
Create or update a calculated column.
Inputs: name (required), table (required), expression (required), data_type, +4 more. Returns: result
pbi_create_contribution_measureB
Create a %-of-total contribution measure.
DAX template:
DIVIDE([{base}], CALCULATE([{base}], ALL({scope_columns})))
scope_columns defines the denominator scope — typically the dimension
columns whose total you want each row to be a percentage of (e.g.
["Categorie.Nom catégorie"] for "this category's % of all categories").
Inputs: table (required), base_measure (required), scope_columns (required), overwrite, +3 more. Returns: result
pbi_create_csv_import_queryC
Generate and inject a CSV import Power Query for a table.
Inputs: table (required), csv_path (required), encoding, delimiter, +4 more. Returns: result
pbi_create_folder_import_queryC
Generate and inject a folder import Power Query for a table.
Inputs: table (required), folder_path (required), refresh_after, partition_name, +2 more. Returns: result
pbi_create_import_queryC
Generate and inject an Excel import Power Query for a table.
Inputs: table (required), excel_path (required), sheet_name (required), refresh_after, +2 more. Returns: result
pbi_create_measureC
Create or update a DAX measure.
Inputs: name (required), table (required), expression (required), is_hidden, +4 more. Returns: result
pbi_create_measuresA
Batch-create or update multiple DAX measures with a single SaveChanges call.
Each item in measures must have at minimum: name, expression. Optional keys: format_string, description, display_folder, is_hidden.
With dry_run=True, every measure is name + expression validated and the
per-item planned_action is reported (would_create/would_update/
would_fail), but no model mutation happens — SaveChanges is never
called. Use this for an LLM preflight before committing the batch.
Inputs: table (required), measures (required), dry_run, overwrite, +1 more. Returns: result
pbi_create_pageD
Inputs: display_name (required), extract_folder (required), width, height. Returns: result
pbi_create_persistent_reportB
Create a persistent PBIX with DataModel, DAX measures, relationships, pages, and native visuals.
prime_string_store (default True) injects a one-row sentinel
into every empty Import table whose schema declares a String column,
so Vertipaq's DBCC string-store consistency check passes on reopen.
Disable only when you know the table will be populated by Power BI
Desktop's first refresh (e.g. via a DirectQuery binding or a Power
Query expression set after the PBIX is created).
style_preset (optional) names a built-in styling preset
(glassmorph_dark, glassmorph_light, neon_cyber,
minimal_corporate, dark_pro, or custom). When set, the
matching preset is applied to the file via
pbi_apply_style_preset_tool right after save, so the produced
PBIX opens with wallpaper, card chrome, accent colours, and the
preset's theme already wired up. style_wallpaper_path overrides
the preset's default wallpaper; style_custom_spec is required
when style_preset='custom'.
Inputs: tables (required), output_path (required), pages, measures, +6 more. Returns: result
pbi_create_relationshipA
Create or update a single-column relationship.
With overwrite=False (default), raises PowerBIDuplicateError when
a relationship between the same endpoint columns already exists. With
overwrite=True the existing relationship is updated in place
(cardinality / direction / is_active refreshed) and the response carries
action="updated".
Inputs: to_table (required), to_column (required), from_table (required), from_column (required), +5 more. Returns: result
pbi_create_roleC
Create or update a model role.
Inputs: name (required), overwrite, permission, description. Returns: result
pbi_create_rolling_average_measureB
Create a trailing rolling average measure.
DAX template:
AVERAGEX(DATESINPERIOD({date_table}[{date_column}], LASTDATE({date_table}[{date_column}]), -{window}, {granularity}), [{base}])
Inputs: table (required), window (required), date_table (required), date_column (required), +6 more. Returns: result
pbi_create_tableC
Create or update a calculated table.
Inputs: name (required), expression (required), is_hidden, overwrite, +1 more. Returns: result
pbi_create_time_intelligence_packA
Create a family of time-intelligence measures from a base measure.
Default patterns: YTD, MTD, QTD, SPY, YOY, YOY %, MA3. Each generated
measure is named "{base_measure} {suffix}" (e.g. "Sales YTD")
and lives on table (typically the same fact table as the base measure).
Dependency-aware: requesting YOY% automatically adds YOY and SPY
so the whole family resolves.
With format_inherit=True, each measure inherits base_measure's
format string (best-effort lookup on the live model). format_string
overrides that when supplied. Patterns that prescribe their own format
(e.g. YOY % → "0.00%") win unless format_string is explicit.
With dry_run=True no model mutation occurs — the response carries a
plan listing every measure that would be created/updated/skipped.
Inputs: table (required), date_table (required), date_column (required), base_measure (required), +6 more. Returns: result
pbi_create_topn_measureB
Create a Top-N filter measure.
DAX template:
IF(RANKX(ALL({dim_table}[{dim_column}]), [{rank_measure}], , DESC) <= {N}, [{base}], BLANK())
Use as the value of a chart visual to surface only the top N members of a
dimension. rank_measure defaults to base_measure.
Inputs: n (required), table (required), base_measure (required), dimension_table (required), +6 more. Returns: result
pbi_create_variance_measureB
Create a period-over-period variance measure.
DAX template (parametrised by granularity ∈ {year, month, quarter}):
[{base}] - CALCULATE([{base}], DATEADD({date_table}[{date_column}], {offset}, {granularity}))
Default compare_period_offset = -1 ⇒ "current period vs previous one".
Inputs: table (required), date_table (required), date_column (required), base_measure (required), +6 more. Returns: result
pbi_delete_calc_groupC
Delete a calculation group table.
Inputs: table_name (required). Returns: result
pbi_delete_columnC
Delete a column from a table.
Inputs: name (required), table (required). Returns: result
pbi_delete_measureC
Delete a DAX measure.
Inputs: name (required), table (required). Returns: result
pbi_delete_pageD
Inputs: page (required), extract_folder (required). Returns: result
pbi_delete_relationshipA
Delete a relationship by name or by endpoint columns.
Inputs: name, to_table, to_column, from_table, +1 more. Returns: result
pbi_delete_roleC
Delete a model role.
Inputs: name (required). Returns: result
pbi_delete_tableB
Delete a table. Removes associated relationships and measures.
Inputs: name (required). Returns: result
pbi_describe_pageC
Return a structured, LLM-friendly snapshot of a report page.
One entry per visual with id/type/position, role-keyed bindings,
formatting (title + axis titles + label_display_units), and a
binding_health rollup (ok | missing_field | wrong_role)
based on live-model validation when manager is supplied.
Inputs: page (required), extract_folder (required). Returns: result
pbi_detect_circular_dependenciesA
Detect cycles in the measure dependency graph.
Builds a graph of measure → referenced measures (parsed from DAX
[Name] tokens that match a known measure name) and runs a DFS to
find strongly connected cycles. Self-references are reported separately.
Inputs: include_hidden. Returns: result
pbi_detect_dirty_datesC
Detect text columns that look like dirty dates.
Inputs: table, max_samples, scan_all_text_columns, min_parse_success_rate. Returns: result
pbi_detect_empty_visualsC
Execute lightweight DAX probes to detect visuals with no data.
Inputs: extract_folder (required), page, max_rows, include_slicers, +1 more. Returns: result
pbi_detect_missing_visualsB
Detect required visuals that are absent from a page.
Each requirement entry is a dict with at least visual_type and
optionally count (default 1), contains_field (a reference like
Date.Year that must appear in the visual's prototypeQuery), and
label (free-form name surfaced in the report).
Inputs: page (required), requirements (required), extract_folder (required). Returns: result
pbi_detect_name_collisionsC
Detect table, column, and measure name collisions before writes.
Inputs: include_hidden. Returns: result
pbi_diagnose_pbix_dbccA
Statically diagnose DBCC string-store risks on a built .pbix.
Returns a list of issues (each with a type and a short message)
and a valid flag. Use this before opening the file in Power BI
Desktop to avoid the round-trip through the modal repair dialog.
Inputs: pbix_path (required). Returns: result
pbi_diagnose_render_risksA
Aggregate render-risk diagnostic for visuals on disk.
Read-only. Walks the extracted layout and reports conditions known to make Power BI Desktop refuse to render a visual or surface an opaque internal error:
Constant Y measure on a cartesian chart (line / combo / area / waterfall). The bug-0.92 family: a measure whose DAX expression has no column or measure reference (or returns BLANK() unconditionally) collapses every Y point to the same scalar with no axis dependency, which some PBI builds reject.
Unresolved measure home table — the binding falls back to the synthetic
$Measuresentity which PBI refuses to plot.Missing column / measure / wrong reference kind in the live model (only when
manageris supplied).Query-ref mismatch between projections and prototypeQuery Select entries.
A live manager enables DAX-expression heuristics for the
constant-measure check; without it the call still reports unresolved
home tables and binding-shape issues that don't need the live model.
Pass visual_id to narrow to a single visual; pass page to
narrow to a specific page; both omitted scans the whole report.
Inputs: extract_folder (required), page, visual_id, include_hidden. Returns: result
pbi_disable_card_autoscaleB
Disable the auto K/M/B unit-scaling on card visuals (sets
labelDisplayUnits=1 plus an explicit labelPrecision).
Inputs: extract_folder (required), page, visual_ids, label_precision. Returns: result
pbi_excel_import_workflowC
Plan or run an Excel workbook import into Power BI.
Inputs: excel_path (required), apply, refresh_after, promote_headers, +1 more. Returns: result
pbi_execute_daxC
Execute a DAX or DMV query.
Inputs: query (required), max_rows, timeout_seconds. Returns: result
pbi_execute_dax_as_roleB
Execute a DAX query under a specific role context.
Inputs: role (required), query (required), username. Returns: result
pbi_export_active_themeA
Export the currently active theme JSON from an extracted report.
Writes a copy of the theme referenced by activeTheme (or the
last entry in themeCollection) to output_path. Useful for
capturing the baseline theme before customising it.
Inputs: output_path (required), extract_folder (required). Returns: result
pbi_export_correction_reportB
Generate a Markdown correction report aggregating all analysis tools.
Output sections: model overview, star-schema verdict, circular
dependency scan, optional rubric scoring, audit issues. Writes to
output_path and returns the path plus an inline summary.
Inputs: output_path (required), extract_folder, rubric_criteria, fact_table_hints. Returns: result
pbi_export_modelC
Export the full model as JSON, optionally writing it to disk.
Inputs: path, include_hidden, include_row_counts. Returns: result
pbi_export_validation_reportC
Export model, DAX, layout, binding, and score validation as JSON.
Inputs: output_path (required), extract_folder, include_hidden, include_measure_tests, +2 more. Returns: result
pbi_extract_reportD
Inputs: pbix_path (required), extract_folder. Returns: result
pbi_generate_dax_context_promptA
Render a compact markdown snapshot of the model — tables, columns, measures, relationships — ready to paste into an LLM system prompt so the LLM can author DAX with full schema context in one round-trip.
Sections:
# Model: <name>one
## <Table>per table withColumns:and (optionally) DAXMeasures:lines## RelationshipswithA[X] → B[Y] (cardinality, active)rows
Output is truncated to max_chars (default 12 000) with a trailing
note when truncation kicks in. Set include_dax=False to omit the
measure expressions and stay terse.
Inputs: max_chars, include_dax, include_hidden, include_relationships. Returns: result
pbi_generate_measure_testsC
Generate and execute smoke tests for DAX measures.
Inputs: measures, max_measures, include_hidden. Returns: result
pbi_get_pageD
Inputs: page (required), extract_folder (required). Returns: result
pbi_get_power_queryC
Read the M expression for a specific table partition.
Inputs: table (required), partition_name. Returns: result
pbi_import_dax_fileC
Parse a .dax file and bulk-create measures.
Inputs: path (required), table, overwrite, stop_on_error, +2 more. Returns: result
pbi_import_excel_workbookC
Import an Excel workbook into Power BI tables in one call.
Inputs: excel_path (required), refresh_after, promote_headers, sheet_table_map. Returns: result
pbi_lint_daxC
Validate measures, formats, and measure/column name collisions.
Inputs: include_hidden, validate_expressions. Returns: result
pbi_lint_report_layoutA
Detect overlaps, excessive whitespace, tiny visuals, and missing titles.
Optional knobs to silence noise on intentionally dense pages:
ignore_warnings: list of warning types to drop (e.g.["too_many_visuals", "visual_too_small", "missing_title", "excessive_whitespace", "layout_overloaded"]). Issues are never ignored — only warnings.only_pages: restrict the scan to a list of page display names / internal names. Use to lint just the new pages an LLM produced.max_visuals_per_page: override the defaulttoo_many_visualsthreshold (defaults toMAX_VISUALS_PER_PAGE). Set high to effectively disable the warning without ignoring it.
Inputs: extract_folder (required), page, only_pages, ignore_warnings, +1 more. Returns: result
pbi_list_calc_groupsB
List calculation groups and their items.
Inputs: no named parameters. Returns: result
pbi_list_format_presetsA
Return the catalogue of format-string presets.
Optional filter_substring is matched (case-insensitive) against each
preset's name to narrow the result — useful when an LLM only needs the
"percent_*" or "currency_*" subset.
Inputs: filter_substring. Returns: result
pbi_list_instancesA
List discovered Power BI Desktop instances without forcing a connection.
Inputs: no named parameters. Returns: result
pbi_list_measuresB
List all model measures.
Inputs: include_hidden. Returns: result
pbi_list_pagesD
Inputs: extract_folder (required). Returns: result
pbi_list_power_queriesC
List table partitions and their current source expressions.
Inputs: include_hidden. Returns: result
pbi_list_relationshipsB
List model relationships.
Inputs: no named parameters. Returns: result
pbi_list_repairable_errorsA
Return the repairable-error vocabulary used by pbi_repair_loop.
Each entry maps a stable error code to its severity, whether the loop can fix it automatically, and the spec-level repair instruction an LLM should apply when it cannot.
Inputs: no named parameters. Returns: result
pbi_list_rolesA
List all model roles with their members and table filters.
Inputs: no named parameters. Returns: result
pbi_list_scaffold_templatesA
List the available scaffold templates with summary metrics.
Inputs: no named parameters. Returns: result
pbi_list_style_presetsA
Return the catalogue of built-in presets with summary metadata.
Inputs: no named parameters. Returns: result
pbi_list_tablesC
List model tables and columns.
Inputs: include_hidden, include_row_counts. Returns: result
pbi_list_tmdl_filesC
List TMDL files in a Power BI Project semantic model definition folder.
Inputs: project_path (required). Returns: result
pbi_measure_dependenciesC
Return calc-dependency graph rows (source → referenced object) from DISCOVER_CALC_DEPENDENCY.
Inputs: table, measure. Returns: result
pbi_measure_workflowD
Plan or run validated batch measure creation.
Inputs: table (required), measures (required), apply, overwrite. Returns: result
pbi_model_audit_workflowC
Run a compact model audit with recommendations for an agent.
Inputs: include_hidden, include_row_counts. Returns: result
pbi_model_infoC
Return a full model snapshot in a single call.
Inputs: include_hidden, include_row_counts. Returns: result
pbi_move_visualD
Inputs: x (required), y (required), page (required), visual_id (required), +3 more. Returns: result
pbi_operation_historyA
Return the most-recent N tool operations recorded by the connection manager (newest first).
Each entry: {ts, op, kind: "read"|"write", duration_ms, ok} plus
error_type/error_code/error_message when ok is False. Use
this to self-diagnose what just happened — e.g. an LLM can pull the last
5 calls after a failure to see which writes already landed.
Inputs: last_n. Returns: result
pbi_parameterize_data_sourceB
Make data sources portable via a Power Query parameter.
Creates (or updates) an M parameter named parameter_name whose default
value is file_path. Then rewrites every M partition that string-matches
file_path so it calls File.Contents(<parameter_name>) instead of the
hardcoded path. After the parameter is wired in, a collaborator can change
the file location once via Power BI Desktop's Transform data → Manage
parameters dialog without editing each query.
partitions: optional explicit list of "Table[/Partition]" to rewrite. By
default every M-source partition that references file_path is rewritten.
Inputs: file_path (required), parameter_name (required), dry_run, partitions, +1 more. Returns: result
pbi_patch_layoutA
Patch the modified Report/Layout back into the PBIX archive.
When force=True the call closes (and if necessary kills) Power BI
Desktop so the PBIX can be overwritten. save_before_close (default
True) sends Ctrl+S to every running PBI Desktop window via
PostMessage before the kill, then waits up to 10 seconds for the
PBIX mtime to change. This flushes any in-memory TOM mutations
(measures, columns, role filters) that have not yet been persisted —
without this, those changes are lost when the process is killed.
The save attempt is best-effort: it never raises, and the layout patch
proceeds regardless of whether the save succeeded. The response
includes save_attempt with telemetry so the caller can detect
silent loss.
Inputs: pbix_path (required), extract_folder (required), force, include_hidden, +2 more. Returns: result
pbi_patch_tmdl_measureC
Create or replace a measure block in one table TMDL file.
Inputs: expression (required), table_file (required), measure_name (required), project_path (required), +3 more. Returns: result
pbi_persist_nowA
Trigger Power BI Desktop to save the open PBIX (Ctrl+S in the UI).
The Tabular engine has no programmatic save — every TOM mutation lives in memory until the user presses Ctrl+S. This tool drives that key chord through Win32 keyboard injection on the connected Desktop instance's main window.
Hard gates (both required):
The server process must have
PBI_MCP_ALLOW_UI_AUTOMATION=1set in its environment before launch.The caller must pass
confirm=Trueper call.
Either gate failing returns a structured error without acting. The
automation only sends Ctrl+S; no other key sequences are emitted.
Parameters
pbix_path:
Optional. When provided, the call polls the file's modification
timestamp for up to timeout_seconds after sending Ctrl+S, and
reports the observed delta in the response. Without it the call
returns immediately after key injection.
confirm:
Must be True. Refusing-by-default avoids accidental focus
steals from other tools.
timeout_seconds:
Bound on how long to wait for pbix_path mtime to change.
Clamped to [1, 60].
Inputs: confirm, pbix_path, timeout_seconds. Returns: result
pbi_plan_visualA
Plan a visual from a business-intent spec without touching the report.
intent keys (all optional unless a rule needs them): metric / metrics — 'Table.Measure' reference(s) dimension — 'Table.Column' categorical axis time — 'Table.Column' time axis (implies trend) breakdown — 'Table.Column' secondary split (legend/series) target — 'Table.Measure' reference or numeric goal comparison, trend, parts_of_whole, correlation, geographic, detail_table, many_categories, filter_control — boolean hints
Returns the chosen visual_type, the matching pbi_add_visual
config, and a rationale explaining the rule that fired.
Inputs: intent (required). Returns: result
pbi_read_tmdl_fileB
Read one TMDL file from a Power BI Project definition folder.
Inputs: project_path (required), relative_file (required). Returns: result
pbi_refreshC
Trigger a model or table refresh.
Inputs: target, refresh_type. Returns: result
pbi_refresh_metadataA
Reload cached TOM schema from the server (cheaper than full reconnect).
Inputs: no named parameters. Returns: result
pbi_relocate_data_sourceA
Bulk-rewrite a hardcoded file or folder path inside every M partition.
Use when a workbook moves and queries break with DataSource.NotFound. Looks
for old_path as a substring of each M-source partition expression and
replaces it with new_path. Calculated/query-source partitions are
skipped. dry_run=True returns the planned changes without writing.
Inputs: new_path (required), old_path (required), dry_run, refresh_after, +1 more. Returns: result
pbi_remove_role_memberB
Remove a member from a role, matching by MemberName (case-insensitive).
Inputs: role (required), member_name (required). Returns: result
pbi_remove_visualD
Inputs: page (required), visual_id (required), extract_folder (required). Returns: result
pbi_rename_columnC
Rename a column. Callers are responsible for updating dependent DAX.
Inputs: name (required), table (required), new_name (required). Returns: result
pbi_rename_measureA
Rename a DAX measure. Callers must update downstream DAX expressions themselves.
Inputs: name (required), table (required), new_name (required). Returns: result
pbi_rename_tableB
Rename a table. Callers are responsible for updating dependent DAX expressions.
Inputs: name (required), new_name (required). Returns: result
pbi_repair_loopA
Detect → classify → auto-repair → re-verify loop for a report extract.
Each round scans visual bindings, applies the deterministic repairs
(query-ref mismatches, measure home tables) when apply=True, saves,
and rescans — until no repair is applied or max_rounds is reached.
Gauge target consistency and double display-unit scaling are then
checked on the converged layout; check_empty_visuals=True (requires
a live connection) additionally probes every visual's data query.
The response's repairable_errors lists the residual issues in
classified form, each with an llm_action telling the calling model
how to fix its spec.
Inputs: extract_folder (required), page, apply, max_rounds, +2 more. Returns: result
pbi_repair_report_fieldsD
Inputs: extract_folder (required), page, apply, include_hidden. Returns: result
pbi_run_scenarioC
Run a complete QA scenario against the active model and optional extracted layout.
Inputs: scenario (required), extract_folder, include_hidden. Returns: result
pbi_scaffold_pbixA
Create a starter PBIX from a named template.
Templates: blank (date table only), finance, sales,
analytics. Optional theme_json_path is validated against the
Power BI theme schema (size, key allowlist, colour format,
URL-bearing values) and embedded in the generated file. Additional
measures supplied via extra_measures are appended after the
template's baseline pack.
Inputs: output_path (required), template, extra_measures, theme_json_path, +2 more. Returns: result
pbi_score_dashboardC
Score dashboard quality across model, DAX, layout, and readability.
Inputs: extract_folder, include_hidden. Returns: result
pbi_score_rubricA
Aggregate scoring across multiple validators.
Each criterion is a dict with:
id(str): unique identifierlabel(str): human descriptioncheck(str): one ofstar_schema,no_circular_deps,power_query_steps,missing_visuals,measure_existsweight(float, default 1.0)params(dict): check-specific parameters
Returns per-criterion verdicts plus a weighted total score in [0, 1].
Inputs: criteria (required), extract_folder. Returns: result
pbi_set_column_data_typeA
Set the DataType (and optionally FormatString) of an existing column.
Works for any column kind (source, calculated, calculated table column).
Use when Power Query type hints (Int64.Type etc.) are overridden by
PBI's downstream inference and the column ends up as the wrong type.
data_type accepts standard TOM names (Int64, Decimal,
Double, String, DateTime, Boolean, Currency,
Binary, Variant).
Inputs: table (required), column (required), data_type (required), format_string. Returns: result
pbi_set_formatA
Batch-apply format strings to measures or columns.
Inputs: names (required), table (required), format_string (required), object_type. Returns: result
pbi_set_page_sizeD
Inputs: page (required), width (required), height (required), extract_folder (required). Returns: result
pbi_set_power_queryC
Write or update an M expression on a table partition.
Inputs: table (required), m_expression (required), refresh_after, partition_name. Returns: result
pbi_set_role_filterB
Set (or remove when filter_expression is None/empty) the RLS DAX filter on a table for a role.
Inputs: role (required), table (required), filter_expression (required). Returns: result
pbi_set_series_colorA
Set the fill colour for a single series of a chart visual.
Power BI stores per-series overrides inside singleVisual.objects.dataPoint
as additional list entries with an id selector pinned to the target
series' measure or column. The bare defaultColor property only
affects series that do not have an explicit override — using it on a
multi-series chart paints every series the same colour.
Specify the target series by series_index (0-based across the
visual's projections, in role order) or series_name (matches the
queryRef or the underlying measure / column Property name).
Optional role narrows the lookup to a specific projection role
(e.g. "Y", "Values").
Inputs: page (required), color (required), visual_id (required), extract_folder (required), +3 more. Returns: result
pbi_set_visual_format_propertyA
Set / reset formatting properties on a visual's
singleVisual.objects[<object_name>][0].properties.
Parameters
extract_folder, page, visual_id, object_name:
Identify the target. object_name is the Power BI object key
('title', 'dataPoint', 'labels', 'background', 'general', etc.).
properties:
{property_name: value} to set. Values are encoded as Power BI
literals via the type hint in property_types.
property_types:
{property_name: type_hint}. Valid hints:
- ``auto`` (default) — infer from Python type
- ``bool`` — booleans
- ``int`` — integers (alias: ``integer``)
- ``decimal`` — floats / numerics (alias: ``float``, ``number``)
- ``text`` — strings (alias: ``string``)
- ``color`` — hex strings ``"#RRGGBB"`` (alias: ``fill``, ``hex``,
``rgb``); a previously-encoded ``{"solid": {"color": ...}}``
object is also accepted and unwrapped automatically
- ``raw`` — pass the value untouched (advanced)
Type names are case-insensitive. Unknown hints raise with the
full list.reset_properties: Optional list of property names to delete from the visual's property bag. Use this to revert a property to Power BI's default — passing an empty string would leave the key set to a blank value instead.
Examples
Set a title (text):
pbi_set_visual_format_property(
extract_folder, page, visual_id,
object_name="title",
properties={"text": "Sales", "show": True},
property_types={"text": "text", "show": "bool"},
)Set a fill color (single-series default):
pbi_set_visual_format_property(
...,
object_name="dataPoint",
properties={"defaultColor": "#4472C4"},
property_types={"defaultColor": "color"},
)Reset a property to Power BI's default:
pbi_set_visual_format_property(
...,
object_name="title",
reset_properties=["text"],
)
Inputs: page (required), visual_id (required), object_name (required), extract_folder (required), +3 more. Returns: result
pbi_system_healthA
Single-call self-diagnostic for stability and dependency status.
Read-only. Skips any TOM/ADOMD probe gracefully when no connection is active. Use as a preflight from any LLM agent: one call answers "can I talk to Power BI right now?" without juggling connect / list / model_info.
Inputs: no named parameters. Returns: result
pbi_trace_queryC
Execute a DAX query and return result rows with timing diagnostics.
Inputs: query (required), timeout_seconds. Returns: result
pbi_update_relationshipA
Update properties of an existing relationship (cardinality, direction, is_active, name).
Inputs: name, new_name, to_table, direction, +5 more. Returns: result
pbi_update_visual_bindingsA
Update an existing visual's field bindings without removing and recreating it. Modes:
projections: full replacement of all roles. dict keyed by role name (e.g."Category","Y","Values"); each value is a list of field references ("Table.Column"for columns or bare measure names).add_to_role/remove_from_role: incremental edits to specific roles. Same value shape. Roles that end up empty after a remove are dropped fromprojections.
projections is mutually exclusive with the incremental params.
Roles are validated against VISUAL_FIELD_ROLES[visual_type]; field
references are validated against the live model when manager is
supplied. The prototypeQuery is rebuilt from the new reference set
so Power BI Desktop renders the visual correctly. dry_run=True runs
every check but skips the layout disk write.
Inputs: page (required), visual_id (required), extract_folder (required), dry_run, +4 more. Returns: result
pbi_validate_daxA
Parse-check a DAX expression by running a zero/one-row probe and catching errors.
kind='scalar' wraps the expression with EVALUATE ROW("v", ). kind='table' wraps the expression with EVALUATE TOPN(0, ).
semantic=True additionally checks every Table[Column] / [Measure]
reference against the live model index and heuristically flags a
percent-shaped format_string on a scalar-money expression — the
response then carries a semantic block (see
pbi_validate_dax_semantic_tool).
Inputs: expression (required), kind, semantic, format_string, +1 more. Returns: result
pbi_validate_filter_expressionB
Validate a DAX boolean filter expression before visual probes.
Inputs: filter_expression (required). Returns: result
pbi_validate_modelB
Audit the model for common issues: empty expressions, missing format strings, orphan tables, duplicate measure names.
Inputs: include_warnings. Returns: result
pbi_validate_pbix_persistenceC
Validate that a patched PBIX still contains a readable, persistent report layout.
Inputs: pbix_path (required), extract_folder, require_security_bindings_removed. Returns: result
pbi_validate_pbix_reopenB
Open a PBIX in Power BI Desktop and scan for visible repair-error signals.
use_windows_ocr defaults to False because the underlying screenshot
captures the entire primary desktop, not just the Power BI window. The
OCR helper now returns only the matched signal labels and a length —
never raw recognized text — so screen contents from other applications
cannot leak through the response.
Inputs: pbix_path (required), close_after, screenshot_path, timeout_seconds, +2 more. Returns: result
pbi_validate_power_query_stepsA
Verify that a Power Query (M) expression contains expected step patterns.
Each entry in expected_steps is treated as a substring (or regex if it
starts with re:) that must appear at least once in the M expression.
Useful for grading exercises: e.g. checking that a postal-code column has
been left-padded to 5 chars, or that rows with null customer ids are
filtered out.
Inputs: table (required), expected_steps (required), case_sensitive, partition_name. Returns: result
pbi_validate_relationship_planB
Validate relationship cardinality, direction, duplicates, and ambiguity before creation.
Inputs: to_table (required), to_column (required), from_table (required), from_column (required), +3 more. Returns: result
pbi_validate_report_fieldsD
Inputs: extract_folder (required), page, include_hidden. Returns: result
pbi_validate_star_schemaA
Confirm a model follows star schema topology.
Heuristic: a fact table participates as the many-side in ≥1 relationship, a dimension table participates as the one-side. Tables that are both are flagged as bridge tables. Direct dimension-to-dimension relationships are flagged as snowflake violations. Fact tables wired to other facts are flagged as fact-to-fact (constellation).
Optional fact_table_hints lets callers force-tag tables as facts
(matched case-insensitively); useful when a fact table has no incoming
relationships yet because the model is being built incrementally.
Inputs: include_hidden, fact_table_hints. Returns: result
pbi_validate_themeA
Dry-run validation of a user-supplied theme JSON file.
Returns the parsed payload size, any schema issues (errors + warnings), and the list of allowed top-level keys for reference. Performs no disk write and does not require an extract folder.
Inputs: theme_json_path (required). Returns: result
pbi_validate_visual_bindingsC
Alias-level visual binding validation with clearer tool naming.
Inputs: extract_folder (required), page, include_hidden. Returns: result
pbi_write_tmdl_fileC
Create or overwrite one TMDL file inside a Power BI Project definition folder.
Inputs: content (required), project_path (required), relative_file (required), create. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 141 tools
With 141 tools, there is significant overlap in functionality, especially around measure creation (multiple specialized tools) and Excel imports. While descriptions help distinguish them, an agent could easily pick the wrong tool.
Most tools follow a consistent 'pbi_verb_noun' snake_case pattern, but there are minor inconsistencies like mixing 'create' and 'add' for similar operations (e.g., pbi_create_measure vs pbi_add_visual) and plural forms (pbi_create_measures).
141 tools is far too many for any server. This creates a bloated surface where many tools are either redundant or overly specialized, making it difficult for an agent to navigate.
The tool set covers a comprehensive range of Power BI operations, from model management to report layout, DAX, and data source handling. Minor gaps exist (e.g., no direct tool for editing visual types beyond conversion), but the coverage is extensive.
Maintenance
Related MCP Connectors
One MCP server for the services your AI needs: memory, files, Microsoft 365, kanban and more.
MCP Server for Slima - AI Writing IDE for Novel Authors with AI Beta Reader.
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
MCP server unifying ERPs, CRMs, APIs and knowledge base for Claude, ChatGPT and Gemini.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceControl Excel with Natural Language through AI assistants like GitHub Copilot, Claude, and ChatGPT. This MCP server enables AI-powered Excel automation for Power Query, DAX measures, VBA macros, PivotTables, and more.891MIT
- AlicenseBqualityDmaintenanceBuild Power BI reports with natural language through an MCP server that connects AI assistants to Power BI's PBIR file format for creating pages, visuals, themes, and filters locally.25721MIT
- AlicenseNot gradedqualityCmaintenanceMCP server for Power BI — local PBIX file analysis, cloud API operations, report export, and semantic model extraction from Power BI Desktop.38 npm1MIT
- FlicenseNot gradedqualityDmaintenanceMCP server for reading and analyzing Fabric semantic models. Supports getting model definitions and executing DAX queries against Power BI datasets.17-