Skip to main content
Glama
arashnicoomanesh

MCP Zero Shot Agentic Forecaster


Resumen Ejecutivo y Valor de Negocio

¿Qué es este Repositorio?

El MCP Zero Shot Agentic Forecaster es un motor de pronóstico de series temporales de grado de producción, basado en microservicios, expuesto a través del Model Context Protocol (MCP). Impulsado por modelos fundacionales de última generación (Google TimesFM 2.5 XReg y Amazon Chronos-2), permite que agentes de IA autónomos (máquinas de estado LangGraph, enjambres CrewAI, pilas NeSy gobernadas por OPA/Rego y bucles ReAct estándar) consulten pronósticos probabilísticos de demanda bajo demanda, sin entrenamiento de modelos fuera de línea, ajuste de hiperparámetros ni preparación de conjuntos de datos por SKU.

Valor de Negocio y ROI

  • Elimina la latencia de arranque en frío: Ofrece pronósticos probabilísticos zero-shot instantáneos para lanzamientos de nuevos productos, promociones y SKU con historial corto, sin canalizaciones de entrenamiento.

  • Control de riesgo acotado por cuantiles: Emite cuantiles de demanda calibrados $p_{10}$, $p_{50}$ y $p_{90}$, lo que permite a los agentes de compra autónomos equilibrar los buffers de stock de seguridad frente a los costos de capital.

  • Menor costo total de propiedad (TCO): Reemplaza las complejas canalizaciones de ajuste fino con un motor de respaldo unificado de 3 niveles, reduciendo drásticamente los requisitos de cómputo GPU y la deriva de infraestructura.

  • Resiliencia agéntica: Devuelve cargas útiles estructuradas AgentFriendlyError con sugerencias de corrección cuando las entradas no son válidas, lo que permite a los agentes llamantes autocorregirse en los bucles de ejecución sin fallar silenciosamente ni lanzar excepciones no controladas.

Cómo Funciona

  1. Invocación del agente: Los agentes llamantes invocan forecast_demand o forecast_batch a través de stdio/HTTP mediante la interfaz de herramientas MCP.

  2. Aplicación del contrato: Los esquemas Pydantic v2 realizan verificaciones rigurosas de límites numéricos finitos y temporales ([Type-Safe Input Contract]).

  3. Inferencia no bloqueante: FastMCP descarga las operaciones pesadas de tensores a grupos de hilos mediante asyncio.to_thread para preservar la capacidad de respuesta de la puerta de enlace.

  4. Canalización unificada de 3 niveles: Siempre enruta a través de TimesFM 2.5 (Nivel 1), con respaldo a Chronos-2 (Nivel 2, conserva covariables si están presentes) y ARIMA111 (Nivel 3, descarta covariables). Ante OOM de CUDA o fallo, el motor activa la recuperación de memoria (gc.collect() + torch.cuda.empty_cache()) antes de degradar al siguiente nivel.

  5. Saneamiento matemático: Aplica ordenamiento isotónico para garantizar la monotonicidad de los cuantiles de salida ($p_{10} \le p_{50} \le p_{90}$) y normaliza las puntuaciones de confianza epistémica antes de devolver cargas útiles JSON estructuradas.


Related MCP server: Geneva Forecasting MCP

Arquitectura del Sistema

El microservicio cumple una estricta separación de responsabilidades: la capa de herramientas MCP gestiona el transporte no bloqueante, la seguridad de memoria y el saneamiento de salidas a nivel de modelo, dejando las políticas de negocio específicas del dominio a los orquestadores de agentes posteriores.

graph TD
    subgraph External Agent Orchestrator
        Agent[LLM Agent / Swarm / State Machine<br/>LangGraph / OPA Sidecar / ReAct Loop]
    end

    subgraph MCP Microservice Boundary
        Gateway[FastMCP Async Gateway Server<br/>mcp_server.py]
        Sanitizer[Pydantic v2 Input Contract<br/>TimeSeriesInputPayload]
        ErrorFormatter[AgentFriendlyError Formatter]
        
        subgraph Engine Memory & Concurrency Boundary
            ExecThread[Thread Executor<br/>asyncio.to_thread]
            Engine[ZeroShotForecastingEngine<br/>src/models/forecaster.py<br/>Lazy-Load Lock Protected]
            
            subgraph 3-Tier Fallback Model Chain
                T1[Tier 1: TimesFM 2.5<br/>XReg / Univariate]
                T2[Tier 2: Chronos-2<br/>Multivariate / Univariate]
                T3[Tier 3: ARIMA111<br/>CPU Baseline Fallback]
            end
            
            IsoSanitizer[Isotonic Quantile Sanitizer<br/>Enforces p10 ≤ p50 ≤ p90]
        end
    end

    Agent -->|FastMCP Tool Call<br/>forecast_demand / forecast_batch| Gateway
    Gateway -->|1. Validate Schema| Sanitizer
    Sanitizer -->|Validation Error| ErrorFormatter
    ErrorFormatter -.->|Structured Error + Remediation| Agent
    
    Sanitizer -->|2. Valid Payload| ExecThread
    ExecThread -->|3. Route Request| Engine
    Engine --> T1
    T1 -.->|CUDA OOM / Fail| T2
    T2 -.->|Fail| T3
    
    T1 -->|Raw Quantiles| IsoSanitizer
    T2 -->|Raw Quantiles| IsoSanitizer
    T3 -->|Raw Quantiles| IsoSanitizer
    
    IsoSanitizer -->|4. Validated ForecastResponse| Gateway
    Gateway -->|5. Return JSON Payload| Agent

