Read-only MCP server for Power BI semantic models — query workspaces, datasets, and execute DAX via any MCP client
This Power BI MCP server demonstrates solid definition quality with clear tool names, comprehensive descriptions, and proper JSON Schema input definitions. All 12 tools follow consistent verb_noun naming (authenticate, logout, list_*, get_*, execute_*, read_*, search_*, delete_*). Most tools have descriptions in the 100 - 300 character range, meeting the 10 - 1024 baseline. However, output schemas are not formally documented in the code, parameter descriptions could be more precise in some cases (e.g., result_name in execute_dax lacks format guidance), and error handling patterns are not explicitly shown in the provided source. The tools are well-organized for the Power BI domain with clear discovery flow (list_apps → list_datasets → list_tables/measures/columns → execute_dax), demonstrating good composition principles.
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).
Delete a single entry from the query history log by UUID. Removes the log entry and any associated metadata, but does NOT delete the CSV result file on disk.
Execute a DAX query against a Power BI dataset. DAX is the query language for Power BI semantic models. A DAX query must start with EVALUATE and return a table. If the result fits within the inline threshold (50 rows), the full result is returned in the response. For larger results, rows are saved to a CSV file on disk and a paginated reader is provided via `read_dax_result`.
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 formally documented. While tool descriptions state what is returned (e.g., 'Returns dataset id, name, configured-by...'), there is no explicit JSON Schema or structured documentation of the response object shape. This forces LLMs to parse unstructured descriptions and risks field mismatches in downstream composition.
Parameter descriptions lack format constraints and examples. For instance, 'result_name' in execute_dax is described as 'Optional: a human-readable label for the result file (e.g. \'sales by region 2024\')', the example value risks being reused literally. Numeric parameters (offset, limit, since_days) lack min/max bounds; limit in search_query_log has no stated upper bound, risking resource exhaustion.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | C | 63 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 0 | - | v1 |
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) in a Power BI dataset. Optionally filter by table name. Returns column name, table, description, data type, and whether it is a key column.
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. Optionally filter by table name. Returns measure name, table, description, and format string (e.g. "0.00" for currency).
List all user-visible tables in a Power BI dataset. Filters out hidden tables and internal Power BI system tables. Use the `name` field as `table_name` in `list_measures` and `list_columns`.
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 large DAX query result file. When a DAX query returns more rows than the inline threshold, the results are saved to a CSV file. Use this tool to retrieve a slice of those rows without loading the entire file into memory.
Search the query history log. Every successful DAX query is logged alongside its CSV output path (if saved). Use this tool to find prior queries by keyword, dataset, or time range, so you can reuse working DAX or locate saved result files from earlier sessions.
Error handling and recovery guidance not visible in tool definitions. The authenticate tool mentions returning 'Not authenticated' but does not define a structured error schema or recovery actions for other failure modes (network timeouts, invalid DAX, permission denied). Pattern guidance for error-classification and recovery-guide not evident.
read_dax_result parameters (offset, limit) lack reasonable defaults and bounds. The description states 'default 100' for limit but does not specify a maximum to prevent unbounded requests. offset and limit are integers with no documented range (e.g., limit should probably cap at 1000 rows per call).
Tool annotation metadata not present. Tools like delete_query_log_entry (marked Risk: WRITE) and execute_dax (which modifies local state via CSV file creation) should carry readOnlyHint, destructiveHint, or idempotentHint annotations. The risk field in the spec listing is informal; proper toolAnnotations would make the protocol clearer.