Skip to main content
Glama
ericlxbgit

Genie ↔ Fabric/Power BI bridge

by ericlxbgit
README.md
# Genie ↔ Fabric/Power BI bridge (MCP server)

Custom MCP server, deployed as a Databricks App, that lets an MCP client
(Claude, Cursor, etc.) ask questions against Databricks Genie, and check
that the Fabric/Power BI side of the pipeline is healthy.

Read this alongside the architecture diagram shared in chat before deploying.

## What this does — and doesn't — automate

The data model moves from Databricks to Power BI via **Fabric mirroring**,
not via MCP:

1. Your data model lives in Databricks Unity Catalog.
2. Fabric's **Mirrored Azure Databricks Catalog** creates zero-ETL OneLake
   shortcuts to it and keeps them in sync automatically.
3. Power BI reads that data live via a **Direct Lake** semantic model.
4. A person uses **Power BI Copilot**, in the Power BI UI, to generate the
   actual dashboard/report from a natural-language prompt.

This MCP server sits alongside that pipeline. It does not create the
mirroring (set up once, manually, in the Fabric portal — see below), and
it cannot trigger Copilot's report generation (no public API exists for
that). What it *does* give an MCP client:

- `genie_ask` / `genie_get_result` / `genie_list_spaces` — ask Genie
  questions and read back answers, generated SQL, and result rows.
- `fabric_mirror_status` — confirm the mirrored catalog is synced.
- `powerbi_list_datasets` / `powerbi_list_reports` / `powerbi_refresh_dataset`
  — discovery and refresh operations against Power BI.
- `genie_to_copilot_handoff` — turns a Genie answer into a ready-to-paste
  Copilot prompt, so the human's last step is "paste and go" instead of
  starting from scratch.

## Prerequisites (set these up before deploying the server)

1. **Genie space** in Databricks over your Unity Catalog data model. Note
   its space ID.
2. **Fabric mirroring**: in the Fabric portal, create a *Mirrored Azure
   Databricks Catalog* item pointing at your Unity Catalog. Note the
   Fabric workspace ID and the mirrored item ID.
   https://learn.microsoft.com/en-us/fabric/mirroring/azure-databricks-tutorial
3. **Power BI semantic model** in Direct Lake mode built on top of the
   mirrored OneLake tables.
4. **Entra ID app registration** (service principal) for this server to
   call the Power BI REST API and Fabric REST API:
   - Grant it a Power BI service principal profile / workspace access
     (add it as a member of the target Power BI/Fabric workspace).
   - Note its tenant ID, client ID, and client secret.
5. **Databricks CLI / workspace access** to deploy a Databricks App.

## Deploying as a Databricks App

1. Register the values from step 4 as Databricks secrets (scope name is
   up to you), matching the `valueFrom` keys in `app.yaml`:
   `genie-space-id`, `powerbi-tenant-id`, `powerbi-client-id`,
   `powerbi-client-secret`, `powerbi-group-id`, `fabric-workspace-id`,
   `fabric-mirrored-item-id`.
2. Create the Databricks App and upload this folder's source.
3. Deploy. The MCP endpoint will be available at `https://<app-url>/mcp`.
4. Point your MCP client at that URL (OAuth is handled by Databricks Apps
   for inbound access).

Full steps: https://docs.databricks.com/aws/en/generative-ai/mcp/custom-mcp

## Local development

```bash
pip install -r requirements.txt
cp .env.example .env   # fill in real values
python app.py
```

## Before you deploy this for real — verify these against current docs

I wrote this scaffold from public documentation, not against a live
workspace, so a few pieces need a quick check before you trust them:

- `src/genie_tools.py`: the `databricks-sdk` Genie method names
  (`start_conversation_and_wait`, `create_message_and_wait`,
  `get_message_query_result`, `list_spaces`) — confirm against the
  version of `databricks-sdk` you pin.
- `src/fabric_tools.py`: the Fabric REST API path for item status — Fabric's
  API surface is newer and evolves faster than Power BI's.
- `app.yaml`: the secret-binding syntax (`env` / `valueFrom`) — confirm
  against the current Databricks Apps schema.
- `app.py`: the `mcp.run(...)` call signature for the installed `mcp`
  SDK version (host/port handling has changed across releases).

None of these are exotic, but I can't execute this against your workspace,
so treat this as a solid first draft to test, not a verified-working build.