Read-only MCP server for Power BI semantic models — query workspaces, datasets, and execute DAX via any MCP client
Power BI Analyst MCP demonstrates solid definition quality with complete naming conventions, detailed parameter descriptions, and structured schema documentation. All 12 tools follow verb_noun patterns and have descriptions ranging from 100-450 characters. However, there are gaps in output schema documentation and error handling guidance. The server is well-suited for Power BI semantic model discovery and DAX querying, but lacks idempotency hints and confirmation patterns for destructive operations. Tool composition is clean, each tool has a single responsibility, and chaining is straightforward via workspace_id and dataset_id threading.
Authenticate with Power BI using the OAuth 2.0 device code flow. Call this tool first if you have never logged in, or if a previous call returned "Not authenticated". The tool uses a two-step flow: - First call: returns a URL and a one-time code for you to open in a browser. - Second call: completes the authentication after you have signed in. Your credentials are cached locally so you will not need to repeat this step until the refresh token expires (~90 days).
Remove a single entry from the query history log by its UUID.
Execute a DAX (Data Analysis Expressions) query against a Power BI dataset and return the results. DAX is Power BI's query language — similar to SQL but optimized for analytical operations on columnar data models. If the result set is small (≤50 rows), it is returned inline as JSON. Larger results are written to a CSV file and you can paginate through them using `read_csv_page`. The query must start with EVALUATE (the DAX keyword for a query).
Return detailed metadata for a single Power BI dataset. Includes name, owner, refresh schedule, storage mode, web URL, and more. Also returns the last 5 refresh history entries so you can see data freshness.
Output schemas not explicitly documented in tool descriptions. Tools like list_apps, list_datasets, list_tables return structured data, but the response field names and types are not formally documented in descriptions. LLMs must infer response structure from context or trial calls.
Minimal error handling guidance in descriptions. Tools do not indicate what can go wrong (e.g., 403 permission errors, 404 dataset not found, network timeouts) or how to recover. Descriptions focus on happy path only. delete_query_log_entry has especially sparse description (70 chars).
No confirmation or dry-run pattern for delete_query_log_entry. The tool is marked REVERSIBLE but has no safeguards (confirmation, dry-run, or soft-delete option) to prevent accidental log deletion by agents.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | B | 75 | 2026-07-28+ | v2 |
List all Power BI apps installed for the authenticated user. Returns each app's id, name, description, publisher, last update time, and workspaceId of the underlying workspace. Use the `workspaceId` field as `workspace_id` in `list_datasets` and `get_dataset_info`. This is the correct starting point for dataset discovery — at Miinto all dataset access is managed through Power BI apps, so always start here rather than listing workspaces directly.
List all columns (dimensions) defined in a Power BI dataset. Columns are the raw data dimensions available for filtering and grouping in reports and analysis.
List all datasets (semantic models) in a Power BI workspace. Returns dataset id, name, configured-by, web URL, is-refreshable flag, and the target storage mode (Import / DirectQuery / etc.). Use the `id` field as `dataset_id` in subsequent tools. The workspace_id must come from `list_apps` (workspaceId field), not from `list_workspaces` — using the app-backed workspace ensures you are working within the correct permission boundary.
List all measures defined in a Power BI dataset. Measures are aggregation functions (sums, averages, counts) that roll up data to support reporting and analysis.
List all user-visible tables in a Power BI dataset. Filters out hidden tables and internal Power BI system tables (those whose names start with '$').
Sign out of Power BI by clearing the cached credentials. After logging out, call `authenticate` to sign in again.
Read a page of rows from a CSV file created by `execute_dax`. Use this to paginate through large result sets without loading the entire file into memory.
Search the query history log for prior DAX queries and their results. Every successful `execute_dax` call is logged to a JSONL file alongside the CSV output, so you can reuse working queries and find saved result files from earlier sessions.
list_measures and list_columns have optional table_name parameter but do not explain what happens when the parameter is omitted, does it return all measures/columns across all tables, or none? Undocumented conditional behavior confuses LLMs.
No pagination guidance for list_apps, list_datasets, list_tables, list_measures, list_columns. If a user has hundreds of datasets or thousands of measures, response size could explode. No mention of limits, pagination cursors, or result caps in descriptions.
Tool annotations (readOnlyHint, idempotentHint, destructiveHint) not declared. The MCP spec supports these to help clients classify tools; the server omits them entirely, forcing LLMs to infer idempotency and side effects from descriptions alone.