mcp-edf
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-edf What was my electricity consumption last month in kWh and euros?"
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.
@mgcrea/mcp-edf
A Model Context Protocol server for EDF Suivi Conso, the consumption pages of EDF's French customer area: daily and monthly electricity (Linky) and gas (Gazpar) consumption in kWh and in euros, the 30-minute load curve, daily peak power, and the contracts behind them.
It reads; it never writes. There are no mutating tools to enable.
How it talks to EDF. EDF offers no API to its customers. This server uses the same JSON API the Suivi Conso website (suiviconso.edf.fr) uses, after the same EDF login, and borrows that website's own login client to do it. It sends the same requests a browser on that site would, at a similar volume. It is not endorsed by EDF, and it can break whenever EDF changes the site.
Tools
Tool | What it does |
| Signed in or not, which home it reads, where the login is stored |
| Logs in through a Safari tab (macOS) and keeps a refresh token |
| Revokes the refresh token at EDF and deletes it locally |
| Electricity option (BASE / HPHC / TEMPO…), subscribed kVA, gas tariff, history |
| kWh and € per day or month, split by tariff heading, with totals |
|
|
| Daily peak kVA against the subscribed power |
| kWh, m³ and € per day or month, with the conversion factor |
| Daily (with sky) or monthly temperature at the home's weather station |
| Each month against the same month last year, electricity or gas |
| Electricity in two periods, with EDF's warmer/colder weather verdict |
| EDF's modelled split by use (heating, hot water…), and monthly electric heating |
| GET any other Suivi Conso API path (raw JSON) |
None of the comparisons is weather-adjusted: EDF gives a qualitative verdict (warmer or colder, higher or lower) and the temperatures, and the analysis is left to whoever reads them. The usage breakdown is EDF's model, fed by the home profile declared on Suivi Conso, so it lags behind new equipment until that profile is updated.
Costs are EDF's own estimate at the contract's prices, taxes included, as shown on Suivi Conso. They follow the bill closely, but they are not the invoice. Invoices are not available through this API.
Related MCP server: euenergy-mcp
Logging in
There is nothing to configure. Ask your agent to call edf_auth_login:
It opens the EDF login in a background Safari tab. If Safari is already signed in to EDF, the login completes on its own within a second or two.
Otherwise Safari comes forward after two seconds, and you log in as usual.
The first time, macOS asks whether the app running the server (your editor, a terminal, or Bastion) may control Safari. Allow it. That grant is how the server reads the one-time code from the tab's address.
Why Safari automation. EDF registers exactly one redirect for this client,
https://suiviconso.edf.fr/openid, so there is no localhost callback to listen on. The page at
that address uses up the code as soon as it loads. The server polls the tab's address every
20 ms and closes the tab the moment the code arrives, before the page can use it.
The login is kept as a refresh token in ~/.config/edf/tokens.json (mode 600). EDF's access
tokens last 20 minutes and are renewed from it silently. EDF does not rotate the refresh token,
and does not publish how long it lasts. When it expires, the tools answer signedIn: false and
you log in again.
Without macOS. edf_auth_login also takes a redirect_url: the address the browser lands
on after logging in, https://suiviconso.edf.fr/openid?code=…. The Suivi Conso page strips the
code within a second, so you have to copy the address before the page runs, for example with
JavaScript disabled for that site. A refresh token obtained elsewhere can be supplied as
EDF_REFRESH_TOKEN (in Docker, for instance).
Configure (all optional)
Variable | Description |
| The home to read, as part of its address (e.g. |
| A refresh token from outside. Kept in memory only, so a login made in-session lasts until restart. |
| Where the login is stored. Defaults to |
| A JSON config file with the same settings ( |
| Retries for 401 / 429 / 5xx. Default 3. |
| Per-request timeout. Default 30000. |
|
|
The environment wins over the config file, field by field.
Quick start
pnpm install
pnpm build{
"mcpServers": {
"edf": { "command": "node", "args": ["/absolute/path/to/mcp-edf/dist/cli.js"] }
}
}Develop
pnpm dev # tsdown --watch
pnpm test # vitest, against recorded and anonymised Suivi Conso responses
pnpm typecheck
pnpm lint
pnpm formatAPI notes
The Suivi Conso API's traps are documented in the code at the point where each is handled:
Date formats differ by endpoint (
src/client/time.ts):beginTs,beginDateandtswant2026-11-01T00:00:00+01:00;begin-datewants2026-11-01;begin-monthwants2026-11.
v1 and v2 are not interchangeable. Each endpoint lives in exactly one, and the wrong one answers 404.
Site headers. Every
/sites/-/…call needs theperson-ext-idandsite-ext-idheaders (src/client/edf.ts). Without them it answers 401.
Publish
pnpm dlx release-it # bump, commit, tag
git push --follow-tags # CI publishes to npm from the tagLicense
MIT
Available Tools
13 toolsedf_auth_loginEDF: LoginAIdempotent
Sign in to EDF. On macOS this opens the EDF login in a Safari tab and catches the one-time code when EDF redirects back: if Safari is already signed in to EDF it completes in a second or two with nothing to do; otherwise Safari comes forward and the user logs in as usual. The first run triggers macOS's 'allow to control Safari' prompt. Waits up to wait_seconds, then keeps listening in the background for 5 minutes: call edf_auth_status afterwards. Elsewhere, pass redirect_url instead (see that argument). Logging in again replaces the stored login.
Inputs: redirect_url, wait_seconds.
edf_auth_logoutEDF: LogoutADestructiveIdempotent
Revoke the stored refresh token at EDF (best effort) and delete it locally. Recoverable by calling edf_auth_login again.
Inputs: no named parameters.
edf_auth_statusEDF: Auth StatusARead-only
Whether the server is signed in to EDF, which home it reads (the login picks the account, and an account can hold several homes), when the login was made, and where it is stored. Signed out, returns the steps to sign in. Call this first when a data tool answers signedIn: false.
Inputs: no named parameters.
edf_compare_periodsEDF: Compare PeriodsARead-only
Electricity used in one period against a reference period (by default the same dates a year earlier), with EDF's weather verdict: whether the period was warmer, similar or colder than the reference, and whether consumption was higher, similar or lower. Use it to ask "did we use more this summer than last, and was it hotter?". The verdict is qualitative and reads temperature only: the kWh are NOT weather-adjusted, and in summer "colder" just means cooler, which lowers a cooling load rather than raising a heating one. Electricity only; EDF answers FLUID_NOT_SUPPORTED for gas, so use edf_compare_years with energy=gas plus edf_get_weather there.
Inputs: from (required), to, reference_to, reference_from.
edf_compare_yearsEDF: Compare YearsARead-only
Each month of a year against the same month of the year before, from EDF's own comparison: kWh and euros both years and the change in %, for electricity or gas. total_complete_months sums only months present in both years. EDF rounds to whole kWh and euros. These are raw figures, NOT weather-adjusted: pair them with edf_get_weather (step=month) to tell a colder winter from a change in the home, or use edf_compare_periods for EDF's weather verdict on electricity.
Inputs: energy (required), year.
edf_get_contractsEDF: ContractsARead-only
The home's EDF contracts. Electricity: the tariff option (BASE, HPHC for peak/off-peak, TEMPO…), the subscribed power in kVA and EDF's tariff code, as a history of versions, since EDF writes a new one at every price or option change; current is the one in force. For options with off-peak hours, the meter's calendar (e.g. "HC 01:30-07:00"). Gas: tariff code, consumption option and price zone, or null with no gas contract. Call it to learn the option before reading costs by tariff heading.
Inputs: no named parameters.
edf_get_electricity_consumptionEDF: Electricity ConsumptionARead-only
Electricity used per day or per month, in kWh and in euros, from the Linky meter via EDF Suivi Conso. Each row has the total cost, the daily share of the subscription (standing_charge_eur), and, on a peak/off-peak or Tempo contract, the split by tariff heading. total sums the range and gives the average price per kWh. Costs are EDF's own estimate at the contract's prices, taxes included; they track the bill closely but are not the invoice. Rows flagged nature other than REAL are estimates. Use step=month for anything over a few months: a year of days is ~25 kB.
Inputs: from (required), to, step.
edf_get_electricity_load_curveEDF: Electricity Load CurveARead-only
The Linky load curve: energy per 30 minutes (or per hour) as compact rows of [start, kWh, average kW], with the range total and the peak interval. Use it to see when power is drawn (night vs day, a heater, a car charging); use edf_get_electricity_consumption for daily or monthly totals and costs. Paris local times. At most 7 days at 30m, 31 days at 1h, since a single day is 48 rows. The curve only exists if load-curve collection is switched on for the meter (it is on Suivi Conso's hourly view).
Inputs: from (required), to, resolution.
edf_get_electricity_max_powerEDF: Electricity Max PowerARead-only
The highest power drawn each day, in kVA, as [date, max_kva] rows, with the range maximum and the subscribed power of the current contract to compare against. Use it to decide whether the subscription (e.g. 6, 9, 12 kVA) is too high or close to tripping. The meter's history goes back years; this filters it to the range asked.
Inputs: to, from.
edf_get_gas_consumptionEDF: Gas ConsumptionARead-only
Gas used per day or per month from the Gazpar meter via EDF Suivi Conso: kWh, m³, the conversion factor between them, and euros (energy plus the daily share of the subscription). total sums the range. Costs are EDF's estimate at the contract's prices, taxes included. Daily figures need a communicating Gazpar meter and arrive a day or two late; months are available further back. Answers 404 on an account with no gas contract.
Inputs: from (required), to, step.
edf_get_usage_breakdownEDF: Usage BreakdownARead-only
EDF's ESTIMATE of where the energy went over the last 12 months, by use (heating, hot water, cooking, fridge and freezer, washing, lighting…), in kWh, euros and %. For electricity it adds EDF's estimate of electric heating per month as [month, kWh, €] rows. This is a model (model names EDF's algorithm) fed by the home profile declared on suiviconso.edf.fr, not a measurement: profile_declares_air_conditioning shows one profile field that changes it most. A profile that predates new equipment skews it, so update the profile on the site first. For measured figures use the consumption tools.
Inputs: energy (required).
edf_get_weatherEDF: WeatherARead-only
The weather at the home's weather station, as Suivi Conso shows it beside the consumption: the average outdoor temperature per day (to 0.1 °C) with the sky (sunny, sunny spells, overcast, light rain…), or per month (whole °C). Use it to read consumption against the weather: heating demand follows the temperature, cooling the heat, and a sunny day lowers heating needs. The sky is one coarse label per day; for sunshine hours or solar radiation use an external weather archive. Same Paris-time days as the consumption tools, so rows line up with edf_get_electricity_consumption and edf_get_gas_consumption.
Inputs: from (required), to, step.
edf_requestEDF: RequestARead-only
Escape hatch: GET any Suivi Conso API path for this home, returning the raw JSON (cut at 60,000 characters). GET only; the same login and home headers as the other tools. Prefer the dedicated tools: their output is shaped, this one's is not. Paths seen in the Suivi Conso site include /v2/sites/-/elec-price-changes (beginTs, endTs), /v1/sites/-/billing-windows (fluids=ELEC,GAS), /v2/sites/-/elec-tariff-calendars (date=2026-11-11, a bare date), /v1/sites/-/usage-breakdowns (ts, fluid=ELEC|GAS), /v2/sites/-/forecast-consumptions (beginDate, endDate, fluid, strategy=ESTIMATION_AFTER_REAL). - stands for the current home. Some endpoints are v1 and others v2, and a wrong version answers 404.
Inputs: path (required), query.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 13 tools
Each tool targets a distinct resource or analysis: auth lifecycle, contracts, electricity consumption, load curve, max power, gas consumption, weather, two comparison modes, usage breakdown, and a raw escape hatch. The descriptions actively disambiguate the risky pairs (consumption vs load curve vs max power, compare_years vs compare_periods, estimated breakdown vs measured consumption) and frame edf_request as a fallback to be avoided. No two tools appear interchangeable.
All tools share the edf_ prefix with a predictable verb_noun shape, grouped into coherent families (auth_*, get_*, compare_*). The only deviation is edf_request, the generic escape hatch, which reads naturally as a deliberate exception. An agent can guess a tool name from intent.
13 tools is well within the ideal range and each one maps to a real capability (three auth, four electricity reads, gas, weather, two comparisons, breakdown, raw request). Nothing looks like filler or a near-duplicate.
The surface covers the full read-only lifecycle: sign-in/status/sign-out, contract discovery, measured consumption for both energies, power diagnostics, weather context, comparisons, and an escape hatch for anything else. Gaps are minor but real: no tool to list or switch among the multiple homes an account can hold, and billing/invoice or tariff-change data is reachable only through the unstructured edf_request.
Maintenance
Related MCP Connectors
Read-only electricity, gas, and weather data with structured provenance and units.
French energy data, electricity and gas consumption, tariff scenarios and public discovery tools.
LLM API prices and AI agent cost estimates, verified daily. Read-only cost lookup tools.
Real-time electricity price signals for AI agents. Spot prices, cheapest hours, and contract recommendations. 31 countries across Europe and Oceania. No authentication required.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceProvides read-only access to Shelly Cloud energy data, including live power, lifetime energy, and historical consumption with cost, enabling AI agents to monitor electricity usage without device control.1-
- FlicenseNot gradedqualityCmaintenanceA read-only MCP server that exposes European day-ahead electricity prices for ~41 bidding zones via tools like hourly prices, cheapest hours, current price, and cross-zone summary, enabling AI agents to query energy market data.1-
- AlicenseNot gradedqualityBmaintenanceProvides tools to search, inspect, and query energy open data from ODRE (electricity & gas production, consumption, grid load, renewables) using natural language or direct tool calls.112 npmMIT
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to access and analyze Spanish electricity consumption data via the Datadis API, providing tools for supply management, consumption analysis, anomaly detection, and executive reporting.MIT