nordpool-ee-mcp
This server provides Estonia Nord Pool electricity price data through three MCP tools.
Retrieve current-day Estonia prices with 15-minute intervals and hourly averages, both VAT-exclusive and VAT-inclusive, in EUR/MWh and euro cents/kWh, plus the current-hour average and active interval.
Retrieve Estonia prices for a specific local date and clock hour (0–23), including all 15-minute intervals, min/max/average prices, DST handling, and summary.
Retrieve complete next-day Estonia prices with 15-minute intervals and hourly averages in Europe/Tallinn local time, with and without VAT.
View wholesale-only prices; supplier margin, network charges, excise, and other fees are explicitly excluded.
Discovers local TP-Link Tapo smart sockets by MAC address, reads their supported measurements (such as power/energy telemetry), and explicitly sets a selected socket's power on or off.
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., "@nordpool-ee-mcpwhat are Estonia's electricity prices right now?"
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.
Home automation
Nine independent local stdio MCP servers for electricity data, household costs, and explicitly selected device controls, plus integration with Home Assistant's native HTTP MCP server. The local servers share one installable Python distribution, not a hosted service or a background automation daemon.
Repository: https://github.com/vasilyevstan/home_automation
MCP folders
Each folder contains its implementation, a README.md with setup/tool
documentation, and an AGENTS.md with maintenance and safety guidance.
MCP registration | Folder and README | Purpose | Optional runtime extra |
| Published Estonia prices, standalone CLI, and separate experimental forecast | None | |
| Authorized household grid import/export | None | |
| Effective-dated costs, bills, and incremental scenarios | None | |
| Enrolled Sensibo Sky climate devices | None | |
| Local MAC-addressed sockets and measurements |
| |
| Local dish telemetry and opt-in controls |
| |
| Local speakers, playback, groups, and queues |
| |
| LAN-enabled lights | None | |
| Privately provisioned direct-LAN heater |
| |
| Direct HA device integrations and SDK-free household price sensors | Runs in HA; no extra MCP gateway |
The heater's one-time provisioning utility additionally uses heater-setup.
Tests and synthetic examples remain in the shared tests/ and examples/
directories. The pricing server reuses the market and household clients
directly rather than launching other MCP processes.
The HA pricing integration bundles the same pure financial engine without its MCP dependencies. It calculates inside HA; it does not call the pricing MCP or require the checkout/CLI to stay running. See its guide for installation, private profiles, scoped MCP access, and direct-device handover.
The distribution name estonia-nordpool-prices, all existing console
commands, MCP registration names, and tool names are retained for compatibility.
Root-level Python files are small compatibility entry points: imports such as
electricity_pricing and nordpool_ee still refer to the real implementation
modules, including their state and exception classes. Put implementation changes
in the relevant home_automation/ folder, not those compatibility files.
Related MCP server: Steddion Energy MCP Server
Requirements
Python 3.10 or newer
Python 3.11 or newer and the optional
tapoextra fortp-tapo-mcponlyThe optional
starlinkextra and a trusted LAN route to the dish forstarlink-mcpThe optional
sonosextra and trusted LAN access to Sonos speakers forsonos-mcp; no Sonos cloud credentials are requiredTrusted LAN access to supported Govee devices with LAN Control enabled in Govee Home for
govee-mcp; no Govee cloud credentials are requiredThe optional
heaterextra and verified private provisioning for the heaterInternet access to
dashboard.elering.eefor published electricity pricesInternet access to
wattcast.eufor the optional forecast tool (no API key)Elering customer API credentials and access to
estfeed.elering.eeandkc.elering.eefor household consumption and automatic household pricing; pricing supplied readings or individual quantities needs no household credentialsSensibo cloud access and explicit enrollment for
sensibo-mcp
Setup
Clone the repository and install its locked dependencies:
git clone https://github.com/vasilyevstan/home_automation.git
cd home_automation
uv sync --locked --inexactRun checkout commands from this repository root. Choose the optional extra listed for the MCP you need; for example:
uv run --locked --extra tapo --inexact tp-tapo-mcpThe standalone electricity-price CLI is still uv run nordpool-ee.
Each MCP README includes its own launch and registration instructions.
--inexact preserves other extras already installed in a shared development
environment. Persistent installations should use a published Git commit or
their own non-editable environment outside the checkout.
Keep credentials, real tariffs, household readings, device inventories, and invoice or device captures outside the public repository. GitHub publishes the generic code; repository secrets do not make a local MCP a hosted service.
Repository and local-folder rename
The GitHub repository is vasilyevstan/home_automation. An existing checkout
may still be named electro; its directory name is not part of the MCP API.
The remote can be updated without moving the checkout:
git remote set-url origin https://github.com/vasilyevstan/home_automation.gitFor registrations that must survive a later checkout rename, use a
Git-commit-pinned uvx --from launch or a non-editable installation in a
separate persistent environment. Do not point those registrations at
uv run --directory /path/to/the/checkout. Preserve their tool allowlists and
private environment settings when updating the executable source.
After moving a development checkout, run uv sync --locked --inexact from its
new root to refresh the editable installation and generated entry points.
Keep any needed --extra selections. Independently installed MCPs do not need
the checkout to be present.
Existing ~/.config/electro/, ~/.local/share/electro/, environment variable
names, and Keychain services are intentionally unchanged. Do not move private
configuration or re-provision devices merely because the repository was renamed.
Validation
Run the deterministic test suite without live network access:
uv run --locked --inexact python -m unittest discover -s tests -vCheck syntax:
uv run --locked --inexact python -m compileall -q home_automation *.pyRun the CLI for a live next-day source check:
uv run nordpool-eeThe deterministic suite also covers forecast schema/transport/cache errors, quantile and VAT arithmetic, partial/stale data, missing accuracy, DST windows, and MCP text/structured output agreement. Live integration checks must compare the same forecast issuance, distinguish published from predicted hours, and report actual coverage and freshness. Faithful reproduction of provider metrics does not independently validate future predictive accuracy.
Household tests cover credential loading and redaction, OAuth expiry/retries, rate limits, private upstream errors, date/DST boundaries, null-versus-zero readings, independent import/export completeness and MCP output. Live checks should compare the same authorized meter/date window and resolution to the source, without publishing private response data or claiming independent verification of the physical meter.
Pricing tests cover synthetic profile validation, interval weighting, raw/net flows, holiday/time-band and DST boundaries, negative prices, source status, rounding stages/ties, fixed-fee identity, daily allocations, annual/monthly composition, bounded market batches and both MCP input modes. Real invoice replays belong outside the public repository and CI logs.
Run the optional Tapo tests, and then the complete suite with the extra:
uv run --locked --extra tapo python -m unittest discover -s tests -p 'test_tapo*.py' -v
uv run --locked --extra tapo python -m unittest discover -s tests -vTapo tests use synthetic identities and mocked network/relay operations. They cover IP reassignment, unsupported discovery, retained inventory, credential redaction, null versus zero, units, strict boolean commands, serialized mutations, and confirmed/uncertain read-back. Without the extra, the library-dependent tests are explicitly skipped; base startup/credential and MCP schema tests still run. Automated tests never require real Tapo or GitHub secrets and must not switch household loads.
For the complete optional-runtime suite:
uv run --locked --all-extras --inexact python -m unittest discover -s tests -vtest_package_layout.py checks packaged console commands, legacy module
identity, per-MCP documentation, and lazy imports. Each MCP's maintenance file
lists its focused tests. Device tests use synthetic identities and mocked
controls; a repository refactor or installation check does not authorize
physical switching, heating, playback, regrouping, or dish reconfiguration.
License
The source code is available under the MIT License. The license does not cover Nord Pool, Elering or Wattcast data, trademarks, or third-party content.
Available Tools
3 toolsget_estonia_current_day_pricesGet Estonia current-day electricity pricesA
Get complete current-day Nord Pool prices for Estonia.
Returns 15-minute prices and hourly averages with and without VAT, in
EUR/MWh and euro cents/kWh. Show current_hour's average and the active
current_interval separately, using Estonia-local time. Supplier margin,
network charges, excise, and other fees remain excluded.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| area | Yes | |
| source | Yes | |
| summary | Yes | |
| currency | Yes | |
| timezone | Yes | |
| intervals | Yes | |
| current_hour | Yes | |
| delivery_date | Yes | |
| excluded_costs | Yes | |
| interval_count | Yes | |
| wholesale_only | Yes | |
| hourly_averages | Yes | |
| current_interval | Yes | |
| interval_minutes | Yes | |
| vat_rate_percent | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description must carry the load, and it does well: it discloses the time resolution (15-minute and hourly), VAT treatment, both unit systems, Estonia-local time, and explicitly what is excluded (supplier margin, network charges, excise, other fees). It omits whether prices are final day-ahead versus provisional and any refresh/auth behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Short and front-loaded: the scope sentence leads, followed by return-shape and exclusion details. Slight redundancy between 'current_hour's average' and the hourly-averages mention, but no wasted padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present and zero parameters, the description need not explain return values, yet it still characterizes coverage and exclusions usefully. Complete enough to invoke correctly; only the freshness/finality of the data is unstated.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate. Baseline 4 applies; the description adds relevant framing around output shape without inventing parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specifies verb + resource + scope precisely: current-day Nord Pool prices for Estonia. The 'current-day' qualifier implicitly separates it from the 'next_day' sibling, but the description never names the alternatives, so differentiation relies on the reader inferring it from the name.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No when-to-use, when-not-to-use, or alternative-tool guidance beyond what the name implies. With siblings like get_estonia_prices_for_hour and get_estonia_next_day_prices, the agent gets no explicit routing rule for choosing among them.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_estonia_next_day_pricesGet Estonia next-day electricity pricesA
Get complete next-day Nord Pool prices for Estonia.
Returns each 15-minute interval and hourly averages in Europe/Tallinn local time, with and without VAT, in EUR/MWh and euro cents/kWh. Supplier margin, network charges, excise, and other fees remain excluded.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| area | Yes | |
| source | Yes | |
| summary | Yes | |
| currency | Yes | |
| timezone | Yes | |
| intervals | Yes | |
| current_hour | Yes | |
| delivery_date | Yes | |
| excluded_costs | Yes | |
| interval_count | Yes | |
| wholesale_only | Yes | |
| hourly_averages | Yes | |
| current_interval | Yes | |
| interval_minutes | Yes | |
| vat_rate_percent | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it does disclose meaningful behavioral traits: 15-minute granularity plus hourly averages, Europe/Tallinn local time, with-and-without-VAT, and dual units. It also states what is excluded (supplier margin, network charges, excise, other fees). It does not cover auth or rate limits, but for a zero-param read tool this is a strong disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the core purpose, followed by the return-shape and exclusion caveats. Every clause adds information; nothing is padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be re-explained, yet the description usefully summarizes granularity, timezone, VAT treatment, and units, and clarifies fees are excluded. Nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are zero parameters, so the baseline is 4; the description correctly avoids inventing parameter semantics that do not exist.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Get), resource (next-day Nord Pool prices), and geographic scope (Estonia), which cleanly separates it from get_estonia_current_day_prices and get_estonia_prices_for_hour. An agent can route on the name/description alone without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the 'next-day' qualifier against the 'current day' and 'for hour' siblings, but the description never explicitly says when to pick this tool over them or adds any prerequisite/exclusion. It is adequate but leaves the routing inference to the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_estonia_prices_for_hourGet Estonia electricity prices for an hourA
Get Estonia prices for a specific local date and clock hour.
Args:
delivery_date: Estonia delivery date in YYYY-MM-DD format.
hour: Estonia local clock hour from 0 through 23.
Returns every 15-minute market interval in the requested hour plus minimum,
maximum, and average prices with and without VAT. Repeated daylight-saving
hours include two offset-distinct hourly_averages and eight intervals;
summary averages both occurrences. A skipped hour returns a tool error.
Supplier margin, network charges, excise, and other fees remain excluded.
| Name | Required | Description | Default |
|---|---|---|---|
| hour | Yes | ||
| delivery_date | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| area | Yes | |
| hour | Yes | |
| source | Yes | |
| summary | Yes | |
| currency | Yes | |
| timezone | Yes | |
| intervals | Yes | |
| delivery_date | Yes | |
| excluded_costs | Yes | |
| interval_count | Yes | |
| wholesale_only | Yes | |
| hourly_averages | Yes | |
| vat_rate_percent | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so well: it discloses DST behavior (two offset-distinct hourly_averages, eight intervals, summary averaging both occurrences), that a skipped hour returns a tool error, and that supplier margin, network charges, excise and other fees are excluded. These are exactly the behavioral traits an agent needs before calling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded, followed by an Args block and a Returns block. Given the 0% schema coverage the parameter restatement earns its place, and the DST/error sentences are dense with information rather than filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter read tool with an output schema, the description is thorough: it covers edge cases (DST, skipped hour error) and cost exclusions. Minor omissions such as authentication or rate-limit notes are not material here, and the presence of an output schema makes the return-value detail a bonus rather than a requirement.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate, and it does: it specifies the YYYY-MM-DD format for delivery_date, identifies it as the Estonia delivery date, and clarifies hour is Estonia local clock time from 0 through 23. Both parameters gain meaning beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource (get Estonia prices) with a clear scope qualifier (for a specific local date and clock hour). It is distinguishable from the siblings in intent (arbitrary date/hour vs current-day or next-day), though it never names them explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
"For a specific local date and clock hour" implies when to reach for this over the sibling current/next-day tools, but there is no explicit when-to-use, when-not-to-use, or alternative routing. Usage is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v0.3.0- First observed
get_estonia_current_day_prices - First observed
get_estonia_next_day_prices - First observed
get_estonia_prices_for_hour
TDQS
Scored across 3 tools
The three tools target distinct time windows (current day, next day, specific hour), but get_estonia_prices_for_hour partially overlaps with get_estonia_current_day_prices since the current-day tool also surfaces the active interval and current-hour average. An agent can still choose correctly in most cases because each description clearly states its scope.
All three follow a get_estonia_*_prices pattern in snake_case with a consistent verb, which is highly readable. The only minor deviation is the 'for_hour' prepositional suffix versus the adjective prefixes (current_day/next_day), so the shapes aren't perfectly parallel.
Three tools is on the thin side but reasonably well-scoped for a niche single-zone price feed. Each tool earns its place by covering a distinct temporal window, so nothing feels redundant or bloated.
The surface covers the core lifecycle of price retrieval: current day, next day, and arbitrary date/hour lookups (which also enable historical queries). There's no range or multi-zone query and no 'all zones' option, but for an Estonia-focused server the essential operations are present.
Maintenance
Related MCP Connectors
Real-time electricity price signals for AI agents. Spot prices, cheapest hours, and contract recommendations. 31 countries across Europe and Oceania. No authentication required.
Live and historical electricity prices and demand for 25 grids; carbon intensity for GB.
Real-time electricity prices for AI agents. 40+ countries, 100+ zones. No auth required.
European day-ahead electricity prices (43 zones), accuracy-published forecasts, carbon, optimize.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceMCP server for real-time electricity prices, carbon intensity, and energy analytics across 41+ zones in Europe, Great Britain, the United States, and Australia. Query live prices, compare zones, check gas storage levels, get green scores, find optimal charging windows, and access advanced analytics. Free Basic tier requires no API key. Install via npx gridpulse-mcp or connect directly via Streamab-
- FlicenseNot gradedqualityDmaintenanceProvides tools for Dutch energy market data: day-ahead and imbalance prices, weather forecasts, and battery storage business case calculations.-

Voltcast MCP Serverofficial
AlicenseNot gradedqualityCmaintenanceEnables access to European electricity data including day-ahead prices, probabilistic forecasts, carbon intensity, and cheapest-window optimization for 43 bidding zones.MIT- FlicenseNot gradedqualityCmaintenanceProvides real-time electricity prices, cheapest hours, and contract comparison for 40+ countries, enabling AI agents to make energy-aware decisions.4-