Desglose de Componentes de la Arquitectura

Puerta de enlace FastMCP (mcp_server.py): Proporciona transporte JSON-RPC asíncrono y aplica límites de concurrencia por lotes (asyncio.Semaphore(4)).

Límite de contrato con seguridad de tipos (src/schemas/payloads.py): Aplica alineación temporal, garantías de números finitos y límites de contexto/horizonte.

Núcleo de pronóstico seguro para hilos (src/models/forecaster.py): Emplea bloqueo de doble verificación (threading.Lock()) para la carga diferida de modelos y gestiona la recuperación automática ante OOM de CUDA (gc.collect() + torch.cuda.empty_cache()).

Saneador de salidas isotónico: Procesa posteriormente los cuantiles brutos de los modelos fundacionales mediante ordenamiento monótono para eliminar anomalías estadísticas ($p_{10} > p_{50}$) antes de devolver las predicciones a los agentes.

Flujo de Ejecución del Sistema (Diagrama de Secuencia)

sequenceDiagram
    autonumber
    actor Agent as LLM Agent / Orchestrator
    participant Gateway as FastMCP Gateway (Async)
    participant Sanitizer as Pydantic Input Contract
    participant Executor as Thread Executor (asyncio.to_thread)
    participant Pipeline as 3-Tier Fallback Pipeline
    participant Std as Isotonic Quantile Sanitizer

    Agent->>Gateway: forecast_demand / forecast_batch (JSON)
    Gateway->>Sanitizer: Validate TimeSeriesInputPayload
    alt Validation Failure
        Sanitizer-->>Gateway: AgentFriendlyError {error_code, expected, received, remediation}
        Gateway-->>Agent: Structured Error Response
    else Validation Success
        Sanitizer->>Executor: Offload sync inference
        Executor->>Pipeline: Execute prediction
        Note right of Pipeline: Tier 1: TimesFM 2.5 → Tier 2: Chronos-2 → Tier 3: ARIMA111
        alt CUDA OOM / Transient Failure
            Pipeline->>Pipeline: gc.collect() + torch.cuda.empty_cache()
            Pipeline->>Pipeline: Degrade to next tier (retain covariates where possible)
        end
        Pipeline->>Std: Apply _enforce_quantile_monotonicity()
        Std-->>Executor: ForecastResponse {model_used, exogenous_dropped, warnings}
        Executor-->>Gateway: Return validated response
        Gateway-->>Agent: 200 OK with ForecastResponse
    end

Principios Arquitectónicos Fundamentales

Transporte Asíncrono No Bloqueante

Todos los pases de avance de tensores se ejecutan en un grupo de hilos mediante asyncio.to_thread, manteniendo el bucle de eventos de FastMCP receptivo a verificaciones de salud concurrentes e invocaciones de herramientas bajo carga.

# mcp_server.py
result = await asyncio.to_thread(engine.predict, validated_payload)

Carga Diferida de VRAM

Los pesos del modelo se materializan solo en el primer uso mediante métodos de acceso; no se consume VRAM al inicio. El bloqueo de doble verificación seguro para hilos evita la instanciación duplicada en arranques en frío concurrentes.

# src/models/forecaster.py
def _get_timesfm(self):
    if self._timesfm is None:
        with self._timesfm_lock:
            if self._timesfm is None:
                import timesfm
                logger.info(f"Lazily loading TimesFM-2.5 ({self.timesfm_repo_id}) onto {self._device}")
                self._timesfm = timesfm.TimesFM_2p5_200M_torch.from_pretrained(self.timesfm_repo_id)
    return self._timesfm

