Skip to main content
Glama
arashnicoomanesh

MCP Zero Shot Agentic Forecaster


경영 개요 및 비즈니스 가치

이 저장소는 무엇인가요?

MCP Zero Shot Agentic ForecasterModel Context Protocol (MCP) 을 통해 노출되는 프로덕션 등급의 마이크로서비스 기반 시계열 예측 엔진입니다. 최첨단 파운데이션 모델(Google TimesFM 2.5 XRegAmazon Chronos-2)을 기반으로, 자율 AI 에이전트(LangGraph 상태 머신, CrewAI 스웜, OPA/Rego 기반 NeSy 스택, 표준 ReAct 루프)가 오프라인 모델 학습, 하이퍼파라미터 튜닝, SKU별 데이터셋 준비 없이도 온디맨드로 확률적 수요 예측을 조회할 수 있게 합니다.

비즈니스 가치 및 ROI

  • 콜드 스타트 지연 제거: 학습 파이프라인 없이 신제품 출시, 프로모션, 짧은 이력 SKU에 대해 즉각적인 제로샷 확률적 예측을 제공합니다.

  • 분위수 경계 위험 관리: 보정된 $p_{10}$, $p_{50}$, $p_{90}$ 수요 분위수를 출력하여 자율 구매 에이전트가 안전 재고 버퍼와 자본 보유 비용의 균형을 맞출 수 있게 합니다.

  • 낮은 총소유비용(TCO): 복잡한 파인튜닝 파이프라인을 통합 3계층 폴백 엔진으로 대체하여 GPU 컴퓨팅 요구 사항과 인프라 드리프트를 대폭 낮춥니다.

  • 에이전틱 복원력: 입력이 유효하지 않을 때 수정 힌트가 포함된 구조화된 AgentFriendlyError 페이로드를 반환하여, 호출 에이전트가 조용히 실패하거나 처리되지 않은 예외를 발생시키지 않고 실행 루프에서 스스로 수정할 수 있게 합니다.

작동 방식

  1. 에이전트 호출: 호출 에이전트는 MCP 도구 인터페이스를 통해 stdio/HTTP로 forecast_demand 또는 forecast_batch를 호출합니다.

  2. 계약 강제: Pydantic v2 스키마가 엄격한 유한 숫자 및 시간 경계 검사를 수행합니다([Type-Safe Input Contract]).

  3. 비차단 추론: FastMCP는 asyncio.to_thread를 통해 무거운 텐서 연산을 스레드 풀에 오프로드하여 게이트웨이 응답성을 유지합니다.

  4. 통합 3계층 파이프라인: 항상 TimesFM 2.5(1계층)를 통해 라우팅하며, Chronos-2(2계층, 공변량이 있으면 유지) 및 ARIMA111(3계층, 공변량 제거)로 폴백합니다. CUDA OOM 또는 실패 시 엔진은 다음 계층으로 저하되기 전에 메모리 복구(gc.collect() + torch.cuda.empty_cache())를 트리거합니다.

  5. 수학적 정제: 등장성(isotonic) 정렬을 적용하여 출력 분위수의 단조성을 보장하고($p_{10} \le p_{50} \le p_{90}$), 인식론적 신뢰도 점수를 정규화한 후 구조화된 JSON 페이로드를 반환합니다.


Related MCP server: Geneva Forecasting MCP

시스템 아키텍처

이 마이크로서비스는 엄격한 관심사 분리를 준수합니다. MCP 도구 계층은 비차단 전송, 메모리 안전성, 모델 수준 출력 정제를 관리하고, 도메인별 비즈니스 정책은 다운스트림 에이전트 오케스트레이터에 맡깁니다.

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

구성 요소 아키텍처 분석

FastMCP 게이트웨이(mcp_server.py): 비동기 JSON-RPC 전송을 제공하고 배치 동시성 제한(asyncio.Semaphore(4))을 적용합니다.

타입 안전 계약 경계(src/schemas/payloads.py): 시간 정렬, 유한 숫자 보장, 컨텍스트/호라이즌 제한을 강제합니다.

스레드 안전 예측기 코어(src/models/forecaster.py): 지연 모델 로딩을 위해 이중 확인 잠금(threading.Lock())을 사용하고 자동 CUDA OOM 복구(gc.collect() + torch.cuda.empty_cache())를 처리합니다.

등장성 출력 정제기: 원시 파운데이션 모델 분위수를 단조 정렬로 후처리하여 통계적 이상치($p_{10} > p_{50}$)를 제거한 후 예측을 에이전트에 반환합니다.

시스템 실행 흐름(시퀀스 다이어그램)

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

핵심 아키텍처 원칙

비차단 비동기 전송

모든 텐서 순전파는 asyncio.to_thread를 통해 스레드 풀에서 실행되어, 부하 상태에서도 FastMCP 이벤트 루프가 동시 상태 확인 및 도구 호출에 응답성을 유지합니다.

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

VRAM 지연 로딩

모델 가중치는 접근자 메서드를 통해 최초 사용 시에만 메모리에 로드됩니다. 시작 시 VRAM을 소비하지 않습니다. 스레드 안전 이중 확인 잠금은 동시 콜드 스타트 시 중복 인스턴스화를 방지합니다.

# 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

3계층 폴백 엔진

엔진은 페이로드 내용과 관계없이 단일 통합 결정적 저하 체인을 유지합니다.

계층

백엔드

모드

model_used

exogenous_dropped

1

TimesFM 2.5

XReg / 단변량

TimesFM-2.5

false

2

Chronos-2

다변량 / 단변량

Chronos-2-Fallback

false

3

ARIMA111

기준선

ARIMA111-Baseline

true

TimesFM 실패 시(torch.cuda.OutOfMemoryError 포함):

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

  2. 외생 신호는 _build_chronos_covariates()(과거/미래 공변량)를 통해 Chronos-2에 유지됩니다.

  3. exogenous_dropped = true는 폴백이 3계층(ARIMA111)으로 저하된 경우에만 설정됩니다.

  4. 실행이 Chronos-2로 라우팅됩니다.

  5. Chronos도 실패하면 → ARIMA111 기준선

시간 규칙성 강제

Pydantic v2 검증기는 경계에서 잘못된 텔레메트리를 거부합니다:

검증기

규칙

컨텍스트 경계

16 <= len(target_series) <= 16000

호라이즌 경계

1 <= forecast_horizon <= 1024

유한 값

target_series, price_indexNaN/Inf가 없어야 함

외생 변수 정렬

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

이진 플래그

promo_flag 요소는 0 또는 1이어야 함

등장성 분위수 정제

모든 백엔드(TimesFM, Chronos-2, AutoARIMA)는 극단적인 OOD 입력에서 가끔 교차하는($p_{10} > p_{50}$ 또는 $p_{50} > p_{90}$) 원시 분위수를 출력할 수 있습니다. 엔진은 각 시간 단계별로 등장성 정렬을 수행하는 경량 후처리 단계 _enforce_quantile_monotonicity()를 적용합니다. 즉, $(p_{10}, p_{50}, p_{90})$를 쌓아 분위수 축을 따라 정렬한 후 정렬된 삼중항을 반환합니다. 이는 분포 형태를 왜곡하지 않으면서 모든 예측 호라이즌 단계에서 수학적으로 유효한 $p_{10} \le p_{50} \le p_{90}$을 보장합니다.

제한된 배치 동시성

forecast_batch MCP 도구는 asyncio.Semaphore(4)로 제한된 asyncio.gather를 사용하여 다중 SKU 추론을 동시에 실행합니다. 이는 병렬 처리량을 제공하면서 무제한 동시 텐서 할당으로부터 GPU/CPU 메모리를 보호합니다. 각 항목은 세마포어를 획득하고, 페이로드를 검증하고, engine.predictasyncio.to_thread를 통해 스레드 풀에 오프로드한 후 항목별 폴백 메타데이터가 포함된 구조화된 ForecastResponse를 반환합니다. 요약 블록은 총 항목 수, 오류 수, 백엔드별 사용량(model_usage)을 보고합니다.

백엔드별 회로 차단기

각 파운데이션 모델 백엔드는 모델 허브에 연결할 수 없거나 지속적으로 오류가 발생할 때 연쇄 실패를 방지하기 위해 독립적인 회로 차단기(CircuitBreakerState)를 유지합니다. 연속 5회 실패 후 차단기가 열리고 트래픽을 즉시 다음 폴백 계층으로 60초 동안 라우팅한 후 테스트 호출을 허용합니다.

백엔드

실패 임계값

대기 시간

열림 동작

TimesFM 2.5

5회 실패

60초

MODEL_UNAVAILABLE 발생; Chronos-2로 라우팅

Chronos-2

5회 실패

60초

MODEL_UNAVAILABLE 발생; AutoARIMA로 라우팅

이를 통해 일시적인 HuggingFace Hub 중단이나 손상된 가중치 다운로드가 에이전트를 무기한 차단하지 않습니다.

정규화된 신뢰도 지표

신뢰도 점수는 넓은 분산을 0.0으로 압축하는 선형 하한 대신 제한된 상대 불확실성 비율을 사용합니다:

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

여기서 $\epsilon = 10^{-5}$입니다. 속성:

  • 출력 범위 $(0, 1]$ — 음수가 아니며 0으로 압축되지 않음

  • 분산 $(p_{90} - p_{10}) \to 0$이면 신뢰도 $\to 1$(좁은 경계)

  • 분산 $\to \infty$이면 신뢰도가 점근적으로 $\to 0$(극단적 불확실성)

  • 중앙값 크기 $|p_{50}|$로 나누어 규모 불변

에이전틱 아키텍처 중립성

무상태(stateless) 스키마 기반 MCP 도구 마이크로서비스로서, 이 엔진은 OPA/Rego 정책으로 관리되는 신경-기호(Neuro-Symbolic) 스택, LangGraph 상태 머신, CrewAI 스웜, 표준 ReAct 루프 등 모든 에이전트 오케스트레이터와 원활하게 통합됩니다.


MCP 도구 사양 및 API 계약

forecast_demand

단일 시계열 예측.

요청(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, ...]
}

응답(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

항목별 폴백 요약이 포함된 배열 기반 다중 SKU 예측.

요청

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

응답

{
  "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

검증 또는 실행 실패 시 반환되는 자가 수정 오류 스키마.

{
  "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."
}

오류 코드: VALIDATION_ERROR, MODEL_UNAVAILABLE, TRANSIENT_FAILURE, MODEL_FAILURE, INTERNAL_ERROR


빠른 시작 및 MCP 구성

설치

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

환경

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

엔진은 CUDA를 자동 감지합니다. 사용할 수 없으면 CPU로 폴백하고 warnings 필드에 경고를 출력합니다.

MCP 클라이언트 구성(Claude Desktop / OpenCode / LangGraph / CrewAI)

MCP 클라이언트 구성(claude_desktop_config.json, opencode.json 또는 이에 상응하는 파일)에 추가하세요:

{
  "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"
      }
    }
  }
}

MCP 클라이언트를 다시 시작하세요. forecast_demandforecast_batch 도구가 전체 JSON 스키마와 함께 자동 등록됩니다.

호출 예시(Claude / 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]
  }
}

검증 및 테스트

전체 테스트 스위트 실행(62개 테스트, AC-1~AC-5)

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

예상 출력:

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

테스트 커버리지 매트릭스

AC

기준

테스트 함수

AC-1

비차단 이벤트 루프

test_forecast_demand_is_non_blocking

AC-2

지연 로딩 및 VRAM 절약

test_lazy_loading_*, test_hardware_auto_detect_*

AC-3

정상적 폴백 및 신호 제거

test_timesfm_failure_falls_back_to_chronos_strips_exog, test_full_fallback_to_autoarima

AC-4

CUDA OOM 복구

test_cuda_oom_triggers_memory_recovery, test_recover_from_oom_calls_gc_and_empty_cache

AC-5

에이전트 자가 수정 페이로드

test_agent_friendly_error_on_short_sequence, test_forecast_batch_agent_friendly_error_per_item

레거시 테스트(하위 호환성)

기존 테스트 48개 모두 계속 통과합니다:

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

프로젝트 구조(리팩터링 후)

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

라이선스

MIT 라이선스입니다. 자세한 내용은 LICENSE를 참조하세요.

참고 문헌

  • 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