entsoe-mcp
com.entsoemcp/entsoe-mcpVersion 1.0.0European power-market data: day-ahead & balancing prices, load, generation, flows, outages. 47 zones
Status
Responds165 msAnswered our handshake without sign-in.- Last checked
- Nov 14, 2026, 13:55 UTC
- Latency
- 165 ms
- Remotes responding
- 1 of 1
- Sign-in
- No sign-in
- Hosting
- EU hosting detected (detected, not a legal statement)
- Registry data as of
- Nov 14, 2026, 22:14 UTC
Data from the official MCP Registry, checked by run.zero. How we check
Connect
Streamable HTTP
https://entsoemcp.com/mcpResponds165 msNo sign-in
Claude Code
claude mcp add --transport http entsoe-mcp https://entsoemcp.com/mcpClaude Desktop and claude.ai
Settings > Connectors > Add custom connector
Name: entsoe-mcp
Remote MCP server URL: https://entsoemcp.com/mcpCursor
{
"mcpServers": {
"entsoe-mcp": {
"url": "https://entsoemcp.com/mcp"
}
}
}VS Code
code --add-mcp '{"name":"entsoe-mcp","type":"http","url":"https://entsoemcp.com/mcp"}'Built your own server? run.zero hosts MCP servers on European infrastructure.
Tools
14 tools
Read-only | Idempotent | Open world | ||
|---|---|---|---|---|
compare_zonesCompare one endpoint across multiple zones.
`start`/`end` default to UTC; `start` inclusive, `end` EXCLUSIVE.
`tz="local"` is rejected (zones may differ); pass an explicit IANA
tz like "Europe/Berlin" if you need wall-clock alignment.
`filters={column: [values]}` keeps only rows whose categorical column
holds one of the values, in every zone (see get_series); zones whose
periods hold several rows are listed under `split_periods_by_zone`.
A zone whose series stopped upstream before the window's end (GB
day-ahead after 2020-12-31) is listed under `series_ended_by_zone`, with
the endpoint that carries it on — an empty `[]` there is not "no data
yet". | No | Yes | Yes | No |
data_coverageShow ingest coverage and lag for (endpoint × zone) — call before queries
if you're not sure whether the data is landed yet. | No | Yes | Yes | No |
get_crossborder_flowCross-border physical flow (MW) between two adjacent zones.
`start`/`end` default to UTC; `start` inclusive, `end` EXCLUSIVE.
`tz="local"` uses the FROM-zone's timezone; or pass an IANA name. | No | Yes | Yes | No |
get_day_ahead_pricesDay-ahead clearing price for a bidding zone, in the zone's trading
currency (EUR for euro zones; the per-row `currency` column and the
response `unit` say which — GB=GBP, PL/RO/BG carry local-currency eras).
`start`/`end` default to UTC; `start` inclusive, `end` EXCLUSIVE.
For 'all of April 2026' use start=2026-04-01, end=2026-05-01
(end=2026-04-30 silently drops the final UTC day — and 1–2 local-time
hours of April for European zones in CET/CEST). The response's
`period` block shows the resolved window so you can verify
(a 30-day month is 720 hours).
`tz`: pass "local" to interpret start/end as wall-clock in the zone's
timezone, or an explicit IANA name like "Europe/Berlin". The server
converts to UTC at the boundary.
GB/UK: ENTSO-E's GB day-ahead price ended 2020-12-31, when GB left
European market coupling. For later windows use
`get_series(endpoint="day_ahead_price_imrp", zone="GB", …)` — the same
GB day-ahead auction, GBP/MWh, published ~D-2; a window past a series'
end answers with `series_ended`, naming the endpoint that carries it on.
If you're computing a **generation-weighted** price metric — capture
price, capture rate, value factor, merchant-PPA achieved price — use
`get_derivation(slug="capture_price", …)` instead. It runs server-side
over the full window and returns monthly rows; no row cap, no pagination. | No | Yes | Yes | No |
get_derivationCompute **capture price**, **capture rate** (a.k.a. value factor /
quality factor / Marktwertfaktor), **TBx battery-arbitrage spreads**,
and other generation-weighted market metrics server-side from landed
Parquet. Use this instead of fetching hourly prices + hourly generation
yourself and weighting them client-side — server-side aggregation has
no row cap and no pagination.
`slug`: a key from list_derivations() — today: `"capture_price"`,
`"negative_price_hours"`, `"residual_load"`, `"res_share"`,
`"emissions"`, `"tb_spread"`.
`tb_spread` returns monthly (default) or annual (aggregation='annual')
Top-Bottom spreads TB1/TB2/TB4/TB6 in <currency>/MW per period — the sum
of daily (top-x minus bottom-x hourly prices) over SDAC market days. The
only slug accepting `aggregation`, and the only one accepting
multi-zone `zone` ('all', a list, or CSV). Example — annual TB2 across
every European market in ONE call:
get_derivation("tb_spread", "2025-01-01", "2026-01-01",
zone="all", aggregation="annual")
For a single day's top/bottom hour TIMESTAMPS use get_tb_spread.
`capture_price` returns monthly rows per (zone, psr_type, currency) with
columns: currency, capture_price_eur_per_mwh, baseload_price_eur_per_mwh,
quality_factor (the capture rate = capture/baseload), total_gen_mwh,
n_hours. Months are bucketed by local time using the zone's IANA
timezone.
ENDED INPUTS: when an input series stopped upstream before the window's
end, the answer carries `series_ended` (per zone for a multi-zone
tb_spread): which inputs, why, what carries each on, and any metric that
carries this one on. GB: ENTSO-E's day-ahead price ended 2020-12-31, so
GB capture_price, negative_price_hours and tb_spread stop there;
`capture_price_mid` covers GB 2016-09 → now against the Market Index
Price (a traded index, not the auction — read its note).
CURRENCY (capture_price and tb_spread alike): the `*_eur_per_mwh` /
`tb*_eur_per_mw` key names are FIXED for API stability and do NOT tra | No | Yes | Yes | No |
get_generationAggregated generation (MW) per production type.
`start`/`end` default to UTC; `start` inclusive, `end` EXCLUSIVE.
For a full calendar month set `end` to the first day of the next
month. Pass `tz="local"` or an IANA name to interpret start/end as
wall-clock in that timezone.
GB/UK: ENTSO-E's GB generation ended 2021-06-15. For later windows use
`get_series(endpoint="generation_mix", zone="GB", …)` (NESO, 2009→now,
its own wind codes — `list_psr_types(zone="GB")` first); a window past
a series' end answers with `series_ended`, naming that endpoint.
If you're computing a **generation-weighted** price metric — capture
price, capture rate, value factor, merchant-PPA achieved price — use
`get_derivation(slug="capture_price", …)` instead. It runs server-side
over the full window and returns monthly rows; no row cap, no pagination. | No | Yes | Yes | No |
get_loadActual or forecast load (MW). kind = actual | forecast | both.
`start`/`end` default to UTC; `start` inclusive, `end` EXCLUSIVE.
For a full calendar month set `end` to the first day of the next
month. Pass `tz="local"` or an IANA name to interpret start/end as
wall-clock in that timezone. | No | Yes | Yes | No |
get_outagesGeneration-unit unavailability events (UMM).
`start`/`end` default to UTC; `start` inclusive, `end` EXCLUSIVE. An
outage is returned if it overlaps the window. Pass `tz="local"` or an
IANA name to interpret start/end as wall-clock in that timezone.
Each row is one unit's availability step, from its document's latest
revision. ENTSO-E lists some outages under several documents with
identical rows; each such row is served once, and `copies` counts the
documents that filed it. A unit can still have several overlapping
rows that differ. To total unavailable MW, count each unit once per
instant (its largest unavailable MW), not the sum of its rows.
A zone whose outage feed stopped upstream (GB, 2021-06-15) carries
`series_ended`: outages announced since then are missing, though older
documents may still schedule events into the window. | No | Yes | Yes | No |
get_seriesGeneric time-series query for ANY registered series endpoint.
One tool covers every (non-outage) endpoint in the registry, so adding
a new dataset (call `list_endpoints()` to see the current 14) gets an
MCP surface automatically — no new tool to learn.
Argument shape adapts to the endpoint:
• single-zone (day_ahead_price, actual_load, generation_per_type, …)
→ pass `zone="DE_LU"`
• cross-zone (crossborder_flow, scheduled_exchanges,
net_transfer_capacity_dayahead)
→ pass `from_zone="DE_LU"` AND `to_zone="FR"`
• psr-dependent (generation_per_type, wind_solar_forecast,
installed_generation_capacity)
→ optionally filter via `psr_types=["solar","wind_onshore"]`
`start`/`end`: UTC by default; `start` inclusive, `end` EXCLUSIVE
(for "all of April 2026" use end=2026-05-01). Pass `tz="local"` or an
IANA name to interpret as wall-clock in that timezone.
`aggregation`: 'raw' (default — native PT15M/PT60M per endpoint),
'hourly' (AVG over quarters → one row per hour, useful for the
growing list of PT15M-stored endpoints like DE_LU day_ahead_price),
'daily', or 'monthly'. For day-ahead prices specifically the auction
still clears hourly even where stored at PT15M, so AVG=any-quarter;
SUM would 4× over-count.
Currency: price columns keep `_eur_` in their names for stability. An
endpoint whose rows carry a `currency` column (day-ahead and intraday
prices, the A81/A15 capacity prices, activated_balancing_price,
imbalance_prices) labels each row (PLN, HUF, RON, CZK, GBP, …) and the
response `unit` follows it; `unit` is null when the window mixes
currencies (`mixed_currency`) or, for activated_balancing_price and
imbalance_prices, holds rows of unknown currency
(`currency_unknown_rows`). Never average a price across rows with
different `currency`.
Split periods: when a response carries `split_periods`, some periods hold
more than one row — different published series told apart by the listed
columns (activated_balancing_pric | No | Yes | Yes | No |
get_tb_spreadTop-Bottom (TBx) spread — daily battery-arbitrage benchmark.
TBx = sum(top X priced hours) − sum(bottom X priced hours) over the
day-ahead clearing prices for `zone` on `date`. The day is the SDAC
market day (23/25 hours on DST-transition days). `date` must be a
bare YYYY-MM-DD — time-bearing strings are rejected.
Returns both `spread` (<currency>/MW/day) and `mean_spread`
(<currency>/MWh = spread/X) in the zone's trading currency — see the
response `currency`/`unit` (EUR for euro zones; GB=GBP).
Common X: 1, 2, 4. A day past the zone's day-ahead series end (GB after
2020-12-31) answers with `series_ended`, naming the endpoint that carries
the prices on. | No | Yes | Yes | No |
list_derivationsList computed-metric derivations available via get_derivation().
Each derivation is a metric computed on-the-fly from one or more
landed endpoints (Tier-2 Parquet). Today: capture_price (monthly
VWAP capture price + baseload + capture rate per technology;
"capture rate" is the industry-standard name for what the JSON
response calls `quality_factor`), negative_price_hours, residual_load,
res_share, emissions (monthly CO2 emissions per fuel using IPCC
AR5 lifecycle factors, production-based), and tb_spread (monthly or
annual Top-Bottom battery-arbitrage spread TB1/TB2/TB4/TB6 per zone
on SDAC market days; accepts zone='all' for every zone in one call). | No | Yes | Yes | No |
list_endpointsList supported ENTSO-E endpoint families. | No | Yes | Yes | No |
list_psr_typesList production-type (psr_type) codes. Pass zone= to scope the answer.
Most codes are ENTSO-E's B01..B25 and mean the same thing in every
ENTSO-E zone. A few are source-native (source != "entsoe") and exist only
where that source publishes — they express concepts the B-codes cannot,
so they are NOT interchangeable with a similar-looking B-code. Check
`source` and read `description` before comparing a code across zones.
Passing zone= also returns `taxonomy_note` for zones that mix taxonomies
(e.g. GB), and per-code `endpoints` showing where each code comes from.
Each code carries `counts_as_generation`: when False the figure is a net
flow or net storage number, not production — do not sum it into a
generation total. | No | Yes | Yes | No |
list_zonesList registered ENTSO-E bidding zones. | No | Yes | Yes | No |
Details
- Registry status
- Active
- Published
- Aug 29, 2026
- Updated
- Aug 29, 2026
- Repository
- Not given
- Categories (suggested)
- Data and analyticsSuggested categories are assigned automatically from the registry text and may be wrong. Verified operators can correct them.
- GDPR
- Not declared