Command Palette

Search for a command to run...

UnylyUnyly
Browse all

Acopia

FreeNot checked

MCP server for querying and simulating the dispatch plan of a solar PV + battery system in the Chilean electricity market, using deterministic optimization and

GitHubEmbed

About

MCP server for querying and simulating the dispatch plan of a solar PV + battery system in the Chilean electricity market, using deterministic optimization and optional DRL.

README

Motor de optimización de despacho para plantas solares con batería (PV-BESS) en el mercado eléctrico chileno. Pronostica la generación PV y el costo marginal (CMg) nodal con incertidumbre explícita, y decide cuándo cargar/descargar la batería para arbitrar el diferencial de CMg y rescatar energía que se vertería por congestión. El núcleo es determinista predict-then-optimize: mismo forecast, misma semilla → el mismo plan, bit a bit, con el motivo de cada decisión explicable hora por hora.

El problema que ataca: Chile vertió 6.084 GWh de energía renovable en 2025 (+7,8% vs 2024); entre 2022 y mediados de 2025 el vertimiento acumulado ronda los 11.900 GWh ≈ US$562M perdidos, con el CMg colapsando a 0 a mediodía por sobreoferta solar y disparándose en la punta vespertina. Ese diferencial es exactamente lo que una batería bien despachada captura.

🔭 Observatorio en vivo — la cara pública de Acopia: vertimiento renovable de Chile con datos oficiales del Coordinador (ene–may 2026: 2.463 GWh vertidos), regenerado mensualmente, con el snapshot del dashboard demo incluido.

Arquitectura completa y decisiones (ADRs) en SAD_Acopia_energia.md · Contexto de trabajo en CLAUDE.md.

Resultados medidos

Todo número de abajo sale de backtests reproducibles sobre datos reales chilenos (CMg horario de la barra S.GREGORIO, año 2025, del Coordinador Eléctrico; generación PV TMY de Antofagasta, Explorador Solar):

Qué se midió Resultado
Forecast de CMg (backtest anual, 7 folds) Seq2Seq-LSTM régimen-local: RMSE −23% vs baseline estacional-naïve (20.3k vs 26.2k mills/MWh)
Elección de ventana de entrenamiento Sweep de 6 ventanas: curva en U con mínimo en 720 h — la config no es frágil (enmienda ADR-002.2)
Robustez del plan en ejecución Optimización estocástica con 5 escenarios: ~100% de captura del ingreso foresight (vs 93% con escenario único)
Modo DRL (PPO) vs núcleo determinista El DRL captura el 96.1% del LP — el determinista gana y queda medido, no asumido (ADR-005)
Honestidad del experimento La primera corrida DRL "superó" al óptimo → se auditó el baseline y se encontró un bug real de cuantización que valía +8.9% de ingreso del LP (AUD-003, pagada)

Cómo funciona

  1. Pronostica con incertidumbre (nunca un número pelado): estacional-naïve, SARIMAX y Seq2Seq-LSTM detrás de un mismo puerto producen escenarios probabilísticos deterministas.
  2. Optimiza el despacho: LP estocástico de dos etapas (cvxpy + HIGHS) que co-optimiza arbitraje de CMg + reserva de frecuencia (SSCC) en una sola función objetivo, respetando la física de la batería (SoC, eficiencias, throughput) como restricciones duras.
  3. Deja rastro auditable: cada plan persiste su snapshot as-seen (forecast, estado, política versionada, semilla, huella SHA-256 del histórico) — un auditor regenera el plan bit a bit.
  4. Se explica y se simula vía una capa MCP read-only: consultar_despacho, explicar_despacho ("¿por qué cargaste a mediodía?"), simular ("¿y si el CMg colapsa en la punta?") y comparar_modos — nada se ejecuta ni persiste.
  5. Se corrige intradía: detección de desvío de generación + reoptimización desde el estado real de la batería, sin re-versionar la política.

El dominio es puro y stdlib-only (Clean Architecture con frontera verificada por import-linter): PyTorch, cvxpy y DRL viven en adaptadores, nunca en las firmas del núcleo.

Demo en 60 segundos

uv run uvicorn acopia.interfaces.rest.app:app   # → http://127.0.0.1:8000/demo
python -m acopia.interfaces.mcp.servidor        # servidor MCP (stdio) con el mismo día sembrado

¿Sin Python a mano? El mismo dashboard vive como snapshot estático en el Observatorio.

GET /demo sirve el dashboard del día típico chileno (ADR-011): el plan de despacho sobre la duck curve — CMg con anotaciones, PV y acciones de la batería, SoC — con el motivo de cada decisión en el tooltip, y el pipeline de datos que alimenta al motor. HTML autocontenido: sin CDN, sin framework de frontend, legible sin JavaScript, modo claro/oscuro. Es el mismo día que interroga la demo MCP.

Dashboard demo de Acopia

Estado

