@Cyanheads/Eia Energy Server
БесплатноНе проверенBrowse and query the U.S. Energy Information Administration API v2 — electricity, petroleum, natural gas, coal, forecasts, and more via MCP. STDIO or Streamable
Описание
Browse and query the U.S. Energy Information Administration API v2 — electricity, petroleum, natural gas, coal, forecasts, and more via MCP. STDIO or Streamable HTTP.
README
@cyanheads/eia-energy-mcp-server
Browse and query the U.S. Energy Information Administration API v2 — electricity, petroleum, natural gas, coal, forecasts, and more via MCP. STDIO or Streamable HTTP.
Version License Docker MCP SDK npm TypeScript Bun
Install in Claude Desktop Install in Cursor Install in VS Code
Public Hosted Server: https://eia-energy.caseyjhand.com/mcp
Overview
Energy data from the U.S. Energy Information Administration (EIA) API v2 — electricity, petroleum, natural gas, coal, and forecasts. Browse the dataset taxonomy, search it by natural language, and query time-series data with facet filters, then stage large result sets as a SQL-queryable DataCanvas table. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.
Tools
| Tool | Description |
|---|---|
eia_browse_routes |
Lists child routes under a path in the EIA dataset taxonomy; omit path for the 14 top-level categories. |
eia_describe_route |
Returns a leaf route's facets, valid values, data columns, frequencies, and date range. |
eia_search_routes |
Fuzzy text search across route names, descriptions, STEO series names, and facet values. |
eia_query_route |
Fetches data from a leaf route with facet filters, date range, and column selection; optionally stages results for SQL. |
eia_dataframe_describe |
Lists active DataCanvas dataframes staged by eia_query_route, with schema and provenance. |
eia_dataframe_query |
Runs a read-only SQL SELECT against staged DataCanvas dataframes. |
eia_dataframe_drop |
Drops a DataCanvas dataframe, freeing its memory. |
The three eia_dataframe_* tools are registered only when CANVAS_PROVIDER_TYPE=duckdb is set; eia_dataframe_drop additionally requires EIA_DATAFRAME_DROP_ENABLED=true. A default deployment lists the first four tools.
Capability reference
eia_browse_routes tool
- Omit
pathfor the 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); pass a path to drill into subcategories - Each child carries
isLeaf— leaf routes are queryable viaeia_describe_route/eia_query_route; non-leaf routes have further children to browse steois a flat leaf with 1,469 named series and no sub-routes- Accepts
routeas an alias forpath; supplying both is rejected. Leading, trailing, and doubled slashes are stripped before resolving route_not_foundwhen the path does not exist in the taxonomy
eia_describe_route tool
- Returns facets (with valid values), data column names/units, frequency options, and date range for a leaf
route; acceptspathas an alias, but not alongsideroute - Each facet is capped at
EIA_FACET_VALUE_CAPvalues (default 50), withvalue_countandvalues_truncated; page one facet withfacet+values_offset - A
values_offsetpast a facet's last value returns an empty window plus anoticenaming the facet and itsvalue_count, rather than reading as an exhausted enumeration - Errors:
route_not_found,route_not_queryable(category node, not a leaf),facet_not_found,rate_limited(retryable)
eia_search_routes tool
- Fuzzy match over route names/descriptions, STEO's 1,469 series names, and facet values;
limitcaps results (default 10, max 30) scoreruns 0 (exact) to 1 (no match); above 0.72 is a weak match — narrow the query or useeia_browse_routes- Matching facet-value or STEO results carry
filter_hint, a ready-to-use filter object foreia_query_route - The first call after server start waits 24–30 s (never more than 45 s) for the index to warm; every later call is served from the in-process index in milliseconds
indexComplete/indexGapsreport whether the corpus was complete when scored — check before trusting a short result set
eia_query_route tool
- Takes
route(or aliaspath, never both), facet filters keyed by facet ID (fromeia_describe_route), plus optionalcolumns,frequency,start/end, andsort offset/lengthpage the inline preview (lengthdefault 100, max 5000 per EIA's per-request ceiling);totalreports the full match count- Data values arrive as strings; per-column units appear as inline
{col}-unitsfields stage: truepages past the preview and stages the accumulated rows as a DataCanvasdf_<id>table (bounded byEIA_CANVAS_MAX_ROWS, default 25000) foreia_dataframe_query; omitted, the call costs one upstream request regardless oftotal- Errors:
route_not_found,route_not_queryable,invalid_facet/invalid_column/invalid_frequency/invalid_sort/invalid_period,no_data(inverted date range),rate_limited(retryable)
eia_dataframe_describe tool
- Lists DataCanvas dataframes staged by prior
eia_query_routecalls withstage: true; only registered whenCANVAS_PROVIDER_TYPE=duckdb - Omit
nameto list every active dataframe for the tenant; passnameto check one — a miss comes back asfound: falsealongsideactive_names, never as an empty list - Each entry reports
source_tool,query_params,created_at,expires_at,row_count,truncated/max_rows, andcolumn_schema - Listing does not extend a dataframe's expiry — only an
eia_dataframe_querystatement referencing it does canvas_unavailablewhen no canvas is configured
eia_dataframe_query tool
- Runs one read-only SQL SELECT against
df_<id>tables; writes, DDL,DROP,COPY,PRAGMA,ATTACH, and system catalogs (information_schema,pg_catalog,sqlite_master,duckdb_*) are rejected row_limit(default 1000, max 10000) hard-caps materialized rows — rows past it are dropped uncounted, sototalRowsbecomes the cap, not a true total;previewseparately narrows the inline slice without affecting the countregister_aspersists the result as a new dataframe with a fresh expiry; the name must be unused- EIA data columns are VARCHAR — cast with
CAST(col AS DOUBLE)for arithmetic - Errors:
canvas_unavailable,system_catalog_access,missing_table,non_select_statement,invalid_sql,register_as_clash
eia_dataframe_drop tool
- Drops a dataframe by
name; idempotent — returnsdropped: falsewhen nothing matched - Only registered when
EIA_DATAFRAME_DROP_ENABLED=trueandCANVAS_PROVIDER_TYPE=duckdb - Manual cleanup only — the per-dataframe expiry (default 24 h, extended by every referencing query) handles cleanup in normal operation
canvas_unavailablewhen no canvas is configured
Features
Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
EIA-specific:
- Full coverage of EIA API v2's 14 top-level dataset categories, via an in-process route tree cache built once on first use
- Fuzzy search index (Fuse.js) covers route names/descriptions, all 1,469 STEO series names, and facet values for natural-language discovery
- Per-route facet metadata is fetched by fan-out (
Promise.all) and cached, soeia_query_routefilters are validated without re-fetching - A route whose metadata could not be fetched is held as an incomplete stub — reported through
eia_search_routesrather than silently dropped — and re-fetched on the nexteia_browse_routescall that reaches it - DataCanvas (DuckDB) staging is opt-in per call; the three dataframe tools are gated at registration so a canvas-less deployment lists no tool it cannot serve
Agent-friendly output:
- Provenance —
eia_query_routeechoes the canonical, slash-normalized route rather than the caller's spelling, and every staged dataframe records itssource_toolandquery_params - Capped-window disclosure — every truncatable response (facet values, row previews, SQL row limits) reports the count against its cap and a
noticenaming the exact next call to page past it - Discriminated failure — typed error
reasonvalues (e.g.route_not_queryable,invalid_facet,missing_table) each carry arecoveryhint naming the next tool call
Getting started
Public Hosted Instance
A public instance is available at https://eia-energy.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"eia-energy-mcp-server": {
"type": "streamable-http",
"url": "https://eia-energy.caseyjhand.com/mcp"
}
}
}
Self-Hosted / Local
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/mcp
Prerequisites
- Bun v1.4.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.git
- Navigate into the directory:
cd eia-energy-mcp-server
- Install dependencies:
bun install
- Configure 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 |
|---|---|---|
EIA_API_KEY |
Required. Free API key from api.eia.gov — appended as api_key on every request. |
— |
EIA_BASE_URL |
EIA API base URL. | https://api.eia.gov/v2 |
EIA_DATASET_TTL_SECONDS |
Sliding per-dataframe TTL in seconds. The window is extended every time an eia_dataframe_query statement references the dataframe, so a dataframe stays alive through a long analysis and lapses only once it goes unused for the full interval. Listing it with eia_dataframe_describe is not use and does not extend it. |
86400 (24 h) |
EIA_DATAFRAME_DROP_ENABLED |
Set to true to expose eia_dataframe_drop, which also requires CANVAS_PROVIDER_TYPE=duckdb. Off by default to avoid accidental canvas cleanup. |
false |
EIA_CANVAS_MAX_ROWS |
Cumulative row ceiling for eia_query_route canvas staging — five requests at EIA's 5,000-row-per-request ceiling, adding ~8.5 s to a call when it binds. Lower it for snappier exploration, raise it for wider staged analyses. |
25000 |
EIA_FACET_VALUE_CAP |
Facet values eia_describe_route returns per facet before truncating. Bounds the response on high-cardinality facets — STEO's seriesId alone has 1,469 values. Page past it with the tool's facet and values_offset inputs. |
50 |
CANVAS_PROVIDER_TYPE |
Set to duckdb to enable DataCanvas (Node only). Adds the three eia_dataframe_* tools to the surface and lets eia_query_route stage rows when called with stage: true. |
— |
MCP_TRANSPORT_TYPE |
Transport: stdio or http. |
stdio |
MCP_HTTP_PORT |
HTTP server port. | 3010 |
MCP_HTTP_ENDPOINT_PATH |
HTTP endpoint path. | /mcp |
MCP_SESSION_MODE |
HTTP sessions: stateless, stateful, or auto (framework schema default, resolves to stateful). This server defaults to stateless; an explicit environment value overrides it. |
stateless |
MCP_PUBLIC_URL |
Public origin override for TLS-terminating reverse-proxy deployments. | — |
MCP_AUTH_MODE |
Auth mode: none, jwt, or oauth. |
none |
MCP_LOG_LEVEL |
Log level (RFC 5424). | info |
LOGS_DIR |
Directory for log files (Node.js only). | <project-root>/logs |
STORAGE_PROVIDER_TYPE |
Storage backend: in-memory, filesystem, supabase, cloudflare-kv/r2/d1. |
in-memory |
OTEL_ENABLED |
Enable OpenTelemetry instrumentation. | false |
See .env.example for the full list of optional overrides.
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
Docker
docker build -t eia-energy-mcp-server .
docker run --rm -e EIA_API_KEY=your-key -p 3010:3010 eia-energy-mcp-server
The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/eia-energy-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
Project structure
| Directory | Purpose |
|---|---|
src/index.ts |
createApp() entry point — registers tools and inits services. |
src/config |
Server-specific environment variable parsing and validation with Zod. |
src/mcp-server/tools |
Tool definitions (*.tool.ts) — browse, describe, search, query, and three DataCanvas dataframe tools. |
src/services/eia |
EIA API v2 service — route tree cache, Fuse.js index, facet fan-out, HTTP client. |
src/services/canvas-bridge |
DataCanvas bridge — registers EIA query results as DuckDB dataframes, routes SQL queries. |
tests/ |
Unit and integration tests mirroring src/. |
docs/ |
Design documents (design.md, idea.md). |
Development guide
See CLAUDE.md for development guidelines and architectural rules. The short version:
- Handlers throw, framework catches — no
try/catchin tool logic - Use
ctx.logfor request-scoped logging,ctx.statefor tenant-scoped storage - Always call
eia_describe_routebeforeeia_query_route— facet values require a separate API fan-out and are not embedded in route metadata - Wrap EIA responses: validate raw → normalize to domain type → return output schema; data values are strings — never coerce silently
Contributing
Issues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
License
Apache-2.0 — see LICENSE for details.
Установка @Cyanheads/Eia Energy Server
У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.
▸ github.com/cyanheads/eia-energy-mcp-serverFAQ
@Cyanheads/Eia Energy Server MCP бесплатный?
Да, @Cyanheads/Eia Energy Server MCP бесплатный — установка в пару кликов через Unyly без оплаты.
Нужен ли API-ключ для @Cyanheads/Eia Energy Server?
Нет, @Cyanheads/Eia Energy Server работает без API-ключей и переменных окружения.
@Cyanheads/Eia Energy Server — hosted или self-hosted?
Доступен hosted-вариант: Unyly запускает сервер в облаке, локальная установка не обязательна.
Как установить @Cyanheads/Eia Energy Server в Claude Desktop, Claude Code или Cursor?
Открой @Cyanheads/Eia Energy Server на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.
Похожие MCP
GitHub
PRs, issues, code search, CI status
автор: GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
автор: mcpdotdirectAmap Maps Mcp Server
MCP server for using the AMap Maps API
автор: duxiaohuiSupabase
Database, auth and storage
автор: SupabaseEverything
Reference / test server with prompts, resources, and tools.
Git
Tools to read, search, and manipulate Git repositories.
Sequential Thinking
Dynamic and reflective problem-solving through thought sequences.
Time
Time and timezone conversion capabilities.
Compare @Cyanheads/Eia Energy Server with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории development
