@cyanheads/eia-energy-mcp-server 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +351 -0
- package/Dockerfile +99 -0
- package/LICENSE +195 -0
- package/README.md +274 -0
- package/changelog/0.1.x/0.1.0.md +18 -0
- package/changelog/0.1.x/0.1.1.md +42 -0
- package/changelog/0.1.x/0.1.2.md +22 -0
- package/changelog/0.1.x/0.1.3.md +17 -0
- package/changelog/0.1.x/0.1.4.md +17 -0
- package/changelog/0.1.x/0.1.5.md +19 -0
- package/changelog/0.1.x/0.1.6.md +19 -0
- package/changelog/0.1.x/0.1.7.md +11 -0
- package/changelog/0.2.x/0.2.0.md +22 -0
- package/changelog/template.md +93 -0
- package/dist/config/server-config.d.ts +18 -0
- package/dist/config/server-config.d.ts.map +1 -0
- package/dist/config/server-config.js +36 -0
- package/dist/config/server-config.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server/tools/definitions/browse-routes.tool.d.ts +28 -0
- package/dist/mcp-server/tools/definitions/browse-routes.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/browse-routes.tool.js +72 -0
- package/dist/mcp-server/tools/definitions/browse-routes.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/dataframe-describe.tool.d.ts +34 -0
- package/dist/mcp-server/tools/definitions/dataframe-describe.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/dataframe-describe.tool.js +114 -0
- package/dist/mcp-server/tools/definitions/dataframe-describe.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/dataframe-drop.tool.d.ts +22 -0
- package/dist/mcp-server/tools/definitions/dataframe-drop.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/dataframe-drop.tool.js +56 -0
- package/dist/mcp-server/tools/definitions/dataframe-drop.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/dataframe-query.tool.d.ts +28 -0
- package/dist/mcp-server/tools/definitions/dataframe-query.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/dataframe-query.tool.js +124 -0
- package/dist/mcp-server/tools/definitions/dataframe-query.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/describe-route.tool.d.ts +58 -0
- package/dist/mcp-server/tools/definitions/describe-route.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/describe-route.tool.js +164 -0
- package/dist/mcp-server/tools/definitions/describe-route.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/query-route.tool.d.ts +66 -0
- package/dist/mcp-server/tools/definitions/query-route.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/query-route.tool.js +264 -0
- package/dist/mcp-server/tools/definitions/query-route.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/search-routes.tool.d.ts +23 -0
- package/dist/mcp-server/tools/definitions/search-routes.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/search-routes.tool.js +94 -0
- package/dist/mcp-server/tools/definitions/search-routes.tool.js.map +1 -0
- package/dist/services/canvas-bridge/canvas-bridge.d.ts +68 -0
- package/dist/services/canvas-bridge/canvas-bridge.d.ts.map +1 -0
- package/dist/services/canvas-bridge/canvas-bridge.js +206 -0
- package/dist/services/canvas-bridge/canvas-bridge.js.map +1 -0
- package/dist/services/canvas-bridge/sql-gate-extras.d.ts +13 -0
- package/dist/services/canvas-bridge/sql-gate-extras.d.ts.map +1 -0
- package/dist/services/canvas-bridge/sql-gate-extras.js +37 -0
- package/dist/services/canvas-bridge/sql-gate-extras.js.map +1 -0
- package/dist/services/eia/eia-service.d.ts +72 -0
- package/dist/services/eia/eia-service.d.ts.map +1 -0
- package/dist/services/eia/eia-service.js +497 -0
- package/dist/services/eia/eia-service.js.map +1 -0
- package/dist/services/eia/route-cache.d.ts +65 -0
- package/dist/services/eia/route-cache.d.ts.map +1 -0
- package/dist/services/eia/route-cache.js +168 -0
- package/dist/services/eia/route-cache.js.map +1 -0
- package/dist/services/eia/types.d.ts +115 -0
- package/dist/services/eia/types.d.ts.map +1 -0
- package/dist/services/eia/types.js +7 -0
- package/dist/services/eia/types.js.map +1 -0
- package/package.json +104 -0
- package/server.json +163 -0
package/README.md
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<h1>@cyanheads/eia-energy-mcp-server</h1>
|
|
3
|
+
<p><b>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.</b>
|
|
4
|
+
<div>7 Tools</div>
|
|
5
|
+
</p>
|
|
6
|
+
</div>
|
|
7
|
+
|
|
8
|
+
<div align="center">
|
|
9
|
+
|
|
10
|
+
[](./CHANGELOG.md) [](./LICENSE) [](https://github.com/users/cyanheads/packages/container/package/eia-energy-mcp-server) [](https://modelcontextprotocol.io/) [](https://www.npmjs.com/package/@cyanheads/eia-energy-mcp-server) [](https://www.typescriptlang.org/) [](https://bun.sh/)
|
|
11
|
+
|
|
12
|
+
[](https://github.com/cyanheads/eia-energy-mcp-server/releases/latest/download/eia-energy-mcp-server.mcpb) [](https://cursor.com/en/install-mcp?name=eia-energy-mcp-server&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjeWFuaGVhZHMvZWlhLWVuZXJneS1tY3Atc2VydmVyIl0sImVudiI6eyJFSUFfQVBJX0tFWSI6InlvdXItYXBpLWtleSJ9fQ==) [](https://vscode.dev/redirect?url=vscode:mcp/install?%7B%22name%22%3A%22eia-energy-mcp-server%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40cyanheads/eia-energy-mcp-server%22%5D%2C%22env%22%3A%7B%22EIA_API_KEY%22%3A%22your-api-key%22%7D%7D)
|
|
13
|
+
|
|
14
|
+
[](https://www.npmjs.com/package/@cyanheads/mcp-ts-core)
|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<div align="center">
|
|
19
|
+
|
|
20
|
+
**Public Hosted Server:** [https://eia-energy.caseyjhand.com/mcp](https://eia-energy.caseyjhand.com/mcp)
|
|
21
|
+
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Tools
|
|
27
|
+
|
|
28
|
+
Seven tools covering the two-phase EIA workflow — find the right dataset route, pull the data, and query spilled results via SQL:
|
|
29
|
+
|
|
30
|
+
| Tool | Description |
|
|
31
|
+
|:-----|:------------|
|
|
32
|
+
| `eia_browse_routes` | 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. |
|
|
33
|
+
| `eia_describe_route` | Returns full metadata for a leaf route: available facets with valid values, data column names, frequency options, units, and date range. Call before `eia_query_route` to understand filter options. |
|
|
34
|
+
| `eia_search_routes` | 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. |
|
|
35
|
+
| `eia_query_route` | 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. |
|
|
36
|
+
| `eia_dataframe_describe` | Lists active DataCanvas dataframes created by prior `eia_query_route` calls. Shows table name, column names and types, row count, and canvas ID. |
|
|
37
|
+
| `eia_dataframe_query` | Runs a read-only SQL SELECT against a DataCanvas dataframe by canvas ID or table name. |
|
|
38
|
+
| `eia_dataframe_drop` | Drops a DataCanvas dataframe, freeing its memory. Only exposed when `EIA_DATAFRAME_DROP_ENABLED=true`. |
|
|
39
|
+
|
|
40
|
+
### `eia_browse_routes`
|
|
41
|
+
|
|
42
|
+
Walk the EIA dataset taxonomy from root to leaf.
|
|
43
|
+
|
|
44
|
+
- 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
|
|
45
|
+
- Intermediate paths return subcategories; leaf routes are flagged so callers know when to switch to `eia_describe_route`
|
|
46
|
+
- `STEO` (Short-Term Energy Outlook) is a flat leaf with 1,469 named series — no sub-routes
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
### `eia_describe_route`
|
|
51
|
+
|
|
52
|
+
Full schema for a leaf route. Required before constructing facet filters.
|
|
53
|
+
|
|
54
|
+
- Returns facets with valid values (fetched via per-facet API calls and cached in-process)
|
|
55
|
+
- Returns data column names, units, frequency options, and date range
|
|
56
|
+
- `eia_search_routes` and `eia_browse_routes` resolve the route path; this tool provides the filter vocabulary
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
### `eia_search_routes`
|
|
61
|
+
|
|
62
|
+
Fuzzy search across the in-memory route index.
|
|
63
|
+
|
|
64
|
+
- Indexes route names, descriptions, and category labels — plus STEO's 1,469 series names
|
|
65
|
+
- Resolves natural language ("natural gas spot prices", "ethanol net imports") to queryable route paths
|
|
66
|
+
- Route tree is cached in-process at first call; subsequent searches hit the Fuse.js index with no upstream cost
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
### `eia_query_route`
|
|
71
|
+
|
|
72
|
+
Pull data from a leaf route.
|
|
73
|
+
|
|
74
|
+
- Facet filters keyed by facet ID (e.g. `{ "stateid": "TX", "sectorid": ["RES", "COM"] }`)
|
|
75
|
+
- Date range and frequency selection; valid values discoverable via `eia_describe_route`
|
|
76
|
+
- Pagination via `offset`/`length` (max 5,000 rows per page); total row count in response
|
|
77
|
+
- All numeric values arrive as strings from the EIA API — units appear as inline `{col}-units` fields per row
|
|
78
|
+
- DataCanvas spillover when result set exceeds `length`: returns `canvas_id` for SQL queries over the full dataset
|
|
79
|
+
|
|
80
|
+
## Features
|
|
81
|
+
|
|
82
|
+
Built on [`@cyanheads/mcp-ts-core`](https://www.npmjs.com/package/@cyanheads/mcp-ts-core):
|
|
83
|
+
|
|
84
|
+
- Declarative tool definitions — single file per tool, framework handles registration and validation
|
|
85
|
+
- Unified error handling — handlers throw, framework catches, classifies, and formats
|
|
86
|
+
- Pluggable auth: `none`, `jwt`, `oauth`
|
|
87
|
+
- Swappable storage backends: `in-memory`, `filesystem`, `Supabase`, `Cloudflare KV/R2/D1`
|
|
88
|
+
- Structured logging with optional OpenTelemetry tracing
|
|
89
|
+
- STDIO and Streamable HTTP transports
|
|
90
|
+
|
|
91
|
+
EIA-specific:
|
|
92
|
+
|
|
93
|
+
- Full coverage of EIA API v2 — all 14 top-level dataset categories
|
|
94
|
+
- In-process route tree cache with Fuse.js fuzzy index — built once at startup, no repeated upstream calls
|
|
95
|
+
- Per-route facet cache via `Promise.all` fan-out — valid filter values available without re-fetching
|
|
96
|
+
- STEO series names (1,469 entries) indexed for natural-language discovery
|
|
97
|
+
- DataCanvas (DuckDB) opt-in for tabular spillover — graceful degradation when unavailable
|
|
98
|
+
|
|
99
|
+
## Getting started
|
|
100
|
+
|
|
101
|
+
Get a free API key at [api.eia.gov](https://www.eia.gov/opendata/), then add the following to your MCP client configuration file.
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"mcpServers": {
|
|
106
|
+
"eia": {
|
|
107
|
+
"type": "stdio",
|
|
108
|
+
"command": "bunx",
|
|
109
|
+
"args": ["@cyanheads/eia-energy-mcp-server@latest"],
|
|
110
|
+
"env": {
|
|
111
|
+
"MCP_TRANSPORT_TYPE": "stdio",
|
|
112
|
+
"MCP_LOG_LEVEL": "info",
|
|
113
|
+
"EIA_API_KEY": "your-api-key"
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Or with npx (no Bun required):
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"mcpServers": {
|
|
125
|
+
"eia": {
|
|
126
|
+
"type": "stdio",
|
|
127
|
+
"command": "npx",
|
|
128
|
+
"args": ["-y", "@cyanheads/eia-energy-mcp-server@latest"],
|
|
129
|
+
"env": {
|
|
130
|
+
"MCP_TRANSPORT_TYPE": "stdio",
|
|
131
|
+
"MCP_LOG_LEVEL": "info",
|
|
132
|
+
"EIA_API_KEY": "your-api-key"
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Or with Docker:
|
|
140
|
+
|
|
141
|
+
```json
|
|
142
|
+
{
|
|
143
|
+
"mcpServers": {
|
|
144
|
+
"eia": {
|
|
145
|
+
"type": "stdio",
|
|
146
|
+
"command": "docker",
|
|
147
|
+
"args": [
|
|
148
|
+
"run", "-i", "--rm",
|
|
149
|
+
"-e", "MCP_TRANSPORT_TYPE=stdio",
|
|
150
|
+
"-e", "EIA_API_KEY=your-api-key",
|
|
151
|
+
"ghcr.io/cyanheads/eia-energy-mcp-server:latest"
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
For Streamable HTTP, set the transport and start the server:
|
|
159
|
+
|
|
160
|
+
```sh
|
|
161
|
+
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 EIA_API_KEY=your-key bun run start:http
|
|
162
|
+
# Server listens at http://localhost:3010/mcp
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Prerequisites
|
|
166
|
+
|
|
167
|
+
- [Bun v1.3.0](https://bun.sh/) or higher (or Node.js v24+).
|
|
168
|
+
- A free EIA API key from [api.eia.gov](https://www.eia.gov/opendata/). The `DEMO_KEY` hits rate limits quickly; a real key is required for sustained use.
|
|
169
|
+
|
|
170
|
+
### Installation
|
|
171
|
+
|
|
172
|
+
1. **Clone the repository:**
|
|
173
|
+
|
|
174
|
+
```sh
|
|
175
|
+
git clone https://github.com/cyanheads/eia-energy-mcp-server.git
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
2. **Navigate into the directory:**
|
|
179
|
+
|
|
180
|
+
```sh
|
|
181
|
+
cd eia-energy-mcp-server
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
3. **Install dependencies:**
|
|
185
|
+
|
|
186
|
+
```sh
|
|
187
|
+
bun install
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
4. **Configure environment:**
|
|
191
|
+
|
|
192
|
+
```sh
|
|
193
|
+
cp .env.example .env
|
|
194
|
+
# edit .env and set required vars (at minimum, EIA_API_KEY)
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Configuration
|
|
198
|
+
|
|
199
|
+
All configuration is validated at startup via Zod schemas in `src/config/server-config.ts`. Key environment variables:
|
|
200
|
+
|
|
201
|
+
| Variable | Description | Default |
|
|
202
|
+
|:---------|:------------|:--------|
|
|
203
|
+
| `EIA_API_KEY` | **Required.** Free API key from api.eia.gov — appended as `api_key` on every request. | — |
|
|
204
|
+
| `EIA_BASE_URL` | EIA API base URL. | `https://api.eia.gov/v2` |
|
|
205
|
+
| `EIA_DATASET_TTL_SECONDS` | Per-table TTL for DataCanvas dataframes in seconds. | `86400` (24 h) |
|
|
206
|
+
| `EIA_DATAFRAME_DROP_ENABLED` | Set to `true` to expose `eia_dataframe_drop`. Off by default to avoid accidental canvas cleanup. | `false` |
|
|
207
|
+
| `CANVAS_PROVIDER_TYPE` | Set to `duckdb` to enable DataCanvas spillover for large result sets (Node only). | — |
|
|
208
|
+
| `MCP_TRANSPORT_TYPE` | Transport: `stdio` or `http`. | `stdio` |
|
|
209
|
+
| `MCP_HTTP_PORT` | HTTP server port. | `3010` |
|
|
210
|
+
| `MCP_HTTP_ENDPOINT_PATH` | HTTP endpoint path. | `/mcp` |
|
|
211
|
+
| `MCP_PUBLIC_URL` | Public origin override for TLS-terminating reverse-proxy deployments. | — |
|
|
212
|
+
| `MCP_AUTH_MODE` | Auth mode: `none`, `jwt`, or `oauth`. | `none` |
|
|
213
|
+
| `MCP_LOG_LEVEL` | Log level (RFC 5424). | `info` |
|
|
214
|
+
| `LOGS_DIR` | Directory for log files (Node.js only). | `<project-root>/logs` |
|
|
215
|
+
| `STORAGE_PROVIDER_TYPE` | Storage backend: `in-memory`, `filesystem`, `supabase`, `cloudflare-kv/r2/d1`. | `in-memory` |
|
|
216
|
+
| `OTEL_ENABLED` | Enable OpenTelemetry instrumentation. | `false` |
|
|
217
|
+
|
|
218
|
+
## Running the server
|
|
219
|
+
|
|
220
|
+
### Local development
|
|
221
|
+
|
|
222
|
+
- **Build and run:**
|
|
223
|
+
|
|
224
|
+
```sh
|
|
225
|
+
# One-time build
|
|
226
|
+
bun run rebuild
|
|
227
|
+
|
|
228
|
+
# Run the built server
|
|
229
|
+
bun run start:stdio
|
|
230
|
+
# or
|
|
231
|
+
bun run start:http
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
- **Run checks and tests:**
|
|
235
|
+
|
|
236
|
+
```sh
|
|
237
|
+
bun run devcheck # Lint, format, typecheck, security
|
|
238
|
+
bun run test # Vitest test suite
|
|
239
|
+
bun run lint:mcp # Validate MCP definitions against spec
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## Project structure
|
|
243
|
+
|
|
244
|
+
| Directory | Purpose |
|
|
245
|
+
|:----------|:--------|
|
|
246
|
+
| `src/index.ts` | `createApp()` entry point — registers tools and inits services. |
|
|
247
|
+
| `src/config` | Server-specific environment variable parsing and validation with Zod. |
|
|
248
|
+
| `src/mcp-server/tools` | Tool definitions (`*.tool.ts`) — browse, describe, search, query, and three DataCanvas dataframe tools. |
|
|
249
|
+
| `src/services/eia` | EIA API v2 service — route tree cache, Fuse.js index, facet fan-out, HTTP client. |
|
|
250
|
+
| `src/services/canvas-bridge` | DataCanvas bridge — registers EIA query results as DuckDB dataframes, routes SQL queries. |
|
|
251
|
+
| `tests/` | Unit and integration tests mirroring `src/`. |
|
|
252
|
+
| `docs/` | Design documents (`design.md`, `idea.md`). |
|
|
253
|
+
|
|
254
|
+
## Development guide
|
|
255
|
+
|
|
256
|
+
See [`CLAUDE.md`](./CLAUDE.md) for development guidelines and architectural rules. The short version:
|
|
257
|
+
|
|
258
|
+
- Handlers throw, framework catches — no `try/catch` in tool logic
|
|
259
|
+
- Use `ctx.log` for request-scoped logging, `ctx.state` for tenant-scoped storage
|
|
260
|
+
- Always call `eia_describe_route` before `eia_query_route` — facet values require a separate API fan-out and are not embedded in route metadata
|
|
261
|
+
- Wrap EIA responses: validate raw → normalize to domain type → return output schema; data values are strings — never coerce silently
|
|
262
|
+
|
|
263
|
+
## Contributing
|
|
264
|
+
|
|
265
|
+
Issues and pull requests are welcome. Run checks and tests before submitting:
|
|
266
|
+
|
|
267
|
+
```sh
|
|
268
|
+
bun run devcheck
|
|
269
|
+
bun run test
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## License
|
|
273
|
+
|
|
274
|
+
Apache-2.0 — see [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Initial scaffold from @cyanheads/mcp-ts-core with tool-surface design for the EIA API v2."
|
|
3
|
+
breaking: false
|
|
4
|
+
security: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 0.1.0 — 2026-05-21
|
|
8
|
+
|
|
9
|
+
## Added
|
|
10
|
+
|
|
11
|
+
- Project scaffolded from `@cyanheads/mcp-ts-core`.
|
|
12
|
+
- Idea seed (`docs/idea.md`) covering the EIA data domain: electricity, petroleum, natural gas, coal, international, STEO forecasts, and emissions.
|
|
13
|
+
- Tool-surface design (`docs/design.md`) for four tools: `eia_browse_routes`, `eia_describe_route`, `eia_search_routes`, `eia_query_route` — verified against the live EIA API v2 on 2026-05-21.
|
|
14
|
+
- Skills synced to `.claude/skills/`.
|
|
15
|
+
|
|
16
|
+
## Removed
|
|
17
|
+
|
|
18
|
+
- Unused echo definitions (resource, app-resource, prompt, app-tool) — design is tools-only; no resources or prompts surface.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Full tool surface implementation: EIA API service layer, four domain tools, three DataCanvas dataframe tools, and a complete test suite."
|
|
3
|
+
breaking: false
|
|
4
|
+
security: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 0.1.1 — 2026-05-21
|
|
8
|
+
|
|
9
|
+
## Added
|
|
10
|
+
|
|
11
|
+
- `src/config/server-config.ts` — Zod-validated env config for `EIA_API_KEY`, `EIA_BASE_URL`, `EIA_DATASET_TTL_SECONDS`, and `EIA_DATAFRAME_DROP_ENABLED`.
|
|
12
|
+
- `src/services/eia/types.ts` — EIA API v2 domain types: raw route/facet/data shapes and normalized domain objects.
|
|
13
|
+
- `src/services/eia/route-cache.ts` — In-process route tree cache with Fuse.js fuzzy index; STEO's 1,469 series names included. Built lazily on first browse/search call.
|
|
14
|
+
- `src/services/eia/eia-service.ts` — EIA API v2 service: route tree fetch, facet fan-out via `Promise.all`, data query with retry/rate-limit handling, and `OVER_RATE_LIMIT` → `ServiceUnavailable` classification.
|
|
15
|
+
- `src/services/canvas-bridge/canvas-bridge.ts` — DataCanvas bridge: registers query result sets as DuckDB dataframes, manages per-table TTL cleanup, graceful degradation when canvas is absent.
|
|
16
|
+
- `src/services/canvas-bridge/sql-gate-extras.ts` — SQL gate helpers for SELECT-only enforcement on dataframe queries.
|
|
17
|
+
- `src/mcp-server/tools/definitions/browse-routes.tool.ts` — `eia_browse_routes`: walk the EIA taxonomy from root to leaf.
|
|
18
|
+
- `src/mcp-server/tools/definitions/describe-route.tool.ts` — `eia_describe_route`: full leaf metadata with facet values, columns, frequencies, and date range.
|
|
19
|
+
- `src/mcp-server/tools/definitions/search-routes.tool.ts` — `eia_search_routes`: Fuse.js fuzzy search across route names, descriptions, and STEO series names.
|
|
20
|
+
- `src/mcp-server/tools/definitions/query-route.tool.ts` — `eia_query_route`: paginated data fetch with facet filters, date range, frequency, and DataCanvas spillover for large result sets.
|
|
21
|
+
- `src/mcp-server/tools/definitions/dataframe-describe.tool.ts` — `eia_dataframe_describe`: list active DataCanvas dataframes from prior query calls.
|
|
22
|
+
- `src/mcp-server/tools/definitions/dataframe-query.tool.ts` — `eia_dataframe_query`: read-only SQL SELECT against a DataCanvas dataframe by canvas ID or table name.
|
|
23
|
+
- `src/mcp-server/tools/definitions/dataframe-drop.tool.ts` — `eia_dataframe_drop`: drop a DataCanvas dataframe; exposed only when `EIA_DATAFRAME_DROP_ENABLED=true` (disabled by default via `disabledTool`).
|
|
24
|
+
- `tests/services/route-cache.test.ts` — Unit tests for the route-cache Fuse.js index and cache behavior.
|
|
25
|
+
- `tests/tools/browse-routes.tool.test.ts` — Tests for `eia_browse_routes` (root, intermediate, leaf paths, not-found error).
|
|
26
|
+
- `tests/tools/describe-route.tool.test.ts` — Tests for `eia_describe_route` (full metadata, sparse upstream, non-leaf rejection).
|
|
27
|
+
- `tests/tools/search-routes.tool.test.ts` — Tests for `eia_search_routes` (match, no-match, STEO series hit).
|
|
28
|
+
- `tests/tools/query-route.tool.test.ts` — Tests for `eia_query_route` (inline data, canvas spillover, rate-limit error, pagination).
|
|
29
|
+
- `tests/tools/dataframe-describe.tool.test.ts` — Tests for `eia_dataframe_describe`.
|
|
30
|
+
- `tests/tools/dataframe-query.tool.test.ts` — Tests for `eia_dataframe_query` (SELECT enforcement, unknown frame error).
|
|
31
|
+
- `tests/tools/dataframe-drop.tool.test.ts` — Tests for `eia_dataframe_drop` (success, unknown frame error).
|
|
32
|
+
- `fuse.js ^7.3.0` dependency for in-process fuzzy route search.
|
|
33
|
+
|
|
34
|
+
## Changed
|
|
35
|
+
|
|
36
|
+
- `src/index.ts` — Replaced echo tool scaffolding with full tool registration (`browseRoutesTool`, `describeRouteTool`, `searchRoutesTool`, `queryRouteTool`, `dataframeDescribeTool`, `dataframeQueryTool`, `dropTool`), `setup()` hook calling `initEiaApiService()` and `initCanvasBridge()`.
|
|
37
|
+
- `scripts/list-skills.ts` — Updated skill listing script.
|
|
38
|
+
|
|
39
|
+
## Removed
|
|
40
|
+
|
|
41
|
+
- `src/mcp-server/tools/definitions/echo.tool.ts` — Placeholder echo tool replaced by domain tools.
|
|
42
|
+
- `tests/tools/echo.tool.test.ts` — Echo tool tests removed with the tool.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "mcp-ts-core ^0.9.5, error code semantics for domain validation, MCPB bundle support."
|
|
3
|
+
breaking: false
|
|
4
|
+
security: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 0.1.2 — 2026-05-23
|
|
8
|
+
|
|
9
|
+
## Added
|
|
10
|
+
|
|
11
|
+
- **MCPB bundle support** — `manifest.json`, `.mcpbignore`, and `bundle` / `lint:packaging` / `audit:refresh` / `publish-mcp` scripts added; `bun run bundle` produces a `.mcpb` for one-click Claude Desktop install.
|
|
12
|
+
|
|
13
|
+
## Changed
|
|
14
|
+
|
|
15
|
+
- **`@cyanheads/mcp-ts-core`** `^0.9.1 → ^0.9.5` — picks up `RequestContextLike` interface (0.9.3), error code refinements, and associated fixes.
|
|
16
|
+
- **`zod`** `^4.4.3` added as an explicit dependency (was previously a transitive-only dep).
|
|
17
|
+
- **`ctx as unknown as …` cast removed** from canvas bridge — `Context` is now directly assignable to `RequestContextLike` since 0.9.3; cast was dead code.
|
|
18
|
+
- **`async` removed** from `browse-routes` handler — handler body has no `await`; spurious modifier dropped.
|
|
19
|
+
- **Error code semantics** — domain validation errors in `eia_query_route` (facet validation, length checks) now throw `validationError()` instead of `invalidParams()`; aligns with framework contract for user-supplied value failures.
|
|
20
|
+
- **`describe-on-fields` lint fixes** across `browse-routes`, `describe-route`, `search-routes`, `query-route`, and `dataframe-query` tool files — all Zod fields now carry `.describe()`.
|
|
21
|
+
- **Skills synced** — `field-test` 2.4 → 2.5, `maintenance` 2.1 → 2.4, `polish-docs-meta` 1.8 → 2.1, `release-and-publish` 2.2 → 2.4.
|
|
22
|
+
- **`devcheck.ts` updated**, `lint-packaging.ts` added to `scripts/`.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "mcp-ts-core ^0.9.5 → ^0.9.6, LICENSE file, lint-packaging updates."
|
|
3
|
+
breaking: false
|
|
4
|
+
security: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 0.1.3 — 2026-05-23
|
|
8
|
+
|
|
9
|
+
## Added
|
|
10
|
+
|
|
11
|
+
- **LICENSE** — Apache-2.0 license file added to the repo root and included in the npm package.
|
|
12
|
+
|
|
13
|
+
## Changed
|
|
14
|
+
|
|
15
|
+
- **`@cyanheads/mcp-ts-core`** `^0.9.5 → ^0.9.6`.
|
|
16
|
+
- **`scripts/lint-packaging.ts`** — updated to validate manifest name scope and `user_config` field alignment.
|
|
17
|
+
- **Skills synced** — `polish-docs-meta` 2.1 → 2.2, `release-and-publish` 2.4 → 2.5.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Field-test bug fixes: route tree misclassification, ZodError on value-array columns, 4xx error codes, auto-populate data[] columns, STEO filter_hint, description normalization."
|
|
3
|
+
breaking: false
|
|
4
|
+
security: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 0.1.4 — 2026-05-23
|
|
8
|
+
|
|
9
|
+
## Fixed
|
|
10
|
+
|
|
11
|
+
- **Route tree classification** — second-level nodes were misclassified as leaves because `buildRouteTree` fetched them using only their segment `id` instead of the full path (e.g. `petroleum/gnd` instead of `gnd`). Now tracks `parentPath` through recursion and preserves the stub's `id`/`name` on merge so EIA's domain-category responses don't overwrite route segment IDs.
|
|
12
|
+
- **ZodError on `data.value:[]` column format** — time-series routes that return `{ value: [] }` instead of the standard `{ colId: { alias, units } }` shape caused a Zod parse crash when normalizing data columns. `describeRoute` now filters out array entries and synthesizes a `{ id: "value", alias: "Value", units: "" }` column instead.
|
|
13
|
+
- **EIA 4xx errors mapped to correct codes** — `404` responses now throw `NotFound` and `400` responses throw `ValidationError` (both non-retryable), instead of `ServiceUnavailable`. The upstream error body (`{ error: string }`) is preserved in the error message.
|
|
14
|
+
- **Auto-populate `data[]` columns** — `queryRoute` omitted the `data[]` query parameter when `columns` was not specified, causing EIA to return rows without measurement values. The call now falls back to all `dataColumns` from route metadata cache when `columns` is omitted.
|
|
15
|
+
- **STEO `filter_hint`** — `eia_search_routes` results for STEO series now include a `filter_hint` field (`{ seriesId: "<id>" }`) that can be passed directly as `filters` to `eia_query_route`, removing the need to parse the series ID from the description string.
|
|
16
|
+
- **Route description normalization** — EIA descriptions containing embedded `\r\n` + whitespace (source-level line wrapping) are now collapsed to clean single-line strings in both the route cache and `describeRoute` output.
|
|
17
|
+
- **`filters` vs `facets` cross-reference** — `eia_describe_route` facet `id` field description and `eia_query_route` `filters` parameter description now cross-reference each other by name (e.g. "use as key in the `filters` parameter of `eia_query_route`").
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Pre-launch polish: code simplification, docs/metadata sync, bunfig.toml, Dockerfile labels, server.json env var coverage."
|
|
3
|
+
breaking: false
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 0.1.5 — 2026-05-23
|
|
7
|
+
|
|
8
|
+
## Changed
|
|
9
|
+
|
|
10
|
+
- **`eia-service.ts`** — simplified `OVER_RATE_LIMIT` detection (extracted `parsedResponse` variable) and `dataColumns` map (extracted `col` binding); equivalent behavior.
|
|
11
|
+
- **`canvas-bridge.ts`** — moved `registerAs` destructure after the `instance.query()` call to match its actual first use.
|
|
12
|
+
- **`query-route.tool.ts`** — added `.describe()` to the passthrough row object in the output schema.
|
|
13
|
+
- **`server.json`** — added `EIA_DATASET_TTL_SECONDS`, `EIA_DATAFRAME_DROP_ENABLED`, and `CANVAS_PROVIDER_TYPE` env var entries to both stdio and HTTP packages (were missing from the registry manifest).
|
|
14
|
+
- **`Dockerfile`** — filled in `org.opencontainers.image.description` and added `org.opencontainers.image.source` label.
|
|
15
|
+
- **`.env.example`** — replaced generic placeholder section with concrete EIA and Canvas env var entries.
|
|
16
|
+
- **`README.md`** — added Docker badge, updated Cursor/VS Code deeplink configs to include `EIA_API_KEY` env, added `cp .env.example .env` install step, added `EIA_DATASET_TTL_SECONDS` and `EIA_DATAFRAME_DROP_ENABLED` to the configuration table.
|
|
17
|
+
- **`package.json`** — removed stale `AGENTS.md` from `files[]`; added `energy-api` and `llm` keywords.
|
|
18
|
+
- **`bunfig.toml`** — added with `[install] auto=fallback` and `[run] bun=true`.
|
|
19
|
+
- **`CLAUDE.md`** — updated server config pattern to reflect current `datasetTtlSeconds`/`dataframeDropEnabled` schema (removed stale `canvasProvider` field).
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Field-test bug fixes: error contracts, schema handling, and UX across eia_describe_route, eia_query_route, and eia_search_routes."
|
|
3
|
+
breaking: false
|
|
4
|
+
security: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 0.1.6 — 2026-05-23
|
|
8
|
+
|
|
9
|
+
## Fixed
|
|
10
|
+
|
|
11
|
+
- **`eia_describe_route` / `eia_query_route`**: `route_not_found` error now fires with contract `reason` and recovery hint when the route does not exist.
|
|
12
|
+
- **`eia_query_route`**: `invalid_facet` error now fires with contract `reason` and recovery hint on a 400 from EIA; dead `invalid_facet_value` contract entry removed.
|
|
13
|
+
- **`eia_query_route`**: units columns extracted to table headers (`col (unit)`) instead of repeated as `{col}-units` fields on every row.
|
|
14
|
+
- **`eia_search_routes`**: description example replaced with one that resolves (`electricity retail sales by state`); weak-match label added for scores > 0.5.
|
|
15
|
+
- **`eia_describe_route`**: null facet `id`/`name` values from EIA (e.g. international route) are now filtered out instead of surfaced.
|
|
16
|
+
- **`eia_describe_route`**: undefined data column `alias` (e.g. crude-oil-imports route) now falls back to the column `id` instead of crashing.
|
|
17
|
+
- **`eia_query_route`**: category (non-leaf) route now returns a typed `ValidationError` before hitting the EIA API.
|
|
18
|
+
- **`eia_query_route`**: inverted date range (`start > end`) now returns a `no_data` validation error with a swap hint.
|
|
19
|
+
- **`eia_describe_route`**: nonexistent route now returns `route_not_found` with a recovery hint pointing to `eia_browse_routes` / `eia_search_routes`.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Add @duckdb/node-api ^1.5.3-r.1 — enables DuckDB canvas provider for dataframe tools."
|
|
3
|
+
breaking: false
|
|
4
|
+
security: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 0.1.7 — 2026-05-23
|
|
8
|
+
|
|
9
|
+
## Dependencies
|
|
10
|
+
|
|
11
|
+
- `@duckdb/node-api ^1.5.3-r.1` added — provides the DuckDB runtime required by the DataCanvas canvas provider (`CANVAS_PROVIDER_TYPE=duckdb`). The three dataframe tools (`eia_dataframe_describe`, `eia_dataframe_query`, `eia_dataframe_drop`) now function end-to-end when DuckDB is enabled.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Repo and package renamed from eia-mcp-server to eia-energy-mcp-server; tool names (eia_*) unchanged."
|
|
3
|
+
breaking: true
|
|
4
|
+
security: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 0.2.0 — 2026-05-24
|
|
8
|
+
|
|
9
|
+
Package rename. All tool names (`eia_*`) and the MCP tool surface are unchanged — this is a breaking change only for npm consumers referencing the old package identifier.
|
|
10
|
+
|
|
11
|
+
## Changed
|
|
12
|
+
|
|
13
|
+
- **npm package** renamed from `@cyanheads/eia-mcp-server` to `@cyanheads/eia-energy-mcp-server` ([#18](https://github.com/cyanheads/eia-energy-mcp-server/issues/18)).
|
|
14
|
+
- **GitHub repo** renamed from `cyanheads/eia-mcp-server` to `cyanheads/eia-energy-mcp-server`.
|
|
15
|
+
- **Docker image** renamed from `ghcr.io/cyanheads/eia-mcp-server` to `ghcr.io/cyanheads/eia-energy-mcp-server`.
|
|
16
|
+
- **Hosted endpoint** moving to `https://eia-energy.caseyjhand.com/mcp` (subdomain change; old `eia.caseyjhand.com` redirects during transition).
|
|
17
|
+
- **MCP server name** updated to `io.github.cyanheads/eia-energy-mcp-server` in `server.json`.
|
|
18
|
+
- **Tool names unchanged** — all seven `eia_*` tools retain their existing identifiers; no client-side tool renames needed.
|
|
19
|
+
|
|
20
|
+
## Deprecated
|
|
21
|
+
|
|
22
|
+
- `@cyanheads/eia-mcp-server` on npm — deprecated with a migration notice pointing to `@cyanheads/eia-energy-mcp-server`.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
# FORMAT REFERENCE — do not edit. Copy this file to
|
|
3
|
+
# `changelog/<major.minor>.x/<version>.md` (e.g. `changelog/0.8.x/0.8.6.md`)
|
|
4
|
+
# to author a new release. Set that file's H1 to `# <version> — YYYY-MM-DD`
|
|
5
|
+
# with a concrete date.
|
|
6
|
+
|
|
7
|
+
# Required. One-line GitHub Release-style headline. 350 character cap.
|
|
8
|
+
# Default short and scannable. Don't pad, don't stitch unrelated changes with
|
|
9
|
+
# semicolons — pick the headline. Quotes required: unquoted YAML treats `: `
|
|
10
|
+
# inside the value as a key separator and fails GitHub's strict parser.
|
|
11
|
+
summary: ""
|
|
12
|
+
|
|
13
|
+
# Set `true` when consumers must change code to upgrade: API removals,
|
|
14
|
+
# signature changes, config renames, behavior changes that break existing
|
|
15
|
+
# usage. Flagged as `Breaking` in the rollup.
|
|
16
|
+
breaking: false
|
|
17
|
+
|
|
18
|
+
# Set `true` if this release contains any security fix. Pairs with the
|
|
19
|
+
# `## Security` section below. Flagged as `Security` in the rollup so
|
|
20
|
+
# users can triage upgrade urgency at a glance.
|
|
21
|
+
security: false
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
# <version> — YYYY-MM-DD
|
|
25
|
+
|
|
26
|
+
<!--
|
|
27
|
+
AUTHORING GUIDE — applies to the new per-version file you create from this
|
|
28
|
+
template.
|
|
29
|
+
|
|
30
|
+
Audience: someone scanning release notes to decide what affects them. Lead
|
|
31
|
+
each bullet with the symbol or concept name in **bold** so they can skip
|
|
32
|
+
what's irrelevant and zoom in on what's not.
|
|
33
|
+
|
|
34
|
+
Tone: terse, fact-dense, not verbose. Default to one sentence per bullet —
|
|
35
|
+
name the symbol, state what changed, stop. Use a second sentence only when
|
|
36
|
+
it carries weight. If a bullet feels long, it is.
|
|
37
|
+
|
|
38
|
+
Cut: mechanism walkthroughs (those belong in JSDoc, AGENTS.md, or the
|
|
39
|
+
relevant skill), ceremonial framings ("This release introduces…",
|
|
40
|
+
backwards-compat paragraphs), file-by-file test enumerations, internal
|
|
41
|
+
implementation notes. Prefer code/symbol names over English re-explanations.
|
|
42
|
+
|
|
43
|
+
Narrative intro: skip by default. Add one short sentence only when the
|
|
44
|
+
release theme genuinely needs framing the bullets can't carry.
|
|
45
|
+
|
|
46
|
+
Sections: Keep a Changelog order — Added, Changed, Deprecated, Removed,
|
|
47
|
+
Fixed, Security. Include only sections with entries; delete the rest
|
|
48
|
+
(including the commented-out scaffolding below). Don't ship empty headers.
|
|
49
|
+
|
|
50
|
+
Include: every distinct fact a reader needs to adopt or audit the release —
|
|
51
|
+
new exports, signatures, lint rule IDs, env vars, breaking changes, version
|
|
52
|
+
bumps on shipped skills. Nothing more.
|
|
53
|
+
|
|
54
|
+
Links: link issues, PRs, docs, or skills where they help a reader jump to
|
|
55
|
+
context. Once per item per entry — don't re-link the same issue in summary,
|
|
56
|
+
narrative, and bullet. Skip links for inline symbol names; code spans speak
|
|
57
|
+
for themselves.
|
|
58
|
+
|
|
59
|
+
Issue/PR URLs: use full URLs. GitHub's bare `#NN` auto-link only resolves
|
|
60
|
+
inside its own UI, not in npm reads or local editors.
|
|
61
|
+
|
|
62
|
+
[#38](https://github.com/cyanheads/mcp-ts-core/issues/38) ← issue
|
|
63
|
+
[#42](https://github.com/cyanheads/mcp-ts-core/pull/42) ← PR
|
|
64
|
+
|
|
65
|
+
Verify numbers exist before linking (`gh issue view NN`, `gh pr view NN`).
|
|
66
|
+
Never speculate on a future number — `#42` for an upcoming PR silently
|
|
67
|
+
resolves to whatever real item already owns 42, and timeline previews pull
|
|
68
|
+
in that unrelated item's metadata.
|
|
69
|
+
-->
|
|
70
|
+
|
|
71
|
+
## Added
|
|
72
|
+
|
|
73
|
+
-
|
|
74
|
+
|
|
75
|
+
## Changed
|
|
76
|
+
|
|
77
|
+
-
|
|
78
|
+
|
|
79
|
+
<!-- ## Deprecated
|
|
80
|
+
|
|
81
|
+
- -->
|
|
82
|
+
|
|
83
|
+
<!-- ## Removed
|
|
84
|
+
|
|
85
|
+
- -->
|
|
86
|
+
|
|
87
|
+
## Fixed
|
|
88
|
+
|
|
89
|
+
-
|
|
90
|
+
|
|
91
|
+
<!-- ## Security
|
|
92
|
+
|
|
93
|
+
- -->
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview EIA server-specific environment configuration. Parsed lazily on
|
|
3
|
+
* first call; validated via Zod so errors name the actual env var at fault.
|
|
4
|
+
* @module config/server-config
|
|
5
|
+
*/
|
|
6
|
+
import { z } from '@cyanheads/mcp-ts-core';
|
|
7
|
+
declare const ServerConfigSchema: z.ZodObject<{
|
|
8
|
+
apiKey: z.ZodString;
|
|
9
|
+
baseUrl: z.ZodDefault<z.ZodString>;
|
|
10
|
+
datasetTtlSeconds: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
11
|
+
dataframeDropEnabled: z.ZodDefault<z.ZodPreprocess<z.ZodBoolean>>;
|
|
12
|
+
}, z.core.$strip>;
|
|
13
|
+
export type ServerConfig = z.infer<typeof ServerConfigSchema>;
|
|
14
|
+
export declare function getServerConfig(): ServerConfig;
|
|
15
|
+
/** Reset for tests that need to change config. */
|
|
16
|
+
export declare function _resetServerConfig(): void;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=server-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-config.d.ts","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAG3C,QAAA,MAAM,kBAAkB;;;;;iBAatB,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAI9D,wBAAgB,eAAe,IAAI,YAAY,CAQ9C;AAED,kDAAkD;AAClD,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview EIA server-specific environment configuration. Parsed lazily on
|
|
3
|
+
* first call; validated via Zod so errors name the actual env var at fault.
|
|
4
|
+
* @module config/server-config
|
|
5
|
+
*/
|
|
6
|
+
import { z } from '@cyanheads/mcp-ts-core';
|
|
7
|
+
import { parseEnvConfig } from '@cyanheads/mcp-ts-core/config';
|
|
8
|
+
const ServerConfigSchema = z.object({
|
|
9
|
+
apiKey: z.string().describe('EIA API key'),
|
|
10
|
+
baseUrl: z.string().url().default('https://api.eia.gov/v2').describe('EIA API base URL'),
|
|
11
|
+
datasetTtlSeconds: z.coerce
|
|
12
|
+
.number()
|
|
13
|
+
.int()
|
|
14
|
+
.positive()
|
|
15
|
+
.default(86400)
|
|
16
|
+
.describe('Per-table TTL for canvas dataframes in seconds (default 24 h)'),
|
|
17
|
+
dataframeDropEnabled: z
|
|
18
|
+
.preprocess((v) => v === 'true' || v === true, z.boolean())
|
|
19
|
+
.default(false)
|
|
20
|
+
.describe('Expose eia_dataframe_drop when true'),
|
|
21
|
+
});
|
|
22
|
+
let _config;
|
|
23
|
+
export function getServerConfig() {
|
|
24
|
+
_config ??= parseEnvConfig(ServerConfigSchema, {
|
|
25
|
+
apiKey: 'EIA_API_KEY',
|
|
26
|
+
baseUrl: 'EIA_BASE_URL',
|
|
27
|
+
datasetTtlSeconds: 'EIA_DATASET_TTL_SECONDS',
|
|
28
|
+
dataframeDropEnabled: 'EIA_DATAFRAME_DROP_ENABLED',
|
|
29
|
+
});
|
|
30
|
+
return _config;
|
|
31
|
+
}
|
|
32
|
+
/** Reset for tests that need to change config. */
|
|
33
|
+
export function _resetServerConfig() {
|
|
34
|
+
_config = undefined;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=server-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-config.js","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC;IAC1C,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC,QAAQ,CAAC,kBAAkB,CAAC;IACxF,iBAAiB,EAAE,CAAC,CAAC,MAAM;SACxB,MAAM,EAAE;SACR,GAAG,EAAE;SACL,QAAQ,EAAE;SACV,OAAO,CAAC,KAAK,CAAC;SACd,QAAQ,CAAC,+DAA+D,CAAC;IAC5E,oBAAoB,EAAE,CAAC;SACpB,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;SAC1D,OAAO,CAAC,KAAK,CAAC;SACd,QAAQ,CAAC,qCAAqC,CAAC;CACnD,CAAC,CAAC;AAIH,IAAI,OAAiC,CAAC;AAEtC,MAAM,UAAU,eAAe;IAC7B,OAAO,KAAK,cAAc,CAAC,kBAAkB,EAAE;QAC7C,MAAM,EAAE,aAAa;QACrB,OAAO,EAAE,cAAc;QACvB,iBAAiB,EAAE,yBAAyB;QAC5C,oBAAoB,EAAE,4BAA4B;KACnD,CAAC,CAAC;IACH,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,kBAAkB;IAChC,OAAO,GAAG,SAAS,CAAC;AACtB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG"}
|