{
  "markdown": "# aeso-mcp\n\n<!-- mcp-name: io.github.bchoi-qwe/aeso-mcp -->\n\n**Agent-native, strongly typed access and analytics for Alberta's electricity market using official AESO data.**\n\n> Independent open-source project. **Not affiliated with or endorsed by the Alberta Electric System Operator (AESO).**\n\n## What it is\n\n`aeso-mcp` is a Model Context Protocol (MCP) server that exposes Alberta electricity-market observations and deterministic analytics to AI clients. It is designed for energy analysts, researchers, developers, journalists, market participants, and AI agents that need reliable, structured AESO data—not a thin REST decorator layer.\n\n## Features\n\n- Typed MCP tools with Pydantic inputs/outputs and structured results\n- Current market snapshot combining price, load, generation, interchange, and reserves\n- Paginated historical Pool Price, System Marginal Price, load, and generation retrieval\n- Official individual-asset Historical CSD Generation Data at hourly and five-minute resolution\n- Optional incremental DuckDB index and partitioned Parquet snapshots for repeatable research\n- Official AIL, Pool Price, wind, solar, and combined wind/solar forecast publications through\n  one typed `get_forecast` contract, with persisted publication vintages and point-in-time\n  `as_of` selection that excludes unknown publication chronology\n- Official supply-adequacy, supply-surplus, FFR Net Schedule, Dispatch Down Service, TMR\n  reference-price, and AIES system-event reports\n- Official historical adequacy/cushion web codes, transmission outages, planning-area hourly\n  load/generation, constrained volume, EEA events, operating-reserve directives, and the current\n  Pool Participant registry through one typed research-archive contract\n- Authenticated APIM reports for merit order, commitments, capability/outages, interties,\n  metered volumes, and operating-reserve offer control\n- Deterministic analytics: compact history summaries, period comparison, event detection,\n  condition evidence, price distributions, capture price, net load, supply stack, generation,\n  outage association, generalized forecast accuracy, asset gross energy revenue, CSD-versus-\n  metered comparisons, ramps, supply-surplus associations, and transparent supply-tightness\n  indicators, plus participant concentration, regional, constrained-volume, scarcity, and compact\n  system-frequency analysis\n- Deterministic research manifests identify exact input publications, parameters, methodology,\n  completeness, and degradation warnings for multi-source market-event analysis\n- Public operating-reserve active/standby prices, seven-day forecasts, activations, and summaries\n- One complete server package and startup path: `AESO_API_KEY` is always required; there is no\n  reduced credential-free server mode\n- Query bounds, cache provenance, completeness metadata, upstream `Retry-After` handling, and\n  secret-safe machine-readable errors\n- Hardened HTTP transport with Host/Origin validation, bearer authentication required for\n  non-loopback binds by default, rate/concurrency limits, request-size bounds, probes, and\n  correlation IDs\n- Reusable MCP prompts plus glossary, capability, dataset, and methodology resources\n\n## Implemented datasets\n\n| Dataset | Tool | Notes |\n| --- | --- | --- |\n| Market snapshot | `get_market_snapshot` | Current cohesive view |\n| Pool Price | `get_pool_prices` | Hourly CAD/MWh |\n| System Marginal Price | `get_system_marginal_prices` | Minute-level CAD/MWh |\n| Alberta Internal Load | `get_load` | MW; optional forecast |\n| Generation / fuel mix | `get_generation` | Current all fuels; historical wind/solar |\n| Interchange | `get_interchange` | Current path flows MW |\n| Operating reserves | `get_reserves` | Current MW indicators |\n| Generator outages | `get_outages` | Hourly outage capacity by fuel/technology |\n| AIES capacity/outages | `get_generation_capacity` | Hourly MC, AC, operating, and mothball outage MW |\n| Load outage forecast | `get_load_outage_forecast` | Hourly forecast MW |\n| Energy Merit Order | `get_energy_merit_order` | Historical blocks; 60-day publication delay |\n| Unit commitments | `get_unit_commitments` | Generating-unit commitment directives |\n| Intertie capability | `get_intertie_capability` | Import/export ATC, TTC, margins, gross offers |\n| Intertie capability outages | `get_intertie_outages` | Outages affecting interties/flowgates |\n| Metered volumes | `get_metered_volumes` | Hourly MWh by asset; optional ID filters |\n| OR offer control | `get_operating_reserve_offer_control` | Historical reserve offer blocks; 60-day delay |\n| Approved Tx outages | `get_approved_transmission_outages` | AESO-approved planned transmission outages |\n| Long-range Tx outages | `get_long_range_transmission_outages` | Tentative ~24-month significant outages |\n| MCSINR | `get_monthly_cumulative_net_revenue` | Cumulative net revenue vs offer-cap trigger |\n| Secondary offer limit | `get_secondary_offer_price_limit` | Whether secondary offer cap is in effect |\n| Assets | `get_assets` | Registry with filters |\n| Historical CSD generation | `get_historical_generation` | Individual assets; hourly / five-minute operational MW |\n| Official forecasts | `get_forecast` | AIL / Pool Price / wind / solar; source-specific horizons and cadence |\n| Official research archive | `get_research_data` | Historical adequacy/cushion, transmission, planning-area, constraint, EEA, OR-directive, and current participant records |\n| Supply adequacy / cushion | `get_supply_adequacy` | Official hourly categorical status bands |\n| Supply surplus | `get_supply_surplus` | Official hourly zero-price forecast status |\n| FFR Net Schedule | `get_ffr_net_schedule` | Hourly scheduled imports (negative) / exports (positive) MW |\n| Dispatch Down Service | `get_dispatch_down_service` | Published DDS availability MW |\n| TMR reference price | `get_tmr_reference_price` | Published CAD/MWh value by effective date |\n| AIES system events | `get_system_events` | Bounded event-log comments; no inferred event end |\n| UC settlement summary | `get_uc_settlement_summary` | Hourly CAD amount and charged MW |\n| OR prices | `get_operating_reserve_prices` | Active and standby price components and volumes |\n| OR forecast | `get_operating_reserve_forecast` | Current seven-day hourly MW forecast |\n| OR activations | `get_operating_reserve_activations` | Hourly standby volume and activation price |\n\nAnalytics: `summarize_market_history`, `assess_supply_tightness`, `compare_market_periods`,\n`find_price_events`, `explain_market_conditions`, `compare_forecast_to_actual`,\n`get_price_statistics`, `get_price_duration_curve`, `analyze_market_event`,\n`calculate_capture_prices`, `analyze_net_load`, `analyze_supply_stack`,\n`analyze_intertie_utilization`, `analyze_generation_mix`, `analyze_asset_dispatch`,\n`analyze_outage_impact`, `analyze_forecast_error`, `calculate_asset_energy_revenue`,\n`compare_csd_to_metered`, `analyze_ramps`, `analyze_supply_surplus_events`,\n`summarize_operating_reserve_market`, `analyze_participant_concentration`,\n`analyze_regional_load_generation`, `analyze_constrained_volume`, `analyze_scarcity`, and\n`analyze_system_frequency`.\n\n## Architecture\n\nThe documentation site includes a full [architecture and MCP Inspector walkthrough](docs/architecture.md).\n\n```text\nMCP clients\n    |\n    v\nFastMCP adapter (aeso_mcp/mcp)\n    |\n    v\nDomain services (market, grid, history, forecasts, reports, research, reserves, operations)\n    |\n    +---------------+----------------+----------------+----------------+\n    |               |                |                |\n    v               v                v                v\nGridStatus     Direct APIM     Public reports    CSD archive\n    |               |           (ets.aeso.ca)      (Box)\n    +-------+-------+\n            |\n            v\n      AESO APIM gateway\n```\n\nDomain code does not depend on FastMCP. Framework changes should stay in `aeso_mcp/mcp/`.\nAll upstream clients are implementation details of this single server: the APIM key is sent only\nto `apimgw.aeso.ca` and is never sent to the allow-listed ETS or Box hosts.\n\n## Requirements\n\n- Python 3.13+\n- AESO APIM API key from [developer-apim.aeso.ca](https://developer-apim.aeso.ca/)\n- [`uv`](https://docs.astral.sh/uv/) recommended\n\n## Installation\n\nSee [LIMITATIONS.md](LIMITATIONS.md) for an honest gap inventory.\n\n### From PyPI (recommended)\n\n```bash\nexport AESO_API_KEY=your-key\nuvx aeso-mcp\n```\n\nFor incremental DuckDB/Parquet historical storage:\n\n```bash\nuvx --from 'aeso-mcp[analytics]' aeso-mcp\n```\n\n### From GitHub\n\nTo run the current repository version directly:\n\n```bash\nexport AESO_API_KEY=your-key\nuvx --from git+https://github.com/bchoi-qwe/aeso-mcp.git aeso-mcp\n```\n\n### Development\n\n```bash\ngit clone https://github.com/bchoi-qwe/aeso-mcp.git\ncd aeso-mcp\nuv sync --group dev\ncp .env.example .env   # set AESO_API_KEY\nuv run aeso-mcp\n```\n\n### Docker\n\n```bash\ndocker build -t aeso-mcp .\ndocker run --rm \\\n  -e AESO_API_KEY=your-key \\\n  -e AESO_MCP_HTTP_BEARER_TOKEN=replace-with-a-long-random-token \\\n  -p 8000:8000 \\\n  aeso-mcp\n```\n\nSend the same token in the MCP client's `Authorization: Bearer ...` header. The image binds to\n`0.0.0.0`, so it intentionally requires bearer authentication by default.\n\n## Obtaining an AESO API key\n\n1. Register at the [AESO developer portal](https://developer-apim.aeso.ca/)\n2. Subscribe to the AESO public API product\n3. Copy the primary/secondary subscription key\n4. Set `AESO_API_KEY` in your environment (never commit it)\n\nMissing credentials produce an actionable startup error. The key is never returned through MCP tools or logged.\n\n## Example MCP client configuration\n\nSee the documentation site's [MCP client configurations](docs/client-configs.md) for maintained\nCodex, ChatGPT desktop app, Claude Desktop, Claude Code, and Cursor setup instructions.\n\n### Cursor / Claude Desktop style (stdio)\n\n```json\n{\n  \"mcpServers\": {\n    \"aeso\": {\n      \"command\": \"uvx\",\n      \"args\": [\"aeso-mcp\"],\n      \"env\": {\n        \"AESO_API_KEY\": \"your-key\"\n      }\n    }\n  }\n}\n```\n\n### HTTP transport\n\n```bash\nuv run aeso-mcp --transport http --host 127.0.0.1 --port 8000\n```\n\nHTTP always validates Host and Origin. A non-loopback bind now refuses to start unless\n`AESO_MCP_HTTP_BEARER_TOKEN` is configured. An explicit\n`AESO_MCP_HTTP_ALLOW_INSECURE_REMOTE=true` override exists for isolated environments that accept\nthe risk; it is never the default. Also set `AESO_MCP_HTTP_ALLOWED_HOSTS` and\n`AESO_MCP_HTTP_ALLOWED_ORIGINS` for the deployment. `/healthz` and `/readyz` contain no market data\nor secrets. See [.env.example](.env.example) for all bounded runtime settings.\n\n## Example prompts\n\n- What is Alberta's current grid situation?\n- What is the current pool price?\n- Show Alberta pool prices over the last 24 hours.\n- Compare today's pool prices with yesterday's.\n- Which hours had the highest prices this week?\n- How much wind and solar are producing right now?\n- What happened during the largest price spike this week?\n- How inaccurate was the seven-day wind forecast during that event?\n- Was AESO publishing a supply-surplus or tight supply-cushion status at the time?\n- What gross Pool Price energy revenue did this asset's metered MWh earn?\n- Explain the evidence associated with today's price increase.\n\n## Tools\n\n| Tool | Purpose |\n| --- | --- |\n| `get_market_snapshot` | Current market overview |\n| `get_pool_prices` | Hourly Pool Price history |\n| `get_system_marginal_prices` | Minute-level SMP history |\n| `get_load` | Alberta Internal Load |\n| `get_generation` | Fuel mix / renewable history |\n| `get_interchange` | Intertie flows |\n| `get_reserves` | Operating reserve indicators |\n| `get_outages` | Hourly generator outage capacity by fuel |\n| `get_generation_capacity` | AIES capability and outage grouping by fuel |\n| `get_load_outage_forecast` | Hourly load-outage forecast |\n| `get_energy_merit_order` | Historical energy merit-order blocks |\n| `get_unit_commitments` | Generating-unit commitment directives |\n| `get_intertie_capability` | Intertie/flowgate ATC, TTC, and margins |\n| `get_intertie_outages` | Outages affecting intertie capability |\n| `get_metered_volumes` | Metered energy by asset |\n| `get_operating_reserve_offer_control` | Historical reserve offer-control blocks |\n| `get_approved_transmission_outages` | Approved planned transmission outages |\n| `get_long_range_transmission_outages` | Tentative long-range transmission outages |\n| `get_assets` | Asset registry |\n| `get_monthly_cumulative_net_revenue` | Current MCSINR publication |\n| `get_secondary_offer_price_limit` | Current secondary offer-cap status |\n| `compare_market_periods` | Aggregate period comparison |\n| `find_price_events` | High-price event detection |\n| `explain_market_conditions` | Structured evidence (not causal prose) |\n| `compare_forecast_to_actual` | AIL forecast vs actual accuracy |\n| `summarize_market_history` | Compact hourly/daily/weekly/monthly price and load summaries |\n| `assess_supply_tightness` | Transparent reserve-adjusted supply-margin screening |\n| `get_historical_generation` | Official individual-asset CSD archive history |\n| `sync_historical_store` | Incremental local DuckDB/Parquet ingestion |\n| `get_historical_store_status` | Local coverage, manifests, and partition status |\n| `get_forecast` | Official AIL, Pool Price, wind, solar, and combined wind/solar forecasts |\n| `get_research_data` | Bounded page from one verified official historical/spatial/reliability archive |\n| `get_supply_adequacy` | Official supply-adequacy and market-supply-cushion status bands |\n| `get_supply_surplus` | Official hourly supply-surplus forecast status |\n| `get_ffr_net_schedule` | Historical scheduled FFR intertie transfer |\n| `get_dispatch_down_service` | Dispatch Down Service availability report |\n| `get_tmr_reference_price` | Published TMR reference price |\n| `get_system_events` | Bounded AIES Event Log messages |\n| `get_uc_settlement_summary` | Public hourly UC amount and charged volume |\n| `get_price_statistics` | Price distribution and volatility statistics |\n| `get_price_duration_curve` | Pool Price exceedance curve |\n| `analyze_market_event` | Focus versus baseline multi-series associations |\n| `calculate_capture_prices` | Generation-weighted price and capture rate |\n| `analyze_net_load` | AIL minus selected renewable generation |\n| `analyze_supply_stack` | Historical offer-stack analysis |\n| `analyze_intertie_utilization` | Gross-offer to capability proxy |\n| `analyze_generation_mix` | CSD energy and share by fuel |\n| `analyze_asset_dispatch` | Asset output, capacity factor, and ramps |\n| `analyze_outage_impact` | Hourly outage-price association |\n| `analyze_forecast_error` | General forecast error, percentiles, market-hour and lead-time profiles |\n| `calculate_asset_energy_revenue` | Metered MWh × Pool Price gross energy revenue |\n| `compare_csd_to_metered` | Operational CSD output versus metered MWh |\n| `analyze_ramps` | Cadence-aware AIL, net-load, renewable, or asset ramps |\n| `analyze_supply_surplus_events` | Price/load/renewable associations during explicit surplus states |\n| `get_operating_reserve_prices` | Active/standby price components and volumes |\n| `get_operating_reserve_forecast` | Seven-day reserve-volume forecast |\n| `get_operating_reserve_activations` | Hourly standby activations |\n| `summarize_operating_reserve_market` | Product price/volume/activation summary |\n| `analyze_participant_concentration` | Offered-volume shares and HHI using current participant mapping |\n| `analyze_regional_load_generation` | Planning-area and regional load/generation aggregates |\n| `analyze_constrained_volume` | Planning-area/fuel constrained MWh and optional price association |\n| `analyze_scarcity` | Historical adequacy/cushion web codes, EEA, and price context |\n| `analyze_system_frequency` | Compact six-hour 10-second frequency statistics; no raw row output |\n\nMarket and research tools are read-only. `sync_historical_store` writes only to the configured\nlocal historical-store root; it does not mutate AESO or another external system.\n\n## Resources\n\n| URI | Content |\n| --- | --- |\n| `aeso://glossary` | Market terminology |\n| `aeso://datasets` | Dataset catalog |\n| `aeso://methodology/pool-price` | Pool Price interpretation |\n| `aeso://methodology/system-marginal-price` | SMP interpretation |\n| `aeso://capabilities` | Complete tool, prompt, and resource surface |\n| `aeso://methodology/{dataset}` | Dataset-specific interpretation and caveats |\n\nPrompts: `daily_market_brief`, `investigate_price_event`, and `compare_market_days`.\n\n## Data semantics\n\n- **Timezone**: `America/Edmonton` (AESO market time). DST days may have 23 or 25 local hours.\n- **Intervals**: Explicit `interval_start` / `interval_end` (half-open ranges in requests).\n- **Units**: Pool Price / SMP → CAD/MWh; load / generation / interchange / reserves → MW.\n- **Status**: Metadata includes `actual` / `forecast` / etc. Forecasts are never implied to be settled actuals.\n- **Finality**: Operational feeds may be preliminary; do not assume final settlement.\n- **Point-in-time forecasts**: `as_of` selects only vintages with known issue/publication times at\n  or before the boundary. Unknown chronology is excluded; target intervals absent from persisted\n  history remain unobserved rather than being backfilled from a later publication.\n- **Completeness**: Metadata reports available/missing series and expected/missing observations\n  where the source cadence is known. Optional enrichment failures are surfaced as partial or\n  degraded results with warnings.\n- **Pagination**: Raw price, SMP, load, generation, and operational reports return `page` metadata\n  with `next_offset`. Use `summarize_market_history` before retrieving long raw series.\n- **Cache timing**: `retrieved_at` identifies the upstream fetch; `served_at`, `cache_hit`, and\n  `cache_age` identify when and how the response was served.\n- **Research identity**: `analyze_market_event.analysis_manifest` records exact sources,\n  parameters, methodology version, warnings, and a deterministic SHA-256 `analysis_id`.\n\n## Development\n\n```bash\nuv sync --group dev\nuv run ruff check src tests scripts\nuv run pyright src\nuv run pytest tests/unit tests/contract tests/mcp tests/evals --cov=aeso_mcp\nuv run python scripts/generate_catalog.py --check\nuv run mkdocs build --strict\nuv build\n```\n\nOptional live tests:\n\n```bash\nAESO_API_KEY=... uv run pytest tests/integration -m integration\n```\n\nMCP Inspector:\n\n```bash\n# Prefer the console entrypoint; or point Inspector at:\n# uv run aeso-mcp\nnpx @modelcontextprotocol/inspector uv run aeso-mcp\n```\n\n## Tests\n\n- `tests/unit` — time, bounds, analytics, config\n- `tests/contract` — AESO APIM fixtures via `respx`\n- `tests/mcp` — tool/resource discovery and structured outputs\n- `tests/integration` — opt-in live AESO calls\n\n## Security\n\nSee [SECURITY.md](SECURITY.md). Highlights: no arbitrary URL/shell/SQL tools, host allow-list, secret hygiene, bounded queries, stderr logging for stdio.\n\n## Development status\n\nVersion 0.3.0 includes the historical store, full CSD generation adapter, official forecast/report\nproviders, general research analytics, operating-reserve market surface, eval suite, and\ndocumentation site. Unreleased work adds point-in-time forecast vintages, reproducibility\nmanifests, release-policy hardening, and the verified official research-data archive.\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md).\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n\n## Disclaimer\n\nThis project is an independent open-source interface to publicly documented AESO APIs. It is **not** an official AESO product and is **not affiliated with or endorsed by AESO**. Market data may be preliminary or incomplete; verify critical decisions against official AESO publications.\n",
  "bytes": 19836,
  "sha": "f9fa1152693006463ac16800f4361cf1c3d8337e8792fd4b797c3c0cd6770eab",
  "repo_slug": "bchoi-qwe/aeso-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_bchoi_qwe_aeso_mcp_edda82ab/readme"
}