Horizun PBI MCP
OfficialHorizun PBI MCP provides 127 tools across live model (ADOMD.NET/TOM) and on-disk (TMDL/PBIR) layers for Power BI Desktop and .pbip projects, covering:
Connection & DAX: Discover and select open models, run read-only DAX queries, validate DAX syntax (dry-run), test connections.
Model Documentation: List tables/measures/relationships/hierarchies/roles/partitions; analyze model quality; generate Markdown documentation; search objects; show dependencies.
Model Editing: Create/update/delete measures, calculated columns/tables; add tables from files; hide/show columns; set cross-filter direction, storage mode, auto date/time; build relationships/hierarchies.
Refresh & Desktop: Refresh model (full, calculate, per table); open .pbip/.pbix in Desktop; capture Desktop screenshot.
PBIP Project Management: Open, validate, backup, create projects; convert .pbix to .pbip (single/batch); inspect .pbix; list convertible files.
Report & Visual Editing (PBIR): List pages/visuals; create, duplicate, delete visuals; update titles, positions, Z-order, conditional formatting; replace fields, copy formats; align/distribute visuals; detect layout overlaps.
Page Generation & Design: Generate page specs from presets; validate, preview (HTML), diff, and apply specs; compose pages with design systems; propose dashboard designs; export page HTML.
Page Management: Create, duplicate, rename, reorder, delete pages.
Themes & Design Systems: List and apply themes/design systems (with accessible palettes); set canvas size, grid, typography.
Resources & Bookmarks: Add/list image resources; create/list/delete bookmarks.
Auditing & Quality: Audit model, report, or full project with scoring; profile data anomalies; plan and apply auto-fixes; list rules.
Safety & Recovery: Health/capabilities checks; journal-based recovery; dry-run change plans with confirmation required; backup purge.
Navigation & Discovery: Guided entry point (
pbi_start_here), dashboard proposals, building blocks inventory, capabilities snapshot.
All destructive actions require explicit confirmation.
Click on "Install 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., "@Horizun PBI MCPList all measures and their DAX formulas."
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.
Horizun PBI MCP
MCP (Model Context Protocol) server for working with local Power BI Desktop and .pbip projects from Claude Code.
v1.2.0 — 128 tools, 1793 tests passed (3 skipped, with their condition documented). Covers two complementary layers:
Layer | For what | How |
Live (Power BI Desktop open on | Query data (DAX), document the model, create/edit measures, refresh | ADOMD.NET + TOM via |
On disk ( | Generate/arrange visuals, edit the model durably | TMDL (model) + PBIR (report), editing files |
Key rule: the local endpoint only exposes the DATA layer (semantic model). Visuals/pages/layout are NOT in that endpoint or in any live API — they're edited via PBIR files. This MCP respects that separation: it doesn't try to move visuals "live".
Documentation
Document | For what |
Install and register the server in Claude Code, Claude Desktop, Codex or a stdio client | |
The 34 baseline tools: domain, risk class, preconditions | |
Current architecture, structural debt and invariants | |
Coexistence with other Power BI MCPs, with verification levels | |
Rules for modifying this repository without breaking the contract | |
The 128 tools by block, with their risk class | |
Why | |
The two PBIR validation layers and their limits | |
What is checked before publishing | |
What remains open, with evidence and how to check it | |
From installation to a dashboard, step by step | |
Threat model, guarantees and what it does not promise | |
What to do when something is left half-done | |
Design of the security layer | |
Version history | |
Fixture strategy: versioned synthetic + ignored local copy |
Related MCP server: Semantic Model MCP Server
What it does
Live DAX: runs queries against the open model and returns columns/rows with timings.
Documentation: tables, columns, measures, relationships, hierarchies, roles (RLS) and quality analysis → Markdown.
Measures: create/edit/delete DAX measures in the open model (
live), in the TMDL file (pbip) or in both (both).Local refresh: refreshes the open model in Desktop (not the Service).
PBIP: open/validate projects, automatic backups.
.pbix→.pbipconversion: report to PBIR (copied if the.pbixalready carries it, translated if it keeps the legacy format) and model to TMDL, single file or batch folder.PBIR visuals: list/document visuals, create visuals (cloning real templates from the report), move/resize and arrange by layouts.
What it does NOT do
It doesn't move or create visuals "live" on the open canvas (Power BI Desktop doesn't expose an API for that). Visuals are edited via PBIR files with the
.pbipproject.It doesn't refresh or publish to the Power BI Service (local only).
It doesn't extract the model from a
.pbixwithout Power BI Desktop: theDataModelstream is a backup compressed with XPress9 that only the Analysis Services engine knows how to read. When converting, the.pbixis opened in Desktop to serialize the model.It doesn't translate legacy format bookmarks to PBIR: their state model is different and the conversion reports them as pending (
dropped) instead of losing them silently. Creating new bookmarks is possible (pbi_create_bookmark).It doesn't invent fields or nonexistent measures when generating pages.
Requirements
Windows (Power BI Desktop is Windows-only) with Power BI Desktop installed.
Python 3.10+ (tested on 3.14).
.NET Framework 4.x (comes with Windows) — used by
pythonnet.Python dependencies:
mcp(includes FastMCP),pythonnet,psutil,python-dotenv.ADOMD.NET + TOM DLLs (Analysis Services). Downloaded without admin rights via
scripts/fetch_libs.py(no need to install in the GAC).To edit/create visuals: the report saved as
.pbipwith PBIR enabled.(Optional) Tabular Editor is not required — see Technical decisions.
Installation
Direct from Codex or Claude (recommended)
You don't need to download or register a .exe, create .mcp.json or manually
locate this repository. The plugin sets up an isolated Python environment in
the client's data folder and verifies every download.
Codex:
codex plugin marketplace add HorizunGroup/horizun-pbi-mcp
codex plugin add horizun-pbi-mcp@horizunClaude Code:
claude plugin marketplace add HorizunGroup/horizun-pbi-mcp
claude plugin install horizun-pbi-mcp@horizunWhen the first session opens, the plugin runs the full setup automatically in
the background. Check pbi_install_status; once it finishes, restart the
client and the 128 pbi_* tools will be available. There are no downloads or
additional scripts the user needs to run manually.
Honest technical limit: there's no dedicated executable, but you do need Windows, Power BI Desktop and Python 3.10+. The server must run locally: a remote MCP cannot access Desktop's local engine or your
.pbipfiles.
Manual installation for development
cd horizun-pbi-mcp
# 1) Python dependencies
python -m pip install -r requirements.txt
# or: python -m pip install -e .
# 2) Analysis Services DLLs (ADOMD.NET + TOM) -> libs/ folder
# Pinned version (19.84.1) and SHA-256 verified before installing.
python scripts/fetch_libs.py
# 3) Official PBIR schemas (needed to WRITE)
# Without them, every PBIR write fails with schema_unavailable.
python scripts/fetch_pbir_schemas.py
# 4) (optional, recommended) Microsoft's official PBIR validator
# Requires Node >= 20. Adds semantic validation of the full report.
python scripts/fetch_report_validator.py
# 5) (optional) configuration
copy .env.example .env # and edit itCheck the result at any time:
python scripts/doctor.pyVerify
With Power BI Desktop open on a report:
python -m horizun_pbi_mcp.server # starts the MCP server (stdio); Ctrl+C to exitFor a quick test without MCP, in Python:
import sys; sys.path.insert(0, "src")
from horizun_pbi_mcp.config import get_session
from horizun_pbi_mcp.powerbi import desktop_discovery, dax_runner
s = get_session()
print(desktop_discovery.discover_instances())
desktop_discovery.select_model(s)
print(dax_runner.run_dax(s, 'EVALUATE ROW("ok", 1)'))Registering with an MCP client
Full guide for Claude Code, Claude Desktop, Codex and generic stdio clients: docs/INSTALL.md.
Each client resolves environment variables, the working directory and the Python interpreter differently, so instead of a ${VAR} template that fails on half of them, there's a generator that resolves the absolute paths on your machine:
python scripts/make_mcp_config.py --client allIt only prints. To create this repository's local .mcp.json (which is in .gitignore):
python scripts/make_mcp_config.py --client claude-code --writeBefore registering anything, check the installation:
python scripts/doctor.pyExits with code 0 if everything mandatory is fine. It distinguishes missing dependency, missing DLL, server that won't start, unexpected MCP contract, Desktop closed, stale session and multiple instances. Power BI Desktop being closed does not fail the base diagnostic (use --require-desktop if you want to require it).
Environment variables (all optional)
Variable | Default | Description |
|
| Folder with the ADOMD.NET/TOM DLLs |
|
| pythonnet runtime ( |
|
| Default row limit in DAX |
|
| Documentation and |
|
|
|
|
|
|
| — |
|
Available tools (128)
Full catalog by block:
docs/TOOL_CATALOG.md. Baseline inventory with risk class and preconditions:docs/TOOL_INVENTORY.md. Names and signatures are frozen intests/golden/tools_v1.jsonand verified bytests/test_tool_contract.py.
Connection / DAX
pbi_list_desktop_models— lists open models (port, connection string, catalog, number of tables).pbi_select_model— sets the active model (byportif there are several).pbi_run_dax— runs DAX (query,max_rows).pbi_test_connection— validates the active connection.pbi_validate_measures— validates measure DAX WITHOUT modifying the model (dry-run withDEFINE MEASURE); useful before creating them.pbi_validate_desktop_render— opens a.pbix/.pbip, captures the exact window by PID without depending on focus and only closes Desktop if the tool itself opened it.
Documentation (Phase 3)
pbi_list_tables,pbi_list_measures,pbi_list_relationships— withsource: live|pbip.pbi_analyze_model_quality— typical model issues.pbi_document_model— complete documentation in Markdown tooutputs/.
Measures (Phase 4) — mode: live|pbip|both, overwrite
pbi_create_measure,pbi_update_measure,pbi_delete_measure(destructive:confirm=true).
Refresh (Phase 5)
pbi_refresh_model—type: full|calculate|clear_values,tablesoptional (local).
PBIP project (Phase 6)
pbi_open_pbip_project(path),pbi_validate_pbip_project,pbi_backup_pbip_project(mode: folder|zip,scope: report|model|both).
.pbix → .pbip conversion
pbi_inspect_pbix— X-ray of the file without converting it or opening Desktop: report format, whether it carries its own model, pages and resources.pbi_list_convertible_pbix— preview of a folder: what would be copied, what would need translating and which ones need Desktop.pbi_convert_pbix_to_pbip— generates the project. Accepts a.pbixor a folder (recursive), and returns per file what was written, the warnings and what was left out (dropped).
The report is translated without Desktop, but the model requires opening each
.pbixin Power BI Desktop (the session is reused if it's already open, and closed if the tool opened it). Withinclude_model=falseonly the report half is generated, instantly. The original.pbixis never modified.Power BI Desktop does not open a
.pbipwith paths of 260 characters or more: pick a shortout_dir(C:\pbip). The tool checks this before writing and aborts with the detail instead of leaving a project that won't open.
Model editing
pbi_set_column_visibility/pbi_hide_columns— hide/show columns (e.g. IDs).mode: live|pbip|both.pbi_set_relationship_direction— cross filtersingle|bothof a relationship.mode: live|pbip|both.pbi_disable_auto_date_time— enables/disables "Auto date/time" (pbiponly).
PBIR Report (Phases 7–10)
pbi_list_report_pages,pbi_list_visuals(page),pbi_document_report_layout.pbi_create_visual—page,visual_type,fields,position,title(clones an existing visual as a template).pbi_update_visual_position,pbi_arrange_visuals(layout: grid|dashboard|executive_summary|custom).pbi_generate_report_page— assisted page generation from the model.
HTML inside Power BI
pbi_add_custom_visual— registers an AppSource custom visual in the report (defaults to HTML Content, which renders HTML/SVG from a DAX measure).pbi_create_html_visual— creates an HTML Content visual bound to a measure that returns HTML (html_measure).pbi_create_measurewithdata_category: "ImageUrl"— measures that return an SVG data-URI and render as an image in native tables/matrices.
Natural-language sheet generation
pbi_page_building_blocks— content inventory (model + catalog of existing visuals + canvas) to design a sheet.pbi_preview_spec_html— HTML mockup of a proposed sheet (review before writing).pbi_create_page_from_spec— materializes a full PBIR sheet from aspec(clones existing visuals by style).pbi_export_page_html— exports an existing page to an HTML mockup.
Every tool returns {"ok": true/false, ...}; on error it includes error (code) and message (the engine's original message, never hidden).
Sheet generation flow:
pbi_page_building_blocks→ (Claude interprets your instruction and builds aspec) →pbi_preview_spec_html(you review the HTML) →pbi_create_page_from_spec(the PBIR gets written).
Usage examples (in natural language with Claude)
Run DAX: "List the open models, select the only one, and run
EVALUATE TOPN(10, Sales)."Document: "Document the active model and analyze its quality." → generates
outputs/model_documentation_*.md.Create measure: "Create the measure
Margin % = DIVIDE([Profit],[Sales])in the Sales table, format0.0%, mode both."List visuals: "Open the
.pbipat C:/…/Report.pbip and list the visuals on the 'Summary' page."Create visual: see
examples/sample_visual_specs.json.Arrange page: "Arrange the 'Summary' page with executive_summary layout."
More DAX in examples/sample_queries.md.
⚠️ PBIR editing and Desktop state: report edits (visuals/layout) are made to files; it's best to make them with Power BI Desktop closed and reopen it to see them (if Desktop is open and you save, it overwrites the changes on disk). Live model edits (
livemeasures) require Desktop open and are persisted on save (Ctrl+S).
Troubleshooting
Doesn't detect the port / "No se detecto ningun modelo": open the report in Power BI Desktop; the port changes on every startup (the MCP discovers it on its own). If you use the Microsoft Store version, it's still detected by process.
adomd_not_installed/tom_not_installed: runpython scripts/fetch_libs.py. Check thatlibs/Microsoft.AnalysisServices.AdomdClient.dllexists.clr_not_available: .NET is missing; tryPBI_MCP_DOTNET_RUNTIME=coreclr.DAX error: the engine's message is returned as-is in
message. Check the syntax (EVALUATE, quotes).pbir_not_enabled: the report isn't in PBIR. Save as.pbipand enable Power BI Project (PBIR) format under Options → Preview Features (if applicable to your version) before saving.Power BI doesn't reload visual changes: close it and reopen it; PBIR loads on open, not live.
Permissions/OneDrive: if the
.pbipis in OneDrive, close Desktop before editing files and wait for OneDrive to finish syncing; backups are saved inbackups/.
Technical decisions
TOM via
pythonnet(not the Tabular Editor CLI). Evaluated: (1) Tabular Editor 2 CLI, (2)pythonnetloading TOM, (3) editing TMDL directly. Sincepythonnetworks on Python 3.14 and the ADOMD.NET/TOM DLLs can be vendored intolibs/without admin or GAC, loading them directly withpythonnet(runtimenetfx) was chosen. It's more stable, has no external installation dependencies, and gives full control (create/edit measures and refresh, just like Tabular Editor). Durable editing is still available via TMDL in.pbip.Visuals by cloning.
pbi_create_visualclones an existing visual of the same type as a template (preserving the format/theme scaffolding) and only falls back to a minimal template if none exists, warning that it must be validated in Desktop.Security (Phase 11): automatic backup before every
.pbipwrite; atomic JSON (never leaves corrupted files); doesn't overwrite unreadable JSON; path validation;change_log.mdinoutputs/; destructive operations requireconfirm=true.
Limitations / open risks
None of these is a defect that can be fixed from here. They're documented because they affect what the server can promise.
Schemas Microsoft doesn't publish
Power BI Desktop writes visualContainer/2.10.0 and 2.11.0 in recent
reports, and those URLs return 404 at the official source. The same
happens with bookmarks/2.0.0. Microsoft's own official CLI can't validate
them either: it emits PBIR_SCHEMA_UNREACHABLE and skips validation of
those files.
For visualContainer, 2.10/2.11 are compared against 2.7 because that
downgrade was measured against 275 real files and only differs in what a
later version might add. bookmarks/2.0.0 is blocked with
schema_unavailable because there's no earlier version of the same family to
check it against.
Measured on a real 443-document report: 176 validate, 240 remain blocked for this reason.
G10 remains a documented release exception.
mode="both" blocked
live requires Power BI Desktop open; pbip requires it closed. There's no system state in which both destinations can be safely written in a single call. See docs/DUAL_MODE.md. R15 open.
filters and interactions in the page spec
They are rejected with unsupported_feature indicating the exact JSON path. They aren't silently dropped. Their serialization to PBIR is pending.
Others
PBIR must be enabled in the
.pbip;pbi_validate_pbip_projectchecks this.The friendly name of the open report isn't always readable from the engine (port + catalog are reported instead).
The on-disk TMDL parser is pragmatic (tables, columns, measures, relationships); for rich metadata, use the
livepath.pbi_generate_report_pageis a heuristic composition; it doesn't invent fields and warns about what it ignores.The server starts without Node; what gets blocked are the writes that need the official validator.
Project structure
horizun-pbi-mcp/
├─ src/horizun_pbi_mcp/ # single installable package
│ ├─ server.py # FastMCP + tool registration
│ ├─ config.py # settings + session (active model/pbip)
│ ├─ logging_config.py
│ ├─ reporting.py # Markdown documentation + quality
│ ├─ branding.py # product identity and version
│ ├─ powerbi/ # live layer (ADOMD/TOM)
│ ├─ pbip/ # on-disk layer (TMDL/PBIR)
│ ├─ services/ # security, validation, audit, workflows
│ ├─ tools/ # MCP tools by area
│ └─ utils/ # JSON, files, validation, change_log
├─ scripts/fetch_libs.py # downloads Analysis Services DLLs
├─ examples/ tests/ outputs/ libs/
├─ README.md PLAN.md pyproject.toml requirements.txt .env.exampleTests
python -m pytest -q1793 tests, 3 skipped. The skip is environmental and says how to run it:
Skipped | Condition |
| Requires a Power BI Desktop instance serving a model. |
| Requires the synthetic model to trigger only informational rules |
Available markers:
python -m pytest -m "not packaging" # fast: skips wheel and sdist
python -m pytest -m live # against an open Power BI Desktop
python -m pytest -m live_validator # against Microsoft's official CLIVerify the MCP contract (the 128 tools are frozen):
python -m tests.contract_utilsReturns 0 if there are no breaks, 1 if there are, with a report stating what changed and whether it breaks compatibility.
Installation diagnostics:
python scripts/doctor.pyLicense
Open source under the Apache License 2.0. Also see NOTICE for third-party attributions and trademarks.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseCqualityAmaintenanceLocal-first MCP server for Power BI Desktop automation. Automate semantic model changes, DAX, Power Query, Excel, and report layout from MCP-capable AI clients.Last updated100MIT
- Alicense-qualityDmaintenanceMCP server for connecting to Microsoft Fabric and Power BI semantic models, enabling workspace browsing, dataset management, TMSL retrieval, DAX queries, model creation/editing, and includes a Best Practice Analyzer with 71 rules.Last updated2MIT
- Alicense-qualityBmaintenanceLocal MCP server for editing Power BI Project reports saved in PBIR format.Last updatedGPL 2.0
- Flicense-qualityDmaintenanceMCP server for reading and analyzing Fabric semantic models. Supports getting model definitions and executing DAX queries against Power BI datasets.Last updated17
Related MCP Connectors
The MCP server for Azure DevOps, bringing the power of Azure DevOps directly to your agents.
Official Microsoft MCP Server to query Microsoft Entra data using natural language
MCP server for interacting with the Supabase platform
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/HorizunGroup/horizun-pbi-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server