Endpoints: 28,729MCP servers: 18,413Payout addresses: 2,071Paid calls: 1,539Letters: 14Defects: 1,323counted just now
teppi

Server definition

Hash
sha256:3b40789fc4ecd3fea16d3fac267f6b7a389d05997699278ff32037e511fae3ee
What it is
What a remote MCP server returned when asked what it offers: 14 tools

The blob, as servednamed by its sha256

{ "instructions": "ENTSO-E European power-market data: prices, load, generation, cross-border flows, outages. Hot-path is DuckDB-over-Parquet — queries are sub-second over the cached ingest. Use `data_coverage` before assuming a recent date is landed.\n\nDATE CONVENTION (read before every series query):\n • Default: `start`/`end` are UTC. `start` is INCLUSIVE, `end` is EXCLUSIVE — i.e. ts_utc ∈ [start, end).\n • For 'all of April 2026' use start=2026-04-01, end=2026-05-01 (NOT end=2026-04-30 — that drops April 30 entirely, plus any local-time hours of April that fall on UTC dates outside the window for non-UTC zones).\n • For 'yesterday' use start=YESTERDAY, end=TODAY.\n\nMARKET-DAY CONVENTION (use this for any 'what was the price on day X' question):\n • The SDAC pan-European day-ahead auction defines its delivery day on a CET/CEST-aligned 24-hour grid for every coupled bidding zone — same UTC window for DE_LU, ES, GR, FI, PT, etc. (EPEX SPOT MRC process: 'All timings indicated in this document are CET timings'). UTC midnights slice off the last 1–2 hours of the real market day and pull in 1–2 from the next.\n • For market-day questions ('yesterday's DE_LU baseload', 'May 2026 ES capture rate'), pass tz='Europe/Berlin' so the window aligns to the auction's delivery day. Example: get_day_ahead_prices(zone='DE_LU', start='2026-05-11', end='2026-05-12', tz='Europe/Berlin') returns exactly the 24 SDAC delivery hours for May 11.\n • For per-zone-local-clock questions (rare; consumer-style: 'when was the consumption peak in Spain yesterday in Madrid time?') pass tz='local' — resolves to the zone's own IANA tz (Europe/Madrid for ES, etc.), NOT the auction grid.\n • For zone-agnostic / cross-time-zone analysis, keep the UTC default.\n • Responses always include a `period` field with start_utc, end_utc, duration_hours, and (when a zone is involved) start_local/end_local — verify duration_hours matches your intent (a 30-day month is 720 h).\n • aggregation='daily'|'monthly' buckets follow the resolved tz: UTC by default; with tz= set, buckets align to that tz's day/month and are labeled by the local period start as a plain 'YYYY-MM-DD' string (the period block echoes bucket_tz). Market-day daily means = tz='Europe/Berlin' + aggregation='daily' in one call.\n\nDATA RESOLUTION (read before per-hour math):\n • Most endpoints publish at PT60M (one row per hour). Some zones have rolled over to MTU=15min (PT15M) for select endpoints — notably `day_ahead_price` for DE_LU, and `actual_load`/`generation_per_type` across many zones. Data is stored at the native resolution it was published at.\n • For day-ahead prices specifically: the auction still clears HOURLY, so the 4 quarter rows of an hour all carry the same price value. An hourly AVG of PT15M DA prices equals the original hourly price; a SUM would 4× over-count.\n • For per-hour math on raw rows: aggregate to hourly first via `DATE_TRUNC('hour', ts_utc)` + AVG, THEN operate. The `get_derivation` tools handle this internally — `capture_price`, `negative_price_hours`, `residual_load`, `res_share`, `tb_spread` all aggregate to hourly before counting/averaging so the per-hour math is consistent across zones.\n • For raw-row consumers: check the response row count vs expected hours. 2880 rows for a 720-hour April → PT15M storage; 720 rows → PT60M. Use `aggregation='hourly'` on `get_series` (or the `/api/series` / `/download` query param) to collapse to one row per hour at query time, regardless of native storage.", "tools": [ { "description": "Compare one endpoint across multiple zones.\n\n`start`/`end` default to UTC; `start` inclusive, `end` EXCLUSIVE.\n`tz=\"local\"` is rejected (zones may differ); pass an explicit IANA\ntz like \"Europe/Berlin\" if you need wall-clock alignment.", "inputSchema": { "additionalProperties": false, "properties": { "aggregation": { "default": "daily", "type": "string" }, "end": { "type": "string" }, "endpoint": { "type": "string" }, "start": { "type": "string" }, "tz": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "zones": { "items": { "type": "string" }, "type": "array" } }, "required": [ "endpoint", "zones", "start", "end" ], "type": "object" }, "name": "compare_zones", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Show ingest coverage and lag for (endpoint × zone) — call before queries\nif you're not sure whether the data is landed yet.", "inputSchema": { "additionalProperties": false, "properties": { "endpoint": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "zone": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null } }, "type": "object" }, "name": "data_coverage", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Cross-border physical flow (MW) between two adjacent zones.\n\n`start`/`end` default to UTC; `start` inclusive, `end` EXCLUSIVE.\n`tz=\"local\"` uses the FROM-zone's timezone; or pass an IANA name.", "inputSchema": { "additionalProperties": false, "properties": { "aggregation": { "default": "raw", "type": "string" }, "end": { "type": "string" }, "from_zone": { "type": "string" }, "start": { "type": "string" }, "to_zone": { "type": "string" }, "tz": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null } }, "required": [ "from_zone", "to_zone", "start", "end" ], "type": "object" }, "name": "get_crossborder_flow", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Day-ahead clearing price for a bidding zone, in the zone's trading\ncurrency (EUR for euro zones; the per-row `currency` column and the\nresponse `unit` say which — GB=GBP, PL/RO/BG carry local-currency eras).\n\n`start`/`end` default to UTC; `start` inclusive, `end` EXCLUSIVE.\nFor 'all of April 2026' use start=2026-04-01, end=2026-05-01\n(end=2026-04-30 silently drops the final UTC day — and 1–2 local-time\nhours of April for European zones in CET/CEST). The response's\n`period` block shows the resolved window so you can verify\n(a 30-day month is 720 hours).\n\n`tz`: pass \"local\" to interpret start/end as wall-clock in the zone's\ntimezone, or an explicit IANA name like \"Europe/Berlin\". The server\nconverts to UTC at the boundary.\n\nIf you're computing a **generation-weighted** price metric — capture\nprice, capture rate, value factor, merchant-PPA achieved price — use\n`get_derivation(slug=\"capture_price\", …)` instead. It runs server-side\nover the full window and returns monthly rows; no row cap, no pagination.", "inputSchema": { "additionalProperties": false, "properties": { "aggregation": { "default": "raw", "type": "string" }, "end": { "type": "string" }, "start": { "type": "string" }, "tz": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "zone": { "type": "string" } }, "required": [ "zone", "start", "end" ], "type": "object" }, "name": "get_day_ahead_prices", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Compute **capture price**, **capture rate** (a.k.a. value factor /\nquality factor / Marktwertfaktor), **TBx battery-arbitrage spreads**,\nand other generation-weighted market metrics server-side from landed\nParquet. Use this instead of fetching hourly prices + hourly generation\nyourself and weighting them client-side — server-side aggregation has\nno row cap and no pagination.\n\n`slug`: a key from list_derivations() — today: `\"capture_price\"`,\n`\"negative_price_hours\"`, `\"residual_load\"`, `\"res_share\"`,\n`\"emissions\"`, `\"tb_spread\"`.\n\n`tb_spread` returns monthly (default) or annual (aggregation='annual')\nTop-Bottom spreads TB1/TB2/TB4/TB6 in <currency>/MW per period — the sum\nof daily (top-x minus bottom-x hourly prices) over SDAC market days. The\nonly slug accepting `aggregation`, and the only one accepting\nmulti-zone `zone` ('all', a list, or CSV). Example — annual TB2 across\nevery European market in ONE call:\n get_derivation(\"tb_spread\", \"2025-01-01\", \"2026-01-01\",\n zone=\"all\", aggregation=\"annual\")\nFor a single day's top/bottom hour TIMESTAMPS use get_tb_spread.\n\n`capture_price` returns monthly rows per (zone, psr_type, currency) with\ncolumns: currency, capture_price_eur_per_mwh, baseload_price_eur_per_mwh,\nquality_factor (the capture rate = capture/baseload), total_gen_mwh,\nn_hours. Months are bucketed by local time using the zone's IANA\ntimezone.\n\nCURRENCY (capture_price and tb_spread alike): the `*_eur_per_mwh` /\n`tb*_eur_per_mw` key names are FIXED for API stability and do NOT track\nthe actual unit — read the row's `currency` column, which is\nauthoritative (EUR for euro zones, GBP for GB, PLN/RON/BGN for the\nPL/RO/BG local-currency eras). The response echoes it top-level as\n`currency`; a window spanning two currencies instead sets `unit` to null\nwith `mixed_currency: true` and a `currencies` list. A month (or period)\nspanning a redenomination splits into one row PER CURRENCY, each computed\nonly from that currency's hours — so never average or sum a price column\nacross rows with different `currency` values. Summing `total_gen_mwh`\nacross them IS correct: the split rows partition the month's hours rather\nthan duplicating them. `quality_factor` is a ratio and stays comparable\nacross currencies.\n\n`emissions` returns monthly rows per (zone, psr_type) with columns:\ngeneration_mwh, n_hours, emission_factor_kg_per_mwh, emissions_t_co2.\nProduction-based; IPCC AR5 lifecycle factors. Zero-emission rows\n(nuclear, wind, solar, hydro, geothermal, marine) appear with\nemissions_t_co2 = 0 — useful for stacked charts.\n\nFilter via `psr_types=[\"solar\",\"wind_onshore\",\"wind_offshore\"]` (or\nraw B-codes like \"B16\") to get only the technologies you care about.\nDefaults to all psr_types that have generation data.\n\nExample — Spain solar capture price, last 12 months:\n get_derivation(\"capture_price\", \"2025-05-01\", \"2026-05-01\",\n zone=\"ES\", psr_types=[\"B16\"], tz=\"Europe/Madrid\")\nExample — Germany 2024 emissions by fuel:\n get_derivation(\"emissions\", \"2024-01-01\", \"2025-01-01\",\n zone=\"DE_LU\", tz=\"Europe/Berlin\")\nReturns 12 monthly rows in one call; no pagination.", "inputSchema": { "additionalProperties": false, "properties": { "aggregation": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "end": { "type": "string" }, "from_zone": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "psr_types": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "default": null }, "slug": { "type": "string" }, "start": { "type": "string" }, "to_zone": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "tz": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": "local" }, "zone": { "anyOf": [ { "type": "string" }, { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "default": null } }, "required": [ "slug", "start", "end" ], "type": "object" }, "name": "get_derivation", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Aggregated generation (MW) per production type.\n\n`start`/`end` default to UTC; `start` inclusive, `end` EXCLUSIVE.\nFor a full calendar month set `end` to the first day of the next\nmonth. Pass `tz=\"local\"` or an IANA name to interpret start/end as\nwall-clock in that timezone.\n\nIf you're computing a **generation-weighted** price metric — capture\nprice, capture rate, value factor, merchant-PPA achieved price — use\n`get_derivation(slug=\"capture_price\", …)` instead. It runs server-side\nover the full window and returns monthly rows; no row cap, no pagination.", "inputSchema": { "additionalProperties": false, "properties": { "aggregation": { "default": "raw", "type": "string" }, "end": { "type": "string" }, "psr_types": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "default": null }, "start": { "type": "string" }, "tz": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "zone": { "type": "string" } }, "required": [ "zone", "start", "end" ], "type": "object" }, "name": "get_generation", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Actual or forecast load (MW). kind = actual | forecast | both.\n\n`start`/`end` default to UTC; `start` inclusive, `end` EXCLUSIVE.\nFor a full calendar month set `end` to the first day of the next\nmonth. Pass `tz=\"local\"` or an IANA name to interpret start/end as\nwall-clock in that timezone.", "inputSchema": { "additionalProperties": false, "properties": { "aggregation": { "default": "raw", "type": "string" }, "end": { "type": "string" }, "kind": { "type": "string" }, "start": { "type": "string" }, "tz": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "zone": { "type": "string" } }, "required": [ "zone", "kind", "start", "end" ], "type": "object" }, "name": "get_load", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Generation-unit unavailability events (UMM).\n\n`start`/`end` default to UTC; `start` inclusive, `end` EXCLUSIVE. An\noutage is returned if it overlaps the window. Pass `tz=\"local\"` or an\nIANA name to interpret start/end as wall-clock in that timezone.", "inputSchema": { "additionalProperties": false, "properties": { "end": { "type": "string" }, "kind": { "default": "generation", "type": "string" }, "min_mw": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "default": null }, "start": { "type": "string" }, "tz": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "zone": { "type": "string" } }, "required": [ "zone", "start", "end" ], "type": "object" }, "name": "get_outages", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Generic time-series query for ANY registered series endpoint.\n\nOne tool covers every (non-outage) endpoint in the registry, so adding\na new dataset (call `list_endpoints()` to see the current 14) gets an\nMCP surface automatically — no new tool to learn.\n\nArgument shape adapts to the endpoint:\n • single-zone (day_ahead_price, actual_load, generation_per_type, …)\n → pass `zone=\"DE_LU\"`\n • cross-zone (crossborder_flow, scheduled_exchanges,\n net_transfer_capacity_dayahead)\n → pass `from_zone=\"DE_LU\"` AND `to_zone=\"FR\"`\n • psr-dependent (generation_per_type, wind_solar_forecast,\n installed_generation_capacity)\n → optionally filter via `psr_types=[\"solar\",\"wind_onshore\"]`\n\n`start`/`end`: UTC by default; `start` inclusive, `end` EXCLUSIVE\n(for \"all of April 2026\" use end=2026-05-01). Pass `tz=\"local\"` or an\nIANA name to interpret as wall-clock in that timezone.\n\n`aggregation`: 'raw' (default — native PT15M/PT60M per endpoint),\n'hourly' (AVG over quarters → one row per hour, useful for the\ngrowing list of PT15M-stored endpoints like DE_LU day_ahead_price),\n'daily', or 'monthly'. For day-ahead prices specifically the auction\nstill clears hourly even where stored at PT15M, so AVG=any-quarter;\nSUM would 4× over-count.\n\nOutage-family endpoints (different schema) stay on `get_outages()`.", "inputSchema": { "additionalProperties": false, "properties": { "aggregation": { "default": "raw", "type": "string" }, "end": { "type": "string" }, "endpoint": { "type": "string" }, "from_zone": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "psr_types": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "default": null }, "start": { "type": "string" }, "to_zone": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "tz": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null }, "zone": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null } }, "required": [ "endpoint", "start", "end" ], "type": "object" }, "name": "get_series", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "Top-Bottom (TBx) spread — daily battery-arbitrage benchmark.\nTBx = sum(top X priced hours) − sum(bottom X priced hours) over the\nday-ahead clearing prices for `zone` on `date`. The day is the SDAC\nmarket day (23/25 hours on DST-transition days). `date` must be a\nbare YYYY-MM-DD — time-bearing strings are rejected.\nReturns both `spread` (<currency>/MW/day) and `mean_spread`\n(<currency>/MWh = spread/X) in the zone's trading currency — see the\nresponse `currency`/`unit` (EUR for euro zones; GB=GBP).\nCommon X: 1, 2, 4.", "inputSchema": { "additionalProperties": false, "properties": { "date": { "type": "string" }, "x": { "default": 2, "type": "integer" }, "zone": { "type": "string" } }, "required": [ "zone", "date" ], "type": "object" }, "name": "get_tb_spread", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "List computed-metric derivations available via get_derivation().\n\nEach derivation is a metric computed on-the-fly from one or more\nlanded endpoints (Tier-2 Parquet). Today: capture_price (monthly\nVWAP capture price + baseload + capture rate per technology;\n\"capture rate\" is the industry-standard name for what the JSON\nresponse calls `quality_factor`), negative_price_hours, residual_load,\nres_share, emissions (monthly CO2 emissions per fuel using IPCC\nAR5 lifecycle factors, production-based), and tb_spread (monthly or\nannual Top-Bottom battery-arbitrage spread TB1/TB2/TB4/TB6 per zone\non SDAC market days; accepts zone='all' for every zone in one call).", "inputSchema": { "additionalProperties": false, "properties": {}, "type": "object" }, "name": "list_derivations", "outputSchema": { "properties": { "result": { "items": { "additionalProperties": true, "type": "object" }, "type": "array" } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } }, { "description": "List supported ENTSO-E endpoint families.", "inputSchema": { "additionalProperties": false, "properties": { "family": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null } }, "type": "object" }, "name": "list_endpoints", "outputSchema": { "properties": { "result": { "items": { "additionalProperties": true, "type": "object" }, "type": "array" } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } }, { "description": "List production-type (psr_type) codes. Pass zone= to scope the answer.\n\nMost codes are ENTSO-E's B01..B25 and mean the same thing in every\nENTSO-E zone. A few are source-native (source != \"entsoe\") and exist only\nwhere that source publishes — they express concepts the B-codes cannot,\nso they are NOT interchangeable with a similar-looking B-code. Check\n`source` and read `description` before comparing a code across zones.\n\nPassing zone= also returns `taxonomy_note` for zones that mix taxonomies\n(e.g. GB), and per-code `endpoints` showing where each code comes from.\n\nEach code carries `counts_as_generation`: when False the figure is a net\nflow or net storage number, not production — do not sum it into a\ngeneration total.", "inputSchema": { "additionalProperties": false, "properties": { "zone": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null } }, "type": "object" }, "name": "list_psr_types", "outputSchema": { "additionalProperties": true, "type": "object" } }, { "description": "List registered ENTSO-E bidding zones.", "inputSchema": { "additionalProperties": false, "properties": { "active_only": { "default": true, "type": "boolean" }, "cluster": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null } }, "type": "object" }, "name": "list_zones", "outputSchema": { "properties": { "result": { "items": { "additionalProperties": true, "type": "object" }, "type": "array" } }, "required": [ "result" ], "type": "object", "x-fastmcp-wrap-result": true } } ] }
Verify it yourselfcurl -s https://api.teppi.xyz/v1/evidence/sha256:3b40789fc4ecd3fea16d3fac267f6b7a389d05997699278ff32037e511fae3ee | sha256sum