Guia de operacion de SIAG (motor de indicadores/BI de PascalAI) para agentes: el DSL de lectura (QUERY/DRILL/INSPECT/NAVIGATE), el de escritura, trampas verificadas (LAST anclado a hoy, LIMIT cambia la forma de la respuesta, sin DROP INDICATOR) y el mapa de operaciones de mcp-siag/mcp-siag-query. Companion skill de los paquetes mcp-siag y mcp-siag-query.
ppm install skill-siag
ppm skill install-claude
The second command activates the skill in Claude Code
(copies it into .claude/skills/).
SIAG es un motor de indicadores sobre series de tiempo. Backend Delphi/DataSnap
REST (/datasnap/rest/TSigServerMethods), datos en PostgreSQL/TimescaleDB.
El modelo tiene tres piezas:
region, tipo) y medidas
(ej. monto, unidades). Los datos son mensuales.margen_bruto = ventas.monto - costos.monto).TREE) — se navegan por niveles padre/hijo.Multi-tenant: la autenticación fija el tenant y su entidad (el schema de datos). Nunca se pasa el tenant en la consulta.
| Server | Uso |
|---|---|
siag-query (mcp-siag-query) |
Solo lectura. Preferirlo siempre para consultar. Rechaza verbos de escritura del lado del cliente, antes de enviar. |
siag (mcp-siag) |
Full: escrituras del DSL + CRUD de configuración. Usarlo solo cuando la tarea exige modificar. Las escrituras exigen rol=admin en el servidor. |
Ambos exponen un solo tool con un parámetro operation y (según la
operación) dsl.
siag-query: health, get_me, query, drill, navigate, inspect, dsl.
En query/drill/navigate/inspect el verbo inicial del DSL debe coincidir
con la operación; dsl acepta cualquiera de los cuatro de lectura.siag: health, login, get_me, execute_dsl (cualquier DSL), más
get_categorias, save_categoria, delete_categoria, get_variables,
save_variable, delete_variable, get_indicadores, save_indicador,
delete_indicador, get_biblioteca_categorias, get_biblioteca_indicadores.
Los getters son plurales.La autenticación es automática por variables de entorno
(SIAG_URL/SIAG_EMAIL/SIAG_PASSWORD/SIAG_TENANT); el token nunca pasa por
el modelo.
INSPECT antes de consultarLos nombres de tablas, medidas, dimensiones e indicadores son distintos en cada instalación. No los inventes ni los adivines. Empieza siempre por:
INSPECT INDICATORS -- nombre, fórmula, unidad, grupo de cada indicador
INSPECT TABLES -- tablas de hechos con su descripción
INSPECT DIMENSIONS OF <tabla>
INSPECT DATA RANGE OF <tabla> -- desde / hasta / total_registros
INSPECT DATA RANGE es especialmente importante: dice hasta qué fecha hay
datos, y eso condiciona qué períodos tiene sentido pedir (ver Trampa #1).
Otras formas: INSPECT INDICATOR <nom>, INSPECT TABLE <nom>,
INSPECT VALUES OF DIMENSION <dim> INTO <tabla>,
INSPECT DEPENDENCIES OF <indicador>.
Cuatro verbos: QUERY, DRILL, INSPECT, NAVIGATE.
Se pueden combinar en cualquier orden:
FILTER <dim>=<val> [AND <dim>=<val> ...]
PERIOD <año> | FROM <año> TO <año> | LAST <n> MONTHS | LAST <n> YEARS
GRANULARITY MONTHLY | YEARLY
QUERY <indicador> -- o <tabla>.<medida>
QUERY ingresos PERIOD 2024 GRANULARITY MONTHLY
QUERY ingresos PERIOD 2024 GRANULARITY YEARLY FILTER region=NORTE
QUERY margen_pct FROM 2022 TO 2024 GRANULARITY YEARLY
Devuelve {indicador, granularidad, puntos, series:[{t,v}]}.
Dos modos, con respuestas de forma distinta:
DRILL <target> BY DIMENSION <dim> [CHILDREN OF <cod>]
DRILL <target> BY FORMULA [DEPTH n] [THEN BY DIMENSION <dim>]
BY DIMENSION reparte el valor entre los valores de la dimensión.
BY FORMULA descompone el indicador en los términos de su fórmula — devuelve un
árbol con la serie de cada componente. Excelente para explicar por qué se
movió un indicador.
<target> puede ser un indicador o tabla.medida. Acepta además LIMIT n.
NAVIGATE <tabla> DIMENSIONS [FILTER ...] -- qué dimensiones tiene
NAVIGATE <tabla> DIMENSION <dim> [FILTER ...]
NAVIGATE <tabla> DIMENSION <dim> ROOT -- nivel raíz de un árbol
NAVIGATE <tabla> DIMENSION <dim> FROM <cod> -- hijos de un nodo
Para dimensiones con es_arbol: true, NAVIGATE es la forma correcta de bajar
nivel por nivel en vez de pedir todo de una vez.
LAST n se ancla a HOY, no a los datosLAST 24 MONTHS cuenta hacia atrás desde la fecha actual. Si los datos
terminaron hace tiempo, el resultado sale vacío o —peor— parcial y sin
avisar: en una instalación con datos hasta 2024-11 consultada en 2026,
QUERY ingresos LAST 24 MONTHS GRANULARITY YEARLY devolvió 2024 = 6.183.486,
que parece la cifra anual pero son solo 4 meses; el año completo era
15.396.878.
Regla: para cualquier cifra que vayas a reportar como anual usa PERIOD o
FROM..TO. Reserva LAST n para "los últimos n meses" literales, y verifica
antes con INSPECT DATA RANGE OF.
LIMIT cambia la forma de la respuestaEn DRILL ... BY DIMENSION:
LIMIT → mode: BY_DIMENSION, con groups[].series[{t,v}]LIMIT → mode: BY_DIMENSION_NAV, con periodos[] + filas[].valores[]Y en modo NAV la granularidad se ignora: GRANULARITY YEARLY LIMIT 2
devuelve una grilla de 12 casillas mensuales con el total anual en la primera y
ceros en el resto. No combines LIMIT con GRANULARITY YEARLY; si necesitas
recortar, pide todo y recorta tú.
DROP INDICATOREl DSL solo tiene DROP TABLE. Un indicador creado con DEFINE INDICATOR no se
puede borrar por el MCP. Antes de crear indicadores, avísale al usuario que
deshacerlo requiere SQL directo
(DELETE FROM metadata.indicadores WHERE nombre='...').
Las aperturas deben sumar el total. Si DRILL BY DIMENSION de un año no suma lo
mismo que el QUERY de ese año, hay un filtro implícito o datos incompletos:
repórtalo, no lo dejes pasar.
siag, requiere rol admin)Seis verbos: CREATE TABLE, ALTER TABLE, DROP TABLE [SAFE],
LOAD DIMENSION, LOAD DATA, DEFINE INDICATOR.
CREATE TABLE ventas
DESCRIPTION "Ventas brutas mensuales por región"
DIMENSIONS: region
MEASURES: monto UNIT monto unidades UNIT unidades
LOAD DIMENSION region INTO ventas
VALUES:
NORTE : "Región Norte"
SUR : "Región Sur"
LOAD DATA INTO ventas
DIMENSIONS: region=NORTE
MEASURE: monto
VALUES:
2024-01 : 419904
2024-02 : 447898
DEFINE INDICATOR margen_bruto
FORMULA: ventas.monto - costos.monto
UNIT: monto
DESCRIPTION: "Margen bruto"
GROUP: "Rentabilidad"
Se pueden mandar muchos statements en una sola llamada execute_dsl separados
por saltos de línea; la respuesta trae statements y un results[] con el
status de cada uno. Revisa cada elemento: que la llamada no falle no
significa que los 25 statements hayan pasado.
DEFINE INDICATOR sobre un nombre existente lo redefine.
Hay dos mundos que conviene no confundir:
metadata.*, vía DSL): lo que ven QUERY/DRILL/INSPECT.config.*, vía get_/save_/delete_*): categorías,
variables e indicadores del editor visual, donde la fórmula se guarda como
tokens.save_indicador intenta sincronizar hacia el motor emitiendo un DEFINE y
devuelve el resultado en un campo sync. Si sync.ok es false, el
indicador existe en el editor pero NO en el motor — no aparecerá en
QUERY/DRILL. Razones típicas en sync.reason: hoja_con_filtros,
formula_incompleta, nombre_no_es_identificador. Siempre revisa sync.
DROP TABLE, delete_* o de redefinir un indicador existente,
confirma con el usuario.{"error": "..."}; el tool los
convierte en {"ok":false,"error":"..."}. Un No autorizado en una escritura
casi siempre significa que el usuario no es admin.ppm install mcp-siag-query y ppm install mcp-siag desde
https://registry.pascalai.org, luego ppm mcp register. Requiere las env vars
SIAG_URL, SIAG_EMAIL, SIAG_PASSWORD, SIAG_TENANT.