Skip to main content
Glama
FreelexHo
by FreelexHo
README.md
# Power BI MCP Server

An [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) server that lets AI agents manage Power BI workspaces, datasets, and refreshes via natural language.

## Features

### Authentication & Discovery

| Tool | Description |
|---|---|
| `pbi_auth` | Authenticate via Azure AD device code flow (with token caching & auto-refresh) |
| `pbi_list_workspaces` | List accessible workspaces (with optional name filter) |
| `pbi_list_datasets` | List datasets in a workspace |

### Dataset & Refresh Management

| Tool | Description |
|---|---|
| `pbi_dataset_info` | Aggregate dataset metadata + datasources + gateways + refresh schedule + impacted reports + PBIP locate (single call) |
| `pbi_refresh_dataset` | Trigger an Enhanced refresh (supports table-level, polling, retry, timeout) |
| `pbi_refresh_manage` | Refresh lifecycle: view history (`status`), get execution details (`details`), or cancel (`cancel`) |

### Diagnostics & Source Code

| Tool | Description |
|---|---|
| `pbi_diagnose` | One-shot diagnostic report for refresh failures — root cause classification, error catalog, next actions, PBIP source hints |
| `pbi_locate_pbip` | Locate PBIP source code for a dataset (fuzzy folder match + optional table TMDL & M source extraction) |

### Query & Reporting

| Tool | Description |
|---|---|
| `pbi_execute_query` | Execute DAX queries against a dataset (supports RLS impersonation) |
| `pbi_scheduled_refresh_report` | Generate a daily scheduled-refresh status report across all datasets in a workspace (JSON or Markdown table) |

## Architecture

```
server.py            # Entry point — configures logging, runs MCP via stdio
app.py               # FastMCP instance with server instructions
config.py            # Configuration loader (config.json, defaults, constants)
auth.py              # Azure AD device code flow, token caching, HTTP helpers
diagnostics.py       # Refresh error classification, PBIP folder/table locator
error_catalog.py     # Error code catalog + regex patterns for failure classification
tools/               # MCP tool modules (auto-registered via __init__.py)
  ├── auth_tool.py   #   pbi_auth
  ├── workspace.py   #   pbi_list_workspaces, pbi_list_datasets
  ├── dataset.py     #   pbi_dataset_info
  ├── refresh.py     #   pbi_refresh_dataset, pbi_refresh_manage
  ├── diagnose.py    #   pbi_diagnose, pbi_locate_pbip
  ├── query.py       #   pbi_execute_query
  └── report.py      #   pbi_scheduled_refresh_report
setup.ps1            # Azure AD App Registration automation (PowerShell)
config.json          # User-specific config (gitignored)
```

## Quick Start

### 1. Install dependencies

```bash
git clone https://github.com/FreelexHo/power-bi-mcp.git && cd power-bi-mcp
uv venv && uv sync
```

<details>
<summary>Don't have uv? Use pip instead</summary>

```bash
python -m venv .venv
# Windows
.venv\Scripts\activate
# macOS/Linux
source .venv/bin/activate

pip install -e .
```

</details>

### 2. Register in your MCP client

Add to your MCP client configuration:

**Cursor / Windsurf / Antigravity IDE** (`mcp.json`):

```json
{
  "mcpServers": {
    "power-bi": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/power-bi-mcp", "server.py"],
      "transport": "stdio"
    }
  }
}
```

### 3. Authenticate (one-time)

Just use the MCP! On first use, the agent will call `pbi_auth` and show you a message like:

```
To sign in, visit https://microsoft.com/devicelogin
and enter the code XXXXXXXX
```

1. Open the link in your browser
2. Enter the code shown
3. Sign in with your Microsoft work account
4. Approve the permissions

That's it. Tokens are cached to `~/.powerbi-mcp/token.json` and auto-refreshed — you won't need to do this again unless you revoke access.

## Configuration

The server works out of the box with a built-in public `client_id`. Create a `config.json` in the project root to customize:

```json
{
    "client_id": "<your-azure-ad-client-id>",
    "token_cache_dir": "~/.powerbi-mcp",
    "pbip_root": "C:/path/to/your/pbip-repo/data/power-bi-report"
}
```

