Dashboard Builder MCP server
Servidor MCP de Dashboard Builder
Permite que un cliente de IA descubra tus conjuntos de datos y cree paneles en Dashboard Builder.
Se comunica con la aplicación Next.js a través de HTTP como un cliente API ordinario, por lo que todos los permisos, políticas de dependencia y reglas de validación de la aplicación siguen aplicándose. Nada cambia en la aplicación principal.
Se puede ejecutar de dos maneras:
Quién lo ejecuta | Identidad | Los usuarios necesitan | |
Alojado | un servidor, toda la org | la cuenta de cada persona, vinculada a su clave una vez | una URL y una clave |
Local | cada persona, su máquina | la cuenta de esa persona | Node y una copia de esta carpeta |
El modo alojado es el despliegue normal y es lo que cubre este documento. El modo local es para desarrollar el propio servidor, o para identidad por usuario, y se encuentra en DEVELOPMENT.md.
Para usuarios: conectarse a un servidor alojado
Necesitas dos cosas de quien lo haya desplegado: la URL y tu clave de acceso. Nada que clonar, sin archivos que apuntar, sin .env.
Añade esto a claude_desktop_config.json (Claude Desktop) o .mcp.json (Claude Code):
{
"mcpServers": {
"dashboard-builder": {
"command": "npx",
"args": [
"-y", "mcp-remote",
"https://mcp.yourcompany.com/mcp",
"--header", "Authorization: Bearer YOUR_KEY_HERE",
"--header", "X-Dashboard-Username: you",
"--header", "X-Dashboard-Password: your-dashboard-password"
]
}
}
}mcpServers es una clave de nivel superior, hermana de preferences — no anidada dentro de ella. Sal de Claude Desktop desde la bandeja del sistema y vuelve a abrirlo; cerrar la ventana no es suficiente.
Con las dos cabeceras X-Dashboard-* presentes, el servidor inicia sesión como tú automáticamente en el primer uso y de nuevo cada vez que la sesión expire — no hay nada más que hacer, y cada llamada actúa como tú: tus permisos, tu rastro de auditoría. La contrapartida es que tu contraseña de dashboard reside en este archivo de configuración y viaja (a través de HTTPS) con cada solicitud. Si la contraseña contiene caracteres fuera de ASCII, usa el enlace curl de abajo — las cabeceras HTTP no los transportan de forma fiable.
Alternativa: vincular una vez con curl, mantener la contraseña fuera de la configuración
Omite las dos cabeceras X-Dashboard-* y en su lugar vincula tu clave una vez — la contraseña se usa para ese único inicio de sesión y nunca se almacena en ningún sitio; el servidor conserva solo los tokens de sesión resultantes, exactamente como un navegador guarda las cookies:
curl -X POST https://mcp.yourcompany.com/auth/bind \
-H "Authorization: Bearer YOUR_KEY_HERE" \
-H "content-type: application/json" \
-d '{"username":"you","password":"your-dashboard-password"}'La diferencia con la ruta de cabeceras: cuando la cadena de sesión finalmente expire, vuelves a ejecutar este comando, mientras que las cabeceras se re-vinculan automáticamente. DELETE /auth/bind con la misma cabecera Authorization cierra la sesión de la clave en cualquier caso.
Alice's Claude ──[gate key]──> MCP server ──[Alice's session cookies]──> Dashboard API
^ ^
client config bound via credential headers or
POST /auth/bind; refreshed
automatically after thatCredencial | Vive en | Responde |
Clave de acceso | la configuración del cliente de cada usuario | ¿puede esta persona usar el servidor MCP? |
Tokens de sesión | el servidor, un archivo por clave | ¿como quién actúa esta clave? |
Si una clave nunca se vincula, las llamadas a herramientas fallan con un error que explica el paso de vinculación — o, cuando el servidor está configurado con una cuenta de servicio heredada, caen en esa identidad compartida.
mcp-remote es un pequeño puente que se ejecuta localmente y reenvía al servidor, por lo que Node debe estar instalado en la máquina del usuario. Para evitar incluso eso, Configuración → Conectores → Añadir conector personalizado de Claude Desktop acepta una URL directamente sin nada local — esa ruta espera OAuth en lugar de una clave estática, y la disponibilidad varía según la versión de Desktop.
Related MCP server: MCP SQL Server Data Warehouse Connector
Desplegando el servidor
server.js es el archivo de inicio. Escucha en PORT como un server.js de Next.js, y pone una puerta de clave API delante de cada solicitud MCP para que los llamadores no autenticados sean rechazados antes de que nada llegue al sistema de paneles.
Endpoints: POST /mcp (con puerta), POST /auth/bind y DELETE /auth/bind (con puerta — vincula o desvincula la identidad de dashboard de la clave que llama), y GET /health (abierto, para la comprobación de salud de la plataforma). Todo lo demás devuelve 404.
Variables de entorno
Requeridas — el servidor no arrancará sin ellas
Variable | Valor |
|
|
|
|
Genera claves con openssl rand -hex 24. La etiqueta antes de los dos puntos aparece en los registros y en los cubos de límite de velocidad; el secreto en sí nunca se registra. Revoca a una persona eliminando su entrada y reiniciando — y elimina su archivo de sesión bajo ~/.dashboard-mcp/sessions/ para eliminar también la identidad vinculada.
Cada clave se vincula luego a una cuenta de dashboard por su titular mediante POST /auth/bind — ver la sección de usuarios arriba. Ninguna credencial de dashboard reside en el entorno del servidor.
Respaldo heredado opcional — una cuenta de servicio compartida
Variable | Valor |
| una cuenta de servicio |
| la contraseña de esa cuenta |
Cuando se establecen, las claves que no se han vinculado actúan como esta cuenta compartida en lugar de fallar — al igual que una clave cuya vinculación ha expirado, hasta que se vuelva a vincular. Útil durante la migración; omítelo para nuevos despliegues para que cada llamador tenga su propia identidad.
Muy recomendado
Variable | Valor | Por qué |
|
| empezar en solo lectura hasta que las identidades estén vinculadas |
|
| habilita la protección contra rebinding de DNS |
| tu origen de cliente | lo mismo |
Deja DASHBOARD_MCP_PERSIST_SESSION en su valor predeterminado (true): las vinculaciones se almacenan un archivo por clave y sobreviven a los reinicios. Ponerlo en false mantiene las vinculaciones solo en memoria, por lo que cada reinicio — y cada worker en un host multi-worker — necesita su propio re-vinculado.
MCP_ALLOWED_HOSTS y MCP_ALLOWED_ORIGINS son opcionales — el servidor funciona sin ellos y la puerta de clave API sigue aplicándose. Establecer cualquiera de ellos activa la protección contra rebinding de DNS del transporte. Deja ambos sin establecer y el registro de inicio lo dice explícitamente.
Opcional
Variable | Predeterminado |
| 3001 |
|
|
| 120 solicitudes por clave por ventana |
| 60000 |
Variables de ajuste adicionales — ruta del archivo de sesión, tiempo de espera de solicitud, límites de respuesta y la anulación del id de tipo de dashboard — están documentadas en línea en .env.example, que está organizado por modo y lista cada variable que el servidor lee.
Nota sobre múltiples workers
Las vinculaciones son un archivo por clave, y un worker cuyo token en memoria ha sido rotado por otro worker se recupera releyendo ese archivo, que el worker ganador ya ha actualizado. La ventana de fallo es dos workers refrescando el mismo token al mismo instante; el perdedor se recupera en su siguiente intento, y en el peor caso la clave debe re-vincularse. El transporte MCP en sí es sin estado, por lo que las solicitudes pueden aterrizar en cualquier worker.
Configuración de Plesk
Configuración | Valor |
Raíz de la aplicación | el directorio |
Archivo de inicio de la aplicación |
|
Modo de aplicación | producción |
Variables de entorno | las tablas anteriores, en el panel de Node.js |
Antes de iniciar |
|
Añade a las directivas nginx adicionales del dominio:
proxy_buffering off;
proxy_read_timeout 300s;MCP responde como Server-Sent Events y nginx almacena en búfer las respuestas proxy por defecto. Sin proxy_buffering off, las solicitudes parecen colgarse en lugar de fallar, lo cual es una forma confusa de perder una tarde.
Mantén el puerto de Node fuera del firewall público. El nginx de Plesk hace proxy hacia él y establece X-Forwarded-For, que es lo que hace que las IPs de cliente registradas sean fiables.
Acceso versus identidad
La clave de acceso controla el acceso; la identidad proviene de la vinculación. La clave permite al llamador pasar la puerta, y la sesión vinculada a esa clave decide quién ve el dashboard — sus permisos, su rastro de auditoría. Los dos están deliberadamente separados: rotar el secreto de una clave elimina su vinculación (la sesión se archiva bajo el digest de la clave), y revocar una clave elimina el acceso sin tocar la cuenta.
La vinculación funciona como un inicio de sesión de navegador. POST /auth/bind ejecuta el /api/auth/login real de la aplicación una vez, la contraseña se descarta después del intercambio, y solo se conserva la sesión de token de refresco rotatorio — un archivo por clave, modo 0600. Como la aplicación rota el token de refresco en cada uso, un archivo de sesión filtrado muere rápidamente; como la contraseña nunca se almacena, no hay nada de larga duración que filtrar. La contrapartida: cuando una cadena de refresco expira o se rompe, esa clave se re-vincula con un curl.
Una credencial estable por solicitud (ApiKey en el sistema principal, o OAuth) eliminaría incluso ese re-vinculado, pero requiere cambios en la aplicación principal. Este diseño deliberadamente no necesita ninguno.
Desarrollando o ejecutándolo localmente
Ejecutar el servidor en tu propia máquina — para desarrollo, o para identidad por usuario sin alojamiento — está documentado por separado en DEVELOPMENT.md.
Herramientas
La cadena es: fuente de datos (API HTTP o carga de Excel) → conjunto de datos (una vista con forma con un flujo de trabajo de transformación) → widgets de dashboard. Las herramientas cubren las tres etapas.
Herramienta | Modo | Propósito |
| read | Ids de fuentes de datos, etiquetas, tipos (http/excel) y destinos |
| read | Forma de una fuente: parámetros, ruta de respuesta, columnas — nunca credenciales |
| read | Filas en vivo de una fuente; lista rutas de respuesta candidatas cuando una falla |
| read | Ids de conjuntos de datos, etiquetas y ámbitos |
| read | Nombres exactos de campos, tipos inferidos, un valor de muestra por cada uno |
| read | Una muestra limitada de filas reales |
| read | Definición completa del conjunto de datos: fuente, materialización, resumen del flujo de trabajo o envoltorio sin procesar |
| read | Ejecutar un borrador de flujo de trabajo contra datos reales sin guardar; diagnósticos por paso |
| read | Ids de paneles, etiquetas y ámbitos |
| read | Detalles del panel más una línea por widget; una configuración bajo petición |
| read | Los tipos de widget que se pueden crear |
| read | Contrato de configuración para un tipo, más un ejemplo real de tu espacio de trabajo |
| write | Prueba en seco de una configuración de endpoint HTTP; no se guarda nada, se infieren columnas y rutas |
| write | Crear una fuente de datos HTTP; el servidor sondea la URL y siembra un conjunto de datos por defecto |
| write | Cambiar partes de una fuente HTTP; se fusiona con la configuración almacenada |
| write | Crear un conjunto de datos; el servidor construye el flujo de trabajo por defecto cuando no se proporciona ninguno |
| write | Actualización parcial: etiqueta, fuente, límites, materialización, o reemplazar el flujo de trabajo |
| write | Volver a ejecutar un conjunto de datos materializado por instantánea, o informar de su última actualización |
| write | Crear un panel y adjuntar sus conjuntos de datos |
| write | Reemplazar la lista de conjuntos de datos del panel |
| write | Añadir un widget, colocado automáticamente en la cuadrícula |
| write | Cambiar título, conjunto de datos o claves de configuración |
| write | Eliminar un widget |
| write | Reempaquetar la cuadrícula o aplicar posiciones explícitas |
test_datasource está en el conjunto de escritura porque la aplicación lo restringe tras el permiso
de creación/edición de fuentes de datos y llama al endpoint ascendente — pero no persiste nada.
Notas de diseño
Disciplina de contexto. Toda la superficie de herramientas cuesta unos 7 KB — 24 descripciones más
las instrucciones del servidor —, así que resulta barato mantenerla cargada. Las respuestas son texto
compacto en lugar de JSON sin procesar, y cada lista está limitada con una nota explícita sobre lo que
se omitió. get_dashboard omite deliberadamente las configuraciones de los widgets; pides un widget
por id cuando necesitas su configuración.
Divulgación progresiva. Una configuración de gráfico tiene aproximadamente 59 campos. Poner eso en
una descripción de herramienta dominaría el contexto del cliente en cada petición, así que
describe_widget_kind sirve el contrato bajo demanda en su lugar: nombres de campos, tipos, notas, un
ejemplo mínimo funcional y — la parte útil — una configuración real extraída de un widget existente de
ese tipo en tu propio espacio de trabajo. Copiar una forma que ya se renderiza es mejor que inventar
una a partir de nombres de campos.
El servidor hace la geometría. Los modelos no son fiables en el empaquetado 2D. add_widget
acepta una pista de size (small, medium, large, full) y encuentra la primera celda libre sin
solapamiento en la cuadrícula de 12 columnas por sí mismo. arrange_dashboard en modo auto
reempaqueta un panel completo.
Fallar antes de la API, no después. Las configuraciones de los widgets se almacenan como JSON
opaco en la aplicación, así que una clave mal escrita produce un widget en blanco en lugar de un error.
add_widget valida la configuración contra el contrato del tipo primero — claves obligatorias, nombres
de agregación válidos, field presente cuando la agregación lo necesita — y devuelve una lista
específica de lo que falta.
Los widgets coinciden con lo que crearía la interfaz. La paleta de la aplicación siembra cada
nuevo widget con el defaultConfig del tipo desde el registro (config === undefined ? def.defaultConfig : config).
add_widget refleja eso: los valores por defecto del tipo se superponen debajo de lo que proporcione
el llamador, de modo que un gráfico creado por MCP lleva la misma línea base de paginationMode y
maxPoints que uno construido a mano, en lugar de una configuración dispersa sobre la que el
renderizador tenga que recurrir a valores de respaldo. El objeto fusionado es lo que se valida.
Fusionar en lugar de reenviar. PATCH /widgets/:id reemplaza el objeto de configuración por
completo. update_widget por defecto fusiona tus claves en la configuración existente, de modo que
cambiar un ajuste no significa reenviarlo todo.
Fallar cerrado al arrancar. El servidor HTTP se niega a arrancar sin al menos una entrada
MCP_API_KEYS, y rechaza claves de menos de 24 caracteres. Un endpoint MCP sin autenticación nunca
debería ser posible por accidente. Las claves se comparan como resúmenes SHA-256 con
timingSafeEqual, y solo se registran las etiquetas.
Los secretos permanecen en el servidor. describe_datasource lee el endpoint /schema de la
aplicación, que nunca incluye credenciales. update_datasource necesita la configuración completa
almacenada para fusionar contra ella — la obtiene dentro de la ejecución de la herramienta y envía el
resultado fusionado sin renderizar nunca authConfig, cabeceras almacenadas o cuerpo en el contexto
del modelo.
Validar antes de guardar. Los envoltorios de flujo de trabajo son fáciles de estropear de forma
sutil, así que el flujo es: copiar un envoltorio funcional con get_dataset includeWorkflow,
editarlo, ejecutar validate_dataset_workflow (que lo ejecuta en el servidor e informa de recuentos
de filas por paso, campos de salida y recuentos de nulos sin persistir nada), y luego guardar con
update_dataset.
Limitaciones conocidas
El catálogo de tipos de widget es una copia.
src/catalog/widget-kinds.tsreflejasrc/features/dashboard/widgets/registry.ts— incluido eldefaultConfigde cada tipo — y las interfaces de configuración por tipo. El registro de la aplicación es un componente de cliente e importa React, así que no se puede importar aquí. Si un tipo de widget gana un campo, o un valor dedefaultConfigcambia, actualiza también el catálogo, o los widgets creados por MCP se desviarán de los creados por la interfaz.La cobertura del catálogo es alta pero no total. Campos de configuración documentados vs. reales: tabla 18/21, estadística 22/25, gráfico 39/59, select 9/12, texto 16/17. Lo que se omite son sobre todo variantes cosméticas (opciones de estilo de tarta/línea/barra, anulaciones del eje derecho) y claves de interacción heredadas superadas por
highlightBindings. El ejemplo en vivo devuelto pordescribe_widget_kindes la referencia para esas. Los campos se agrupan en núcleo / visualización / interacción para que el contrato de datos se lea primero.Los enlaces caducan con la cadena de actualización. La sesión de una clave dura tanto como la aplicación mantenga vivo su token de actualización rotatorio. Cuando caduca, las llamadas fallan con un error que nombra la solución y el titular de la clave se vuelve a enlazar con un curl. Una identidad que nunca caduca necesita
ApiKeyconectado ensrc/lib/api-guard.tsen el sistema principal, lo cual no está hecho.Las escrituras son directas. La aplicación tiene un flujo de trabajo de borrador de cambios y aprobación (
ChangeDraft,ApprovalRequest). Estas herramientas escriben directamente con los permisos de la cuenta con sesión iniciada. Si los paneles creados por IA deben revisarse antes de publicarse, enruta las herramientas de escritura a través de/api/change-draftsen su lugar y mantén los permisos de la cuenta como solo lectura.Las fuentes de datos de Excel son de solo lectura aquí. Crear o actualizar una requiere una carga de archivo multiparte, que no encaja en el flujo de texto de MCP. Siguen apareciendo en
list_datasources,describe_datasourceypreview_datasource; créalas y actualízalas en la interfaz.No hay herramientas de eliminación. Eliminar una fuente de datos propaga un borrado suave a cada conjunto de datos construido sobre ella, así que las eliminaciones siguen siendo una acción humana en la interfaz.
delete_widgetes la única herramienta destructiva expuesta.
This server cannot be deployed
Maintenance
Related MCP Connectors
- Muvia BIOAuthcom.muviabi
Company and industrial data for AI assistants: datasets, SQL, dashboards, alarms, with approvals.
Query your org's data in natural language — read-only MCP access to SQL, NoSQL, files & warehouses.
Query your warehouse or a CSV with Claude/ChatGPT over MCP, governed by table-level ACL + audit.
Ask your organization's connected business data in plain language, with each person's permissions.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables secure querying of analytics data stored in AWS Athena/S3 through natural language, with multiple security layers including query validation, resource limits, and automatic PII redaction to prevent data breaches and destructive operations.-
- FlicenseNot gradedqualityDmaintenanceEnables AI assistants to interact with SQL Server Data Warehouses using natural language for automatic schema discovery and report generation. It ensures security by restricting operations to read-only SELECT queries through both code validation and database permissions.-
- AlicenseNot gradedqualityDmaintenanceEnables natural language querying and management of Apache Superset dashboard metadata, including user activity, data lineage, and change tracking.392 PyPI4MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI applications to interact with Tableau for querying data, exploring content, and retrieving views through natural language.20,867 npmApache 2.0