@cyanheads/eia-energy-mcp-server
Enables use of Cloudflare KV, R2, or D1 as a storage backend for persistent state.
Enables tabular data spillover and SQL querying via DuckDB-powered DataCanvas for large result sets.
Provides optional OpenTelemetry tracing for observability.
Enables use of Supabase as a storage backend for persistent state.
Click on "Install 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., "@@cyanheads/eia-energy-mcp-serverFind electricity net generation data for California in 2022"
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.
Public Hosted Server: https://eia-energy.caseyjhand.com/mcp
Tools
Seven tools covering the two-phase EIA workflow — find the right dataset route, pull the data, and query spilled results via SQL:
Tool | Description |
| Lists child routes under a given path in the EIA dataset taxonomy. Start at root to see top-level categories, then drill into subcategories and leaf routes. |
| Returns full metadata for a leaf route: available facets with valid values, data column names, frequency options, units, and date range. Call before |
| Fuzzy text search across route names, descriptions, and category labels. Resolves natural-language queries like "gasoline retail prices" or "solar capacity by state" to matching route paths. |
| Fetches data from a leaf route with optional facet filters, date range, frequency, and column selection. Spills large result sets to a DataCanvas table for SQL analysis. |
| Lists active DataCanvas dataframes created by prior |
| Runs a read-only SQL SELECT against a DataCanvas dataframe by canvas ID or table name. |
| Drops a DataCanvas dataframe, freeing its memory. Only exposed when |
eia_browse_routes
Walk the EIA dataset taxonomy from root to leaf.
Root call returns 14 top-level categories: electricity, petroleum, natural-gas, coal, international, total-energy, steo, aeo, ieo, seds, crude-oil-imports, nuclear-outages, densified-biomass, co2-emissions
Intermediate paths return subcategories; leaf routes are flagged so callers know when to switch to
eia_describe_routeSTEO(Short-Term Energy Outlook) is a flat leaf with 1,469 named series — no sub-routes
eia_describe_route
Full schema for a leaf route. Required before constructing facet filters.
Returns facets with valid values (fetched via per-facet API calls and cached in-process)
Returns data column names, units, frequency options, and date range
eia_search_routesandeia_browse_routesresolve the route path; this tool provides the filter vocabulary
eia_search_routes
Fuzzy search across the in-memory route index.
Indexes route names, descriptions, and category labels — plus STEO's 1,469 series names
Resolves natural language ("natural gas spot prices", "ethanol net imports") to queryable route paths
Route tree is cached in-process at first call; subsequent searches hit the Fuse.js index with no upstream cost
eia_query_route
Pull data from a leaf route.
Facet filters keyed by facet ID (e.g.
{ "stateid": "TX", "sectorid": ["RES", "COM"] })Date range and frequency selection; valid values discoverable via
eia_describe_routePagination via
offset/length(max 5,000 rows per page); total row count in responseAll numeric values arrive as strings from the EIA API — units appear as inline
{col}-unitsfields per rowDataCanvas spillover when result set exceeds
length: returnscanvas_idfor SQL queries over the full dataset
Related MCP server: aemo-mcp
Features
Built on @cyanheads/mcp-ts-core:
Declarative tool definitions — single file per tool, framework handles registration and validation
Unified error handling — handlers throw, framework catches, classifies, and formats
Pluggable auth:
none,jwt,oauthSwappable storage backends:
in-memory,filesystem,Supabase,Cloudflare KV/R2/D1Structured logging with optional OpenTelemetry tracing
STDIO and Streamable HTTP transports
EIA-specific:
Full coverage of EIA API v2 — all 14 top-level dataset categories
In-process route tree cache with Fuse.js fuzzy index — built once at startup, no repeated upstream calls
Per-route facet cache via
Promise.allfan-out — valid filter values available without re-fetchingSTEO series names (1,469 entries) indexed for natural-language discovery
DataCanvas (DuckDB) opt-in for tabular spillover — graceful degradation when unavailable
Getting started
Get a free API key at api.eia.gov, then add the following to your MCP client configuration file.
{
"mcpServers": {
"eia-energy-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/eia-energy-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"EIA_API_KEY": "your-api-key"
}
}
}
}Or with npx (no Bun required):
{
"mcpServers": {
"eia-energy-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/eia-energy-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"EIA_API_KEY": "your-api-key"
}
}
}
}Or with Docker:
{
"mcpServers": {
"eia-energy-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"-e", "EIA_API_KEY=your-api-key",
"ghcr.io/cyanheads/eia-energy-mcp-server:latest"
]
}
}
}For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 EIA_API_KEY=your-key bun run start:http
# Server listens at http://localhost:3010/mcpPrerequisites
Bun v1.3.0 or higher (or Node.js v24+).
A free EIA API key from api.eia.gov. The
DEMO_KEYhits rate limits quickly; a real key is required for sustained use.
Installation
Clone the repository:
git clone https://github.com/cyanheads/eia-energy-mcp-server.gitNavigate into the directory:
cd eia-energy-mcp-serverInstall dependencies:
bun installConfigure environment:
cp .env.example .env
# edit .env and set required vars (at minimum, EIA_API_KEY)Configuration
All configuration is validated at startup via Zod schemas in src/config/server-config.ts. Key environment variables:
Variable | Description | Default |
| Required. Free API key from api.eia.gov — appended as | — |
| EIA API base URL. |
|
| Per-table TTL for DataCanvas dataframes in seconds. |
|
| Set to |
|
| Set to | — |
| Transport: |
|
| HTTP server port. |
|
| HTTP endpoint path. |
|
| Public origin override for TLS-terminating reverse-proxy deployments. | — |
| Auth mode: |
|
| Log level (RFC 5424). |
|
| Directory for log files (Node.js only). |
|
| Storage backend: |
|
| Enable OpenTelemetry instrumentation. |
|
Running the server
Local development
Build and run:
# One-time build bun run rebuild # Run the built server bun run start:stdio # or bun run start:httpRun checks and tests:
bun run devcheck # Lint, format, typecheck, security bun run test # Vitest test suite bun run lint:mcp # Validate MCP definitions against spec
Project structure
Directory | Purpose |
|
|
| Server-specific environment variable parsing and validation with Zod. |
| Tool definitions ( |
| EIA API v2 service — route tree cache, Fuse.js index, facet fan-out, HTTP client. |
| DataCanvas bridge — registers EIA query results as DuckDB dataframes, routes SQL queries. |
| Unit and integration tests mirroring |
| Design documents ( |
Development guide
See CLAUDE.md for development guidelines and architectural rules. The short version:
Handlers throw, framework catches — no
try/catchin tool logicUse
ctx.logfor request-scoped logging,ctx.statefor tenant-scoped storageAlways call
eia_describe_routebeforeeia_query_route— facet values require a separate API fan-out and are not embedded in route metadataWrap EIA responses: validate raw → normalize to domain type → return output schema; data values are strings — never coerce silently
Contributing
Issues and pull requests are welcome. Run checks and tests before submitting:
bun run devcheck
bun run testLicense
Apache-2.0 — see LICENSE for details.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/cyanheads/eia-energy-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server