| Key | Default | Description |
|---|---|---|
| `client_id` | Built-in public app | Azure AD App Registration client ID |
| `token_cache_dir` | `~/.powerbi-mcp` | Directory for cached OAuth tokens |
| `pbip_root` | *(none)* | Local PBIP repo root — enables `pbi_locate_pbip` and `pbi_diagnose` source-level hints |

A `setup.ps1` script is included to automate App Registration creation via Azure CLI. See [Advanced Setup](#advanced-setup) below.

## Troubleshooting

### `AADSTS7000218: The request body must contain ... client_assertion`

Your organization may block public client flows. Ask your Azure AD admin to either:
- Allow public client flows on the app registration, **or**
- Create a dedicated App Registration for your team (use `setup.ps1`)

### `AADSTS65001: The user or administrator has not consented`

First-time users in a new Azure AD tenant need to consent to Power BI permissions. If your tenant requires admin consent:
- Ask your admin to grant consent via Azure Portal -> App registrations -> API permissions -> "Grant admin consent"
- Or use `setup.ps1` to create your own App Registration where you are the owner

### `AADSTS50076: MFA required` or `AADSTS50079`

Multi-factor authentication is required by your organization. The device code flow supports MFA — complete the MFA challenge in your browser when prompted.

### `Not authenticated. Call pbi_auth first.`

Token has expired and could not be refreshed. The agent should automatically re-trigger `pbi_auth`. If it doesn't, ask the agent to call `pbi_auth` again.

### Token keeps expiring

By default, tokens are cached at `~/.powerbi-mcp/token.json`. Make sure:
- The directory is writable
- You are not running multiple instances that overwrite each other's tokens

### Refresh details return 403

A 403 on `pbi_refresh_manage action=details` typically indicates insufficient permissions or the refresh record has expired.

## Advanced Setup

For organizations that require their own App Registration:

### Prerequisites
- [Azure CLI](https://aka.ms/installazurecli)
- Azure AD permissions to create App Registrations

### Run setup

```powershell
./setup.ps1
```

This creates an Azure AD App Registration with the correct configuration:

| Setting | Value |
|---|---|
| Sign-in audience | Multi-tenant (any Azure AD directory) |
| Public client flows | Enabled |
| Redirect URI | `https://login.microsoftonline.com/common/oauth2/nativeclient` |
| API Permissions | `Power BI Service`: `Dataset.ReadWrite.All`, `Workspace.Read.All` (Delegated) |

## Tech Stack

- **Python** ≥ 3.10
- **[FastMCP](https://github.com/jlowin/fastmcp)** (`mcp[cli]` ≥ 1.6.0) — MCP server framework, stdio transport
- **[httpx](https://www.python-httpx.org/)** ≥ 0.27.0 — HTTP client for Azure AD & Power BI REST API calls

## License

MIT

TDQS

A4.1/5.0

Scored across 11 tools

Disambiguation5/5

Every tool focuses on a distinct Power BI operation—auth, dataset info, diagnostics, querying, listing, refreshing, managing refreshes, and local model exploration—with no functional overlaps. Descriptions clearly differentiate each tool's role.

Naming Consistency4/5

All tools share a consistent 'pbi_' prefix. Most follow a verb_noun pattern (e.g., pbi_list_datasets, pbi_execute_query), but a few deviate (e.g., pbi_auth is a bare verb, pbi_local_model is adjective_noun, pbi_scheduled_refresh_report is lengthy). Overall pattern is recognizable.

Tool Count5/5

11 tools is well-scoped for a Power BI dataset-focused server. It covers authentication, workspace/dataset listing, dataset info, DAX queries, refresh triggering, refresh management, diagnostics, and local source file interaction without bloat.

Completeness4/5

The tool surface provides strong coverage for dataset lifecycle: query, refresh, diagnose failures, and inspect local models. Minor gaps exist, such as no direct tool for creating or deleting datasets, but these are often handled outside the server's intended scope.

Maintenance

ActivityInactive
ResponsivenessNo issues