MCP server that connects an AI agent to your own Power BI / Fabric tenant. Wraps a toolkit and exposes it as MCP tools over stdio with built-in guardrails.
Server exposes 10 tools with mostly complete schemas and descriptions. Naming follows verb_noun convention (list_, get_, run_, deploy_, validate_, capture_, refresh_). Descriptions are substantive (100-300 chars), explaining WHAT and WHEN. However, several parameters lack descriptions (e.g., 'workspace' and 'model' in get_model_schema have descriptions but max_names lacks context on why it matters). Output schemas are not documented, callers cannot predict response structure. Error handling is present but generic (SystemExit → {error: ...}). No tool annotations (readOnlyHint/destructiveHint) despite clear risk levels. Parameter validation is minimal, no enums for item_type, no bounds on max_rows/max_names. The _guarded wrapper captures stdout but does not provide structured error recovery guidance.
Screenshot every page of a deployed report and save its accessibility text (Playwright for Python). Writes <out>/<n>-<page>.png and <out>/<n>-<page>.txt. Exit code 1 if any page shows an error banner.
What the server is pointed at: config file, workspace, model, prefixes, and whether the Azure CLI can mint tokens for the Power BI and Fabric APIs (expiry shown). Call this first in a session.
Deploy a local PBIR report item folder to the workspace (create or update by display name). Enforces guardrails: item name must start with configured prefix, definition must bind byConnection to an allowed model, hidden files excluded except .platform.
Export the semantic model's definition (TMDL) into paths.schema_dir and summarise it: tables with their columns and measures. Read-only. Defaults to the configured model. Read this before writing DAX.
The rules enforced in code and the rules you must keep yourself. Read this before the first change.
Output schemas not documented. Callers cannot predict response structure (e.g., what fields does list_workspaces return? Is it {workspaces: [...]} or {items: [...]}?). LLMs cannot plan downstream tool calls without knowing what data is available.
No tool annotations (readOnlyHint/destructiveHint/idempotentHint). Tools clearly have different risk levels (list_workspaces is read-only; deploy_report is destructive), but this is not declared in the schema. Agents cannot reason about safety or retry semantics.
Parameter constraints missing. 'item_type' in list_items accepts free-form strings (should be enum: Report, SemanticModel, Lakehouse, etc.). 'max_rows' and 'max_names' lack bounds (should be 1 - 1000). 'settle' and 'rail_wait' in capture_pages lack units and ranges. LLMs will hallucinate invalid values.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 59 | 2026-07-28+ | v2 |
Items in a workspace (Report, SemanticModel, Lakehouse, ...). workspace = display name or id; empty = the configured workspace. item_type filters (e.g. "Report").
Workspaces the signed-in identity can see (Fabric): id and display name.
Refresh history of the semantic model: status, start/end times, duration, error messages. Read-only on purpose - there is no tool that triggers a refresh.
Run a READ-ONLY DAX query (must start with EVALUATE or DEFINE) against the model via executeQueries. Batch what you need into one query; every call runs under the user's identity and costs capacity.
Offline checks on a PBIR report folder: no tenant, seconds. PASS/FAIL per check, exit 1 on any FAIL. Checks validator, theme, state, pages, names, bounds, overlaps, filters, measures, pins, ytd, slicers, mobile.
Error handling is generic. All errors return {error: <message>} with no recovery guidance. E.g., 'workspace not found' should suggest 'Call list_workspaces() to see available workspaces.' Agents cannot self-correct without explicit hints.
guardrails tool has minimal schema (empty input {}) and vague description ('The rules enforced in code...'). It appears to be a documentation tool, not a functional tool. If it returns a document, the response schema should be documented.