aemo-mcp
MCP server for the Australian Energy Market Operator (AEMO) National Electricity Market. Plain-English access to 5-min dispatch prices, regional demand, interconnector flows, generation by fuel, rooftop PV.
README
aemo-mcp
Ask Claude about Australia's electricity market and get real, current numbers — 5-minute spot prices, regional demand, generation by fuel, interconnector flows, rooftop solar — not "I don't have access to that data." This MCP server gives Claude (and other MCP clients like Cursor) live access to the Australian Energy Market Operator (AEMO) NEMWEB feeds, with curated mappings for the most-asked indicators.
Companion to abs-mcp (ABS macro stats), rba-mcp (RBA interest + FX rates), ato-mcp (ATO tax + ACNC charity), apra-mcp (banking + superannuation), aihw-mcp (health & welfare), asic-mcp (companies + financial advisers), and au-weather-mcp (Australian weather) — together they cover the most-asked Australian official data.
What you can ask
Once installed, your LLM can answer questions like:
| Question | What the tool does |
|---|---|
| What's the current NSW spot price? | latest("dispatch_price", filters={"region":"NSW1"}) |
| Did SA hit negative pricing in the last 24 hours? | get_data("dispatch_price", filters={"region":"SA1"}, start_period=…) and filter value < 0 |
| Generation by fuel type right now in QLD | latest("generation_scada", filters={"region":"QLD1"}), aggregated by fuel |
| Weekly average dispatch price for VIC, last 4 weeks | get_data("dispatch_price", filters={"region":"VIC1"}, start_period=…) |
| Rooftop PV forecast for tomorrow | get_data("rooftop_pv", filters={"section":"forecast"}, start_period="<tomorrow>") |
| What's the current flow across Heywood (VIC ↔ SA)? | latest("interconnector_flows", filters={"interconnector":"V-SA"}) |
| Total NEM demand right now | latest("dispatch_region") |
Every answer comes with the interval timestamp (AEMO market time, UTC+10), units (MW, $/MWh), and a link back to the NEMWEB source. The MCP wraps NEMWEB's CSV/ZIP feeds and exposes them through 5 plain-English tools.
Install
# After publish:
uvx --upgrade aemo-mcp
# Local dev:
uv pip install -e .
Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"aemo": {
"command": "uvx",
"args": ["--upgrade", "aemo-mcp"]
}
}
}
Why
--upgrade?uvx aemo-mcp(without the flag) uses whatever wheel is cached and never adopts new PyPI releases on its own.--upgrademakes uvx check PyPI on each launch and pull a newer release if one exists. Recommended for everyone except offline-first / pinned-version workflows. To verify which version is currently serving you, look at theserver_versionfield on anyDataResponse.
If you also have rba-mcp / abs-mcp installed, all servers run side-by-side.
Claude disambiguates with the server prefix (aemo:get_data, rba:get_data,
abs:get_data).
For local dev (pre-PyPI):
{
"mcpServers": {
"aemo": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/aemo-mcp", "aemo-mcp"]
}
}
}
Cursor
Add to ~/.cursor/mcp.json (or workspace .cursor/mcp.json):
{
"mcpServers": {
"aemo": {
"command": "uvx",
"args": ["--upgrade", "aemo-mcp"]
}
}
}
Tools
| Tool | What it does |
|---|---|
search_datasets(query, limit=10) |
Fuzzy-search the 7 curated NEM datasets by name, topic, or region. |
describe_dataset(dataset_id) |
Schema, filters, source URL, cadence, and example queries for one dataset. |
get_data(dataset_id, filters, start_period, end_period, format) |
Query data. Records / series / csv format. |
latest(dataset_id, filters) |
Most recent 5-min or 30-min interval for time-series feeds. |
list_curated() |
The 7 curated dataset IDs. |
Curated datasets
The 7 datasets cover ~95% of typical NEM analytic queries:
dataset_id |
Cadence | Source | Use case |
|---|---|---|---|
dispatch_price |
5 min | DispatchIS / DISPATCHPRICE | Current spot price per region; negative-pricing detection |
dispatch_region |
5 min | DispatchIS / DISPATCHREGIONSUM | Demand + scheduled + semi-scheduled gen + net interchange |
interconnector_flows |
5 min | DispatchIS / DISPATCHINTERCONNECTORRES | MW flow + losses across NEM interconnectors |
generation_scada |
5 min | Dispatch_SCADA | DUID-level MW (every unit), aggregable by fuel |
rooftop_pv |
30 min | ROOFTOP_PV/ACTUAL + FORECAST | Regional rooftop solar (actual + forecast) |
predispatch_30min |
30 min | PredispatchIS | 30-min forecast, ~40h horizon |
daily_summary |
Daily | Daily_Reports | Yesterday's full data in one drop |
Use list_curated() to enumerate, describe_dataset(dataset_id) to learn
the filters available on each.
Regions
NSW1 (New South Wales), QLD1 (Queensland), SA1 (South Australia), TAS1 (Tasmania), VIC1 (Victoria). Western Australia (WEM) and the Northern Territory are not on the NEM and are out of scope.
Trust contract
Every DataResponse carries:
source = "Australian Energy Market Operator"attribution— AEMO Copyright Permissions verbatim attribution stringsource_url— the NEMWEB folder the data came fromretrieved_at— UTC timestamp of the fetchinterval_start/interval_end— period coveredstale—Trueif the latest interval is older than 2× the feed cadenceserver_version— the wheel that served the call
Licence + attribution
This package is MIT-licensed (see LICENSE).
The AEMO data it fetches is published under AEMO's Copyright Permissions policy: AEMO grants general permission to use AEMO Material for any purpose (commercial included) on the sole condition of accurate attribution of the relevant material and AEMO as its author. See https://aemo.com.au/privacy-and-legal-notices/copyright-permissions.
End-users redistributing data fetched via this server must credit AEMO.
The canonical attribution string is on every DataResponse.attribution.
Worked examples
"What's the current NSW spot price?"
latest(dataset_id="dispatch_price", filters={"region": "NSW1"})
→ {"records": [{"period": "2026-05-14T10:05:00+10:00", "value": 87.5, "dimensions": {"region": "NSW1", "metric": "rrp"}, "unit": "$/MWh"}], ...}
"NSW spot price for the last 24 hours"
get_data(dataset_id="dispatch_price", filters={"region": "NSW1"},
start_period="2026-05-13", end_period="2026-05-14")
"Did SA hit negative pricing in the last 24 hours?"
get_data(dataset_id="dispatch_price", filters={"region": "SA1"},
start_period="<24h ago>")
Then the LLM filters value < 0 client-side.
"Generation by fuel type right now in QLD"
latest(dataset_id="generation_scada", filters={"region": "QLD1"})
→ DUID-level rows with fuel attribution; the LLM aggregates by fuel.
How it works
- Live-fetch only. No NEMWEB archives in the wheel. Every request goes through the cache.
- Cache TTLs tuned per cadence. 60s for 5-min feeds, 5min for 30-min feeds, 1h forecasts, 24h daily archive. Timestamped historical files are immutable in NEMWEB and cache effectively forever.
- In-flight request deduplication. Concurrent callers for the same URL share one HTTP request. Critical at 5-min cadence with many users.
- Latest-file detection is purely lexicographic on the NEMWEB directory
listing — AEMO embeds the interval timestamp in every filename
(
PUBLIC_DISPATCHIS_YYYYMMDDHHmm_<seq>.zip), somax()is enough. - Multi-section CSV parser handles AEMO's
I,/D,row format where a single ZIP holds several tables (DISPATCHPRICE, DISPATCHREGIONSUM, DISPATCHINTERCONNECTORRES, etc.).
Development
git clone https://github.com/Bigred97/aemo-mcp
cd aemo-mcp
uv sync --extra dev
uv pip install -e .
uv run pytest -q
Run live tests (hit NEMWEB):
uv run pytest -q -m live
Zero-flake validation:
for i in $(seq 1 10); do uv run pytest -q || break; done
Sister MCPs (Australian Public Data portfolio)
- abs-mcp — Australian Bureau of Statistics (CPI, unemployment, ERP, building approvals)
- rba-mcp — Reserve Bank of Australia (cash rate, lending stats, exchange rates)
- ato-mcp — Australian Taxation Office (tax stats, ACNC charities)
- apra-mcp — Australian Prudential Regulation Authority (banking, insurance, super)
- aihw-mcp — Australian Institute of Health and Welfare
- asic-mcp — Australian Securities and Investments Commission (company registers)
- aemo-mcp — this one. Australian Energy Market Operator (NEM dispatch, spot prices, generation).
- au-weather-mcp — Open-Meteo (Bureau of Meteorology aggregator)
- wgea-mcp — Workplace Gender Equality Agency
- aus-identity — Postcode / state / ABN normalisation helper used by all sisters
Author
Built by Harry Vass. Issues + PRs welcome at github.com/Bigred97/aemo-mcp.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。