def _get_chronos(self):
    if self._chronos is None:
        with self._chronos_lock:
            if self._chronos is None:
                from chronos import BaseChronosPipeline
                logger.info(f"Lazily loading Chronos-2 ({self.chronos_repo_id}) onto {self._device}")
                self._chronos = BaseChronosPipeline.from_pretrained(
                    self.chronos_repo_id, device_map=self._device, dtype=torch.float32
                )
    return self._chronos

Motor de Respaldo de 3 Niveles

El motor mantiene una única cadena de degradación determinista unificada, independientemente del contenido de la carga útil.

Nivel

Backend

Modo

model_used

exogenous_dropped

1

TimesFM 2.5

XReg / Univariado

TimesFM-2.5

false

2

Chronos-2

Multivariado / Univariado

Chronos-2-Fallback

false

3

ARIMA111

Línea base

ARIMA111-Baseline

true

Ante un fallo de TimesFM (incluido torch.cuda.OutOfMemoryError):

  1. gc.collect() + torch.cuda.empty_cache()

  2. Las señales exógenas se conservan para Chronos-2 mediante _build_chronos_covariates() (covariables pasadas/futuras)

  3. exogenous_dropped = true solo si el respaldo degrada al Nivel 3 (ARIMA111)

  4. La ejecución se enruta a Chronos-2

  5. Si Chronos falla → línea base ARIMA111

Aplicación de Regularidad Temporal

Los validadores Pydantic v2 rechazan telemetría no válida en el límite:

Validador

Regla

Límites de contexto

16 <= len(target_series) <= 16000

Límites de horizonte

1 <= forecast_horizon <= 1024

Valores finitos

target_series, price_index no deben contener NaN/Inf

Alineación exógena

len(price_index) == len(target_series) + forecast_horizon

Indicadores binarios

los elementos de promo_flag deben ser 0 o 1

Saneamiento Isotónico de Cuantiles

Todos los backends (TimesFM, Chronos-2, AutoARIMA) emiten cuantiles brutos que ocasionalmente pueden cruzarse ($p_{10} > p_{50}$ o $p_{50} > p_{90}$) ante entradas OOD extremas. El motor aplica un paso de procesamiento posterior ligero _enforce_quantile_monotonicity() que realiza un ordenamiento isotónico por paso temporal: apila $(p_{10}, p_{50}, p_{90})$, ordena a lo largo del eje de cuantiles y devuelve los tripletes ordenados. Esto garantiza $p_{10} \le p_{50} \le p_{90}$ matemáticamente válidos para cada paso del horizonte de pronóstico sin distorsionar la forma distribucional.

Concurrencia por Lotes Acotada

La herramienta MCP forecast_batch ejecuta inferencia multi-SKU de forma concurrente mediante asyncio.gather acotado por un asyncio.Semaphore(4). Esto proporciona rendimiento paralelo mientras protege la memoria GPU/CPU de asignaciones de tensores concurrentes ilimitadas. Cada elemento adquiere el semáforo, valida su carga útil, descarga engine.predict a un grupo de hilos mediante asyncio.to_thread y devuelve una ForecastResponse estructurada con metadatos de respaldo por elemento. El bloque de resumen informa el total de elementos, el recuento de errores y el uso por backend (model_usage).

Interruptores de Circuito por Backend

Cada backend de modelo fundacional mantiene un interruptor de circuito independiente (CircuitBreakerState) para evitar fallos en cascada cuando un hub de modelos es inalcanzable o falla de forma consistente. Después de 5 fallos consecutivos, el interruptor se abre y enruta el tráfico inmediatamente al siguiente nivel de respaldo durante 60 segundos antes de permitir una llamada de prueba.

Backend

Umbral de fallos

Enfriamiento

Comportamiento abierto

TimesFM 2.5

5 fallos

60s

Lanza MODEL_UNAVAILABLE; enruta a Chronos-2

Chronos-2

5 fallos

60s

Lanza MODEL_UNAVAILABLE; enruta a AutoARIMA

Esto garantiza que una interrupción transitoria del HuggingFace Hub o una descarga corrupta de pesos no bloquee al agente indefinidamente.

Métrica de Confianza Normalizada

La puntuación de confianza utiliza una relación de incertidumbre relativa acotada en lugar de un piso lineal que comprime la varianza amplia a 0.0:

$$\text{Confidence} = \frac{1}{1 + \frac{p_{90} - p_{10}}{\vert p_{50}\vert + \epsilon}}$$

