Skip to main content
Glama
HorizunGroup

Horizun PBI MCP

by HorizunGroup

Horizun PBI MCP

Servidor MCP (Model Context Protocol) para trabajar con Power BI Desktop local y con proyectos .pbip desde Claude Code.

v1.0.0-rc.1 — 90 tools, 851 pruebas (2 omitidas, ambas con su condición documentada). Cubre dos capas complementarias:

Capa

Para qué

Cómo

En vivo (Power BI Desktop abierto en localhost:<puerto>)

Consultar datos (DAX), documentar el modelo, crear/editar medidas, refrescar

ADOMD.NET + TOM vía pythonnet

En disco (proyecto .pbip)

Generar/acomodar visuales, editar el modelo de forma durable

TMDL (modelo) + PBIR (informe), editando archivos

Regla clave: el endpoint local solo expone la capa de DATOS (modelo semántico). Los visuales/páginas/layout NO están en ese endpoint ni en ninguna API en vivo — se editan por archivos PBIR. Este MCP respeta esa separación: no intenta mover visuales "en vivo".


Documentación

Documento

Para qué

docs/INSTALL.md

Instalar y registrar el servidor en Claude Code, Claude Desktop, Codex o un cliente stdio

docs/TOOL_INVENTORY.md

Las 34 tools del baseline: dominio, clase de riesgo, precondiciones

docs/ARCHITECTURE.md

Arquitectura actual, deuda estructural e invariantes

docs/CAPABILITY_MATRIX.md

Convivencia con otros MCP de Power BI, con niveles de verificación

AGENTS.md

Reglas para modificar este repositorio sin romper el contrato

docs/TOOL_CATALOG.md

Las 90 tools por bloque, con su clase de riesgo

docs/DUAL_MODE.md

Por qué mode="both" está bloqueado (R15)

docs/VALIDATION.md

Las dos capas de validación PBIR y sus límites

docs/RELEASE_CHECKLIST.md

Qué se comprueba antes de publicar

docs/TUTORIAL.md

De la instalación a un dashboard, paso a paso

docs/SECURITY.md

Modelo de amenazas, garantías y lo que no promete

docs/RECOVERY.md

Qué hacer cuando algo queda a medias

docs/PHASE_1A_DESIGN.md

Diseño de la capa de seguridad

CHANGELOG.md

Historial de versiones

tests/fixtures/README.md

Estrategia de fixtures: sintéticos versionados + copia local ignorada


Related MCP server: powerbi-mcp-local

Qué hace

  • DAX en vivo: ejecuta consultas contra el modelo abierto y devuelve columnas/filas con tiempos.

  • Documentación: tablas, columnas, medidas, relaciones, jerarquías, roles (RLS) y análisis de calidad → Markdown.

  • Medidas: crear/editar/borrar medidas DAX en el modelo abierto (live), en el archivo TMDL (pbip) o en ambos (both).

  • Refresh local: refresca el modelo abierto en Desktop (no el Service).

  • PBIP: abrir/validar proyectos, backups automáticos.

  • Visuales PBIR: listar/documentar visuales, crear visuales (clonando plantillas reales del informe), mover/redimensionar y acomodar por layouts.

Qué NO hace

  • No mueve ni crea visuales "en vivo" en el lienzo abierto (Power BI Desktop no expone API para eso). Los visuales se editan por archivos PBIR con el proyecto .pbip.

  • No refresca ni publica en el Power BI Service (solo local).

  • No convierte un .pbix a .pbip por ti: guarda el informe como Power BI Project (.pbip) con el formato de reporte mejorado (PBIR) activado.

  • No inventa campos ni medidas inexistentes al generar páginas.


Requisitos

  • Windows (Power BI Desktop es Windows-only) con Power BI Desktop instalado.

  • Python 3.10+ (probado en 3.14).

  • .NET Framework 4.x (viene con Windows) — lo usa pythonnet.

  • Dependencias Python: mcp (incluye FastMCP), pythonnet, psutil, python-dotenv.

  • DLLs de ADOMD.NET + TOM (Analysis Services). Se descargan sin admin con scripts/fetch_libs.py (no requieren instalarse en el GAC).

  • Para editar/crear visuales: el informe guardado como .pbip con PBIR activado.

  • (Opcional) Tabular Editor no es necesario — ver Decisiones técnicas.


Instalación

cd horizun-pbi-mcp

# 1) Dependencias Python
python -m pip install -r requirements.txt
#   o:  python -m pip install -e .

# 2) DLLs de Analysis Services (ADOMD.NET + TOM) -> carpeta libs/
#    Versión fijada (19.84.1) y verificada por SHA-256 antes de instalar.
python scripts/fetch_libs.py

# 3) Esquemas oficiales del PBIR (necesarios para ESCRIBIR)
#    Sin ellos, toda escritura PBIR falla con schema_unavailable.
python scripts/fetch_pbir_schemas.py

# 4) (opcional, recomendado) validador PBIR oficial de Microsoft
#    Requiere Node >= 20. Añade validación semántica del informe completo.
python scripts/fetch_report_validator.py

# 5) (opcional) configuración
copy .env.example .env    # y edítalo

Comprueba el resultado en cualquier momento:

python scripts/doctor.py

Verificar

Con Power BI Desktop abierto en un informe:

python src/server.py     # arranca el servidor MCP (stdio); Ctrl+C para salir

Para una prueba rápida sin MCP, en Python:

import sys; sys.path.insert(0, "src")
from config import get_session
from powerbi import desktop_discovery, dax_runner
s = get_session()
print(desktop_discovery.discover_instances())
desktop_discovery.select_model(s)
print(dax_runner.run_dax(s, 'EVALUATE ROW("ok", 1)'))

Registro en un cliente MCP

Guía completa para Claude Code, Claude Desktop, Codex y clientes stdio genéricos: docs/INSTALL.md.

Cada cliente resuelve las variables de entorno, el directorio de trabajo y el intérprete de Python de forma distinta, así que en vez de una plantilla con ${VAR} que falla en la mitad de ellos, hay un generador que resuelve las rutas absolutas de tu máquina:

python scripts/make_mcp_config.py --client all

Sólo imprime. Para crear el .mcp.json local de este repositorio (que está en .gitignore):

python scripts/make_mcp_config.py --client claude-code --write

Antes de registrar nada, comprueba la instalación:

python scripts/doctor.py

Sale con código 0 si todo lo obligatorio está bien. Distingue dependencia faltante, DLL faltante, servidor que no arranca, contrato MCP inesperado, Desktop cerrado, sesión obsoleta y múltiples instancias. Que Power BI Desktop esté cerrado no hace fallar el diagnóstico base (usa --require-desktop si quieres exigirlo).

Variables de entorno (todas opcionales)

Variable

Default

Descripción

HORIZUN_PBI_MCP_LIBS_DIR

./libs

Carpeta con las DLLs de ADOMD.NET/TOM

HORIZUN_PBI_MCP_DOTNET_RUNTIME

netfx

Runtime de pythonnet (netfx o coreclr)

HORIZUN_PBI_MCP_MAX_ROWS

1000

Límite de filas por defecto en DAX

HORIZUN_PBI_MCP_OUTPUTS_DIR

./outputs

Documentación y change_log.md

HORIZUN_PBI_MCP_BACKUPS_DIR

./backups

Backups de .pbip

HORIZUN_PBI_MCP_LOG_LEVEL

INFO

DEBUG/INFO/WARNING/ERROR

HORIZUN_PBI_MCP_DEFAULT_PBIP

.pbip a abrir al iniciar


Tools disponibles (90)

Catálogo completo por bloque: docs/TOOL_CATALOG.md. Inventario del baseline con clase de riesgo y precondiciones: docs/TOOL_INVENTORY.md. Los nombres y firmas están congelados en tests/golden/tools_v1.json y verificados por tests/test_tool_contract.py.

Conexión / DAX

  • pbi_list_desktop_models — lista modelos abiertos (puerto, connection string, catálogo, nº tablas).

  • pbi_select_model — fija el modelo activo (por port si hay varios).

  • pbi_run_dax — ejecuta DAX (query, max_rows).

  • pbi_test_connection — valida la conexión activa.

  • pbi_validate_measures — valida DAX de medidas SIN modificar el modelo (dry-run con DEFINE MEASURE); útil antes de crearlas.

Documentación (Fase 3)

  • pbi_list_tables, pbi_list_measures, pbi_list_relationships — con source: live|pbip.

  • pbi_analyze_model_quality — problemas típicos del modelo.

  • pbi_document_model — documentación completa en Markdown a outputs/.

Medidas (Fase 4)mode: live|pbip|both, overwrite

  • pbi_create_measure, pbi_update_measure, pbi_delete_measure (destructiva: confirm=true).

Refresh (Fase 5)

  • pbi_refresh_modeltype: full|calculate|clear_values, tables opcional (local).

Proyecto PBIP (Fase 6)

  • pbi_open_pbip_project (path), pbi_validate_pbip_project, pbi_backup_pbip_project (mode: folder|zip, scope: report|model|both).

