Skip to main content
Glama
franklan-pm

eia-energy-data-mcp

by franklan-pm
README.md
# EIA Energy Data MCP Server

An MCP server that wraps the U.S. Energy Information Administration's
Open Data API (v2), so an MCP-aware assistant can pull live energy data
through natural conversation instead of you writing API calls by hand.

It exposes four tools:

| Tool | What it does |
|---|---|
| `get_series(series_id)` | Pull a well-known series by its classic EIA id, e.g. `"PET.RBRTE.D"` for daily Brent crude prices. Fastest option when you already know the id. |
| `browse_routes(route)` | Explore what data exists. Call with `route=""` for top-level categories (electricity, petroleum, natural-gas, coal...), then drill down. |
| `list_facet_values(route, facet_id)` | List valid filter values for a dataset, e.g. all state codes or sector codes. |
| `get_data(route, data_columns, facets, ...)` | Run a full custom query — any dataset, any filters, any date range. |

This was verified against EIA's current API documentation
(https://www.eia.gov/opendata/documentation.php) and tested against the
current official MCP Python SDK (`mcp` v2.0.0) before being published.

---

## 1. Prerequisites

- **Python 3.10+** installed on your computer.
- **An MCP-aware client that supports local (stdio) servers.** This
  includes Claude Desktop, VS Code (1.101+), Cursor, and Windsurf, among
  others. It runs as a local process on your machine — it does not run
  inside claude.ai's browser-based chat, which can't launch local
  subprocesses.
- **Your own EIA API key** — free at
  https://www.eia.gov/opendata/register.php.

## 2. Set up the project

Open a terminal, then:

```bash
git clone https://github.com/YOUR_GITHUB_USERNAME/eia-energy-data-mcp.git
cd eia-energy-data-mcp
pip install -r requirements.txt
cp .env.example .env
# then edit .env and add your own EIA_API_KEY
```

> Note: one important thing worth knowing — the official MCP Python SDK
> renamed its main server class from `FastMCP` to `MCPServer` in the 2.x
> line. If you see older tutorials online using
> `from mcp.server.fastmcp import FastMCP`, that import path no longer
> exists in the current SDK. This project already uses the current,
> correct import (`from mcp.server.mcpserver import MCPServer`), so you
> don't need to do anything — just worth knowing if you go looking at
> other examples.

## 3. Test it runs

```bash
EIA_API_KEY=your_real_key_here python server.py
```

If it starts without errors and just sits there waiting, that's correct —
an MCP server communicates over stdio and expects a client to talk to it,
not a human. Press Ctrl+C to stop it.

## 4. Connect it to a client

### Claude Desktop

Open Claude Desktop's config file:

- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`

Add an entry like this (create the file if it doesn't exist), replacing
the path and key with your own:

```json
{
  "mcpServers": {
    "eia-energy-data": {
      "command": "python",
      "args": ["/absolute/path/to/eia-energy-data-mcp/server.py"],
      "env": {
        "EIA_API_KEY": "your_real_key_here"
      }
    }
  }
}
```

Restart Claude Desktop. You should see "eia-energy-data" listed as a
connected tool (usually via a small hammer/plug icon in the chat box).

### VS Code, Cursor, Windsurf, and other MCP hosts

Most hosts use the same `mcpServers` JSON shape shown above, added to
their own settings file or MCP config panel. Consult your client's docs
for the exact file location — the `command`, `args`, and `env` fields are
typically identical to the Claude Desktop example.

## 5. Try it

Once connected, just ask things like:

- "What's the daily Brent crude oil price trend for the last month?"
  → calls `get_series("PET.RBRTE.D")`.
- "Show me residential electricity prices in Colorado, monthly, for 2023."
  → calls `browse_routes` to confirm the route/facets, then
  `get_data(route="electricity/retail-sales", data_columns=["price"],
  facets={"stateid": ["CO"], "sectorid": ["RES"]}, frequency="monthly",
  start="2023-01", end="2023-12")`.
- "What energy datasets does EIA have on natural gas?"
  → calls `browse_routes("natural-gas")`.

## Notes on the EIA API itself

- Max 5,000 rows per request (300 for XML — we always request JSON).
- Legacy v1 series IDs (like `PET.RBRTE.D`) still work via the
  `/v2/seriesid/{id}` compatibility route — that's what `get_series` uses.
- Everything else in v2 is organized as a browsable hierarchy of routes,
  each with its own facets (filters), data columns, and frequency options
  — that's what `browse_routes` and `get_data` are for.
- Rate limits apply per API key; if you hammer it with rapid recursive
  calls your key can be temporarily throttled (it recovers on its own).

## Security

This server reads your API key from the `EIA_API_KEY` environment
variable — it is never hardcoded or logged. `.env` is gitignored;
`.env.example` is a template only and contains no real key. Use your own
key, and don't commit a `.env` file to a public fork.

## Extending this

Ideas if you want to keep building:
- Add a `search_series` tool once you find data columns you query often,
  hardcoding common routes as shortcuts.
- Add caching (e.g. a simple dict with a TTL) since energy series update
  at most daily.
- Add a resource (not just tools) that exposes a curated list of
  interesting series ids as a static reference the model can read.

## License

MIT — see [LICENSE](./LICENSE).