Skip to content

Repository files navigation

Power BI MCP Server

A remote Model Context Protocol (MCP) server that exposes Power BI operations as tools for AI assistants. Built with the official Microsoft MCP C# SDK and served over Streamable HTTP.

Portfolio summary

  • What it demonstrates: A typed, remote MCP integration over enterprise analytics rather than a local toy server.
  • Tools: Workspace and dataset discovery, schema inspection, and DAX query execution.
  • Identity: DefaultAzureCredential supports local development, service principals, workload identity, and managed identity.
  • Engineering: .NET 8, Streamable HTTP, structured error handling, tests, and client configuration for VS Code.

Tools

Tool Description Parameters
list_workspaces List all Power BI workspaces accessible to the authenticated user
list_datasets List datasets in a workspace workspaceId
list_tables List tables and columns in a dataset (via DAX COLUMNSTATISTICS()) workspaceId, datasetId
execute_dax Execute a DAX query via REST API workspaceId, datasetId, daxQuery

Prerequisites

  • .NET 8 SDK
  • ASP.NET Core 8 Runtime (aspnetcore-runtime-8.0)
  • Azure CLI (az login) or a service principal for authentication
  • A Power BI Pro/PPU/Premium workspace

Quick Start

# 1. Clone and enter the repo
git clone <repo-url> && cd pbi-mcp

# 2. Log in to Azure (use your Power BI tenant)
az login --tenant <your-tenant-id>

# 3. Update appsettings.json with your tenant ID
#    (already configured if you cloned this repo)

# 4. Build and run
dotnet run

The server starts at http://localhost:3001/mcp.

Configuration

appsettings.json

{
  "PowerBi": {
    "TenantId": "your-tenant-id-here"
  }
}

The TenantId is passed to DefaultAzureCredential to ensure tokens are acquired for the correct tenant.

Authentication

The server uses DefaultAzureCredential, which tries these sources in order:

Priority Source Use case
1 AZURE_TENANT_ID / AZURE_CLIENT_ID / AZURE_CLIENT_SECRET env vars Service principal / CI
2 Workload Identity Kubernetes
3 Managed Identity Azure VMs, App Service, ACA
4 Azure CLI (az login) Local development

Local development (az login)

az login --tenant <your-tenant-id>
dotnet run

Service principal (environment variables)

export AZURE_TENANT_ID="your-tenant-id"
export AZURE_CLIENT_ID="your-sp-app-id"
export AZURE_CLIENT_SECRET="your-sp-secret"
dotnet run

No code changes needed — DefaultAzureCredential picks up the env vars automatically.

Connecting an MCP Client

VS Code (Copilot)

The repo includes .vscode/mcp.json:

{
  "servers": {
    "pbi-mcp": {
      "type": "http",
      "url": "http://localhost:3001/mcp"
    }
  }
}

Start the server with dotnet run, then Copilot will discover the tools automatically.

MCP Inspector

npx @modelcontextprotocol/inspector

Connect to http://localhost:3001/mcp using the Streamable HTTP transport.

Project Structure

PbiMcpServer.csproj          # ASP.NET Core Web project
Program.cs                   # Entry point — DI, MCP server, HTTP transport
PowerBiService.cs            # Power BI REST API + XMLA service layer
PowerBiTools.cs              # MCP tool definitions (4 tools)
appsettings.json             # Tenant ID + logging config
.vscode/mcp.json             # VS Code MCP client config
tests/
  PbiMcpServer.Tests/
    PowerBiServiceUnitTests.cs        # 11 offline tests (mocked HTTP)
    PowerBiServiceIntegrationTests.cs # 5 live API tests
    XunitLoggerProvider.cs            # xUnit ↔ ILogger bridge

Testing

# Unit tests (offline, fast — no credentials needed)
dotnet test tests/PbiMcpServer.Tests/PbiMcpServer.Tests.csproj \
  --filter "Category!=Integration"

# Integration tests (hits live Power BI API — requires az login)
dotnet test tests/PbiMcpServer.Tests/PbiMcpServer.Tests.csproj \
  --filter "Category=Integration"

# All tests
dotnet test tests/PbiMcpServer.Tests/PbiMcpServer.Tests.csproj

# With detailed HTTP request/response logging
dotnet test tests/PbiMcpServer.Tests/PbiMcpServer.Tests.csproj \
  --filter "Category=Integration" \
  --logger "console;verbosity=detailed"

Architecture Notes

DAX execution

All DAX queries use the Power BI REST API (POST /datasets/{id}/executeQueries). This works with any Pro/PPU/Premium workspace — no XMLA endpoint required.

The XMLA path (via ADOMD.NET) is included in the codebase but commented out. It requires Premium/PPU capacity with XMLA read enabled by a tenant admin.

Table discovery

The list_tables tool uses EVALUATE COLUMNSTATISTICS() via the REST DAX endpoint rather than the REST /tables endpoint, because /tables only works for push datasets. The DAX approach works for all dataset types (import, DirectQuery, composite).

.NET runtimes

This project requires both:

  • Microsoft.NETCore.App — base .NET runtime (console, I/O, networking)
  • Microsoft.AspNetCore.App — web runtime (Kestrel, routing, middleware)

Install with: sudo apt install aspnetcore-runtime-8.0 (includes both).

Tech Stack

License

This project is licensed under the MIT License.

About

Authenticated MCP server for exploring and querying Power BI semantic models with Azure identity.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages