65 MCP tools across three layers: data, analytics, and narrative. Your AI agent searches 2.8M+ series, runs forecasts, classifies market signals into 16 named contradictions, persists report runs for "what changed" diffs — all by natural language. The analytical narrative lives in the platform, not in the prompt.
Every contradiction that fired was downstream of a Strait of Hormuz disruption dating to February 28. The platform got the WHAT and HOW MUCH right without knowing the WHY — exactly the division of labor the signal layer was designed for.
Platform = WHAT + HOW MUCH. Analyst / IEA / OPEC = WHY. The signal layer does not need to know the cause to flag the regime — and the regime is what trades.
Every published report includes an MCP methodology appendix documenting the exact tools, data sources, and signal-layer stats used to produce it — the product demo in 20 lines, replicable by any MCP client.
Real conversations with Claude Code connected to EnergyScope via MCP.
diesel_clean_long is firing at score 1.0 (dominant lens), which requires
diesel_crack_extreme AND excludes distillate_oversupplied. Distillate
supply_shock_signature is firing — VIX-WTI
distillate_oversupplied firing
freight_extreme would collapse toward baseline (z → 0) within
diesel_clean_long (global product shortage persists until
opec_iea_spread_widening
opec_iea_spread_widening
forced_storage_build just started firing for the first time this cycle.
forced_storage_build escalates further, the snap-back risk intensifies.
diesel_clean_long contradiction (score 1.0,
distillate_oversupplied
forced_storage_build and freight_extreme first.
compare_runs() against yesterday's diesel_brief snapshot will
"Generate a full oil market report as html using the quarterly preset with my oil_daily watchlist. Include seasonal context, curve structure, crack spreads, positioning, and forecasts."
One prompt in Claude Code. 30 MCP tool calls (~8s for data + analytics pull from EnergyScope server), then your Claude Code may take a few minutes to write the full HTML report with KPIs, charts, risk matrix, and tool audit.
15 data & discovery tools + 41 analytics tools. All available via the Model Context Protocol.
Search 2.8M series by keyword. Returns series_id, name, units, frequency.
Fetch time series data. Multiple series, date range filtering.
Latest value for one or more series. Period, value, name, units.
Browse the category tree. Discover data hierarchically.
List available datasets with row counts and load state.
Server status — series count, data rows, connection check.
Submit bug reports, feature requests, and data gaps. Goes straight to the team with push notification.
Browse series IDs by dataset or prefix. Grouped by frequency. Feeds directly into correlate_all() and other multi-series tools.
Catalyst calendar — EIA weekly reports, CFTC COT, Fed FOMC, OPEC MOMR, IEA OMR, NFP, CPI. Days-ahead timing with UTC timestamps.
Save named baskets of series IDs server-side. Reusable across report(), correlate_all(), changes(), get_data().
Retrieve, browse, and remove saved watchlists. Analysts track their own custom tickers, invoke tools with watchlist="name".
Compare installed MCP version to latest PyPI release. Show changelog since your installed version. health() also flags updates.
Multi-factor XGBoost forecast. Auto-forecasts predictors with ARIMA + Prophet. Compares both engines.
Univariate auto-ARIMA with confidence intervals. Reports model order and AIC.
Facebook Prophet with holidays, seasonality, changepoints. Trend decomposition.
Theta method — M3 competition winner. Fast, robust benchmark forecast.
Exponential smoothing (single, double, Holt-Winters, ETS auto) with forecast.
Structural break detection. Regime changes with dates, shift magnitudes, segment means.
Descriptive statistics — mean, median, stdev, skewness, kurtosis, percentiles.
Rolling + GARCH(1,1) conditional volatility, annualised.
Log returns, cumulative returns, max drawdown with peak/trough dates.
Pairwise Pearson correlation matrix, aligned on common periods.
Stationarity tests (ADF, KPSS, Phillips-Perron) with consensus.
Johansen or Engle-Granger cointegration test with trace statistics.
Vector Autoregression with impulse response functions and Granger causality.
Autocorrelation, partial autocorrelation, and Ljung-Box Q-statistics.
Diff, pct, log, logdiff, lag, moving average, EMA, cumsum, z-score.
Boosted Hodrick-Prescott filter — trend vs cycle decomposition.
Band-pass filter (Baxter-King / Christiano-Fitzgerald) for cycle extraction.
Seasonal decomposition — trend, seasonal, and residual components.
Fill missing values — linear, log-linear, spline, cardinal interpolation.
Outlier detection — Z-score, IQR, or Isolation Forest.
Elastic net regression with variable selection and coefficient ranking.
Quantile autoregression — conditional quantile estimates for tail risk.
GSADF test for explosive bubbles with episode start/end dates. Feeds the bubble_detected derived signal via bubble_gsadf_excess snapshot key (WISH-59a, 2026-04-14).
Local Projection Impulse Response — non-parametric IRF (Jordà 2005).
MIDAS mixed-frequency volatility — daily returns to forecast monthly vol.
Pair spread with z-score, percentile, half-life (mean reversion), rolling z-score.
Rolling Pearson correlation with configurable window. Tracks regime shifts in co-movement.
Refining margins — 3-2-1, gasoline, diesel. Defaults to WTI / Gulf gasoline / NY heating oil.
Detect significant changes — period-over-period diff, ranked by z-score, flags outliers.
Supply & Demand balance model — supply, demand, Theta forecasts, pinned scenarios, implied stock change.
ASCII sparkline chart for quick visualisation in-chat. Min, max, current, range.
Meta-tool with presets: trader / analyst / daily / deep. Bundles spreads, cracks, curves, positioning, seasonal, forecast.
Rank any value within the series' own history. Z-score, percentile, quartile breakdown (p5/p25/p50/p75/p95).
Current value vs N-year same-week/month average. Delta, z-score, range position — essential for commodity analysis.
Futures curve analytics — contango/backwardation, calendar spreads, roll yield. Reads M1–M12 rolls.
Detect likely refinery turnaround weeks from utilization drops vs trailing trend. Clusters consecutive flagged weeks into events. Feeds the maintenance_detected derived signal via maintenance_trough_z snapshot key (WISH-59a, 2026-04-14).
Scan many candidates against a target, rank by rolling correlation. "What tracks WTI best lately?" Discovery → analysis in one call. Automatically runs inside report(preset='quarterly'|'deep'|'regime'|'analyst'|'macro') — the macro correlation matrix against MACRO.* candidates, 60d rolling vs target (WISH-59b, 2026-04-14).
Unified crude arb score (−2 to +2) combining Brent-WTI spread + tanker freight + ICE.BRENT curve shape. Extremes surfaced as alerts.
Theta + ARIMA + Prophet side-by-side with min/median/max/spread. Flags model AGREEMENT vs DISAGREEMENT — when methods disagree, the disagreement IS the finding.
The analytical narrative now lives in the platform, not in the prompt. Same dataset, different desk lenses, coherent house view across all reports.
Classify a metrics dict into 53 named oil-market signals across 7 themes (crude_supply, refined_products, market_structure, positioning, macro, european, opec_compliance) that compose into 16 trade-thesis contradictions — including the 9 original US headlines (refiner_margin_trap, freight_locked_arb, fundamental_rally, regime_curve_destruction, forced_storage_build, supply_shock_signature, diesel_clean_long, gasoline_overhang) plus 6 cross-Atlantic contradictions (arb_shut_but_eu_drawing, rotterdam_squeeze, global_stocks_tight, opec_revision_vs_price, ...). Each signal returns a scored 0–1 intensity with severity bucket (mild/elevated/extreme) and a rendered trigger sentence. Pass prev_metrics for transition-aware classification (new_firing, intensifying, easing). Contradictions ARE the report headlines. 59 input key aliases tolerated. schema=True for catalog introspection.
Persist a report run with HTML output, key-metric snapshot, and the prompt used. Per-user storage. Tomorrow's report can reference today's snapshot to narrate "what changed".
Retrieve a previous report run — HTML, snapshot, prompt, timestamp. Read yesterday's emphasis before generating today's, then anchor the new report on what shifted.
Structured diff between two report runs. Numeric deltas (abs + pct), categorical before/after, plus signal diff (signals_added/removed, contradictions_added/removed). Regime-shift detection in one tool call. The "Changes Since Last Brief" section writes itself.
Browse saved reports per user. Or list all timestamps for a specific report.
Server-side MCP catalog. The agent fetches its own dataset list and key series on connect — new datasets show up immediately, no PyPI release needed.
53 named oil-market signals (organized into 7 themes) compose into 16 trade-thesis contradictions — 9 US and 6 cross-Atlantic. The contradictions ARE the report headlines. Same data, 9 different desk lenses, coherent house view.
derived_signals() — get back which signals are firing and which contradictions activate. Pass two snapshots to compare_runs() — get back which signals/contradictions appeared/disappeared between runs (regime-shift detection in one tool call). Thresholds and definitions live server-side; tune without a client release.
The v2 narrative layer powers the Hormuz case study above. Every capability here feeds into the same derived_signals() call — pass a metrics dict, get back scored intensities, severity labels, theme summaries, virtual composites, and transition diffs against the previous run.
Every signal past its threshold returns a 0–1 score. "Firing" is a question of degree — the agent can rank severity across the whole firing set, not just count them.
Scores bin into three severity labels the report can cite directly. "freight extreme at z=7.92 → extreme" writes itself.
Signals group into crude_supply, refined_products, market_structure, positioning, macro, european, opec_compliance. Each theme gets a one-line banner — the report scaffold falls out of this structure.
Metrics like the OPEC-IEA demand spread or US-EU stock ratio are computed on the server from the raw snapshot — agents never need to assemble them. Same inputs, same numbers, every run.
prev_metrics → new_firing / intensifying / easingPass yesterday's metrics alongside today's. The classifier labels each firing signal as new_firing, intensifying, or easing — regime-shift detection without a client-side diff.
derived_signals(schema=True) for the full catalog| Group | Signal | Predicate |
|---|---|---|
| Cracks | crack_extreme | 3-2-1 crack z > 3 |
diesel_crack_extreme | diesel crack z > 3 | |
gasoline_crack_extreme | gasoline crack z > 3 | |
| Inventories | gasoline_oversupplied | gasoline seasonal pctl > 90 |
gasoline_undersupplied | gasoline seasonal pctl < 20 | |
distillate_oversupplied | distillate seasonal pctl > 90 | |
distillate_undersupplied | distillate seasonal pctl < 20 | |
crude_oversupplied | crude seasonal pctl > 80 | |
crude_undersupplied | crude seasonal pctl < 20 | |
| Cushing | cushing_full | cushing z > 2 |
cushing_tight | cushing z < -2 | |
cushing_building_fast | cushing 7d pct > 5% | |
| Production | production_at_seasonal_high | production seasonal pctl ≥ 99 |
| Curve | steep_backwardation | M1−M12 < -$10 |
steep_contango | M1−M12 > +$5 | |
punishing_carry | roll yield < -30% | |
| Freight | freight_extreme | BWET z > 3 |
freight_collapsed | BWET z < -2 | |
| Spread | spread_wide | Brent−WTI z > 2 |
spread_inverted | Brent < WTI | |
| Refinery | refinery_strong | refinery util > 92% |
refinery_weak | refinery util < 85% | |
| Positioning | wti_specs_extended | WTI MM pctl > 90 |
wti_specs_short | WTI MM pctl < 10 | |
wti_positioning_median | 30 ≤ WTI MM pctl ≤ 70 | |
brent_specs_extended | Brent MM pctl > 90 | |
brent_specs_short | Brent MM pctl < 10 | |
brent_positioning_median | 30 ≤ Brent MM pctl ≤ 70 | |
| Macro | vix_oil_supply_shock | VIX-WTI rolling correlation > 0.5 |
| European | eu_oil_stocks_tight | EU27 oil seasonal pctl < 20 |
eu_gas_stocks_tight | EU27 gas seasonal pctl < 20 | |
nl_stocks_tight | Netherlands oil seasonal pctl < 20 | |
eu_oil_imports_surging | EU27 oil imports 3m pct > +15% | |
| OPEC compliance | opec_compliance_gap_extreme | max direct-vs-secondary gap > 200 tb/d |
opec_iea_spread_widening | OPEC-IEA 2026 demand spread > 1.5 mb/d | |
opec_demand_downgraded | OPEC world demand MoM revision < -0.3 mb/d | |
| Weather | weather_cold_extreme | HDD anomaly z > 2 |
weather_hot_extreme | CDD anomaly z > 2 | |
weather_mild_winter | HDD anomaly z < -2 | |
| New (2026-04-14) | maintenance_detected | refinery runs trough z < -2 |
bubble_detected | GSADF test exceeds critical value |
Each contradiction composes positive named signals (no negation tricks). When multiple fire simultaneously, dominant_lens picks the most extreme one based on underlying signal magnitudes.
crack_extreme + gasoline_oversupplied
Cracks at extremes while gasoline stocks are oversupplied — refiner margin compression risk.
diesel_crack_extreme (excludes distillate_oversupplied)
Diesel crack extreme without inventory overhang — cleanest long signal in the complex.
gasoline_oversupplied + gasoline_crack_extreme
Both crack and inventories at extremes — false-signal risk on gasoline length.
punishing_carry + cushing_building_fast
Cushing building despite punishing carry — non-economic storage, supply pressure.
spread_wide + freight_extreme
Spread wide while freight sits at an extreme — a wide spread with expensive shipping may not be an executable arb. Compares z-scores, not $/bbl economics.
spread_wide + wti_positioning_median
Prices at extremes but spec positioning at median — rally is fundamental, not crowded, no unwind risk.
vix_oil_supply_shock + freight_extreme
VIX and oil correlated positively + freight extreme — the pattern associated with supply-side shocks rather than demand panic. A pattern match, not an identification.
steep_backwardation + punishing_carry
Backwardation steep, roll yield punishing — storage economics destroyed.
Added to capture the EU / US divergences that surface when derived_signals() runs against a cross-Atlantic snapshot. Compose US signals with EUROSTAT + national-level EU series.
freight_extreme + spread_wide + eu_oil_stocks_tight
Physical arb shut while European inventories are draining. Pain point for the EU trader — watch for the spread to break.
nl_stocks_tight + freight_extreme
Netherlands (Rotterdam/ARA hub) tight + freight extreme — ARA squeeze, watch the physical premium.
crude_undersupplied + eu_oil_stocks_tight
US and EU stocks both in the bottom fifth of their seasonal ranges — a wider arb cannot relieve one from the other. Not tested: freight, actual flows, flat price.
eu_oil_stocks_tight + crude_oversupplied
EU stocks in the bottom fifth of their range while US crude sits in the top fifth — an Atlantic divergence that historically argues for a wider Brent-WTI. Levels only; says nothing about why the sides differ.
crude_undersupplied + eu_oil_stocks_comfortable
The reverse divergence — US crude tight while EU is comfortable; historically a Brent-WTI compressor.
eu_oil_imports_declining − freight_collapsed
EU imports falling without the cheap shipping a demand-driven slowdown usually brings. The exclusion leg has never fired on the live convention, so it currently adds no information — the narrative says so.
derived_signals() surfaces composition-level patterns:
all_lenses_dislocated — ≥15 of 16 contradictions firing (coherent extreme regime)single_lens_extreme — only 1 contradiction firing (concentrated dislocation)dominant_lens — pick the most extreme firing contradiction by underlying signal magnitudes (use as primary report headline)Three layers, all server-side. The analytical narrative lives in the platform, not in the prompt.
2.8M energy series, 21 datasets, sub-200ms response. Arrow Flight transport.
41 server-side tools — forecasts, spreads, cracks, volatility, breakpoints, term structure, seasonal context. Your analytics where the data sits.
53 named market signals (7 themes) + 16 trade-thesis contradictions (9 US + 6 cross-Atlantic). Scored intensity, history-aware transitions, cross-dataset virtual metrics. Report run storage with snapshot diffs. Same data, different desks, coherent house view. Bloomberg-style commentary writes itself.
No installation needed. uvx downloads and runs the MCP server automatically.
claude mcp add energyscope -e ENERGYSCOPE_SERVER=grpc+tls://data.energyscope.io:443 -e ENERGYSCOPE_API_KEY=your-api-key -- uvx energyscope-mcp
That's it. Start a new Claude Code session and ask about energy data.
Alternative: pip install energyscope-mcp then claude mcp add energyscope -- energyscope-mcp
Requires Python 3.10+ and uv (for uvx). Works with Claude Code, Claude Desktop, or any MCP-compatible client. View on PyPI →
| You ask | Agent does |
|---|---|
| "What's happening with WTI?" | Calls latest + breakpoints + volatility. Gives price, recent regime changes, and current vol. |
| "Forecast crude stocks for next month" | Calls prophet with US holidays on PET.WCESTUS1.W. Returns forecast + confidence bands. |
| "Which series predict WTI best?" | Calls forecast with multiple predictors. Reports R², feature importances, and ranked coefficients. |
| "Is there a bubble in natural gas?" | Searches for NG price series, runs unit_root + checks via analytics. Reports stationarity and any explosive episodes. |
| "Compare all forecasting engines on WTI" | Runs arima, prophet, theta, forecast (XGBoost). Compares RMSE side by side. |
| "Build me an S&D balance for US crude" | Searches for stocks, production, imports, demand series. Gets latest + forecasts for each. Assembles supply/demand/balance view. |
Sign up for an API key. Install the MCP server. Your AI assistant gets 2.8M energy series + 65 MCP tools across data, analytics, and narrative layers.
Sign Up FreeExcel Add-in · Forecasting · Workflows · Demo Report · Data Coverage · Contact