donde $\epsilon = 10^{-5}$. Propiedades:

  • Rango de salida $(0, 1]$: nunca negativa, nunca comprimida a 0

  • A medida que la dispersión $(p_{90} - p_{10}) \to 0$, la confianza $\to 1$ (límites ajustados)

  • A medida que la dispersión $\to \infty$, la confianza $\to 0$ asintóticamente (incertidumbre extrema)

  • Invariante a la escala mediante división por la magnitud mediana $|p_{50}|$

Agnóstico a la Arquitectura Agéntica

Como microservicio de herramientas MCP sin estado y vinculado a esquemas, este motor se integra sin fricción con cualquier orquestador de agentes, incluidas pilas Neuro-Simbólicas gobernadas por políticas OPA/Rego, máquinas de estado LangGraph, enjambres CrewAI o bucles ReAct estándar.


Especificaciones de Herramientas MCP y Contratos de API

forecast_demand

Predicción de una única serie temporal.

Solicitud (TimeSeriesInputPayload)

{
  "target_series": [120.5, 115.0, 130.2, 125.8, 140.1],
  "forecast_horizon": 30,
  "price_index": [19.99, 19.99, 24.99, 24.99, 24.99, 24.99, ...],
  "promo_flag": [0, 0, 1, 0, 1, 0, ...]
}

Respuesta (ForecastResponse)

{
  "model_used": "Chronos-2-Fallback",
  "mean_prediction": [142.3, 145.1, 140.8, 148.2, 150.0],
  "p10_quantile": [120.1, 122.4, 118.7, 125.3, 127.9],
  "p50_quantile": [142.3, 145.1, 140.8, 148.2, 150.0],
  "p90_quantile": [165.2, 168.5, 162.1, 170.4, 172.8],
  "confidence_score": 0.87,
  "horizon_length": 30,
  "exogenous_dropped": false,
  "warnings": ["CUDA unavailable; running on CPU. Expect degraded inference performance."]
}

forecast_batch

Predicción multi-SKU basada en arreglos con resumen de respaldo por elemento.

Solicitud

{
  "payloads": [
    {"target_series": [10.0]*20, "forecast_horizon": 5},
    {"target_series": [11.0]*30, "forecast_horizon": 3, "price_index": [20.0]*33}
  ]
}

Respuesta

{
  "results": [
    {"model_used": "Chronos-2-Fallback", "mean_prediction": [...], ...},
    {"model_used": "TimesFM-2.5", "mean_prediction": [...], ...}
  ],
  "summary": {
    "total": 2,
    "errors": 0,
    "model_usage": {"Chronos-2-Fallback": 1, "TimesFM-2.5": 1}
  }
}

AgentFriendlyError

Esquema de error autocorrectivo devuelto ante fallos de validación o ejecución.

{
  "error_code": "VALIDATION_ERROR",
  "message": "Input validation failed at 'price_index': Price array misalignment. Expected 25 elements (Context: 20 + Horizon: 5), got 2.",
  "expected": "Payload matching TimeSeriesInputPayload schema (context 16-16000 finite values, aligned exogenous signals).",
  "received": "{\"location\": \"price_index\", \"message\": \"Price array misalignment. Expected 25 elements (Context: 20 + Horizon: 5), got 2.\", \"context\": {\"expected\": \"25\", \"got\": \"2\"}}",
  "remediation_suggestion": "Correct field 'price_index' (Price array misalignment. Expected 25 elements (Context: 20 + Horizon: 5), got 2.) and resubmit. Ensure context length is between 16 and 16000, values are finite (no NaN/Inf), and exogenous arrays align to len(target_series) + forecast_horizon."
}

Códigos de error: VALIDATION_ERROR, MODEL_UNAVAILABLE, TRANSIENT_FAILURE, MODEL_FAILURE, INTERNAL_ERROR


Inicio Rápido y Configuración de MCP

Instalación

# Requires Python 3.11+
uv sync --extra gpu   # or: pip install -r requirements.txt

Entorno

# Optional: force CPU if GPU memory constrained
export MODEL_CONFIG_PATH=configs/model_config.yaml
export DATA_STORAGE_ROOT=data/

El motor detecta automáticamente CUDA. Si no está disponible, recurre a CPU y emite una advertencia en el campo warnings.

Configuración del Cliente MCP (Claude Desktop / OpenCode / LangGraph / CrewAI)

Agregue a la configuración de su cliente MCP (claude_desktop_config.json, opencode.json o equivalente):

{
  "mcpServers": {
    "zero-shot-forecaster": {
      "command": "python",
      "args": ["mcp_server.py"],
      "cwd": "/absolute/path/to/zero-shot-demand-foundation",
      "env": {
        "MODEL_CONFIG_PATH": "configs/model_config.yaml"
      }
    }
  }
}

Reinicie su cliente MCP. Las herramientas forecast_demand y forecast_batch se registrarán automáticamente con sus esquemas JSON completos.

