# PowerBI MCP Server

[![PyPI](https://img.shields.io/pypi/v/powerbi-mcp.svg)](https://pypi.org/project/powerbi-mcp/)
[![Python Versions](https://img.shields.io/pypi/pyversions/powerbi-mcp.svg)](https://pypi.org/project/powerbi-mcp/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

<!-- mcp-name: io.github.gurvinder-dhillon/powerbi-mcp -->

A Model Context Protocol (MCP) server that provides tools for interacting with PowerBI REST APIs. This server enables AI assistants like Claude to query PowerBI workspaces, datasets, and execute DAX queries.

> [!WARNING]
> **Security Best Practices**
> - Never commit credentials to version control
> - Store credentials in `.env` files (add to `.gitignore`)
> - Rotate client secrets regularly in Azure AD
> - Use least-privilege access (only grant necessary workspace permissions)
> - This server has read/write access to PowerBI datasets - use with caution

## ✨ Features

- **Query Your Data**: Run DAX queries to extract insights and analyze your PowerBI data directly through conversation
- **Discover Workspaces & Datasets**: Explore what data is available across your organization's PowerBI environment
- **Understand Data Models**: Get detailed schema information to know what tables, columns, and relationships exist
- **Natural Language to Insights**: Ask questions about your data and get answers without opening PowerBI

See all [available tools](#-available-tools) below.

## 💡 What Can You Do?

| Scenario | Example Prompt |
|----------|----------------|
| Explore available data | "What workspaces do I have access to?" |
| Discover reports | "What reports are available in my workspace?" |
| Understand data schema | "Show me the schema for dataset [dataset-name]" |
| Monitor data freshes | "When was this dataset last refreshed?" |
| Check parameters | "What parameters does this dataset accept?" |
| Query data with DAX | "Run a DAX query to get top 10 sales by region from [dataset]" |
| Analyze data quality | "What tables are in the Sales dataset?" |
| Extract insights | "Get the list of all measures in the Financial dataset" |

## 📋 Prerequisites

- **Azure AD Service Principal**: Required for authentication. Follow the [Azure AD Configuration](#-azure-ad-configuration) steps below to set this up.

## 🔐 Azure AD Configuration

Before installing the server, you need to set up an Azure AD application with PowerBI access.

### Create Azure AD App Registration

1. Go to [Azure Portal](https://portal.azure.com)
2. Navigate to **Azure Active Directory** > **App registrations**
3. Click **New registration**
4. Enter a name (e.g., "PowerBI MCP Server")
5. Click **Register**

### Get Credentials

After registration, collect these values:

- **Tenant ID**: Found in app Overview page (Directory ID)
- **Client ID**: Found in app Overview page (Application ID)
- **Client Secret**:
  - Go to **Certificates & secrets**
  - Click **New client secret**
  - Add description and set expiry
  - Copy the secret **Value** (you can only see this once!)

### Enable Service Principal in PowerBI

1. Go to [PowerBI Admin Portal](https://app.powerbi.com/admin-portal)
2. Navigate to **Tenant settings** > **Developer settings**
3. Enable **Service principals can use PowerBI APIs**
4. Add your app to the security group or enable for entire organization
5. Click **Apply**

> [!NOTE]
> Service principals can access workspaces where they've been granted explicit permissions (Admin, Member, or Contributor roles).

### Grant Workspace Access

For each workspace you want to access:

1. Go to the workspace in PowerBI
2. Click workspace settings (⚙️) > **Access**
3. Click **Add people or groups**
4. Search for your app name
5. Assign role: **Admin**, **Member**, or **Contributor**
6. Click **Add**

## 📦 Installation

### Method 0: From PyPI (Recommended)

Once published to PyPI, this is the simplest installation method.

Add the following to your MCP client configuration file:

**For Claude Desktop** (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):

```json
{
  "mcpServers": {
    "powerbi-mcp": {
      "command": "uvx",
      "args": ["powerbi-mcp"],
      "env": {
        "POWERBI_TENANT_ID": "your-tenant-id-here",
        "POWERBI_CLIENT_ID": "your-client-id-here",
        "POWERBI_CLIENT_SECRET": "your-client-secret-here"
      }
    }
  }
}
```

**For Claude Code** (`./.mcp.json` in your project directory):

```json
{
  "mcpServers": {
    "powerbi-mcp": {
      "command": "uvx",
      "args": ["powerbi-mcp"],
      "env": {}
    }
  }
}
```

When using Claude Code, create a `.env` file in your project directory (where you run Claude Code from):

```env
POWERBI_TENANT_ID=your-tenant-id-here
POWERBI_CLIENT_ID=your-client-id-here
POWERBI_CLIENT_SECRET=your-client-secret-here
```

> [!TIP]
> The `.env` file should be in your working directory, not where the server is installed.

**For OpenCode** (`~/.config/opencode/opencode.json`):

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "powerbi-mcp": {
      "type": "local",
      "command": ["uvx", "powerbi-mcp"],
      "enabled": true,
      "env": {
        "POWERBI_TENANT_ID": "your-tenant-id-here",
        "POWERBI_CLIENT_ID": "your-client-id-here",
        "POWERBI_CLIENT_SECRET": "your-client-secret-here"
      }
    }
  }
}
```

After adding the configuration, restart your MCP client.

### Method 1: Direct from GitHub (Development)

This method uses `uvx` to run the server directly from GitHub without cloning the repository.

Add the following to your MCP client configuration file:

**For Claude Desktop** (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):

```json
{
  "mcpServers": {
    "powerbi-mcp": {
      "command": "uvx",
      "args": [
        "--from",
        "git+https://github.com/gurvinder-dhillon/powerbi-mcp@main",
        "run-server"
      ],
      "env": {
        "POWERBI_TENANT_ID": "your-tenant-id-here",
        "POWERBI_CLIENT_ID": "your-client-id-here",
        "POWERBI_CLIENT_SECRET": "your-client-secret-here"
      }
    }
  }
}
```

**For Claude Code** (`./.mcp.json` in your project directory):

```json
{
  "mcpServers": {
    "powerbi-mcp": {
      "command": "uvx",
      "args": [
        "--from",
        "git+https://github.com/gurvinder-dhillon/powerbi-mcp@main",
        "run-server"
      ],
      "env": {}
    }
  }
}
```

When using Claude Code, create a `.env` file in your project directory (where you run Claude Code from):

```env
POWERBI_TENANT_ID=your-tenant-id-here
POWERBI_CLIENT_ID=your-client-id-here
POWERBI_CLIENT_SECRET=your-client-secret-here
```

> [!TIP]
> The `.env` file should be in your working directory, not where the server is installed.

The server will automatically load environment variables from the `.env` file in your current working directory.

**For OpenCode** (`~/.config/opencode/opencode.json`):

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "powerbi-mcp": {
      "type": "local",
      "command": [
        "uvx",
        "--from",
        "git+https://github.com/gurvinder-dhillon/powerbi-mcp@main",
        "run-server"
      ],
      "enabled": true,
      "env": {
        "POWERBI_TENANT_ID": "your-tenant-id-here",
        "POWERBI_CLIENT_ID": "your-client-id-here",
        "POWERBI_CLIENT_SECRET": "your-client-secret-here"
      }
    }
  }
}
```

After adding the configuration, restart your MCP client.

### Method 2: Local Clone (Contributors)

For contributors who want to run from a local clone:

1. Clone the repository:

```bash
git clone https://github.com/gurvinder-dhillon/powerbi-mcp.git
cd powerbi-mcp
```

2. Install dependencies:

```bash
uv sync
```

3. Add to your MCP client configuration:

**For Claude Desktop**:

```json
{
  "mcpServers": {
    "powerbi-mcp-local": {
      "command": "uv",
      "args": [
        "--directory",
        "/absolute/path/to/powerbi-mcp",
        "run",
        "run-server"
      ],
      "env": {
        "POWERBI_TENANT_ID": "your-tenant-id-here",
        "POWERBI_CLIENT_ID": "your-client-id-here",
        "POWERBI_CLIENT_SECRET": "your-client-secret-here"
      }
    }
  }
}
```

**For Claude Code** (`./.mcp.json` in your project directory):

```json
{
  "mcpServers": {
    "powerbi-mcp-local": {
      "command": "uv",
      "args": [
        "--directory",
        "/absolute/path/to/powerbi-mcp",
        "run",
        "run-server"
      ],
      "env": {}
    }
  }
}
```

**For OpenCode** (`~/.config/opencode/opencode.json`):

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "powerbi-mcp-local": {
      "type": "local",
      "command": [
        "uv",
        "--directory",
        "/absolute/path/to/powerbi-mcp",
        "run",
        "run-server"
      ],
      "enabled": true,
      "env": {
        "POWERBI_TENANT_ID": "your-tenant-id-here",
        "POWERBI_CLIENT_ID": "your-client-id-here",
        "POWERBI_CLIENT_SECRET": "your-client-secret-here"
      }
    }
  }
}
```

Replace `/absolute/path/to/powerbi-mcp` with the actual path to your cloned repository.

When using Claude Code or OpenCode, create a `.env` file in your project directory with your credentials (see Method 1 Claude Code section above for the format).

## 🚀 Quick Start

Once installed, try these steps to get started:

1. **Verify Connection**: Ask Claude "What PowerBI workspaces do I have access to?"
2. **Explore Data**: "Show me the datasets in workspace [workspace-name]"
3. **View Schema**: "What tables are in dataset [dataset-name]?"
4. **Run a Query**: "Execute this DAX query on [dataset-name]: EVALUATE TOPN(10, Sales)"

## 🛠️ Available Tools

| Tool | Description | Key Parameters |
|------|-------------|----------------|
| `get_workspaces` | List accessible PowerBI workspaces | `top`, `detail` |
| `get_datasets` | Get datasets from workspace or "My workspace" | `workspace_id`, `detail` |
| `get_dataset` | Get detailed dataset info including schema | `dataset_id`, `workspace_id`, `detail` |
| `get_reports` | List PowerBI reports in workspace | `workspace_id`, `format`, `detail` |
| `get_refresh_history` | Get dataset refresh history with status/timestamps | `dataset_id`, `workspace_id`, `top`, `format` |
| `get_parameters` | List dataset parameters and their current values | `dataset_id`, `workspace_id`, `format`, `detail` |
| `query_dataset` | Execute DAX queries against dataset | `dataset_id`, `dax_query`, `workspace_id` |

### Tool Details

#### 1. get_workspaces

List PowerBI workspaces accessible to the service principal.

**Parameters:**
- `top` (optional): Number of workspaces to return (default: 100, max: 5000)
- `detail` (optional): Level of detail - "concise", "normal", or "full" (default: "normal")

#### 2. get_datasets

Get list of datasets from a workspace or "My workspace".

**Parameters:**
- `workspace_id` (optional): Workspace ID (omit for "My workspace")
- `detail` (optional): Level of detail - "concise", "normal", or "full" (default: "normal")

#### 3. get_dataset

Get detailed information about a specific dataset including schema and tables.

**Parameters:**
- `dataset_id` (required): Dataset ID
- `workspace_id` (optional): Workspace ID (omit for "My workspace")
- `detail` (optional): Level of detail - "concise", "normal", or "full" (default: "normal")

#### 4. get_reports

List PowerBI reports in a workspace.

**Parameters:**
- `workspace_id` (optional): Workspace ID (omit for "My workspace")
- `format` (optional): Response format - "markdown" or "json" (default: "markdown")
- `detail` (optional): Level of detail - "concise" or "normal" (default: "concise")

#### 5. get_refresh_history

Get refresh history for a dataset showing recent refresh operations.

**Parameters:**
- `dataset_id` (required): Dataset ID
- `workspace_id` (optional): Workspace ID (omit for "My workspace")
- `top` (optional): Number of refresh records to return (default: 5, max: 60)
- `format` (optional): Response format - "markdown" or "json" (default: "markdown")

#### 6. get_parameters

Get parameters defined in a dataset.

**Parameters:**
- `dataset_id` (required): Dataset ID
- `workspace_id` (optional): Workspace ID (omit for "My workspace")
- `format` (optional): Response format - "markdown" or "json" (default: "markdown")
- `detail` (optional): Level of detail - "concise" or "normal" (default: "normal")

**Note:** Not supported for datasets with SQL, Oracle, Teradata, SAP HANA DirectQuery connections or datasets modified via XMLA endpoint.

#### 7. query_dataset

Execute DAX queries against a dataset.

**Parameters:**
- `dataset_id` (required): Dataset ID
- `dax_query` (required): DAX query (must start with "EVALUATE")
- `workspace_id` (optional): Workspace ID (omit for "My workspace")

### DAX Query Examples

**Basic Table Scan:**
```dax
EVALUATE
'Sales'
```

**Top N with Sorting:**
```dax
EVALUATE
TOPN(10, 'Sales', [Amount], DESC)
```

**Filtered Results:**
```dax
EVALUATE
FILTER('Sales', [Year] = 2024)
```

**Calculated Columns:**
```dax
EVALUATE
ADDCOLUMNS(
    'Sales',
    "Profit", [Revenue] - [Cost]
)
```

**Aggregated Summary:**
```dax
EVALUATE
SUMMARIZE(
    'Sales',
    'Product'[Category],
    "Total Sales", SUM('Sales'[Amount])
)
```

## ⚠️ Troubleshooting

### Authentication Errors

**Error: "Authentication failed"**
- Verify your `POWERBI_TENANT_ID`, `POWERBI_CLIENT_ID`, and `POWERBI_CLIENT_SECRET` are correct
- Check that the client secret hasn't expired in Azure AD
- Ensure the service principal is enabled in PowerBI Admin Portal

### Permission Errors

**Error: "403 Forbidden" or "Access denied"**
- Verify the service principal has been granted access to the workspace
- Check that the workspace role is Admin, Member, or Contributor (Viewer is not sufficient for API access)
- Confirm "Service principals can use PowerBI APIs" is enabled in PowerBI Admin Portal

### Connection Issues

**Server not appearing in MCP client**
- Restart your MCP client after adding the configuration
- Check the configuration file syntax (JSON must be valid)
- For local clone, verify the absolute path is correct

**Tools not working**
- Ensure credentials are configured
- Check the MCP client logs for detailed error messages
- For Claude Code, verify `.env` file is in the current working directory

## 📚 Resources

- [PowerBI REST API Reference](https://learn.microsoft.com/en-us/rest/api/power-bi/)
- [Model Context Protocol](https://modelcontextprotocol.io/)
- [DAX Guide](https://dax.guide/)
- [Azure AD App Registration](https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app)

## 💬 Feedback and Support

- **Issues**: Report bugs or request features via [GitHub Issues](https://github.com/gurvinder-dhillon/powerbi-mcp/issues)
- **Discussions**: Ask questions in [GitHub Discussions](https://github.com/gurvinder-dhillon/powerbi-mcp/discussions)
- **Pull Requests**: Contributions welcome! See [DEVELOPER_GUIDE.md](DEVELOPER_GUIDE.md)

## 🤝 Contributing

See [DEVELOPER_GUIDE.md](DEVELOPER_GUIDE.md) for information about developing and contributing to this project.

## License

This project is licensed under the MIT License.
