关于 eia-mcp-server
eia-mcp-server 将美国能源信息署(EIA)API v2 的能源数据提供给分析人员和研究者。它结合数据路由发现与筛选,并可对暂存结果执行 SQL 查询。
主要功能
- 01浏览并描述 EIA 数据路由
- 02搜索系列、路由和维度值
- 03按筛选条件和日期范围查询能源数据
- 04暂存结果以进行只读 SQL 分析
适用场景
- 01查找特定能源指标的数据集
- 02获取电力或燃料时间序列
- 03用 SQL 分析大型查询结果
MCP 相关
向 MCP 客户端提供 EIA API v2 的发现、搜索和查询工具,并可通过 DataCanvas 工具对暂存数据执行 SQL。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y @cyanheads/eia-mcp-serverEIA_API_KEY密钥Free API key from api.eia.gov. Required — all requests use this as the api_key query parameter.EIA_DATASET_TTL_SECONDSPer-table TTL for DataCanvas dataframes in seconds.EIA_DATAFRAME_DROP_ENABLEDSet to 'true' to expose eia_dataframe_drop for manual canvas cleanup.CANVAS_PROVIDER_TYPESet to 'duckdb' to enable DataCanvas spillover for large query result sets (Node.js only).MCP_LOG_LEVELSets the minimum log level for output (e.g., 'debug', 'info', 'warn').MCP_HTTP_HOSTThe hostname for the HTTP server.MCP_HTTP_PORTThe port to run the HTTP server on.MCP_HTTP_ENDPOINT_PATHThe endpoint path for the MCP server.MCP_PUBLIC_URLPublic origin override for deployments behind a TLS-terminating reverse proxy (e.g. https://mcp.example.com).MCP_AUTH_MODE密钥Authentication mode to use: 'none', 'jwt', or 'oauth'.本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
@cyanheads/eia-energy-mcp-server
通过 MCP 浏览和查询美国能源信息署 API v2——电力、石油、天然气、煤炭、预测等数据。支持 STDIO 或 Streamable HTTP。
概述
美国能源信息署(EIA)的美国能源数据:电力、石油、天然气、煤炭和预测。通过自然语言查找数据集,使用分面筛选条件查询时间序列,并对大型结果运行 SQL。
工具
| 工具 | 描述 |
|---|---|
eia_browse_routes | 列出 EIA 数据集分类体系中某个路径下的子路径;省略 path 可查看 14 个顶层类别。 |
eia_describe_route | 返回叶子路径的分面、有效值、数据列、频率和日期范围。 |
eia_search_routes | 在路径名称、描述、STEO 和 SEDS 序列名称以及分面值中进行模糊文本搜索,包括 Henry Hub、WTI 和 Cushing 等基准序列。将旧版 APIv1 序列 ID(PET.RWTC.W)解析为对应路径及筛选条件。 |
eia_query_route | 使用分面筛选条件、日期范围和列选择,从叶子路径获取数据;也可选择将结果暂存以供 SQL 使用。 |
eia_dataframe_describe | 列出由 eia_query_route 暂存的活动 DataCanvas 数据帧,并提供架构和来源信息。 |
eia_dataframe_query | 对暂存的 DataCanvas 数据帧运行只读 SQL SELECT 查询。 |
eia_dataframe_drop | 删除 DataCanvas 数据帧,释放其占用的内存。 |
这三个 eia_dataframe_* 工具需要 DataCanvas;默认情况下已启用;eia_dataframe_drop 还需要 EIA_DATAFRAME_DROP_ENABLED=true。在 Claude Desktop 捆绑包设置的 CANVAS_PROVIDER_TYPE=none 情况下,这些工具既无法调用,也不会由 MCP 列出。已禁用的定义仍会保留在服务清单中,并附带启用提示。默认部署会列出前六个工具。
功能参考
浏览工具接受 route 作为 path 的别名;描述和查询工具接受 path 作为 route 的别名。若同时提供两种写法,将被拒绝。空白字符和斜杠会被规范化,随后只移除一个完整的前导 v2 段:/v2/electricity/retail-sales/ 会解析为 electricity/retail-sales,而 /v2/ 会浏览根目录。完整 URL、/data 后缀、路径中间的 v2 和大小写均保持不变。
所有四个路径工具都会区分可重试的上游故障:HTTP 429 或 OVER_RATE_LIMIT 对应 rate_limited;传输故障对应 upstream_unreachable;HTTP 服务中断对应 upstream_unavailable;响应正文不可用或缺少信封对应 upstream_invalid_response;EIA 未能及时响应对应 upstream_timeout。每次尝试的时限为 45 s;一次调用中的各次尝试、退避和链式请求共用 56 s 的时限,低于 MCP 客户端采用的 60 s 超时。恢复提示会显示在两种响应界面中。HTTP 501 仍视为确定性错误,504 仍视为超时,调用方取消操作仍视为取消。
eia_browse_routes 工具
- 省略
path可查看 14 个顶层类别;传入路径可浏览其子项。 - 每个子项都带有
isLeaf:叶子路径使用 describe 和 query;类别则继续浏览。 - 缺失路径会返回
route_not_found;EIA 限流、无法访问或未能及时响应时,会返回可重试的rate_limited、upstream_unreachable或upstream_timeout。
eia_describe_route 工具
- 传入叶子
route,可获取分面、数据列、频率和日期范围。每个分面窗口的上限为EIA_FACET_VALUE_CAP(默认值为 50);可使用facet和values_offset分页。 - 若要在大型分面中按名称查找值(电厂、实体和矿井 ID 数以千计),请传入
values_query:每个分面会保留id、name或alias中包含该字符串的值,且不区分大小写;使用values_offset对匹配项分页。在electricity/facility-fuel的plantCode上传入values_query: "palo verde",一次调用即可返回6008和57773。 date_range是默认频率的元数据;其他频率的日期范围可能超出该范围。两种响应界面都会在未更改的起止值旁注明这一点。value_count、values_truncated以及在使用values_query时的values_matched,用于描述各个窗口。若 EIA 未返回某个分面的值,该分面会列在unavailable_facets中;下一次调用会重试该分面。- 错误:
route_not_found、route_not_queryable、facet_not_found,以及可重试的facet_unavailable、rate_limited、upstream_unreachable、upstream_timeout。
eia_search_routes 工具
- 搜索路由名称、描述、STEO 的 1,469 个和 SEDS 的 968 个序列名称,以及分面值。在描述任何路由之前,分面值涵盖燃料、行业、技术和煤炭等级词汇、RTO 平衡机构(
Electric Reliability Council of Texas→respondent: ERCO),以及每日和每周石油与天然气路由的序列和产品名称(Henry Hub→natural-gas/pri/fut、series: RNGWHHD);描述路由时还会添加该路由自身的分面值。limit默认为 10;大于 30 的正整数会被限制为 30,并披露请求值和实际采用值,即使结果较少或为空也一样。存在更多匹配项时,truncated为 true。搜索的query仅取前 256 个字符,截断时会显示提示。 - 匹配项包含
score(0 表示精确匹配,1 表示无匹配;大于 0.72 表示匹配较弱),也可能包含供eia_query_route使用的filter_hint。在信任较短的结果集之前,请先检查indexComplete和indexGaps。 - EIA 网站和 Excel 加载项使用的旧版 APIv1 序列 ID,会先通过 EIA 的
/v2/seriesid查询进行解析,再进行任何文本搜索,无论大小写:ELEC.PRICE.TX-RES.M会返回一个结果,即electricity/retail-sales,并附带filter_hint{sectorid: "RES", stateid: "TX"}、frequency: "monthly"和columns: ["price"],可直接用于eia_query_route。命中不需要索引,因此即使服务刚启动,也能在不到一秒内返回。如果 EIA 自身的查询报告该映射没有行(部分 AEO ID 属于这种情况),提示会说明查询将返回空结果。EIA 无法识别的 ID(PET.ZZZZZZ.W或看起来像 ID 的U.S.A)会返回文本搜索结果,并附带说明;查询超时、受到速率限制或遇到服务中断时也会如此,并附带重试提示,而不会报错。 - 首次搜索会构建索引,通常需要 20–40 秒(最长 45 秒);之后的搜索会从已构建的索引中返回结果。如果 EIA 限制请求速率、无法访问或未能及时响应,调用会失败,并返回可重试的
rate_limited、upstream_unreachable或upstream_timeout。
eia_query_route 工具
- 传入叶级
route,以及可选的 facet IDfilters、columns、frequency、start/end和sort。使用offset和length分页(默认值为 100;超过 5000 的正整数会限制为 5000,并附带提示)。 - 响应大小不超过 64,000 字节:页面可能会在最后一整行处提前结束,以确保不超出限制;
next_offset会给出继续读取的位置。若单行过大而无法容纳,则会跳过该行,提示中会给出用于跳过它的偏移量。 describe缓存完整的 facet 词汇表后,查询提示会指出未匹配的筛选值,并在可能时建议区分大小写的 ID。筛选条件及其回显保持不变;诊断不会获取元数据或 facet 值。- 对于有效频率为月度的
YYYY-MM数据,仅指定年份的边界表示 1 月:end: "2021"会在2021-01截止;若要覆盖全年,请使用2021-12。对于任一边界,查询提示都会说明这一点,但不会展开该边界。 - EIA 会将每个边界视为其首日所属的有效频率周期,因此在月度频率下,
start: "2023-01", end: "2023"会返回 1 月。仅当 EIA 未返回任何行,且start选定的周期晚于end时,才会将范围报告为倒置(no_data);消息会指出两个周期。对于local-hourly,每个边界都必须包含小时和 UTC 偏移量(2024-02-01T02-06);缺少其中任一项时,会在发出任何请求前报错为invalid_period。如果边界指定的日期或小时在其频率精确读取的形状中不存在,也会报错,例如daily或weekly频率下的2024-02-30,以及hourly频率下的2024-02-01T24;对于这些情况,EIA 返回的是 HTTP 500,而不是数据行。 total报告完整的匹配数;值仍以字符串表示,单位以{col}-units的形式出现。错误涵盖无效的 route、facet、列、频率、排序或周期,倒置范围(no_data),筛选列表过长、超出 EIA 约 8 KB 请求 URI 限制(uri_too_long;请将值拆分到多次调用中),以及可重试的rate_limited、upstream_unreachable和upstream_timeout。stage: true会将最多EIA_CANVAS_MAX_ROWS(默认 25000)行暂存为用于 SQL 的dataset句柄,供eia_dataframe_describe和eia_dataframe_query使用(列名中的连字符会替换为下划线)。如果暂存失败,则不会返回dataset,并会在提示中说明。若暂存过程会超出调用截止时间,则会在请求下一页之前停止,暂存已获取的行,并在提示中说明时间已耗尽,同时给出可继续读取的偏移量。
eia_dataframe_describe 工具
- 省略
name可列出当前有效的暂存 dataframe;传入句柄可查看单个 dataframe。未找到时会返回found: false及active_names。 - 条目包含
source_tool、query_params、created_at、expires_at、row_count、truncated/max_rows和column_schema。列出条目不会延长过期时间。
eia_dataframe_query 工具
- 对暂存句柄运行一条只读 SQL SELECT。
row_limit默认值为 1000;preview用于缩小内联结果的范围,并接受 0。任一输入中的整数超过 10000 时,都会限制为 10000,并披露请求值和实际采用的值;每个输出面的 64,000 字节限制可能会导致行数更早截断。register_as仍会暂存完整结果。 truncated: true表示totalRows是上限,而非完整计数。register_as会使用未占用的名称暂存完整结果,并提供精确计数;提示中会给出用于分页读取剩余结果的ORDER BY … LIMIT/OFFSET查询。- 对 EIA VARCHAR 值进行算术运算前,请先转换其类型。写入、读取文件和访问系统目录均会被拒绝;声明的失败包括
missing_table、invalid_sql、non_select_statement、denied_function、multi_statement、sql_read_only、system_catalog_access和register_as_clash。
eia_dataframe_drop 工具
- 传入
name可移除暂存的 dataframe;需要EIA_DATAFRAME_DROP_ENABLED=true。 - 未匹配到任何内容时会返回
dropped: false;删除失败时会返回可重试的canvas_drop_failed,且 dataframe 会继续保持暂存状态。清理为可选操作:未使用的 dataframe 会在 24 h 后过期。
功能
基于 @cyanheads/mcp-ts-core 构建:支持 stdio 和 Streamable HTTP 传输、可插拔的身份验证(none / jwt / oauth)、可替换的存储(in-memory、filesystem、Supabase、Cloudflare KV/R2/D1),以及支持可选 OpenTelemetry 跟踪的结构化日志。
EIA 专属功能:
- 覆盖 EIA API v2 的全部 14 个顶级数据集类别,并在进程内缓存路由树
- 对路由名称和描述、全部 1,469 个 STEO 和 968 个 SEDS 系列名称以及分面值进行模糊搜索(Fuse.js)——其中包含 1,753 个基准石油和天然气系列名称及 RTO 平衡机构,并在预热时建立索引
eia_describe_route会按路由获取并缓存分面值;如果 EIA 未返回某个列表,则会将其报告在unavailable_facets中,并在下次调用时重试- 无法获取元数据的路由会通过
eia_search_routes报告,而不会被丢弃 - 默认启用 DataCanvas(DuckDB),每次调用均可选择是否暂存;关闭 DataCanvas 后,三个数据框工具将无法调用
便于 Agent 使用的输出:
- 来源信息——
eia_query_route会回显规范路由,暂存的数据框会记录其source_tool和query_params - 窗口上限说明——响应被截断时会报告数量上限及达到的数量,并提供指明下一次调用的
notice - 类型化失败——错误
reason值(例如route_not_queryable、invalid_facet、missing_table)会附带recovery提示
开始使用
公共托管实例
公共实例可通过 https://eia-energy.caseyjhand.com/mcp 访问——无需安装。通过 Streamable HTTP 将任意 MCP 客户端连接到该实例:
{
"mcpServers": {
"eia-energy-mcp-server": {
"type": "streamable-http",
"url": "https://eia-energy.caseyjhand.com/mcp"
}
}
}
自托管 / 本地运行
在 api.eia.gov 免费获取 API 密钥,然后将以下内容添加到 MCP 客户端配置文件中。
{
"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"
}
}
}
}
也可以使用 npx(无需 Bun):
{
"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"
}
}
}
}
也可以使用 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"
]
}
}
}
对于 Streamable HTTP,设置传输方式并启动服务:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 EIA_API_KEY=your-key bun run start:http
# Server listens at http://localhost:3010/mcp
前置条件
- Bun v1.4.0 或更高版本(或 Node.js v24+)。
- 从 api.eia.gov 免费获取 EIA API 密钥。
DEMO_KEY很快就会触及速率限制;持续使用需要真实密钥。
安装
- 克隆代码仓库:
git clone https://github.com/cyanheads/eia-energy-mcp-server.git
- 进入目录:
cd eia-energy-mcp-server
- 安装依赖:
bun install
- 配置环境:
cp .env.example .env
# edit .env and set required vars (at minimum, EIA_API_KEY)
配置
所有配置都会在启动时通过 src/config/server-config.ts 中的 Zod 架构进行验证。主要环境变量:
| 变量 | 说明 | 默认值 |
|---|---|---|
EIA_API_KEY | 必填。 从 api.eia.gov 获取的免费 API 密钥,每次请求都会将其作为 api_key 附加。 | — |
EIA_BASE_URL | EIA API 基础 URL。 | https://api.eia.gov/v2 |
EIA_DATASET_TTL_SECONDS | 数据帧的存活时间(秒);每次引用数据帧的 eia_dataframe_query 都会延长其存活时间。 | 86400(24 小时) |
EIA_DATAFRAME_DROP_ENABLED | 设为 true 可启用 eia_dataframe_drop(当 CANVAS_PROVIDER_TYPE=none 时无效)。默认关闭,以避免意外清理 Canvas。 | false |
EIA_CANVAS_MAX_ROWS | eia_query_route 暂存操作的行数上限。达到上限需要额外 5 次请求:窄路由(如 electricity/retail-sales)约需 8.5 秒,宽路由(如 electricity/facility-fuel)约需 30–46 秒。若暂存操作会超出调用期限,则会提前停止并指出可继续执行的偏移量。 | 25000 |
EIA_FACET_VALUE_CAP | eia_describe_route 每个分面返回的值数量上限,超过后会截断;可使用 facet 和 values_offset 分页,或使用 values_query 缩小范围。 | 50 |
CANVAS_PROVIDER_TYPE | DataCanvas 提供方。duckdb 会启用 eia_dataframe_describe、eia_dataframe_query 和 stage: true;启用 drop 还需要设置 EIA_DATAFRAME_DROP_ENABLED=true。none 会禁用 DataCanvas。Claude Desktop bundle 会设置为 none。 | duckdb |
MCP_TRANSPORT_TYPE | 传输方式:stdio 或 http。 | stdio |
MCP_HTTP_PORT | HTTP 服务端口。 | 3010 |
MCP_HTTP_ENDPOINT_PATH | HTTP 端点路径。 | /mcp |
MCP_SESSION_MODE | HTTP 会话模式:stateless、stateful 或 auto。 | stateless |
MCP_PUBLIC_URL | 用于 TLS 终止型反向代理部署的公共源站覆盖值。 | — |
MCP_AUTH_MODE | 身份验证模式:none、jwt 或 oauth。 | none |
MCP_LOG_LEVEL | 日志级别(RFC 5424)。 | info |
LOGS_DIR | 日志文件目录(仅 Node.js)。 | <project-root>/logs |
STORAGE_PROVIDER_TYPE | 存储后端:in-memory、filesystem、supabase、cloudflare-kv/r2/d1。 | in-memory |
OTEL_ENABLED | 启用 OpenTelemetry 插桩。 | false |
完整的可选覆盖项列表请参见 .env.example。
运行服务
本地开发
-
构建并运行:
# One-time build bun run rebuild # Run the built server bun run start:stdio # or bun run start:http -
运行检查和测试:
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
Dockerfile 默认使用 HTTP 传输、无状态会话模式,并将日志写入 /var/log/eia-energy-mcp-server。默认会安装 OpenTelemetry 对等依赖;构建时使用 --build-arg OTEL_ENABLED=false 可省略这些依赖。
项目结构
| 目录 | 用途 |
|---|---|
src/index.ts | createApp() 入口点——注册工具并初始化服务。 |
src/config | 使用 Zod 解析并验证服务专用环境变量。 |
src/mcp-server/tools | 工具定义(*.tool.ts)——浏览、描述、搜索、查询,以及三个 DataCanvas 数据帧工具。 |
src/services/eia | EIA API v2 服务——路由树缓存、Fuse.js 索引、分面扇出请求、HTTP 客户端。 |
src/services/canvas-bridge | DataCanvas 桥接层——将 EIA 查询结果注册为 DuckDB 数据帧,并路由 SQL 查询。 |
tests/ | 与 src/ 结构对应的单元测试和集成测试。 |
docs/ | 设计文档(design.md、idea.md)。 |
开发指南
开发指南和架构规则请参见 CLAUDE.md。简要概述:
- 处理器抛出异常,框架负责捕获——工具逻辑中不要使用
try/catch - 使用
ctx.log记录请求范围的日志,使用ctx.state保存租户范围的存储 - 始终先调用
eia_describe_route,再调用eia_query_route——分面值需要单独进行 API 扇出请求,不包含在路由元数据中 - 封装 EIA 响应:先验证原始数据,再规范化为领域类型,最后返回输出架构;数据值均为字符串,切勿静默强制转换
贡献
欢迎提交问题。提交前请运行检查和测试:
bun run devcheck
bun run test
许可证
Apache-2.0 — 详情请参阅 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。