Skip to main content
Glama
JL-VALERO

mef_subnational_efficiency_mcp

by JL-VALERO

mef_subnational_efficiency_mcp

Auditoría del gasto público peruano mediante sistemas multi-agente, Claude Code Skills y un servidor MCP local. Procesa datos fiscales del MEF 2025 desde datosabiertos.gob.pe y digitaliza vía OCR un archivo histórico de 1964, exponiendo los resultados en un dashboard Streamlit de 4 pestañas.

Tarea HW_05 — Issue d2cml-ai/Data-Science-Python#178


Métricas clave

Métrica

Fórmula

Avance (%)

(Devengado / PIM) × 100

Presupuesto Paralizado

PIM − Devengado

  • PIM: presupuesto asignado (lo que se podía gastar).

  • Devengado: lo que realmente se gastó.


Related MCP server: mef_subnational_efficiency_mcp

Reglas de diseño

  1. Anti-context-flooding: prohibido cargar CSV/JSON completos en el contexto del LLM. Python filtra los archivos grandes localmente y guarda solo snapshots de 5-10 filas (data/snapshots/) y agregados pequeños (data/processed/).

  2. Updates por CLI: sin fechas hardcodeadas. El período se controla por argumento, p. ej. claude "run executor_skill for period 2025-12".


Estructura del proyecto

mef_subnational_efficiency_mcp/
├── app.py                     # Dashboard Streamlit (4 pestañas)
├── README.md
├── requirements.txt
├── .mcp.json                  # Registro del servidor MCP para Claude Code
├── .streamlit/config.toml     # Config de performance/tema (la genera el Evaluator)
├── .claude/skills/
│   ├── executor_skill.json    # Agente Executor (ingesta, OCR, draft UI)
│   └── evaluator_skill.json   # Agente Evaluator (QA, UI/UX, reporte)
├── src/
│   ├── mcp_server.py          # Servidor MCP local (8 tools)
│   ├── data_pipeline.py       # Ingesta MEF (anti-flooding)
│   ├── ocr_engine.py          # OCR PaddleOCR del archivo 1964
│   ├── analytical_engine.py   # Métricas y Hall of Shame
│   ├── run_skill.py           # Orquestador CLI de los skills (executor/evaluator)
│   └── utils.py               # Helpers comunes
├── data/
│   ├── raw_pdfs/              # PDF fuente 1964 (no versionado)
│   ├── snapshots/            # Muestras de 5-10 filas
│   └── processed/            # Resultados agregados pequeños
└── video/link.txt            # Link del video de presentación

Archivos añadidos a la estructura base: src/run_skill.py (orquestador que mapea claude "run <skill> for period <p>" a la ejecución real), .mcp.json (registro del servidor en Claude Code) y .streamlit/config.toml (introducido por el Evaluator). El resto coincide con la estructura exacta del issue.


Instalación

⚠️ Usa Python 3.10–3.12. PaddlePaddle/PaddleOCR aún no publican wheels para Python 3.13+; en 3.14 la instalación falla. En este proyecto se usó un entorno conda geo (Python 3.10).

conda create -n geo python=3.10 -y && conda activate geo   # recomendado
# o un venv con Python 3.10-3.12:  python3.10 -m venv .venv

pip install -r requirements.txt

Servidor MCP local

El portal datosabiertos.gob.pe corre sobre DKAN (API estilo CKAN, sin autenticación). El servidor MCP expone tools seguras que devuelven únicamente catálogos reducidos y snapshots de pocas filas (regla anti-flooding):

Tool

Qué hace

health_check

Verifica que el servidor está vivo.

search_datasets(query, limit)

Busca datasets por palabra clave (tolerante a acentos).

get_dataset_info(dataset_id)

Metadatos + recursos (id, formato, URL, datastore).

preview_resource(resource_id, rows)

Muestra filas de un recurso del datastore (≈ consultar_datastore_filtrado, máx 10).

preview_csv(url, rows)

Primeras filas de un CSV remoto sin descargarlo (≈ inspeccionar_esquema_csv).

descargar_documento_1964(filename)

Descarga el PDF histórico de 1964 a data/raw_pdfs/.

procesar_ocr_paginas_1964(start, count)

Dispara PaddleOCR sobre ≥15 páginas del 1964.

descargar_y_analizar_estadisticas(period)

Resumen pequeño (KPIs + top Hall of Shame) del período.

Criterio de las 8 tools (no más): se separó por responsabilidad — descubrimiento (search/info), inspección sin flooding (preview_*), e ingesta/cómputo del flujo histórico (descargar_1964/ocr/estadísticas). Se omitieron tools redundantes para mantener el contexto liviano.

Nota CKAN→DKAN: el issue asume CKAN (/api/3/action/package_search), pero el portal real es DKAN y ese endpoint da 404. La búsqueda se implementó con package_list + filtro y package_show (que devuelve el paquete envuelto en lista). Por eso search_datasets no usa package_search.

Ejecutar el servidor (stdio):

python src/mcp_server.py

Registrarlo en Claude Code: ver .mcp.json en la raíz (ya configurado).

Pipeline de datos MEF (anti-flooding)

