Skip to main content
Glama
README.md
# mcp-paginated

MCP server for Power BI paginated reports (.rdl): **validate offline → publish → render → diagnose**.

| Tool | What it does |
|---|---|
| `validate_rdl` | RDL 2016 XSD + Report Builder `RdlSerializer`, plus checks both miss: tablix grid integrity, detail-member nesting (`rsInvalidDetailDataGrouping`), query-parameter binding, references. Printable width is a warning (Excel-only reports are wide on purpose). |
| `list_workspaces`, `list_paginated_reports` | Discovery (name or GUID accepted everywhere). |
| `get_report_datasources` | Service-side bindings. Never shows credential type / SSO — nothing in the API does. |
| `download_rdl` | Pull the deployed .rdl (diff before you overwrite). |
| `publish_rdl` | Imports API. Validates first and refuses on errors. Existing name → `nameConflict=Overwrite` (keeps the report id); new name → `Abort`. Gated by `writable`. |
| `export_report` | ExportTo → poll → download. PDF/MHTML/XLSX/DOCX/PPTX/CSV/XML/PNG; parameters (lists = multi-value); `first_page_only`. |
| `diagnose_report` | Bindings + page-1 PDF probe, mapped to the known failure modes (SSO, missing Build, name-based XMLA connect string, unbound `@Var`, redacted DAX object). |

## Setup
```
python -m venv .venv
.venv\Scripts\pip install -r requirements.txt
copy config.example.json config.json
claude mcp add -s user paginated -- <abs>\.venv\Scripts\python.exe <abs>\server.py
```
Requires Power BI Report Builder for the XSD/object-model half of `validate_rdl` (`report_builder_dll`).

## Auth
Broker/WAM, Power BI scope. `cache_name` + `auth_record_path` point at **mcp-fabric's** persisted
sign-in, so it runs silently as the same identity (`PowerBI.Enterprise`). To use its own sign-in,
remove those two keys. The first sign-in then needs an interactive session, because the WAM picker
can't render in a headless shell.

Renders run the report's queries as that identity; they change nothing, but they do hit the source.
Credentials (OAuth2 / SSO off) are deliberately **not** settable here. Use the Service UI, because
the REST PATCH stores a bare token that expires in about 1 hour.