MCP server for editing Power BI Report Builder paginated reports (RDL)
pbirb-mcp demonstrates solid definition quality with strong naming conventions, generally clear descriptions, and properly structured JSON schemas for all 12 tools. Tool names follow verb_noun patterns consistently (describe_report, get_datasets, update_dataset_query, etc.). Descriptions are substantive and domain-specific, ranging from 100-400+ characters with technical context appropriate for RDL/Power BI domain experts. All tools have complete input schemas with type definitions and required field declarations. However, several gaps prevent a higher score: (1) output schemas are not documented for any tool, LLMs cannot predict response structure; (2) parameter descriptions lack actionable constraints (e.g., no format specs, enums where appropriate, or validation guidance); (3) no error handling guidance or recovery instructions in any tool description; (4) no indication of which tools are idempotent or safe to retry; (5) tools lack risk annotations (readOnlyHint, destructiveHint) despite clear read vs write distinction in the provided metadata. The domain is highly specialized (RDL/SSRS authoring), which explains the technical depth, but the descriptions assume deep Power BI knowledge and could benefit from dependency hints (e.g., 'Call describe_report first to understand available datasets').
Create a new <DataSource> for a Power BI XMLA endpoint. workspace_url accepts a bare workspace name or a full powerbi:// URL. Generates a fresh rd:DataSourceID GUID. Refuses if a DataSource of the same name already exists. provider='sql' (default) emits the legacy DataProvider=SQL + powerbi:// ConnectString + <rd:SecurityType> shape; provider='pbidataset' emits the modern PBI Desktop shape — DataProvider=PBIDATASET, pbiazure:// ConnectString with ClaimsToken auth, plus <rd:PowerBIWorkspaceName> / <rd:PowerBIDatasetName> siblings, no <rd:SecurityType>.
Add a <QueryParameter> binding to a dataset's query. Use to wire report parameters into DAX (e.g. =Parameters!DateFrom.Value). PBIDATASET parameter naming rule: in DAX/<CommandText>, write @MyParam (with @). In <QueryParameter Name=...>, write MyParam (no @). SQL/MDX use @ in both places. This tool detects the dataset's provider and AUTO-STRIPS a leading @ from `name` for PBIDATASET datasets, returning {normalised: true, warning: ...}. Pass force_at_prefix=true to override (rare; needed for some RSCustomDaxFilter patterns).
Top-level inventory of an RDL: data sources, datasets, parameters, tablixes, charts, and page setup. Always the first call when planning edits. v0.4: `tablixes` returns rich shape hints [{name, rows, columns, has_groups, has_subtotals, has_spans}] (was bare strings — migrate with `[t['name'] for t in tablixes]`). `charts` (new in v0.4) is a top-level array of chart names.
Single-DataSource read-back (parity with get_textbox / get_image / get_rectangle / get_chart). Returns the same shape as one entry of list_data_sources.
No output schemas documented for any of 12 tools. LLMs cannot predict response structure, required fields, or chaining relationships.
Parameter constraints not enforced via schema enums or patterns. workspace_url accepts 'bare name or full URL' but no format constraint; action_type in set_textbox_action is documented as one-of three but not declared as enum in schema; no regex patterns or length limits on string parameters.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | B | 74 | <=2025-11-25 | v2 |
Full DAX command text, fields, query parameters, and dataset-level filters for every DataSet in the report.
Report parameter declarations: name, data type, prompt, flags.
Tablix layout with stable IDs: columns, row/column groups, sort expressions, filters, visibility. Required input for any tablix edit.
Return a rich list of every <DataSource> in the report — name, data_provider, connect_string, integrated_security, shared_reference, security_type, data_source_id. describe_report.data_sources returns names only; this tool is the authoring-friendly read.
Repoint a DataSource at a Power BI XMLA endpoint. workspace_url accepts a bare workspace name or a full powerbi:// URL; DataProvider is set to SQL (the AS provider id in RDL).
Set <Textbox>/<Action> to one of Hyperlink / Drillthrough / BookmarkLink. target_expression is the URL (Hyperlink), drill-target report name (Drillthrough), or bookmark id (BookmarkLink). Pass an expression with a leading = for dynamic values. For Drillthrough, drillthrough_parameters is an optional list of {"name": "<paramName>", "value": "<value-or-expr>"} dicts that get wired into <Drillthrough>/<Parameters>. Replaces any existing Action on the textbox. Returns {textbox, kind, action_type, changed: bool}. The change check is structural — same action_type + target + drillthrough_parameters short-circuits without saving.
Replace the DAX command text of a named dataset. The full DAX expression is accepted verbatim; empty bodies are rejected. Optional alias_strategy='preserve_field_names' positionally rewrites <DataField> cells to the new DAX columns while keeping existing <Field Name> identifiers — so Fields!X.Value references in expressions keep resolving.
Change the value expression of an existing query parameter. Same PBIDATASET @-prefix normalisation as add_query_parameter applies on lookup; legacy Name='@X' parameters that already exist on disk are addressable via either @X or X.
No error handling guidance or recovery instructions in any tool. Descriptions lack actionable error messages (e.g., what happens if path doesn't exist? if dataset_name is invalid? if DAX syntax is malformed?). No dry-run pattern for destructive write operations.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). Write operations (update_*, add_*, set_*) are not explicitly marked as destructive; read operations not marked as safe. Unclear which tools are idempotent and safe to retry.
Parameter descriptions lack actionable detail on format, constraints, and dependencies. E.g., 'path' parameters say 'Absolute path to .rdl file' but no validation rules (max length? allowed characters? Windows vs Unix paths?). 'dax_body' accepts 'full DAX expression' with only one example (EVALUATE TOPN...).
Descriptions assume deep Power BI / RDL domain knowledge. Terms like 'PBIDATASET', 'tablix', 'alias_strategy', 'DataField', '@-prefix normalisation' are not explained. Dependency hints missing (e.g., 'Call describe_report first to identify available datasets').