Ejemplo de Invocación (Claude / Agente LLM)

{
  "tool": "forecast_demand",
  "arguments": {
    "target_series": [120, 115, 130, 125, 140, 135, 150, 145, 155, 160, 155, 165, 170, 168, 172, 175, 180, 178, 185, 190],
    "forecast_horizon": 7,
    "price_index": [19.99, 19.99, 19.99, 19.99, 19.99, 19.99, 24.99, 24.99, 24.99, 24.99, 24.99, 24.99, 24.99, 24.99, 24.99, 24.99, 24.99, 24.99, 24.99, 24.99, 24.99, 24.99, 24.99, 24.99, 24.99, 24.99, 24.99],
    "promo_flag": [0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
  }
}

Verificación y Pruebas

Ejecutar la Suite de Pruebas Completa (62 pruebas, AC-1 a AC-5)

uv run pytest tests/ -q
# or
python -m pytest tests/ -q

Salida esperada:

.............................................................. [100%]
62 passed in ~3s

Matriz de Cobertura de Pruebas

AC

Criterio

Función de prueba

AC-1

Bucle de eventos no bloqueante

test_forecast_demand_is_non_blocking

AC-2

Carga diferida y conservación de VRAM

test_lazy_loading_*, test_hardware_auto_detect_*

AC-3

Degradación elegante y eliminación de señales

test_timesfm_failure_falls_back_to_chronos_strips_exog, test_full_fallback_to_autoarima

AC-4

Recuperación de OOM de CUDA

test_cuda_oom_triggers_memory_recovery, test_recover_from_oom_calls_gc_and_empty_cache

AC-5

Cargas útiles de autocorrección del agente

test_agent_friendly_error_on_short_sequence, test_forecast_batch_agent_friendly_error_per_item

Pruebas heredadas (Compatibilidad hacia atrás)

Las 48 pruebas originales siguen pasando:

pytest tests/test_forecasting_engine.py tests/test_forecaster_router.py tests/test_mcp_server.py tests/test_schemas.py tests/test_metrics.py -q

Estructura del proyecto (Post-refactorización)

zero-shot-demand-foundation/
├── configs/
│   └── model_config.yaml            # Model IDs, device_map, num_samples
├── data/                            # Git-ignored (CSV, ZIP)
├── scripts/
│   ├── download_m5.py               # M5 dataset fetcher
│   └── download_favorita.py         # Favorita dataset fetcher
├── src/
│   ├── models/
│   │   └── forecaster.py            # ZeroShotForecastingEngine (refactored)
│   ├── schemas/
│   │   └── payloads.py              # TimeSeriesInputPayload, ForecastResponse, AgentFriendlyError
│   └── utils/
│       ├── data_loader.py           # DemandDataEngine, FavoritaDataLoader
│       └── metrics.py               # WAPE, RMSSE, Pinball Loss, CRPS
├── tests/
│   ├── test_forecasting_engine.py   # Updated for lazy loading
│   ├── test_forecaster_router.py    # Updated fixtures
│   ├── test_mcp_server.py           # Async + AgentFriendlyError
│   ├── test_metrics.py              # Unchanged
│   ├── test_schemas.py              # Unchanged
│   └── test_refactored_forecaster.py # NEW: AC-1..5 coverage
├── main.py                          # CLI evaluation entry point
├── mcp_server.py                    # FastMCP server (async, batch, errors)
├── requirements.txt
├── .gitignore                       # Ignores *.md, data/, __pycache__/
└── README.md                        # This file

Licencia

Licencia MIT. Consulte LICENSE para más detalles.

Referencias

  • Chronos-2: Ansari et al., Chronos: Learning the Language of Time Series, arXiv:2403.07815

  • TimesFM: Das et al., TimesFM: A Decoder-Only Foundation Model for Time-Series Forecasting, arXiv:2402.02592

  • M5 Competition: Makridakis et al., M5 Accuracy Competition, IJF 2022

  • Corporación Favorita: Kaggle Favorita Grocery Sales Forecasting

  • Model Context Protocol: Anthropic MCP Specification

A
license - permissive license
Not graded
quality - not tested
B
maintenance

Maintenance

0dRelease cycle
2Releases (12mo)

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

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

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    An MCP server powered by Meta's Prophet that enables LLMs to perform time-series forecasting, trend analysis, and predictive modeling on historical data. It provides LLM-friendly statistical summaries, automated business-rule validation, and ready-to-render Chart.js visualizations.
    MIT

View all related MCP servers

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/arashnicoomanesh/zero-shot-demand-forecasting'

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