Edición de modelo

  • pbi_set_column_visibility / pbi_hide_columns — ocultar/mostrar columnas (p.ej. IDs). mode: live|pbip|both.

  • pbi_set_relationship_direction — filtro cruzado single|both de una relación. mode: live|pbip|both.

  • pbi_disable_auto_date_time — activa/desactiva "Auto fecha y hora" (solo pbip).

Informe PBIR (Fases 7–10)

  • pbi_list_report_pages, pbi_list_visuals (page), pbi_document_report_layout.

  • pbi_create_visualpage, visual_type, fields, position, title (clona un visual existente como plantilla).

  • pbi_update_visual_position, pbi_arrange_visuals (layout: grid|dashboard|executive_summary|custom).

  • pbi_generate_report_page — página asistida a partir del modelo.

HTML dentro de Power BI

  • pbi_add_custom_visual — registra un custom visual de AppSource en el informe (por defecto HTML Content, que renderiza HTML/SVG desde una medida DAX).

  • pbi_create_html_visual — crea un visual HTML Content enlazado a una medida que devuelve HTML (html_measure).

  • pbi_create_measure con data_category: "ImageUrl" — medidas que devuelven un data-URI SVG y se renderizan como imagen en tablas/matrices nativas.

Generación de hojas por lenguaje natural

  • pbi_page_building_blocks — inventario del contenido (modelo + catálogo de visuales existentes + canvas) para diseñar una hoja.

  • pbi_preview_spec_html — maqueta HTML de una hoja propuesta (revisar antes de escribir).

  • pbi_create_page_from_spec — materializa una hoja PBIR completa desde un spec (clona visuales existentes por estilo).

  • pbi_export_page_html — exporta una página existente a maqueta HTML.

Toda tool devuelve {"ok": true/false, ...}; en error incluye error (código) y message (mensaje original del motor, sin ocultar).

Flujo de generación de hojas: pbi_page_building_blocks → (Claude interpreta tu instrucción y arma un spec) → pbi_preview_spec_html (revisas el HTML) → pbi_create_page_from_spec (se escribe el PBIR).


Ejemplos de uso (en lenguaje natural con Claude)

  • Correr DAX: "Lista los modelos abiertos, selecciona el único, y corre EVALUATE TOPN(10, Ventas)."

  • Documentar: "Documenta el modelo activo y analiza su calidad." → genera outputs/model_documentation_*.md.

  • Crear medida: "Crea la medida Margen % = DIVIDE([Utilidad],[Ventas]) en la tabla Ventas, formato 0.0%, modo both."

  • Listar visuales: "Abre el .pbip en C:/…/Informe.pbip y lista los visuales de la página 'Resumen'."

  • Crear visual: ver examples/sample_visual_specs.json.

  • Acomodar página: "Acomoda la página 'Resumen' con layout executive_summary."

Más DAX en examples/sample_queries.md.

⚠️ Edición de PBIR y estado de Desktop: las ediciones de informe (visuales/layout) se hacen en archivos; conviene hacerlas con Power BI Desktop cerrado y reabrir para verlas (si Desktop está abierto y guardas, sobrescribe los cambios en disco). Las ediciones de modelo en vivo (medidas live) requieren Desktop abierto y se persisten al guardar (Ctrl+S).


Troubleshooting

  • No detecta el puerto / "No se detecto ningun modelo": abre el informe en Power BI Desktop; el puerto cambia en cada arranque (el MCP lo descubre solo). Si usas la versión de Microsoft Store, igual se detecta por proceso.

  • adomd_not_installed / tom_not_installed: ejecuta python scripts/fetch_libs.py. Verifica que libs/Microsoft.AnalysisServices.AdomdClient.dll exista.

  • clr_not_available: falta .NET; prueba PBI_MCP_DOTNET_RUNTIME=coreclr.

  • Error DAX: el mensaje del motor se devuelve tal cual en message. Revisa la sintaxis (EVALUATE, comillas).

  • pbir_not_enabled: el informe no está en PBIR. Guarda como .pbip y activa Formato de reporte mejorado (PBIR) en Opciones → Características de vista previa (si aplica en tu versión) antes de guardar.

  • Power BI no recarga los cambios de visuales: ciérralo y reábrelo; PBIR se carga al abrir, no en caliente.

  • Permisos/OneDrive: si el .pbip está en OneDrive, cierra Desktop antes de editar archivos y espera a que OneDrive termine de sincronizar; los backups se guardan en backups/.


