MCP server for editing Power BI Report Builder paginated reports (`.rdl`) through Claude or any MCP client. 130+ tools across charts, datasets, layout, parameters, validation. Byte-identical RDL round-trip; PBIDATASET-aware.
- ✓Open-source license (MIT)
- ✓Actively maintained (<30d)
- ✓Clear description
- ✓Topics declared
claude mcp add pbirb-mcp -- uvx pbirb-mcp{
"mcpServers": {
"pbirb-mcp": {
"command": "uvx",
"args": ["pbirb-mcp"]
}
}
}MCP Servers overview
# pbirb-mcp
[](https://github.com/mafaq229/pbirb-mcp/actions/workflows/ci.yml)
[](https://pypi.org/project/pbirb-mcp/)
[](https://pypi.org/project/pbirb-mcp/)
[](LICENSE)
An MCP server for editing **Power BI Report Builder paginated reports** (`.rdl`)
through Claude (Desktop, CLI, or any MCP client). Forty-plus tools cover the
gaps that otherwise force hand-written XML: dataset filters, headers and
footers, body composition, groupings, sorting, row visibility, conditional
expressions, styling, page setup, advanced parameters, and embedded images.
The server speaks JSON-RPC 2.0 over stdio. It opens an `.rdl` from disk,
mutates it in place via lxml, validates structure, and writes atomically — a
failed save never leaves a half-written report or scrubs the original.
## Stability
Pre-1.0. The tool surface — tool names, `inputSchema`, output shapes, error
semantics — is the contract. While on `0.x`, MINOR releases may include a
small breaking change with a migration note in
[CHANGELOG.md](CHANGELOG.md); after v1.0, breaking changes require MAJOR.
See [CONTRIBUTING.md](CONTRIBUTING.md#versioning) for the full bump rules
adapted from SemVer for an MCP tool surface.
Pin to a MINOR while on `0.x` (e.g. `pbirb-mcp~=0.1`) if your prompts
depend on specific tool names or schemas.
---
## Quick start
### 1. Install
The simplest path is [uv](https://docs.astral.sh/uv/) + PyPI — no clone, no
venv, no install step:
```bash
uvx pbirb-mcp
```
uvx fetches the package into a throwaway environment, runs the
`pbirb-mcp` console script, and exits. The MCP server speaks JSON-RPC
over stdio, so any MCP client (Claude Desktop, Claude Code, etc.) can
spawn it directly.
For local development against this codebase instead:
```bash
git clone https://github.com/mafaq229/pbirb-mcp
cd pbirb-mcp
uv venv .venv
uv pip install --python .venv/bin/python -e ".[dev]"
```
Verify the binary works:
```bash
printf '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}\n' \
| .venv/bin/pbirb-mcp
```
You should see a single JSON-RPC response with `protocolVersion`,
`capabilities.tools`, and `serverInfo.name = "pbirb-mcp"`.
### 2. Wire into Claude Desktop
Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
```json
{
"mcpServers": {
"pbirb": {
"command": "uvx",
"args": ["pbirb-mcp"],
"env": {
"PBIRB_MCP_LOG_LEVEL": "INFO",
"PBIRB_MCP_LOG_FILE": "/tmp/pbirb-mcp.log"
}
}
}
}
```
Restart Claude Desktop. The hammer icon should show `pbirb` and the 40+ tools
listed below.
For development against a local checkout, swap the `args` for
`["--from", "/absolute/path/to/pbirb-mcp", "pbirb-mcp"]` so uvx runs
your working tree instead of the published version.
### 3. Wire into Claude Code
```bash
claude mcp add pbirb -- uvx pbirb-mcp
```
Or add to `.mcp.json` at the workspace root:
```json
{
"mcpServers": {
"pbirb": {
"command": "uvx",
"args": ["pbirb-mcp"]
}
}
}
```
**Or install it as a Claude Code plugin** — one command instead of editing
config by hand (it wires up the same `uvx pbirb-mcp` server for you):
```bash
/plugin marketplace add mafaq229/pbirb-mcp
/plugin install pbirb-mcp@pbirb
```
### 4. Smoke test
In any chat, ask the model:
> Open `~/path/to/some-report.rdl` and tell me what datasets and parameters it has.
The model should call `describe_report`, `get_datasets`, and `get_parameters`
and summarise the result. If it doesn't, your client probably hasn't loaded
the server — check the client's MCP debug log.
---
## Working with a report
The recommended flow is **read first, then edit by name**. Every mutating
tool addresses elements by their RDL `Name` attribute (Tablix name,
Textbox name, ReportParameter name, DataSet name) — never by index.
Indices break across multi-step edits.
A typical session:
```text
You: Bind the existing report at ~/Reports/sales.rdl to the Finance
workspace's "FY26 Sales" dataset, change the body DAX to a date-
ranged query, and add a header with a logo and a parameter line.
Claude: → describe_report(path=…)
→ set_datasource_connection(name="PBIDataset",
workspace_url="Finance", dataset_name="FY26 Sales")
→ update_dataset_query(dataset_name="MainDataset",
dax_body="EVALUATE FILTER('Sales',
'Sales'[OrderDate] >= @DateFrom &&
'Sales'[OrderDate] <= @DateTo)")
→ add_query_parameter(dataset_name="MainDataset",
name="DateFrom",
value_expression="=Parameters!DateFrom.Value")
→ add_query_parameter(dataset_name="MainDataset",
name="DateTo",
value_expression="=Parameters!DateTo.Value")
→ add_embedded_image(name="Logo",
mime_type="image/png", image_path="~/brand/logo.png")
→ set_page_header(height="0.75in",
print_on_first_page=True, print_on_last_page=True)
→ add_header_image(name="HeaderLogo",
image_source="Embedded", value="Logo",
top="0in", left="0in", width="1in", height="0.5in")
→ add_header_textbox(name="DateLine",
text='="From: " & Parameters!DateFrom.Value & " To: "
& Parameters!DateTo.Value',
top="0.1in", left="1.2in", width="4in", height="0.25in")
```
Open the resulting `.rdl` in Report Builder; the change is visible in the
designer and renders in Preview against the bound dataset.
---
## Tool reference
42 tools, grouped by RDL concern. Every tool takes a `path` argument
(absolute path to the `.rdl`); the rest of the schema is in `tools/list`
output and visible to the LLM at registration time.
### Read-only inventory
The "what's in this report?" tools. Always the first calls when planning a
multi-step edit.
| Tool | Returns |
|------|---------|
| `describe_report` | Top-level inventory: data sources, datasets, parameters, tablixes, page setup |
| `get_datasets` | Full DAX command text, fields, query parameters, dataset filters |
| `get_parameters` | Report parameters with data type, prompt, and flags (multi-value, hidden, nullable, allow-blank) |
| `get_tablixes` | Tablix layout: columns, row/column groups, sort expressions, filters, visibility |
| `list_tablix_filters` | Filters on a tablix in document order with stable indices |
| `list_embedded_images` | Embedded image names + MIME types |
### Datasource & dataset
| Tool | What it edits |
|------|---------------|
| `set_datasource_connection` | Repoint a `<DataSource>` at a Power BI XMLA endpoint. `DataProvider=SQL` (the AS provider id). |
| `update_dataset_query` | Replace `<DataSet>/<Query>/<CommandText>` with a DAX expression |
| `add_query_parameter` | Append `<QueryParameter>` (e.g. `=Parameters!DateFrom.Value`) |
| `update_query_parameter` | Change the value expression of an existing query parameter |
| `remove_query_parameter` | Drop a query parameter (and clean up empty `<QueryParameters>`) |
### Tablix
| Tool | What it edits |
|------|---------------|
| `add_tablix_filter` | Append a `<Filter>`. Operators: Equal, NotEqual, GreaterThan, In, Between, Like, TopN, ... |
| `remove_tablix_filter` | Remove by ordinal index from `list_tablix_filters` |
| `add_row_group` | Wrap the current row hierarchy in a new outer group + insert a header row |
| `remove_row_group` | Inverse of `add_row_group` |
| `set_group_sort` | Replace `<SortExpressions>` on a group |
| `set_group_visibility` | Set `<Visibility>` on a group's TablixMember |
| `set_detail_row_visibility` | Set `<Visibility>` on the Details group |
| `set_row_height` | Set `<Height>` on the Nth body row |
### Page
| Tool | What it edits |
|------|---------------|
| `set_page_setup` | Page dimensions, margins, columns. All fields optional. |
| `set_page_orientation` | Swap PageHeight/PageWidth to match `Portrait` or `Landscape`. Idempotent. |
### Page header & footer
Same set of operations for each region, each accepts named items so
follow-up edits don't drift on indices.
| Tool | What it edits |
|------|---------------|
| `set_page_header` / `set_page_footer` | Section height + `PrintOnFirstPage` / `PrintOnLastPage` |
| `add_header_textbox` / `add_footer_textbox` | Append a Textbox (static text or `=expression`) |
| `add_header_image` / `add_footer_image` | Append an Image (External URL, Embedded name, or Database expression) |
| `remove_header_item` / `remove_footer_item` | Remove by name; tidies empty `<ReportItems>` |
### Body composition
| Tool | What it edits |
|------|---------------|
| `add_body_textbox` | Append a Textbox to `<Body>/<ReportItems>` |
| `add_body_image` | Append an Image to the body |
| `remove_body_item` | Remove a named Textbox / Image / Tablix from the body |
### Snippet templates
Single-call inserts of common report items, programmatically built and
appended to the body.
| Tool | What it builds |
|------|----------------|
| `insert_tablix_from_template` | A basic Tablix mirroring the fixture's shape — header row with the column name as a static label, detail row binding to `=Fields!<column>.Value`. One column per requested field. |
| `insert_chart_from_template` | A basic Column chart: single category axis grouped by `category_field`, single Y series `=Sum(Fields!<value_field>.Value)`. Change `<Type>` post-insert (Bar / Line / Pie / etc.). |
### Styling
| Tool | What it edits |
|------|---------------|
| `set_textbox_style` | Routes properties to the right nested `<Style>` node automatically: box-level (BackgroundColor, Border, VerticalAlign), paragraph-level (TextAlign), run-level (FontFamily, FonWhat people ask about pbirb-mcp
What is mafaq229/pbirb-mcp?
+
mafaq229/pbirb-mcp is mcp servers for the Claude AI ecosystem. MCP server for editing Power BI Report Builder paginated reports (`.rdl`) through Claude or any MCP client. 130+ tools across charts, datasets, layout, parameters, validation. Byte-identical RDL round-trip; PBIDATASET-aware. It has 3 GitHub stars and was last updated today.
How do I install pbirb-mcp?
+
You can install pbirb-mcp by cloning the repository (https://github.com/mafaq229/pbirb-mcp) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.
Is mafaq229/pbirb-mcp safe to use?
+
Our security agent has analyzed mafaq229/pbirb-mcp and assigned a Trust Score of 87/100 (tier: Trusted). See the full breakdown of passed checks and flags on this page.
Who maintains mafaq229/pbirb-mcp?
+
mafaq229/pbirb-mcp is maintained by mafaq229. The last recorded GitHub activity is from today, with 0 open issues.
Are there alternatives to pbirb-mcp?
+
Yes. On ClaudeWave you can browse similar mcp servers at /categories/mcp, sorted by popularity or recent activity.
Deploy pbirb-mcp to your cloud
Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.
Maintain this repo? Add a badge to your README
Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.
[](https://claudewave.com/repo/mafaq229-pbirb-mcp)<a href="https://claudewave.com/repo/mafaq229-pbirb-mcp"><img src="https://claudewave.com/api/badge/mafaq229-pbirb-mcp" alt="Featured on ClaudeWave: mafaq229/pbirb-mcp" width="320" height="64" /></a>More MCP Servers
Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.
User-friendly AI Interface (Supports Ollama, OpenAI API, ...)
An open-source AI agent that brings the power of Gemini directly into your terminal.
The fastest path to AI-powered full stack observability, even for lean teams.
🕷️ An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl!
⭐AI-driven public opinion & trend monitor with multi-platform aggregation, RSS, and smart alerts.🎯 告别信息过载,你的 AI 舆情监控助手与热点筛选工具!聚合多平台热点 + RSS 订阅,支持关键词精准筛选。AI 智能筛选新闻 + AI 翻译 + AI 分析简报直推手机,也支持接入 MCP 架构,赋能 AI 自然语言对话分析、情感洞察与趋势预测等。支持 Docker ,数据本地/云端自持。集成微信/飞书/钉钉/Telegram/邮件/ntfy/bark/slack 等渠道智能推送。