MCP Zero Shot Agentic Forecaster
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@MCP Zero Shot Agentic ForecasterForecast weekly demand for SKU-123 for the next 8 weeks using historical sales."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Executive Overview & Business Value
What is this Repository?
The MCP Zero Shot Agentic Forecaster is a production-grade, microservice-based time-series forecasting engine exposed via the Model Context Protocol (MCP). Powered by state-of-the-art foundation models (Google TimesFM 2.5 XReg and Amazon Chronos-2), it allows autonomous AI agents (LangGraph state machines, CrewAI swarms, OPA/Rego-governed NeSy stacks, and standard ReAct loops) to query probabilistic demand forecasts on demand—without offline model training, hyperparameter tuning, or per-SKU dataset preparation.
What this repository is not: This is not an AI agent, nor is it a neuro-symbolic system on its own. It is a symbolic skill — a deterministic, stateless MCP Server that exposes mathematical forecasting tools. It is designed to be invoked by an external MCP Host (e.g., Claude Desktop, LangGraph, CrewAI, or a neuro-symbolic orchestrator). The agent reasons; this skill computes.
Business Value & ROI
Eliminates Cold-Start Latency: Delivers instant zero-shot probabilistic forecasts for new product launches, promotions, and short-history SKUs without training pipelines.
Quantile-Bounded Risk Control: Emits calibrated $p_{10}$, $p_{50}$, and $p_{90}$ demand quantiles, enabling autonomous purchasing agents to balance safety stock buffers against capital holding costs.
Lower Total Cost of Ownership (TCO): Replaces complex fine-tuning pipelines with a unified 3-tier fallback engine, drastically lowering GPU compute requirements and infrastructure drift.
Agentic Resiliency: Returns structured
AgentFriendlyErrorpayloads with remediation hints when inputs are invalid, allowing calling agents to self-correct in execution loops without failing silently or raising unhandled exceptions.
Empirical Validation
M5 Walmart (30,000+ item-store series): WRMSSE 0.763 in pure zero-shot, outperforming Moirai (0.798) and Prophet (0.812). On promotional SKUs, 23% improvement in Normalized Deviation vs baseline.
Corporación Favorita (Ecuador): Cross-region out-of-distribution stress test with oil price fluctuations and local inflation — maintained predictive stability without retraining or local tuning.
How It Works
Agent Invocation: Calling agents invoke
forecast_demandorforecast_batchover stdio/HTTP via the MCP tool interface.Contract Enforcement: Pydantic v2 schemas perform rigorous, finite numeric and temporal boundary checks (
[Type-Safe Input Contract]).Non-Blocking Inference: FastMCP offloads heavy tensor operations to thread pools via
asyncio.to_threadto preserve gateway responsiveness.Unified 3-Tier Pipeline: Always routes through TimesFM 2.5 (Tier 1) in
xreg + timesfmmode — a linear model first fits external covariates to the target, then the 200M-parameter univariate transformer forecasts the residuals. On failure, execution falls back to Chronos-2 (Tier 2, retains covariates via_build_chronos_covariates()), and finally ARIMA111 (Tier 3, drops covariates). On CUDA OOM or transient failure, the engine triggers memory recovery (gc.collect()+torch.cuda.empty_cache()) before degrading.Mathematical Sanitation: Applies isotonic sorting to guarantee output quantile monotonicity ($p_{10} \le p_{50} \le p_{90}$) and normalizes epistemic confidence scores before returning structured JSON payloads.
Related MCP server: Geneva Forecasting MCP
System Architecture
The microservice adheres to strict separation of concerns: the MCP tool layer manages non-blocking transport, memory safety, and model-level output sanitation, while leaving domain-specific business policies to downstream agent orchestrators.
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<br/>Single-Model VRAM Residency]
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 monotonicity]
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 -.->|OOM / Hub Down / Circuit Open / Struct Error| T2
T2 -.->|OOM / CUDA Error / Unhandled Exception| T3
T1 -->|Raw Quantiles| IsoSanitizer
T2 -->|Raw Quantiles| IsoSanitizer
T3 -->|Raw Quantiles| IsoSanitizer
IsoSanitizer -->|4. Validated ForecastResponse| Gateway
Gateway -->|5. Return JSON Payload| AgentMCP Protocol Mapping: In Model Context Protocol terminology, the Host is the external agent orchestrator (e.g., Claude Desktop, LangGraph, or AXIOMIS). The Client lives inside the Host and manages the stdio/HTTP connection. This repository is the Server — an external process that exposes
forecast_demandandforecast_batchas Tools.
┌─────────────────────────────────────────────────────────────┐
│ NEURAL AGENT (Stochastic Field) │
│ • Goal Planning & Intent Generation │
└──────────────────────────────┬──────────────────────────────┘
│ Natural Language Intent
▼
┌─────────────────────────────────────────────────────────────┐
│ SYMBOLIC ORCHESTRATOR (Deterministic Vault) │
│ • MCP Host / Tool Registry & Discovery │
│ • Policy-as-Code Firewall │
└──────────────────────────────┬──────────────────────────────┘
│ MCP stdio / JSON-RPC Payload
▼
┌─────────────────────────────────────────────────────────────┐
│ THIS REPO: Zero-Shot Demand Forecaster MCP Server │
│ • Pydantic v2 Input Enforcement │
│ • 3-Tier Fallback Engine │
│ • Isotonic Quantile Sanitation │
│ • Structured Error Contracts │
└─────────────────────────────────────────────────────────────┘This repository lives in the bottom box. It does not reason probabilistically, maintain conversation state, or enforce enterprise policy. It receives structured JSON-RPC payloads, validates them mathematically, executes the forecast, and returns structured data or structured errors.
Component Architecture Breakdown
FastMCP Gateway (mcp_server.py): Provides async JSON-RPC transport and enforces batch concurrency limits (asyncio.Semaphore(4)).
Type-Safe Contract Boundary (src/schemas/payloads.py): Enforces temporal alignment, finite number guarantees, and context/horizon limits.
Thread-Safe Forecaster Core (src/models/forecaster.py): Employs double-checked locking (threading.Lock()) for lazy model loading and handles automatic CUDA OOM recovery (gc.collect() + torch.cuda.empty_cache()).
Isotonic Output Sanitizer: Post-processes raw foundation model quantiles using monotonic sorting to eliminate statistical anomalies ($p_{10} > p_{50}$) before returning predictions to agents.
System Execution Flow (Sequence Diagram)
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
endCore Architectural Principles
Non-Blocking Async Transport
All tensor-forward passes execute in a thread pool via asyncio.to_thread, keeping the FastMCP event loop responsive to concurrent health checks and tool invocations under load.
# mcp_server.py
result = await asyncio.to_thread(engine.predict, validated_payload)VRAM Lazy Loading
Model weights are materialized only on first use via accessor methods — no VRAM consumed at startup. Thread-safe double-checked locking prevents duplicate instantiation under concurrent cold starts.
# 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._chronos3-Tier Fallback Engine
The engine maintains a single unified deterministic degradation chain regardless of payload contents.
Why this ordering? TimesFM 2.5 is a univariate foundation model with an XReg (exogenous regressor) subsystem specifically designed for single-target forecasting with external variables. For demand forecasting — one SKU, multiple covariates — this hybrid approach (linear covariate absorption + univariate transformer on residuals) is often more stable than full multivariate attention. Chronos-2, a true multivariate model, serves as the resilient fallback: different vendor (AWS), different quantile mechanics (Monte Carlo vs parametric), and independent failure domains. Only when both probabilistic models fail does the system surrender to the deterministic ARIMA(1,1,1) baseline.
Tier | Backend | Mode |
|
|
1 | TimesFM 2.5 | XReg / Univariate |
|
|
2 | Chronos-2 | Multivariate / Univariate |
|
|
3 | ARIMA111 | Baseline |
|
|
On TimesFM failure (including torch.cuda.OutOfMemoryError):
gc.collect()+torch.cuda.empty_cache()Exogenous signals retained for Chronos-2 via
_build_chronos_covariates()(past/future covariates). The covariate retention policy holds through Tier 1 and Tier 2.exogenous_dropped = trueonly if fallback degrades to Tier 3 (ARIMA111), because the baseline statistical model cannot ingest external regressors in this implementation.Execution routed to Chronos-2
If Chronos fails → ARIMA111 baseline
Temporal Regularity Enforcement
Pydantic v2 validators reject invalid telemetry at the boundary:
Validator | Rule |
Context bounds |
|
Horizon bounds |
|
Finite values |
|
Exogenous alignment |
|
Binary flags |
|
Isotonic Quantile Sanitation
All backends (TimesFM, Chronos-2, ARIMA111) emit raw quantiles that can occasionally cross ($p_{10} > p_{50}$ or $p_{50} > p_{90}$) under extreme OOD inputs. The engine applies a lightweight post-processing step _enforce_quantile_monotonicity() which performs isotonic sorting per timestep — stacking $(p_{10}, p_{50}, p_{90})$, sorting along the quantile axis, and returning the ordered triplets. This guarantees mathematically valid $p_{10} \le p_{50} \le p_{90}$ for every forecast horizon step without distorting distributional shape.
Bounded Batch Concurrency
The forecast_batch MCP tool executes multi-SKU inference concurrently using asyncio.gather bounded by an asyncio.Semaphore(4). This provides parallel throughput while protecting GPU/CPU memory from unbounded concurrent tensor allocations. Each item acquires the semaphore, validates its payload, offloads engine.predict to a thread pool via asyncio.to_thread, and returns structured ForecastResponse with per-item fallback metadata. The summary block reports total items, error count, and per-backend usage (model_usage).
Per-Backend Circuit Breakers
Each foundation model backend maintains an independent circuit breaker (CircuitBreakerState) to prevent cascade failures when a model hub is unreachable or consistently erroring. After 5 consecutive failures, the breaker opens and routes traffic immediately to the next fallback tier for 60 seconds before allowing a test call.
Backend | Failure Threshold | Cooldown | Open Behavior |
TimesFM 2.5 | 5 failures | 60s | Raises |
Chronos-2 | 5 failures | 60s | Raises |
This ensures that a transient HuggingFace Hub outage or corrupted weight download does not block the agent indefinitely.
Normalized Confidence Metric
The confidence score uses a bounded relative uncertainty ratio instead of a linear floor that compresses wide variance to 0.0:
$$\text{Confidence} = \frac{1}{1 + \frac{p_{90} - p_{10}}{\vert p_{50}\vert + \epsilon}}$$
where $\epsilon = 10^{-5}$. Properties:
Output range $(0, 1]$ — never negative, never compressed to 0
As spread $(p_{90} - p_{10}) \to 0$, confidence $\to 1$ (tight bounds)
As spread $\to \infty$, confidence $\to 0$ asymptotically (extreme uncertainty)
Scale-invariant via division by median magnitude $|p_{50}|$
Operational Interpretation:
0.80–1.00: Tight predictive consensus. Safe for automated safety-stock decisions.
0.40–0.79: Moderate uncertainty. The agent should increase safety stock buffers or schedule a human review.
0.00–0.39: Extreme epistemic variance. Flag for immediate human review; do not automate downstream decisions.
Agentic Architecture Agnostic
As a stateless, schema-bound MCP tool microservice, this engine integrates seamlessly with any agent orchestrator — including Neuro-Symbolic stacks governed by OPA/Rego policies, LangGraph state machines, CrewAI swarms, or standard ReAct loops.
MCP Tool Specifications & API Contracts
forecast_demand
Single time-series prediction.
Request (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, ...]
}Response (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
Array-based multi-SKU prediction with per-item fallback summary.
Request
{
"payloads": [
{"target_series": [10.0]*20, "forecast_horizon": 5},
{"target_series": [11.0]*30, "forecast_horizon": 3, "price_index": [20.0]*33}
]
}Response
{
"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
Self-correcting error schema returned on validation or execution failure.
{
"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."
}Error codes: VALIDATION_ERROR, MODEL_UNAVAILABLE, TRANSIENT_FAILURE, MODEL_FAILURE, INTERNAL_ERROR
Quickstart & MCP Configuration
Installation
# Requires Python 3.11+
uv sync --extra gpu # or: pip install -r requirements.txtEnvironment
# Optional: force CPU if GPU memory constrained
export MODEL_CONFIG_PATH=configs/model_config.yaml
export DATA_STORAGE_ROOT=data/The engine auto-detects CUDA. If unavailable, falls back to CPU and emits a warning in warnings field.
MCP Client Configuration (Claude Desktop / OpenCode / LangGraph / CrewAI)
Add to your MCP client config (claude_desktop_config.json, opencode.json, or equivalent):
{
"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"
}
}
}
}Restart your MCP client. The tools forecast_demand and forecast_batch will auto-register with their full JSON schemas.
Invocation Example (Claude / LLM Agent)
{
"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]
}
}Verification & Testing
Run Full Test Suite (110 tests total: 62 acceptance + 48 legacy)
uv run pytest tests/ -q
# or
python -m pytest tests/ -qExpected output:
.............................................................. [100%]
110 passed in ~5sTest Coverage Matrix
AC | Criterion | Test Function |
AC-1 | Non-blocking event loop |
|
AC-2 | Lazy loading & VRAM conservation |
|
AC-3 | Graceful fallback & signal stripping |
|
AC-4 | CUDA OOM recovery |
|
AC-5 | Agent self-correction payloads |
|
Legacy Tests (Backward Compatibility)
The 48 original unit tests are included in the 110 total above and remain passing:
pytest tests/test_forecasting_engine.py tests/test_forecaster_router.py tests/test_mcp_server.py tests/test_schemas.py tests/test_metrics.py -qProject Structure (Post-Refactor)
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 fileCitation
If you use this work in research or production systems, please cite:
@software{nicoomanesh2026zeroshot,
author = {Nicoomanesh, Arash},
title = {MCP Zero Shot Agentic Forecaster: A Production-Ready Symbolic Skill for Zero-Shot Demand Forecasting},
url = {https://github.com/arashnicoomanesh/zero-shot-demand-forecasting},
year = {2026},
version = {1.0.1}
}License
Copyright (c) 2026 Arash Nicoomanesh.
This project is licensed under the MIT License.
References
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
This server cannot be deployed
Maintenance
Related MCP Connectors
Forecast product demand using historical sales and market signals.
PredictOracle - 12 forecasting tools: time-series, scenario analysis, risk projections.
Built-environment forecasts, public benchmarks, and permit or zoning readiness through remote MCP.
Hosted MCP for e-commerce: live product catalog, stock, and pricing for AI agents.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceAn 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
- AlicenseAqualityDmaintenanceGeneva MCP brings production-grade forecasting directly into AI assistants and coding agents. Connect any MCP-compatible client to the Geneva Forecasting Engine and run rigorous time series forecasts through natural conversation.1MIT
- AlicenseBqualityDmaintenanceEnable any AI agent to forecast time-series data (e.g., sales, traffic) using Google's TimesFM or a zero-dependency statistical baseline.3Apache 2.0
- AlicenseNot gradedqualityBmaintenancePredictive supply-chain MCP server that forecasts material confirmation risks and enables AI clients to interact with the system via natural language.MIT