Fases 0–4 cerradas — el alcance de portafolio del SAD está completo (sign-offs en docs/AUDIT.md):

  • F0 — Cimientos: capas Clean Architecture, value objects enteros, ModeloBateria puro, property-tests (determinismo y factibilidad).
  • F1 — Despacho determinista: optimizador predict-then-optimize (cvxpy + HIGHS) con plan factible, ingreso auditable y API REST.
  • F2 — Forecasting + escenarios: tres forecasters intercambiables, snapshot as-seen del forecast (huella SHA-256), pipeline de ingesta de datos chilenos reales.
  • F3 — Robustez + backtest: optimizador estocástico de dos etapas, backtest de política contra el día real (esperado vs realizado vs foresight), reoptimización intradía.
  • F4 — SSCC + MCP + DRL: co-optimización arbitraje + reserva de frecuencia (ADR-010), servidor MCP read-only, modo DRL medido contra el baseline (ADR-005).

La Fase 5 (potencia de suficiencia, multi-planta, nube) se reserva "solo con tracción" — no se construye a futuro sin señal real de demanda.

Estructura

src/acopia/
├── domain/          # núcleo puro (stdlib-only): value objects, entidades, servicios, puertos
├── application/     # casos de uso: planificar, backtest, reoptimizar, comparar modos
├── infrastructure/  # adaptadores: forecasters, solver LP, DRL, ingesta, repositorios
└── interfaces/      # REST (FastAPI), MCP (FastMCP), CLI (acopia-datos), dashboard demo
tests/               # pytest + hypothesis (204 tests)

Desarrollo

Requiere Python 3.12+ y uv.

uv venv
uv pip install -e ".[dev]"

uv run ruff check .          # lint
uv run mypy                  # tipado estricto (mypy --strict)
uv run lint-imports          # fronteras de arquitectura (import-linter)
uv run pytest                # tests
uv run pip-audit             # vulnerabilidades conocidas en dependencias

Extras opcionales: .[forecasting] (torch CPU, LSTM), .[ingesta] (openpyxl, XLSX del Coordinador), .[mcp] (FastMCP, servidor MCP), .[drl] (stable-baselines3 + gymnasium).

Base de datos (TimescaleDB) para la fase de persistencia real:

docker compose up -d db

Datos reales (Chile)

El motor consume una serie horaria timestamp,generacion_w,cmg_mills_por_mwh (la "planta modelo"), que se arma de dos fuentes:

  1. CMg por barra — Coordinador Eléctrico. Vía práctica: descargar el XLS de Costo Marginal Real filtrando una barra y un rango de fechas. (La API existe — costo-marginal-online/v4/findByDate, ver MEMORY.md — pero no filtra por barra en el servidor y está rate-limited: inviable para un año de una barra.)
  2. Generación PV — Explorador Solar (solar.minenergia.cl): exportar la serie horaria de generación de la ubicación de la planta → gen.csv.

Como el Explorador entrega un "año típico" (2004–2016) y el CMg es de otro año, no comparten calendario: se alinean por posición (hora a hora), con el timestamp del CMg. Los lectores toleran el formato real del Coordinador (XLSX ancho, celdas combinadas, coma decimal chilena):

acopia-datos alinear --por-posicion \
  --cmg cmg.xlsx --col-ts-cmg Fecha --col-hora-cmg Hora --col-cmg "S.GREGORIO" --escala-cmg 1000 \
  --generacion gen.csv --col-gen pv --escala-gen 1000 \
  --salida planta.csv

Con la planta modelo armada, los backtests que respaldan la tabla de resultados:

acopia-datos backtest --planta datos/planta.csv --folds 7 \
  --modelos naive,sarimax,lstm --ventana-entrenamiento 720   # error de forecast por modelo
acopia-datos backtest-politica --planta datos/planta.csv     # ingreso esperado vs realizado vs foresight
acopia-datos comparar-modos --planta datos/planta.csv        # ADR-005: DRL (PPO) vs baseline LP

Ingeniería a la vista

El proyecto se rige por un método explícito (SDD + documentación viva): la spec cambia antes que el código, toda decisión tiene su ADR, todo trade-off aceptado tiene su entrada numerada de deuda, y ninguna fase cierra sin auditoría.

from github.com/faborubio/acopia

Install Acopia in Claude Desktop, Claude Code & Cursor

Recommended · one command, every IDE
unyly install acopia

Installs into Claude Desktop, Claude Code, Cursor & VS Code — handles npx, uvx and build-from-source repos for you.

First time? Get the CLI: curl -fsSL https://unyly.org/install | sh

Or configure manually

Run in your terminal:

claude mcp add acopia -- uvx --from git+https://github.com/faborubio/acopia acopia

FAQ

Is Acopia MCP free?

Yes, Acopia MCP is free — one-click install via Unyly at no cost.

Does Acopia need an API key?

No, Acopia runs without API keys or environment variables.

Is Acopia hosted or self-hosted?

A hosted option is available: Unyly runs the server in the cloud, no local setup required.

How do I install Acopia in Claude Desktop, Claude Code or Cursor?

Open Acopia on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.

Related MCPs

Compare Acopia with

Not sure what to pick?

Find your stack in 60 seconds

Author?

Embed badge for your README

Browse similar

All development MCPs