Decisiones técnicas

  • TOM vía pythonnet (no Tabular Editor CLI). Se evaluaron: (1) Tabular Editor 2 CLI, (2) pythonnet cargando TOM, (3) editar TMDL directo. Como pythonnet funciona en Python 3.14 y las DLLs de ADOMD.NET/TOM se pueden vendorizar en libs/ sin admin ni GAC, se eligió cargarlas directamente con pythonnet (runtime netfx). Es más estable, sin dependencias externas de instalación, y da control total (crear/editar medidas y refrescar como lo hace Tabular Editor). La edición durable sigue disponible por TMDL en .pbip.

  • Visuales por clonación. pbi_create_visual clona un visual existente del mismo tipo como plantilla (conserva el andamiaje de formato/tema) y solo cae a una plantilla mínima si no hay ninguno, avisando que debe validarse en Desktop.

  • Seguridad (Fase 11): backup automático antes de cada escritura en .pbip; JSON atómico (no deja archivos corruptos); no sobrescribe JSON ilegible; validación de rutas; change_log.md en outputs/; operaciones destructivas requieren confirm=true.

Limitaciones / riesgos abiertos

Ninguna de estas es un defecto que se pueda corregir desde aquí. Están documentadas porque afectan a lo que el servidor puede prometer.

Esquemas que Microsoft no publica

Power BI Desktop escribe visualContainer/2.10.0 en informes recientes, y esa URL devuelve 404 en el origen oficial. Lo mismo con bookmarks/2.0.0. El CLI oficial de Microsoft tampoco puede validarlos — emite PBIR_SCHEMA_UNREACHABLE y se salta la validación de esquema de esos archivos.

Consecuencia: las escrituras sobre archivos que declaren esos esquemas se bloquean con schema_unavailable (rule=no_publicado_upstream). Es deliberado y fail-closed: validar 2.10.0 contra 2.7.0 sería adivinar, y additionalProperties: false rechazaría propiedades nuevas legítimas.

Medido sobre un informe real de 443 documentos: 176 se validan, 240 quedan bloqueados por esta causa.

G10 queda como excepción de release documentada.

mode="both" bloqueado

live exige Power BI Desktop abierto; pbip lo exige cerrado. No hay ningún estado del sistema en que ambos destinos puedan escribirse con seguridad en una llamada. Ver docs/DUAL_MODE.md. R15 abierto.

filters e interactions del page spec

Se rechazan con unsupported_feature indicando la ruta JSON exacta. No se descartan en silencio. Su serialización a PBIR está pendiente.

Otras

  • PBIR debe estar activado en el .pbip; pbi_validate_pbip_project lo comprueba.

  • El nombre amigable del informe abierto no siempre es legible desde el motor (se reporta puerto + catálogo).

  • El parser TMDL en disco es pragmático (tablas, columnas, medidas, relaciones); para metadatos ricos, usa la ruta live.

  • pbi_generate_report_page es una composición heurística; no inventa campos y avisa lo que ignora.

  • El servidor arranca sin Node; lo que queda bloqueado son las escrituras que necesiten el validador oficial.


Estructura del proyecto

horizun-pbi-mcp/
├─ src/
│  ├─ server.py            # FastMCP + registro de tools
│  ├─ config.py            # settings + sesión (modelo/pbip activos)
│  ├─ logging_config.py
│  ├─ reporting.py         # documentación Markdown + calidad
│  ├─ powerbi/             # capa en vivo (ADOMD/TOM)
│  ├─ pbip/                # capa en disco (TMDL/PBIR)
│  ├─ tools/               # tools MCP por área
│  └─ utils/               # JSON, archivos, validación, change_log
├─ scripts/fetch_libs.py   # descarga DLLs de Analysis Services
├─ examples/  tests/  outputs/  libs/
├─ README.md  PLAN.md  pyproject.toml  requirements.txt  .env.example

Pruebas

python -m pytest -q

851 pruebas, 2 omitidas. Las dos omisiones son de entorno y dicen cómo ejecutarlas:

Omitida

Condición

test_run_dax_live

Requiere una instancia de Power BI Desktop sirviendo un modelo. python -m pytest -m live

test_no_llega_a_cero_por_acumular_infos

Requiere que el modelo sintético dispare solo reglas informativas

Marcadores disponibles:

python -m pytest -m "not packaging"     # rápido: omite wheel y sdist
python -m pytest -m live                # contra Power BI Desktop abierto
python -m pytest -m live_validator      # contra el CLI oficial de Microsoft

Verificar el contrato MCP (las 90 tools están congeladas):

python -m tests.contract_utils

Devuelve 0 si no hay rupturas, 1 si las hay, con un informe que dice qué cambió y si rompe compatibilidad.

Diagnóstico de la instalación:

python scripts/doctor.py

Licencia

MIT.

A
license - permissive license
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
1Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/HorizunGroup/horizun-pbi-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server