Power BI Report MCP Server
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., "@Power BI Report MCP Server Create a sales overview page with KPI cards and a monthly trend line"
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.
"Create an executive summary page with 6 KPI cards, a revenue trend line chart, and a bar chart by country"
One prompt. One batch call. Full page in Power BI Desktop.
What's new in 0.9
Layout validator now reachable via
pbir_validate_wireframe(v0.9.6) — same checks the test suite runs (margins, gaps, overlap, off-canvas, banner geometry), callable from agents on a single page or across the entire reportTier C.1 catalog reduction +
pbir_guidefix (v0.9.5) — see CHANGELOG.md
What's new in 0.8
pbir_tool prefix — every tool name now starts withpbir_to avoid collisions with sibling MCP servers in the same sessionCowork plugin — drop a single
.pluginfile into Claude (no terminal, no Node install) — see Quick Start › Cowork pluginregisterToolmigration — modern MCP SDK entrypoint with structuredoutputSchemaon every read toolTypo catcher + auto-pageId — fewer "did you mean…" round-trips when there's only one page
Tighter
outputSchema(v0.8.2) — 14 read tools now ship per-tool zod response schemas; mutation tools keep the loose envelope
Full details: CHANGELOG.md.
Credit: This project was created and written entirely by Jonathan Papworth (
jonathan-pap). The original repository atgithub.com/jonathan-pap/powerbi-report-mcpis no longer online, so this repository preserves his work unchanged, under his original MIT license. All credit for the design, code, skills, and documentation belongs to him.
What is this?
The first open-source MCP server for Power BI report authoring. It connects Claude (or any MCP-compatible client — see Tested clients) to Power BI's PBIR (Power BI Report) file format, turning natural language into real report pages — cards, charts, tables, themes, filters, and formatting.
No REST API keys. No Power BI service. Just local files + Claude.
You: "Build me a sales dashboard with KPIs, trend charts, and a detail table"
AI: pbir_create_page → pbir_add_visual (batch: 12 visuals) → pbir_set_report_theme → done.
Open in Power BI Desktop. ✓Related MCP server: pbi-mcp
Why MCP?
MCP (Model Context Protocol) is an open standard that lets AI assistants call external tools. Instead of the AI generating code for you to run, it directly executes operations through the MCP server.
graph LR
subgraph AI["AI Assistant"]
LLM["Claude, GPT,<br/>Copilot, Cursor..."]
end
subgraph MCP["Two MCP Servers"]
direction TB
MODEL["powerbi-modeling-mcp<br/><i>Tables, columns, measures, DAX</i>"]
REPORT["powerbi-report-mcp<br/><i>Pages, visuals, themes, filters</i>"]
end
subgraph Files["Power BI Project"]
direction TB
SEM[".SemanticModel<br/><i>TMDL / measures</i>"]
REP[".Report<br/><i>PBIR / visual.json</i>"]
end
PBI["Power BI<br/>Desktop"]
LLM <-->|"stdio / MCP"| MODEL
LLM <-->|"stdio / MCP"| REPORT
MODEL <-->|"read"| SEM
REPORT <-->|"read/write"| REP
REP -->|"open .pbip"| PBIThe typical workflow:
1. Query the model --> "What tables and measures are available?" (modeling-mcp)
2. Build the report --> "Create a dashboard with those measures" (report-mcp)
3. Open in Desktop --> Ctrl+Shift+F5 to refreshBoth servers run simultaneously as MCP tools. The AI queries the semantic model for exact table/column/measure names, then uses those to build correctly-bound report pages — no guessing, no broken fields.
Zero vendor lock-in — built on @modelcontextprotocol/sdk + zod. No Anthropic, OpenAI, or Microsoft SDK imports.
How It Compares
This MCP Server | Manual PBI Desktop | Power BI REST API | pbi-tools | |
Input | Natural language | Mouse clicks | REST calls + auth | CLI commands |
Speed | 10-page report in minutes | Hours | Hours (code-heavy) | Minutes (extract/deploy) |
Auth required | None (local files) | None | Azure AD + Service Principal | None |
AI-native | Yes (MCP) | No | No | No |
Format | PBIR (file-based) | PBIX (binary) | Cloud-only | PBIX ↔ folder |
Creates visuals | Yes | Yes | Limited | No (metadata only) |
Themes & formatting | Yes | Yes | Limited | No |
Filters | Yes | Yes | Yes | No |
Works offline | Yes | Yes | No | Yes |
Quick Start
Full walkthrough: docs/quickstart.md
1. Install
git clone https://github.com/ansehh/powerbi-report-mcp.git
cd powerbi-report-mcp
npm install
npm run build2. Configure your MCP client
Ready-to-use config files are in the configs/ folder — copy the one for your client, update the path, done.
Config | Client | Copy to |
Claude Desktop |
| |
Cursor |
| |
GitHub Copilot |
| |
Windsurf |
| |
Continue.dev |
| |
Cline | VS Code Settings → MCP Servers |
Claude Code (no config file needed):
claude mcp add powerbi-report-mcp node C:\path\to\powerbi-report-mcp\dist\index.jsEach config includes both powerbi-report-mcp and powerbi-modeling-mcp for full dual-layer access. See configs/README.md for optional settings (pre-connect to a report, load all tools at startup).
Optional: opt into minimal tool loading
For long Claude Code / Cowork sessions where catalog tokens matter, set MCP_TOOLS=minimal to load only the 12 default tools at startup (saves ~7,500 catalog tokens; the remaining 44 activate on demand via pbir_load_tools):
{
"mcpServers": {
"powerbi-report-mcp": {
"command": "node",
"args": ["/path/to/powerbi-report-mcp/dist/index.js"],
"env": {
"MCP_TOOLS": "minimal" // optional — saves ~7,500 catalog tokens
}
}
}
}Trade-off summary (full breakdown in Smart Tool Loading below):
Default (load-all) — All 56 tools available immediately. Best for unpredictable/exploratory sessions and clients that snapshot the tool list at startup. ~14,500 catalog tokens.
MCP_TOOLS=minimal— 12 default tools at startup; others activatable viapbir_load_tools. Best for known-narrow workflows. ~7,000 catalog tokens. Requires MCP client support fornotifications/tools/list_changedto surface activated tools mid-session — Claude Code/Desktop don't refresh; Cowork may; verify before relying.
3b. Cowork plugin
Prefer to skip the git clone/npm install dance? Grab the latest .plugin bundle from GitHub Releases and drag it into Claude — the plugin ships the server, skills, and a default MCP wiring in one file.
Step | Action |
1 | Download |
2 | Open Claude → Settings → Plugins → Install from file (or drag-and-drop the |
3 | Approve the bundled MCP server when prompted |
4 | In any Claude conversation: "Connect to C:\Projects\Sales.Report and list pages" |
Cowork is a hosted Claude experience with native plugin support. The plugin bundle is a single zip; nothing leaves your machine and the MCP server still runs locally over stdio.
3. Connect and build
Connect to C:\Projects\Sales.Report
Create a page called "Overview" with 4 KPI cards and a bar chart by country4. Open in Power BI Desktop
Open the .pbip file — or if already open, press Ctrl+Shift+F5 to refresh.
Headless / eval mode
For automated/eval use you can auto-bind a report at startup with the PBIR_REPORT_PATH env var instead of calling pbir_set_report:
PBIR_REPORT_PATH=evals/fixtures/sample.Report node dist/index.jsIf the path is invalid the server logs to stderr and continues running unbound (use pbir_set_report to recover). The CLI arg form (node dist/index.js <path>) still works and wins when both are set.
Smart Tool Loading
By default all 56 tools load at startup — this is the most compatible configuration, and what you want for Claude Desktop and most other MCP clients whose tool catalog is a snapshot taken at session start.
For token-sensitive setups (e.g. Claude Code with large prompt budgets on dev machines), you can opt into the minimal mode — only 12 core tools load at startup, and the LLM activates more on-demand via pbir_load_tools:
"env": { "MCP_TOOLS": "minimal" }graph TD
subgraph DEFAULT["11 Core Tools — always loaded in both modes"]
A1[pbir_set_report] --- A2[pbir_list_pages] --- A3[pbir_list_visuals] --- A4[pbir_create_page] --- A5[pbir_add_visual]
B1[pbir_get_visual] --- B2[pbir_format_visual] --- B3[pbir_update_visual_bindings] --- B4[pbir_set_report_theme] --- B5[pbir_bulk_bind]
C1[pbir_model_usage]
end
LT[pbir_load_tools -- always available]
subgraph ONDEMAND["43 On-Demand Tools"]
C1[pbir_delete_page] --- C2[pbir_rename_page] --- C3[pbir_duplicate_page] --- C4[pbir_move_visual] --- C5[pbir_delete_visual]
D1[pbir_set_datapoint_colors] --- D2[pbir_set_conditional_format] --- D3[pbir_add_page_filter] --- D4[pbir_set_visual_sort] --- D5[guide]
E1[pbir_list_bookmarks] --- E2[pbir_set_page_background] --- E3[...]
end
DEFAULT --> LT --> ONDEMAND
style DEFAULT fill:#1a7f37,color:#fff
style ONDEMAND fill:#333,color:#ccc
style LT fill:#0078D4,color:#fffMode | Tools at Startup | Token Overhead | Use Case |
| 56 + | ~16,500 tokens | Claude Desktop, most clients, first-time users |
| 12 + | ~3,400 tokens | Claude Code / clients that refresh the tool list mid-session |
| 56 + | ~16,500 tokens | Same as default; kept for backward-compat |
Default is "load everything" because Claude Desktop snapshots the MCP tool catalog at session start and never refreshes it — tools activated mid-session via
pbir_load_toolswould otherwise be invisible to the model. Clients that honourtools/list_changednotifications (Claude Code, Cowork) can opt intoMCP_TOOLS=minimalto claw back ~13k tokens.
Tool Reference
Default Tools
Tool | Description |
| Connect to a |
| List all pages (id, name, visual count) |
| List visuals on a page (id, type, position, title) |
| Create a new page |
| Add one or many visuals with bindings, formatting, colors |
| Inspect a visual's config and bindings |
| Format axes, legend, labels, borders, background |
| Replace data bindings on a visual |
| Apply a custom JSON theme to the whole report |
| Rebind multiple visuals in one call |
| Cross-reference semantic model with report — three-tier classification (direct/indirect/unused), DAX lineage, UDF functions, conditional formatting detection |
| List and activate on-demand tools |
Why pbir_model_usage is a default tool — the deletion fail-safe
pbir_model_usage ships in the default set (not on-demand) because it is the safety layer for AI-driven cleanup of the semantic model. When a user asks Claude to "remove unused measures" or "clean up dead columns", the model would otherwise guess based on measure names and delete things blindly — and break visuals that depend on indirect references.
With pbir_model_usage always available, the LLM can call it first and see the full dependency picture before touching anything:
Scenario | Without | With |
User: "delete all unused measures" | LLM guesses by name, deletes | LLM sees |
User: "is | LLM greps the visual JSON, misses conditional formatting bindings | LLM sees it bound to |
User: "which UDF functions can I drop?" | LLM has no lineage info | LLM sees reference counts per function and flags zero-reference functions |
The MCP tool gives Claude that understanding before it mutates anything — what prevents "oops" deletes. The tool returns a slim JSON response (~7K tokens) by default so it's cheap to call before every destructive operation.
On-Demand Tools (43)
Tool | Description |
| Show connected report path |
| Reopen report in PBI Desktop |
| Read report-level settings |
| Merge new report settings |
| All pages + visuals in one call |
| Delete a page and its visuals |
| Rename a page |
| Clone a page with all visuals |
| Set page order |
| Set default page on open |
| Change page dimensions |
| Show/hide from navigation |
| Auto-arrange visuals in a grid |
| Show/hide and expand/collapse the filter pane |
| Set page canvas background color and/or wallpaper |
| Set cross-filter/highlight interaction between visuals |
| Add, list, or remove report-level DAX measures |
Tool | Description |
| Remove a visual |
| Clone a visual |
| Reposition and resize |
| Swap type, keep bindings |
| List all visual types and buckets |
Tool | Description |
| Set title text, font, alignment |
| Per-series or per-category colors |
| Rules-based or gradient formatting |
| Set or change sort order (column/measure, ascending/descending) |
| Apply a preset theme to a page |
| Scan visuals for formatting overrides conflicting with theme |
Tool | Description |
| Get current theme JSON |
| Revert to default theme |
| List stored theme files |
| Compare proposed vs current theme |
Tool | Description |
| List page or visual filters |
| Add categorical, TopN, relative date, or advanced filter |
| Remove a filter by name |
| Remove all filters |
Tool | Description |
| Delete multiple visuals |
| Format multiple visuals |
Tool | Description |
| List all bookmarks in the report |
| Create a new bookmark |
| Delete a bookmark |
| Rename a bookmark |
Tool | Description |
| Domain knowledge for PBI development — topics: |
The pbir_guide tool provides focused, actionable knowledge to help AI agents make better decisions. Instead of loading large skill files into every session, agents call pbir_guide("topic") on demand. The SVG visuals topic includes 4 DAX templates, binding rules, and workflow steps.
Batch Mode — Build Pages Fast
Create an entire page in a single pbir_add_visual call:
{
"pageId": "abc123",
"visuals": [
{
"visualType": "shape", "shapeType": "rectangle",
"x": 0, "y": 0, "width": 1280, "height": 50,
"fillColor": "#1F3864", "textContent": "Sales Dashboard",
"textColor": "#FFFFFF", "textBold": true, "textSize": 20
},
{
"visualType": "card",
"x": 10, "y": 60, "width": 300, "height": 100,
"title": "Revenue",
"bindings": [
{ "bucket": "Fields", "fields": [{ "field": "Sales[Revenue]", "type": "measure" }] }
]
},
{
"visualType": "clusteredBarChart",
"x": 10, "y": 170, "width": 620, "height": 260,
"title": "Revenue by Country",
"bindings": [
{ "bucket": "Category", "fields": [{ "field": "Store[Country]", "type": "column" }] },
{ "bucket": "Y", "fields": [{ "field": "Sales[Revenue]", "type": "measure" }] }
],
"dataColors": [{ "color": "#0078D4" }]
}
]
}One call creates the banner, KPI card, and chart — with data bindings, titles, and colors.
Supported Visual Types
Full reference: docs/visual-types.md
Naming Gotchas
barChart = Stacked bar (NOT clustered)
columnChart = Stacked column (NOT clustered)
clusteredBarChart = Clustered bar ✓
clusteredColumnChart = Clustered column ✓
stackedBarChart = DOES NOT EXIST ✗ (use barChart)
scatterChart = Uses "Details" bucket, NOT "Category"
Combo charts = Use "ColumnY" + "LineY", NOT "Y" + "Y2"Quick Reference
Category | Types |
Bar/Column |
|
Line/Area |
|
Combo |
|
Pie/Donut |
|
Tables |
|
Cards |
|
Slicers |
|
Maps |
|
Scatter |
|
Other |
|
Decorative |
|
Formatting
pbir_format_visual(target="auto") → auto-routes to container or visual (default)
pbir_format_visual(target="container") → title, background, border, padding, shadow
pbir_format_visual(target="visual") → axes, legend, labels, line styles, data pointsCategory | Properties |
|
|
|
|
|
|
|
|
|
|
|
|
Category | Properties | Applies To |
|
| Bar, column, line, combo |
|
| Bar, column, line, combo |
|
| Charts with Series |
|
| Most charts |
|
| Line, area, combo |
|
| Most charts |
Hex colors starting with
#are automatically wrapped in PBIR format.
Themes & Conditional Formatting
Report-Level Theme
{
"name": "Corporate Brand",
"dataColors": ["#0078D4", "#00BCF2", "#00B294", "#FF8C00", "#E81123"],
"background": "#FFFFFF",
"foreground": "#1F3864",
"tableAccent": "#0078D4"
}Gradient Conditional Format
{
"formatType": "gradient",
"entity": "Sales", "property2": "Revenue", "isMeasure": true,
"minColor": "#FF6B6B", "midColor": "#FFD93D", "maxColor": "#6BCB77"
}Page Themes (presets)
dark · light · corporate · blue-purple
Filters
// Categorical — include specific values
{ "filterType": "categorical", "entity": "Store", "property": "Region", "values": ["East", "West"] }
// TopN — top 10 products (visual-level only)
{ "filterType": "topN", "entity": "Product", "property": "Name", "n": 10,
"topNDirection": "Top", "orderByEntity": "Sales", "orderByProperty": "Revenue",
"orderByIsMeasure": true, "visualId": "xyz" }
// Relative date — last 12 months
{ "filterType": "relativeDate", "entity": "Date", "property": "Date",
"period": "months", "count": 12, "dateDirection": "last" }Architecture
powerbi-report-mcp/
├── src/
│ ├── index.ts # Server entry, smart tool loading, safe() wrapper
│ ├── pbir.ts # PbirProject — PBIR file I/O abstraction
│ ├── context.ts # ServerContext interface
│ ├── model-usage.ts # Model usage analysis — three-tier classification, UDF parsing, conditional formatting
│ ├── tools/
│ │ ├── report.ts # Page & report management (20 tools)
│ │ ├── visuals.ts # Visual CRUD (8 tools)
│ │ ├── format.ts # Formatting, sort & colors (6 tools)
│ │ ├── bindings.ts # Data binding (1 tool)
│ │ ├── themes.ts # Report themes (6 tools)
│ │ ├── filters.ts # Page/visual filters (4 tools)
│ │ ├── bulk.ts # Bulk operations (3 tools)
│ │ ├── bookmarks.ts # Bookmark CRUD (4 tools)
│ │ └── guide.ts # Knowledge layer (1 tool, 2 topics)
│ └── helpers/
│ ├── createVisual.ts # Visual creation engine
│ ├── formatting.ts # PBIR formatting builder
│ └── defaults.ts # Theme presets
├── .usage/ # Generated usage dashboards (gitignored)
├── dist/ # Compiled JS (committed for no-build deploy)
├── pbi report/ # Sample report (financials model)
├── docs/ # Guides and references
└── skills/ # LLM skill documentsFull details: ARCHITECTURE.md
Data Flow
sequenceDiagram
actor User
participant AI as AI Assistant
participant Model as powerbi-modeling-mcp
participant Report as powerbi-report-mcp
participant PBI as Power BI Desktop
User->>AI: "Create a sales dashboard with KPIs and a chart by country"
AI->>Model: What measures are on the Sales table?
Model-->>AI: Net Revenue, Net Profit, Margin %, Orders, Units Sold
AI->>Report: pbir_create_page("Sales Dashboard")
Report-->>AI: pageId: abc123
AI->>Report: pbir_add_visual(batch: 6 cards + 2 charts + table)
Report-->>AI: 9 visuals created
AI->>Report: pbir_set_report_theme({ dataColors: [...] })
Report-->>AI: theme applied
AI-->>User: Done! Open .pbip in Power BI Desktop
User->>PBI: Ctrl+Shift+F5PBIR Folder Structure
MyProject.Report/
definition/
report.json # Report settings, theme config
pages/
pages.json # Page order and active page
{pageId}/
page.json # Page name, size, visibility
visuals/
{visualId}/
visual.json # Type, position, bindings, formatting
StaticResources/
RegisteredResources/ # Custom theme JSON files
definition.pbir # Semantic model referenceToken Efficiency
Mode | Tools Loaded | Tokens/Turn | Cost per 10-Page Report |
Default | 11 | ~3,100 | $0.01 – $0.45 |
All | 48 | ~14,500 | $0.02 – $2.50 |
Model | Input $/1M | Output $/1M | Base Report | Fully Styled |
GPT-4o-mini | $0.15 | $0.60 | $0.01 | $0.02 |
GPT-4.1-mini | $0.40 | $1.60 | $0.02 | $0.05 |
GPT-4.1 | $2.00 | $8.00 | $0.11 | $0.25 |
GPT-4o | $2.50 | $10.00 | $0.14 | $0.32 |
Claude Haiku 3.5 | $0.80 | $4.00 | $0.05 | $0.12 |
Claude Sonnet 4 | $3.00 | $15.00 | $0.19 | $0.45 |
Claude Opus 4 | $15.00 | $75.00 | $0.96 | $2.25 |
Approach | Calls | Tokens |
Batch + bulk (recommended) | 22–32 | ~28–32K |
Per-visual calls (naive) | 300+ | ~120K |
Use pbir_add_visual batch mode + inline title, dataColors, containerFormat to build fully styled pages in minimal calls.
Tested clients
The MCP is built on the standard MCP protocol. Currently verified against:
Client | Status | Config |
Claude Code | ✅ Tested |
|
Claude Desktop | ✅ Tested |
|
Claude Cowork | ✅ Tested | Drag the |
Other MCP-compatible clients (Cursor, Continue.dev, Cline, GitHub Copilot agent mode, OpenAI via mcp-proxy, custom @modelcontextprotocol/sdk agents) should work since this is a standard MCP server — but they haven't been verified against this codebase yet. If you try one and it works (or doesn't), please open an issue so we can update this table.
Documentation
Doc | Description |
5-minute setup guide | |
15 example prompts | |
Visual type reference + formatting containers per type | |
Layout guide — zones, spacing, 3 sample layouts with exact positions | |
PBIR schema discoveries | |
Codebase architecture | |
How to contribute | |
Version history |
Known Issues
Feature | Status | Notes |
Visual calculations | Disabled | Correct PBIR format identified but not rendering programmatically |
Tips
Pair with powerbi-modeling-mcp to query the semantic model for exact table/column names before binding
Use
Table[Column]shorthand in bindings:"field": "Sales[Revenue]"barChart= stacked bar,clusteredBarChart= clustered — there is nostackedBarChartAdd shapes before data visuals for correct z-order layering
pbir_format_visualmerges with existing formatting — safe to call incrementallyTopN filters are visual-level only — pass
visualIdtopbir_add_page_filterAll tools return
{ success: false, error: "..." }on failure — the server never crashesUse
pbir_model_usageto see which measures/columns are used in visuals — it classifies fields as direct (on a visual), indirect (referenced by direct measures/relationships), or unused (safe to remove). It detects conditional formatting bindings (images, reference labels, colors) that other tools missAlways call
pbir_model_usagebefore any delete / cleanup request — it's the fail-safe that stops the LLM from removing indirectly-referenced measures. See Whypbir_model_usageis a default tool for the full rationalepbir_model_usagealso parses UDF functions and calculation groups from TMDL/BIM, counts measure references per function, and surfaces DAX lineage
License & Credits
MIT — Copyright (c) 2026 Jonathan Papworth. Use it however you want, but keep his copyright and license notice in every copy.
Everything in this repository — the server, the tools, the skills, the docs, the evals — was written by Jonathan Papworth. This repository only keeps his work available after the original repository went offline.
Available Tools
57 toolspbir_add_bookmarkAdd BookmarkA
Create a new bookmark. The bookmark is created with an empty exploration state — open Power BI Desktop to capture the current view state into it.
Inputs: displayName (required), activePageId.
pbir_add_page_filterAdd Page FilterA
Add a filter to a page or visual. Omit visualId for page-level. topN requires visualId. Types: categorical / topN / relativeDate / advanced (Equals, GreaterThan, Contains, IsBlank, etc; supports And/Or compounds).
Inputs: entity (required), property (required), filterType (required), n, +15 more.
pbir_add_visualAdd VisualA
Add visuals to a page via visuals: [...] batch. Inline containerFormat/visualFormat/dataColors per entry avoids extra pbir_format_visual calls. Stacked charts need a Series binding; 'KPI card' = card with one measure; scatter uses Category bucket. Use pbir_lookup_theme_property for valid category/property names.
Inputs: visuals (required), pageId, includeTypes, strictLayout, +1 more.
pbir_apply_themeApply ThemeB
Apply a named theme preset to all visuals on a page. Themes: dark, light, corporate, blue-purple.
Inputs: theme (required), pageId, applyDataColors.
pbir_audit_theme_complianceAudit Theme ComplianceARead-only
Audit visuals on a page for theme overrides. Returns summary header + topN findings (default 20). topN:0 = all.
Inputs: pageId (required), topN, verbose. Returns: hint, error, _cache, byCode, +11 more
pbir_auto_layoutAuto LayoutC
Auto-arrange all visuals on a page in a grid.
Inputs: pageId (required), columns, padding, marginTop, +1 more.
pbir_bulk_bindBulk BindA
Rebind multiple visuals in one call. Replaces existing bindings. Set confirmBulk:true when >5. continueOnError:true validates per-entry — bad bindings don't abort the batch.
Inputs: updates (required), pageId, autoFilters, confirmBulk, +2 more.
pbir_bulk_delete_visualsBulk Delete VisualsBDestructive
Delete multiple visuals from a page. Set confirmBulk:true when >5.
Inputs: visualIds (required), pageId, confirmBulk.
pbir_bulk_update_formatBulk Update FormatA
Apply the same formatting to multiple visuals. target='container' (title/background/border) or 'visual' (axes/legend/labels). Set confirmBulk:true when >5.
Inputs: visualIds (required), formatting (required), pageId, target, +1 more.
pbir_change_visual_typeChange Visual TypeA
Change the visual type of an existing visual (e.g. barChart to columnChart) while keeping data bindings
Inputs: pageId (required), visualId (required), visualType (required).
pbir_clear_filtersClear FiltersADestructive
Remove ALL filters from a page or a specific visual.
Inputs: pageId (required), visualId.
pbir_create_pageCreate PageB
Create a new page in the report. Supports standard, tooltip, and drillthrough page types.
Inputs: displayName (required), type, width, height, +2 more.
pbir_delete_bookmarkDelete BookmarkADestructive
Delete a bookmark by ID.
Inputs: bookmarkId (required).
pbir_delete_pageDelete PageADestructive
Delete a page and all its visuals
Inputs: pageId (required).
pbir_delete_visualDelete VisualADestructive
Delete a visual from a page
Inputs: visualId (required), pageId.
pbir_diff_report_themeDiff Report ThemeARead-only
Compare a proposed theme JSON against the currently applied theme and return what would be added, removed, or changed. Useful for previewing theme changes before applying.
Inputs: theme (required). Returns: added, error, _cache, changed, +4 more
pbir_duplicate_pageDuplicate PageA
Duplicate an entire page with all its visuals to a new page
Inputs: pageId (required), displayName.
pbir_duplicate_visualDuplicate VisualB
Duplicate an existing visual, optionally to a different page or position
Inputs: pageId (required), visualId (required), offsetX, offsetY, +1 more.
pbir_format_visualFormat VisualA
Format visual properties. Auto-routes title/background/border/padding/dropShadow/visualHeader to container, others to visual; override with target='visual'|'container'. Call pbir_lookup_theme_property for valid category/property names per visualType. Gotchas: slicer uses textSize, not fontSize (items/header); waterfall uses sentimentColors, not dataPoint.
Inputs: visualId (required), formatting (required), pageId, target.
pbir_get_reportGet ReportARead-only
Show the currently connected report path. Includes hasSemanticModel: boolean — true when a sibling .SemanticModel/ folder exists. Check this before calling pbir_model_usage.
Inputs: no named parameters. Returns: error, _cache, success, reportPath, +1 more
pbir_get_report_settingsGet Report SettingsARead-only
Get the report-level settings and theme configuration
Inputs: no named parameters.
pbir_get_report_themeGet Report ThemeARead-only
Get the currently applied theme. Returns base theme name + custom theme JSON if any.
Inputs: no named parameters. Returns: error, _cache, success, baseTheme, +2 more
pbir_get_visualGet VisualARead-only
Get visual details. Default returns id/type/position/title/bindings summary. verbose:true returns full PBIR JSON.
Inputs: visualId (required), slim, pageId, verbose. Returns: h, w, x, y, +12 more
pbir_get_visual_typesGet Visual TypesARead-only
List available visual types. Default returns slim type list (~150 tokens). Pass verbose:true for per-type data-role bucket metadata (~1,200 tokens).
Inputs: verbose.
pbir_guideGuideARead-only
Domain knowledge for Power BI report development. Topics discovered live from skills/*.md — call with topic:'list' to enumerate.
Inputs: topic (required).
pbir_layout_gridLayout GridA
Compute a deterministic rows×cols grid; server owns margin/gap/remainder math. Use this INSTEAD of N pbir_add_visual calls when building a page from scratch. planOnly:true (default) returns the plan; planOnly:false validates bindings+layout then writes in one call. See guide('wireframes') for grid-shape selection.
Inputs: cols (required), rows (required), cells (required), gaps, +7 more.
pbir_list_bookmarksList BookmarksARead-only
List all bookmarks defined in the report.
Inputs: no named parameters. Returns: count, error, _cache, success, +1 more
pbir_list_filtersList FiltersARead-only
List filters on a page or visual. Slim mode (default) returns Table[Column] strings.
Inputs: slim, pageId, visualId. Returns: count, error, scope, _cache, +2 more
pbir_list_pagesList PagesARead-only
List pages (paginated). Slim default returns id/displayName/width/height/visualCount/isActive/hidden; slim:false adds displayOption. includeVisuals:true (or pageId) embeds per-visual summaries. Top-level totalVisualCount sums the FULL set, not just the visible slice. For cross-page sweeps prefer one includeVisuals:true call over fanning out per-page pbir_list_visuals.
Inputs: slim, limit, offset, pageId, +1 more. Returns: error, pages, total, _cache, +9 more
pbir_list_report_themesList Report ThemesARead-only
List all theme files stored in the report's StaticResources/RegisteredResources/ folder.
Inputs: no named parameters. Returns: error, _cache, success, themeFiles
pbir_list_visualsList VisualsARead-only
List visuals on a page (paginated). Default slim returns id/type/x/y/w/h/title. slim:false includes filterCount. Use limit/offset to page through large pages. Use visualType to filter for cross-page sweeps in combination with pbir_list_pages per-page iteration.
Inputs: slim, limit, offset, pageId, +1 more. Returns: error, total, _cache, canvas, +9 more
pbir_load_toolsLoad ToolsA
List on-demand tools (no args) or activate by name (pass tools array).
Inputs: tools. Returns: hint, error, _cache, success, +6 more
pbir_lookup_theme_propertyLookup Theme PropertyARead-only
Query the bundled Power BI theme schema for valid visualStyles property names. No args = list visual types; +visualType = list categories; +category = list properties with types/enums.
Inputs: category, visualType, propertyFilter. Returns: note, count, error, _cache, +8 more
pbir_manage_extension_measuresManage Extension MeasuresADestructive
Manage extension measures (report-level DAX in reportExtensions.json). Empty file crashes PBI Desktop — tool auto-deletes when empty.
Inputs: operation (required), dataType, tableName, expression, +1 more.
pbir_model_usageModel UsageARead-only
Cross-reference the semantic model with the report — shows where every measure and column is used, DAX dependencies, unused fields, and per-page coverage. Also generates an HTML dashboard for visual inspection. Requires a sibling .SemanticModel/ folder alongside the .Report/ — call pbir_get_report first to check hasSemanticModel before invoking this tool.
Inputs: slim, reportPath. Returns: error, pages, _cache, cached, +9 more
pbir_move_visualMove VisualB
Move and/or resize a visual on a page
Inputs: visualId (required), x, y, z, +3 more.
pbir_reload_reportReload ReportADestructive
Reload the report in Power BI Desktop by closing and reopening the .pbip file. SAFETY: closes PBIDesktop.exe, so any unsaved work in Desktop (including modeling-MCP measures/relationships not yet flushed by Desktop autosave) is LOST. Requires confirm:true to proceed — otherwise returns a save-first warning for the agent to relay to the user.
Inputs: confirm.
pbir_remove_filterRemove FilterADestructive
Remove a specific filter by name from a page or visual.
Inputs: pageId (required), filterName (required), visualId.
pbir_remove_report_themeRemove Report ThemeADestructive
Remove the custom theme from the report, reverting to the default base theme. The theme file is kept in StaticResources but unlinked from report.json.
Inputs: no named parameters.
pbir_rename_bookmarkRename BookmarkB
Rename an existing bookmark.
Inputs: bookmarkId (required), displayName (required).
pbir_rename_pageRename PageC
Rename an existing page
Inputs: displayName (required), pageId.
pbir_reorder_pagesReorder PagesC
Set the page order
Inputs: pageOrder (required).
pbir_set_active_pageSet Active PageAIdempotent
Set which page is active (shown on open)
Inputs: pageId.
pbir_set_conditional_formatSet Conditional FormatB
Apply conditional formatting to a visual container background or title font. formatType: rules / gradient / clear. ComparisonKind: 0=Eq,1=GT,2=GTE,3=LT,4=LTE,5=NEq.
Inputs: visualId (required), formatType (required), rules, entity, +8 more.
pbir_set_datapoint_colorsSet Datapoint ColorsA
Set data point colors. Series-based charts use metadata mode. Category-based (no Series) requires categoryEntity+categoryProperty.
Inputs: colors (required), visualId (required), pageId, categoryEntity, +2 more.
pbir_set_filter_paneSet Filter PaneBIdempotent
Show or hide the filter pane.
Inputs: visible (required), expanded.
pbir_set_page_backgroundSet Page BackgroundBIdempotent
Set the page canvas background and/or wallpaper. Hex color (#0D1117). Transparency 0-100.
Inputs: clear, color, pageId, transparency, +2 more.
pbir_set_page_visibilitySet Page VisibilityAIdempotent
Show or hide a page in the navigation pane. Hidden pages still work for drillthrough.
Inputs: hidden, pageId.
pbir_set_reportSet ReportA
Connect to a different Power BI report (.Report folder or parent .pbip project folder). Use this to switch reports mid-session without restarting the server.
Inputs: path (required).
pbir_set_report_themeSet Report ThemeCIdempotent
Apply a custom JSON theme. Hex colors. dataColors 6-12 values. visualStyles keyed by visualType or '*'.
Inputs: name (required), background, dataColors, foreground, +5 more.
pbir_set_visual_interactionSet Visual InteractionAIdempotent
Set cross-filter interaction (Filter/Highlight/NoFilter) from source visual to target visual.
Inputs: type (required), pageId (required), source (required), target (required).
pbir_set_visual_sortSet Visual SortA
Set the sort order of a visual. Overrides the auto-sort. Use Table[Column] for field refs.
Inputs: sort (required), visualId (required), pageId, isDefaultSort.
pbir_set_visual_titleSet Visual TitleBIdempotent
Set or update the title of a visual. Can set text, visibility, font, size, alignment.
Inputs: visualId (required), show, title, pageId, +4 more.
pbir_update_page_sizeUpdate Page SizeC
Update the page dimensions
Inputs: width, height, pageId, displayOption.
pbir_update_report_settingsUpdate Report SettingsBIdempotent
Merge report-level settings. Keys: useStylableVisualContainerHeader, useEnhancedTooltips, exportDataMode (0|1), persistentFilters, keyboardNavigationEnabled, defaultDrillFilterOtherVisuals, allowChangeFilterTypes, useDefaultAggregateDisplayName.
Inputs: settings (required).
pbir_update_visual_bindingsUpdate Visual BindingsA
Update the data bindings of an existing visual. Replaces the query state entirely. Supports Table[Column] shorthand: use { "field": "Sales[Net Price]", "type": "measure" } as an alternative to separate entity/property fields.
Inputs: pageId (required), bindings (required), visualId (required), autoFilters, +1 more.
pbir_validate_wireframeValidate WireframeARead-only
Validate a page's (or the whole report's) layout against the wireframe rules — margins, gaps, overlap, off-canvas, banner geometry. Returns errors + warnings per visual plus stats (visual count, coverage, bottom edge). Read-only. Pair with pbir_audit_theme_compliance for full project verification.
Inputs: scope, pageId. Returns: hint, error, pages, scope, +7 more
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 57 tools
Most tools have distinct resource/action targets, but the formatting and theme areas overlap: pbir_format_visual intersects with pbir_set_visual_title, pbir_set_datapoint_colors, and bulk formatting tools, while theme tools span set/get/remove/diff/list/audit/apply. Descriptions help, but with 57 tools the agent faces real misselection risk.
All tools use a consistent pbir_ prefix with snake_case verb_noun naming. The verbs vary appropriately by action, but the convention is predictable throughout.
57 tools is very high for an agent-facing MCP surface, even for a complex Power BI report editor. On-demand loading and guide tools mitigate this somewhat, but the default surface is heavy and will be difficult to scan reliably.
Coverage is broad: pages, visuals, filters, themes, bookmarks, layout validation, settings, interactions, conditional formatting, and model usage are all represented. Minor gaps remain around editing existing filters without remove/re-add and capturing bookmark state directly, but the lifecycle is largely complete.
Maintenance
Related MCP Connectors
Forge designed Power BI projects (.pbip) from your agent, bound to your own semantic model.
Build and run AI workflows, agents, data tables and 1000+ API integrations from any MCP client.
Official Microsoft MCP Server to query Microsoft Entra data using natural language
Governed BI MCP. Ask questions of live company data and list workspace sources via OAuth.
Related MCP Servers
- 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.85721MIT
- 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
- AlicenseBqualityBmaintenanceMCP server for interacting with local Power BI Desktop and .pbip projects, enabling DAX queries, model documentation, measure editing, and PBIR visual management via natural language.90365 PyPI1Apache 2.0
- AlicenseBqualityAmaintenanceEnables AI agents to author and edit Power BI files locally (.pbix/PBIP), covering semantic models, reports, and Power Query M with 490 tools.10023 npm3Cryptographic Autonomy 1.0 (Combined Work Exception)