Fuente: dataset del MEF Presupuesto y Ejecución de Gasto – Devengado Mensual (un CSV por año; el de 2025 pesa ~2.8 GB). El pipeline nunca lo descarga completo: lo transmite por chunks, lee solo las columnas necesarias, filtra por nivel de gobierno, agrega por entidad ejecutora y guarda solo resultados pequeños en data/processed/ y data/snapshots/.

Período dinámico por CLI (sin fechas hardcodeadas):

# Devengado anual 2025, gobiernos subnacionales (regional + local)
python src/data_pipeline.py --period 2025

# Devengado acumulado a junio 2025
python src/data_pipeline.py --period 2025-06

# Muestra rápida (tope de filas) para pruebas/demo
python src/data_pipeline.py --period 2025-06 --max-rows 150000

Columnas clave del MEF: MONTO_PIM (PIM), MONTO_DEVENGADO_<MES>/_ANUAL (Devengado), NIVEL_GOBIERNO (E/R/M = Nacional/Regional/Local), DEPARTAMENTO_EJECUTORA_NOMBRE, PLIEGO_NOMBRE, EJECUTORA_NOMBRE.

OCR del archivo histórico 1964

Documento: "Cuenta General de la República" (1964), Contraloría General del Perú (Fuentes Históricas del Perú / Google Books, id 9YkbAQAAMAAJ).

  1. Descarga el PDF (botón Descargar PDF en https://books.google.com.pe/books?id=9YkbAQAAMAAJ ) y guárdalo como data/raw_pdfs/cuenta_general_1964.pdf (no se versiona).

  2. Ejecuta el OCR (PaddleOCR) sobre ≥15 páginas:

# 15 páginas con tablas presupuestarias (desde la 60), GPU si está disponible
python src/ocr_engine.py --start 60 --count 15

python src/ocr_engine.py --start 60 --count 15 --cpu   # forzar CPU

Salida (solo resultados pequeños): data/processed/ocr_1964/page_XXXX.txt, ocr_1964.json y un snapshot en data/snapshots/.

GPU (opcional, recomendado): requiere Python 3.10–3.12 (paddle no tiene wheels para 3.14). Combo verificado en una RTX 3050 Ti (CUDA 12):

pip install paddlepaddle-gpu==2.6.1.post120 -f https://www.paddlepaddle.org.cn/whl/windows/mkl/avx/stable.html
pip install nvidia-cudnn-cu12==8.9.7.29 "numpy<2"

El motor registra automáticamente las DLLs de cuDNN/cuBLAS y cae a CPU si no hay GPU.

Motor analítico (métricas + Hall of Shame)

Consume data/processed/execution_<period>.csv (salida del pipeline) y calcula:

  • Avance (%) y Presupuesto Paralizado por entidad.

  • KPIs globales (PIM, devengado, avance global, paralizado total).

  • Agregados por nivel de gobierno, departamento y sector.

  • Hall of Shame: entidades con PIM > 10M PEN y peor avance.

python src/analytical_engine.py --period 2025-06 --top 15

Salida en data/processed/analytics_<period>/ (kpis.json, by_*.csv, hall_of_shame.csv) + snapshot. Sus funciones (kpis, by_dimension, hall_of_shame) las reutiliza el dashboard.

Skills duales y CLI dinámico por período

Dos skills en .claude/skills/ orquestados por src/run_skill.py:

  • executor_skill — refresca el análisis de un período: ingesta MEF (--scope all) → métricas → (opcional) OCR 1964 → dashboard.

  • evaluator_skill — audita consistencia, cross-verifica vía MCP (re-muestrea el origen para detectar extraction drift), modifica código (genera .streamlit/config.toml, verifica cache/guardas) y emite un reporte markdown (qa_report_<period>.md) además del JSON.

El período es dinámico (sin fechas hardcodeadas), admite año, año-mes y trimestre (2025, 2025-06, 2025-Q4). El comando de Claude Code:

claude "run executor_skill for period 2025-Q4"

equivale a:

python src/run_skill.py executor_skill --period 2025-Q4        # ingesta + análisis
python src/run_skill.py executor_skill --period 2025-Q4 --with-ocr   # incluye OCR
python src/run_skill.py executor_skill --period 2025-Q4 --dry-run    # solo muestra los comandos
python src/run_skill.py evaluator_skill --period 2025-Q4       # auditoría QA + markdown

Dashboard

Dashboard de 4 pestañas que reutiliza el motor analítico y lee solo los agregados de data/processed/ (cacheado con st.cache_data):

  1. KPIs 2025 + 1964 — métricas de ejecución, narrativa AI Advisor, y análisis histórico independiente del 1964 (líneas/página, montos detectados, categorías estructurales y conclusiones de texto).

  2. Distribución territorial — paralizado por departamento, heatmap departamento × nivel y treemap del presupuesto (tamaño = PIM, color = avance).

  3. Hall of Shame — entidades > 10M PEN con peor avance (umbral ajustable) y desglose del gasto bloqueado por genérica (infraestructura, bienes…).

  4. Auditoría multi-agente — reporte markdown del Evaluator (checks, cross-verificación, optimizaciones) + playground interactivo.

streamlit run app.py

El selector de período toma los datos ya procesados; genera uno con python src/run_skill.py executor_skill --period 2025-Q2 --max-rows 150000.

Maintenance

ActivityInactive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers