pbi-mcp-remote
by emamuel03
README.md
# pbi-mcp-remote
Servidor **MCP (Model Context Protocol) remoto y centralizado**, en Node.js, que expone herramientas para que
modelos de IA interactúen con **Microsoft Fabric** (workspaces e items: Lakehouse, Warehouse, Notebook,
DataPipeline, SemanticModel, Report, etc.) a través de la **Fabric Core REST API**.
Autenticación: **OAuth 2.1 delegado con Microsoft Entra ID**. Cada usuario final se loguea con su propia cuenta;
el servidor usa el token delegado de ese usuario para llamar a Fabric, por lo que **hereda exactamente los
permisos y restricciones que ya tiene configurados en Fabric** (RBAC de workspace, sensitivity labels, etc.).
No se usa ninguna identidad de aplicación compartida para acceder a datos de Fabric.
Alcance actual: Fabric Core REST API (workspaces e items) y **Power BI REST API clásica** (datasets, reports,
dashboards, gateways). Fuera de alcance por ahora: SQL endpoints de Lakehouse/Warehouse, orquestación de
jobs/pipelines.
Fabric y Power BI son **audiencias distintas de Entra ID** (`api.fabric.microsoft.com` vs
`analysis.windows.net/powerbi/api`), así que el servidor mantiene un access token cacheado por recurso, ambos
derivados del mismo refresh token de la sesión del usuario — ver "Arquitectura" para el detalle.
## Arquitectura
El servidor actúa simultáneamente como:
- **Authorization Server de cara a los clientes MCP** (Claude, MCP Inspector, etc.): expone
`/.well-known/oauth-authorization-server`, `/authorize`, `/token`, `/register`.
- **Proxy hacia Entra ID**: es el único componente que habla directamente con Entra (App Registration fijo,
confidential client). El cliente MCP **nunca** ve el token real de Entra — solo un JWT propio de corta vida
emitido por este servidor, que internamente resuelve a una sesión con los tokens delegados de Entra
(access + refresh), guardados cifrados server-side.
Flujo: cliente MCP → `/authorize` → redirect a Entra (PKCE propio del servidor) → login/consentimiento del
usuario → `/callback` → intercambio de código vía MSAL → sesión guardada → el servidor completa el
`/authorize` original y emite su propio código → el cliente pide `/token` y recibe un JWT propio → cada
llamada a `/mcp` resuelve la sesión y, si el token del recurso correspondiente (Fabric o Power BI) está por
vencer, lo refresca de forma transparente antes de llamar a la API real con el token delegado del usuario.
Un access token solo tiene una audiencia, así que un mismo token no sirve para Fabric y Power BI a la vez. En
el login inicial se piden los scopes combinados de ambos recursos (una sola pantalla de consentimiento), y
luego el servidor deriva un access token por recurso a partir del refresh token compartido
(`acquireTokenByRefreshToken` con los scopes de cada uno), cacheando cada uno con su propio vencimiento.
## Configuración de Entra ID (paso a paso)
1. **Azure Portal → Microsoft Entra ID → App registrations → New registration.**
- Nombre: p. ej. `pbi-mcp-remote`.
- Supported account types: **Single tenant** (recomendado para esta fase).
- Redirect URI: tipo **Web**, `http://localhost:3000/callback` (agregar la URL de producción cuando se
decida el hosting).
2. **Certificates & secrets → New client secret.** Copiar el *value* (no el secret ID) apenas se genera.
3. **API permissions → Add a permission → APIs my organization uses → Power BI Service** (este mismo recurso
expone tanto los scopes de Fabric como los de Power BI clásica). Elegir **Delegated permissions** (nunca
Application permissions):
- `Workspace.ReadWrite.All`, `Item.ReadWrite.All` (Fabric)
- `Dataset.Read.All`, `Dataset.ReadWrite.All` (necesario para `powerbi_trigger_dataset_refresh`),
`Report.Read.All`, `Dashboard.Read.All`, `Gateway.Read.All` (Power BI clásica)
- `openid`, `profile`, `offline_access` (necesarios para el refresh token).
4. Si tu tenant lo requiere, pedile a un admin que haga **Grant admin consent**.
5. Copiar `Directory (tenant) ID`, `Application (client) ID` y el client secret al `.env` (ver abajo).
6. No hace falta una segunda app ni un segundo redirect URI para Power BI — es el mismo App Registration,
solo se amplía la lista de scopes pedidos (`FABRIC_SCOPES` + `POWERBI_SCOPES` en `.env`). Si ya tenías
sesiones activas creadas antes de agregar Power BI, hace falta desconectar/reconectar una vez desde el
cliente MCP para que corra el flujo de consentimiento combinado.
## Configuración local
```bash
cp .env.example .env
# completar ENTRA_TENANT_ID, ENTRA_CLIENT_ID, ENTRA_CLIENT_SECRET,
# MCP_JWT_SIGNING_SECRET y SESSION_ENCRYPTION_KEY con valores propios (no los de ejemplo)
npm install
npm run dev
```
El servidor queda escuchando en `http://localhost:3000`. El endpoint MCP remoto es `http://localhost:3000/mcp`.
## Probar end-to-end
```bash
npx @modelcontextprotocol/inspector
```
Apuntar el Inspector a `http://localhost:3000/mcp`. Al conectar, dispara el flujo OAuth completo: redirige a
Entra ID, el usuario se loguea y consiente los scopes de Fabric y Power BI juntos, vuelve al Inspector ya
autenticado, y desde ahí se pueden listar/invocar las herramientas (`fabric_list_workspaces`,
`powerbi_list_datasets`, etc.) contra el tenant real, respetando los permisos del usuario logueado.
## Docker
```bash
docker compose up --build
```
Levanta el servidor + Redis como session store (recomendado para más de una instancia). Para una sola
instancia en desarrollo, `SESSION_STORE=memory` (default del `.env.example`) alcanza.
## Herramientas MCP disponibles
**Fabric Core REST API:**
- `fabric_list_workspaces`, `fabric_get_workspace`, `fabric_create_workspace`, `fabric_update_workspace`,
`fabric_delete_workspace`
- `fabric_list_workspace_role_assignments`
- `fabric_list_items`, `fabric_get_item`, `fabric_create_item`, `fabric_update_item`, `fabric_delete_item`
- `fabric_list_item_connections`
- `fabric_list_supported_item_types`
**Power BI REST API clásica:**
- `powerbi_list_datasets`, `powerbi_get_dataset`, `powerbi_list_dataset_datasources`,
`powerbi_get_dataset_refresh_history`, `powerbi_trigger_dataset_refresh`
- `powerbi_list_reports`, `powerbi_get_report`, `powerbi_list_report_datasources`
- `powerbi_list_dashboards`, `powerbi_get_dashboard`
- `powerbi_list_gateways`, `powerbi_list_gateway_datasources`
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues