@cyanheads/nasa-power-mcp-server 0.2.0 → 0.4.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/AGENTS.md +26 -11
- package/CLAUDE.md +26 -11
- package/Dockerfile +9 -3
- package/README.md +50 -79
- package/changelog/0.3.x/0.3.0.md +35 -0
- package/changelog/0.4.x/0.4.0.md +36 -0
- package/dist/config/server-config.d.ts +1 -0
- package/dist/config/server-config.d.ts.map +1 -1
- package/dist/config/server-config.js +11 -1
- package/dist/config/server-config.js.map +1 -1
- package/dist/index.js +3 -8
- package/dist/index.js.map +1 -1
- package/dist/mcp-server/tools/definitions/comparison-contracts.d.ts +7 -2
- package/dist/mcp-server/tools/definitions/comparison-contracts.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/comparison-contracts.js +3 -1
- package/dist/mcp-server/tools/definitions/comparison-contracts.js.map +1 -1
- package/dist/mcp-server/tools/definitions/nasa-power-compare-locations.tool.d.ts +5 -0
- package/dist/mcp-server/tools/definitions/nasa-power-compare-locations.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/nasa-power-dataframe-describe.tool.d.ts +1 -0
- package/dist/mcp-server/tools/definitions/nasa-power-dataframe-describe.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/nasa-power-get-climatology.tool.d.ts +15 -0
- package/dist/mcp-server/tools/definitions/nasa-power-get-climatology.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/nasa-power-get-climatology.tool.js +21 -3
- package/dist/mcp-server/tools/definitions/nasa-power-get-climatology.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/nasa-power-get-region.tool.d.ts +24 -4
- package/dist/mcp-server/tools/definitions/nasa-power-get-region.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/nasa-power-get-region.tool.js +9 -3
- package/dist/mcp-server/tools/definitions/nasa-power-get-region.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/nasa-power-get-timeseries.tool.d.ts +2 -0
- package/dist/mcp-server/tools/definitions/nasa-power-get-timeseries.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/nasa-power-list-reference.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/nasa-power-list-reference.tool.js +5 -5
- package/dist/mcp-server/tools/definitions/nasa-power-list-reference.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/point-contracts.d.ts +2 -0
- package/dist/mcp-server/tools/definitions/point-contracts.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/point-contracts.js +1 -5
- package/dist/mcp-server/tools/definitions/point-contracts.js.map +1 -1
- package/dist/services/canvas/canvas-service.d.ts +9 -3
- package/dist/services/canvas/canvas-service.d.ts.map +1 -1
- package/dist/services/canvas/canvas-service.js +58 -32
- package/dist/services/canvas/canvas-service.js.map +1 -1
- package/dist/services/canvas/format.d.ts +0 -1
- package/dist/services/canvas/format.d.ts.map +1 -1
- package/dist/services/canvas/format.js +3 -3
- package/dist/services/canvas/format.js.map +1 -1
- package/dist/services/canvas/types.d.ts +11 -1
- package/dist/services/canvas/types.d.ts.map +1 -1
- package/dist/services/canvas/types.js +2 -3
- package/dist/services/canvas/types.js.map +1 -1
- package/dist/services/power/normalize.d.ts.map +1 -1
- package/dist/services/power/normalize.js +24 -8
- package/dist/services/power/normalize.js.map +1 -1
- package/dist/services/power/power-service.d.ts.map +1 -1
- package/dist/services/power/power-service.js +9 -3
- package/dist/services/power/power-service.js.map +1 -1
- package/dist/services/power/presets.d.ts +2 -0
- package/dist/services/power/presets.d.ts.map +1 -1
- package/dist/services/power/presets.js +2 -0
- package/dist/services/power/presets.js.map +1 -1
- package/dist/services/power/types.d.ts +5 -3
- package/dist/services/power/types.d.ts.map +1 -1
- package/dist/services/power/types.js +12 -4
- package/dist/services/power/types.js.map +1 -1
- package/package.json +11 -8
- package/server.json +37 -19
- package/skills/nasa-power-guide/SKILL.md +73 -0
package/AGENTS.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Developer Protocol
|
|
2
2
|
|
|
3
3
|
**Server:** nasa-power-mcp-server
|
|
4
|
-
**Version:** 0.
|
|
5
|
-
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.
|
|
4
|
+
**Version:** 0.4.0
|
|
5
|
+
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.18`
|
|
6
6
|
**Engines:** Bun ≥1.4.0, Node ≥24.0.0
|
|
7
|
-
**MCP SDK:** `@modelcontextprotocol/server` ^2.
|
|
7
|
+
**MCP SDK:** `@modelcontextprotocol/server` ^2.4.0
|
|
8
8
|
**Zod:** ^4.6.7
|
|
9
9
|
|
|
10
10
|
> **Read the framework docs first:** `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md` contains the full API reference — builders, Context, error codes, exports, patterns. This file covers server-specific conventions only.
|
|
@@ -52,16 +52,18 @@ Read the real contracts before extending them:
|
|
|
52
52
|
- `src/services/power/power-service.ts` owns fixed-origin requests, bounded pacing, cache and deadlines.
|
|
53
53
|
- `src/services/canvas/canvas-service.ts` owns explicit-token admission, provenance, staging and cleanup.
|
|
54
54
|
|
|
55
|
-
Tool files live in `src/mcp-server/tools/definitions/`. Nine tools are registered; eight are enabled by default. `NASA_POWER_DATAFRAME_DROP_ENABLED=true` exposes explicit table removal. No resources or prompts are registered.
|
|
55
|
+
Tool files live in `src/mcp-server/tools/definitions/`. Nine tools are registered; eight are enabled by default. `NASA_POWER_DATAFRAME_DROP_ENABLED=true` exposes explicit table removal. No resources or prompts are registered. `createApp({ skills: 'skills' })` serves the published `skills/nasa-power-guide/SKILL.md` as `skill://nasa-power-guide/SKILL.md`; when a tool's gates, units or identifiers change, update that skill and re-verify its claims against live behavior.
|
|
56
56
|
|
|
57
57
|
### Configuration and distribution
|
|
58
58
|
|
|
59
|
-
`src/config/server-config.ts` lazily parses the drop flag with `z.stringbool().default(false)` and exports fixed `POWER_LIMITS`. Never use `z.coerce.boolean()` for environment flags.
|
|
59
|
+
`src/config/server-config.ts` lazily parses the drop flag with `z.stringbool().default(false)`, the positive `NASA_POWER_MAX_CANVASES_PER_PROCESS` (default eight), and exports fixed `POWER_LIMITS`. Never use `z.coerce.boolean()` for environment flags.
|
|
60
60
|
|
|
61
|
-
`src/index.ts`
|
|
61
|
+
`src/index.ts` defaults DuckDB to 256 MiB engine memory, four canvases per tenant, a one-hour sliding TTL and a six-hour absolute cap while honoring validated operator overrides. Pass resolved core canvas limits to service admission and provenance retention. The service enforces the configured process cap, eight tables per canvas and a 30-minute table TTL. Engine memory is not total RSS or temporary-disk capacity.
|
|
62
62
|
|
|
63
63
|
`src/index.ts` also defaults `CANVAS_PROVIDER_TYPE` to `duckdb` once `parseConfig()` has loaded `.env`, so npm and Docker installs, which install the native dependency normally on supported platforms, stage by default; `none` disables staging. The portable MCPB fixes `CANVAS_PROVIDER_TYPE=none` because its bundle strips DuckDB's native bindings. Keep those option sets distinct.
|
|
64
64
|
|
|
65
|
+
`@duckdb/node-api` stays on 1.5.6: the framework's optional peer also admits 2.x, but its canvas SQL gate refuses `SHOW <table>` on DuckDB 2 with `plan_operator_not_allowed` (cyanheads/mcp-ts-core#800), a query 1.5.x answers with the column listing.
|
|
66
|
+
|
|
65
67
|
### Identity and lifecycle
|
|
66
68
|
|
|
67
69
|
`createApp()` sets both `name` and `title` to `nasa-power-mcp-server`. npm install surfaces use `@cyanheads/nasa-power-mcp-server`; registry identity is `io.github.cyanheads/nasa-power-mcp-server`. Derive descriptions from `package.json`; do not duplicate one into the entrypoint.
|
|
@@ -159,9 +161,18 @@ scripts/ # Build, validation and packaging
|
|
|
159
161
|
|
|
160
162
|
## Skills
|
|
161
163
|
|
|
162
|
-
|
|
164
|
+
Two skill trees live at the project root, written for different readers:
|
|
165
|
+
|
|
166
|
+
| Tree | For | Written by |
|
|
167
|
+
|:-----|:----|:-----------|
|
|
168
|
+
| `framework-skills/` | The agent developing this server — framework skills (`metadata.audience: external`) plus any development-time skills of the server's own | `init` and the `maintenance` sync (framework skills); you (your own) |
|
|
169
|
+
| `skills/` | The agents that install the server and call its tools — tool chains, identifier sources, gates | You, deliberately, with the `add-skill` skill. Absent by default; usually none is needed |
|
|
170
|
+
|
|
171
|
+
Development skills are modular instructions. Read them directly when a task matches — e.g., `framework-skills/add-tool/SKILL.md` when adding a tool. `bun run list-skills` prints the full registry. Their directory is deliberately not `skills/`: Claude Code and Codex auto-load a plugin's root `skills/`, so a server that ships `.claude-plugin/` or `.codex-plugin/` would hand them to every agent that installs it.
|
|
172
|
+
|
|
173
|
+
A published skill in root `skills/` reaches plugin installs and the `.mcpb` bundle as-is, ships in the npm package and the Docker image, and reaches MCP clients when the server opts in with `createApp({ skills: 'skills' })`. `lint:packaging` validates the tree.
|
|
163
174
|
|
|
164
|
-
**Agent skill directory:** Copy skills into the directory your agent discovers (Claude Code: `.claude/skills/`, others: equivalent). Skills then load as context without referencing `framework-skills/` paths. After framework updates, run the `maintenance` skill — Phase B re-syncs the agent directory.
|
|
175
|
+
**Agent skill directory:** Copy `framework-skills/` into the directory your agent discovers (Claude Code: `.claude/skills/`, others: equivalent). Skills then load as context without referencing `framework-skills/` paths. After framework updates, run the `maintenance` skill — Phase B re-syncs the agent directory.
|
|
165
176
|
|
|
166
177
|
Available skills:
|
|
167
178
|
|
|
@@ -173,6 +184,7 @@ Available skills:
|
|
|
173
184
|
| `add-app-tool` | Scaffold an MCP App tool + paired UI resource |
|
|
174
185
|
| `add-resource` | Scaffold a new resource definition |
|
|
175
186
|
| `add-prompt` | Scaffold a new prompt definition |
|
|
187
|
+
| `add-skill` | Author a skill the server publishes in root `skills/` for the agents that use it — when one earns its place, structure, validation, delivery |
|
|
176
188
|
| `add-service` | Scaffold a new service integration |
|
|
177
189
|
| `add-test` | Scaffold test file for a tool, resource, or service |
|
|
178
190
|
| `field-test` | Exercise tools/resources/prompts with real inputs, verify behavior, report issues |
|
|
@@ -220,7 +232,7 @@ When you complete a skill's checklist, check the boxes and add a completion time
|
|
|
220
232
|
| `bun run audit:fix` | `bun audit fix` — upgrade vulnerable packages to the lowest safe version within existing ranges (`--dry-run` previews, `--latest` rewrites ranges). First response when `devcheck` flags a transitive advisory; then `bun update <name>`, then `bun dedupe` |
|
|
221
233
|
| `bun run audit:refresh` | Delete `bun.lock` and reinstall. Last resort after `audit:fix`, `bun update <name>`, and `bun dedupe` — re-resolves every ranged dep (the framework pin included) and rewrites the lockfile as `lockfileVersion: 2` |
|
|
222
234
|
| `bun run lint:mcp` | Run the MCP definition linter standalone (rule catalog: `api-linter` skill) |
|
|
223
|
-
| `bun run lint:packaging` | Packaging surface checks — `server.json`/`manifest.json` env-var parity (run by devcheck) |
|
|
235
|
+
| `bun run lint:packaging` | Packaging surface checks — `server.json`/`manifest.json` env-var parity, `.mcpbignore` coverage, plugin manifests, the published `skills/` tree (run by devcheck) |
|
|
224
236
|
| `bun run list-skills` | Print the skill registry |
|
|
225
237
|
| `bun run tree` | Generate directory structure doc |
|
|
226
238
|
| `bun run format` | Auto-fix formatting (safe fixes only) |
|
|
@@ -242,7 +254,7 @@ When you complete a skill's checklist, check the boxes and add a completion time
|
|
|
242
254
|
|
|
243
255
|
## Bundling
|
|
244
256
|
|
|
245
|
-
`bun run bundle` builds the stdio-only portable MCPB for Claude Desktop. `scripts/clean-mcpb.ts` prunes development dependencies, dependency
|
|
257
|
+
`bun run bundle` builds the stdio-only portable MCPB for Claude Desktop. `mcpb pack` reads `.mcpbignore`, not `.gitignore`, so every root path the bundle must not ship needs a root-anchored line there (`/docs/`, never `docs/`, which also strips `node_modules/*/docs/`); `lint:packaging` names each missing or unanchored line. Root `skills/` ships on purpose. `scripts/clean-mcpb.ts` prunes development dependencies, a dependency package root's agent docs, platform-specific native bindings, node-gyp build output and the framework's build-only files. Its agent-doc selector is anchored to a package root so the MCP SDK's runtime `dist/ext/skills/` modules survive (cyanheads/mcp-ts-core#794); `tests/scripts/mcpb-agent-docs.test.ts` holds the cleaner and `lint:packaging` to the same selection. The manifest fixes `CANVAS_PROVIDER_TYPE=none`: inline observations work, oversized source requests fail with narrowing guidance, and dataframe tools report that the provider is unavailable. `@duckdb/node-api` is a direct dependency for npm and Docker installs on supported platforms; bundle pruning does not change that package contract.
|
|
246
258
|
|
|
247
259
|
**Adding an env var requires both files:** `server.json` (registry discovery, `environmentVariables[]`) and `manifest.json` (bundle install UX, `mcp_config.env` + `user_config`). `lint:packaging` (run by `devcheck`) verifies the env var names match, that every `user_config` option is wired into `mcp_config.env` as `"X": "${user_config.X}"` (the host substitutes nothing else — `"${X}"` reaches the server as that literal string), and that an optional string option carries `"default": ""`.
|
|
248
260
|
|
|
@@ -305,14 +317,17 @@ import { getMyService } from '@/services/my-domain/my-service.js';
|
|
|
305
317
|
- [ ] Handlers throw on failure — error factories or plain `Error`, no try/catch
|
|
306
318
|
- [ ] New codes and presets are checked against the selected community/resolution dictionary; source units, fill-as-`null`, `omittedParameters` and annual-period distinctions survive normalization
|
|
307
319
|
- [ ] Producing tools present through `CanvasService.present()`: oversized data stages completely or fails with `canvas_required` / `dataset_limit`, never a truncated source prefix
|
|
308
|
-
- [ ] Workload bounds live in `POWER_LIMITS`;
|
|
320
|
+
- [ ] Workload bounds live in `POWER_LIMITS`; configurable canvas defaults and process cap match across `src/index.ts`, `.env.example`, `server.json`, `manifest.json` and both plugin manifests
|
|
309
321
|
- [ ] `format()` renders all data the LLM needs — different clients forward different surfaces (Claude Code → `structuredContent`, Claude Desktop → `content[]`); both must carry the same data
|
|
310
322
|
- [ ] If wrapping external API: raw/domain/output schemas reviewed against real upstream sparsity/nullability before finalizing required vs optional fields
|
|
311
323
|
- [ ] If wrapping external API: normalization and `format()` preserve uncertainty; do not fabricate facts from missing upstream data
|
|
312
324
|
- [ ] If wrapping external API: tests include at least one sparse payload case with omitted upstream fields
|
|
313
325
|
- [ ] Registered in `createApp()` arrays (directly or via barrel exports)
|
|
314
326
|
- [ ] Tests use `createMockContext()` from `@cyanheads/mcp-ts-core/testing`
|
|
327
|
+
- [ ] `plugin.json` + `mcp.json` (Agent Plugins 1.0.0 — read by Codex, Cursor, GitHub Copilot, VS Code, Kiro) populated — `plugin.json` `name` = the unscoped repo name (lowercase `a-z`, `0-9`, `-`, `.` only); `version`, `description`, `author`, `homepage`, `repository`, `license`, `keywords` from `package.json`; no other top-level field, `extensions` included. `mcp.json` holds one `"type": "stdio"` entry keyed by the unscoped name, `npx -y <full package name>`, and the same fixed `env` as `.codex-plugin/mcp.json`. Neither file carries a user-supplied variable (no `""`, no `${…}` besides `${PLUGIN_ROOT}`/`${PLUGIN_DATA}`): keys reach Codex through `.codex-plugin/mcp.json` `env_vars`, which works only while `.codex-plugin/plugin.json` keeps `"mcpServers": "./.codex-plugin/mcp.json"`
|
|
315
328
|
- [ ] `.codex-plugin/plugin.json` populated — `name`, `version`, `description`, `repository`, `license` from `package.json`; `interface.displayName` = the unscoped repo name (never the npm scope — `lint:packaging` enforces this); `interface.shortDescription` from `package.json` description
|
|
316
329
|
- [ ] `.codex-plugin/mcp.json` updated — server name key is the unscoped repo name; every user-supplied variable (API key, contact email, instance URL) is listed in `env_vars` so Codex forwards it from the user's environment. Never write `"KEY": ""` into `env` — an empty value replaces the user's exported key and is read as unset
|
|
317
330
|
- [ ] `.claude-plugin/plugin.json` populated — `name`, `version`, `description`, `author`, `repository`, `license`, `keywords` from `package.json`; inline `mcpServers` entry keyed by the unscoped repo name. Every user-supplied variable is declared under `userConfig` (`type`, `title`, `description`; `sensitive: true` for keys and tokens; `required: true` or `default: ""`) and referenced from `env` as `"KEY": "${user_config.<option>}"` — mirror the `user_config` block in `manifest.json`. Never write `"KEY": ""` into `env`
|
|
331
|
+
- [ ] Any new root dev path has a root-anchored line in `.mcpbignore`; `bun run bundle` and `lint:packaging` pass
|
|
332
|
+
- [ ] If the server publishes a skill in root `skills/`: `lint:packaging` passes, and `field-test` verified every gate and identifier claim in it against live tool behavior
|
|
318
333
|
- [ ] `npm run devcheck` passes
|
package/CLAUDE.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Developer Protocol
|
|
2
2
|
|
|
3
3
|
**Server:** nasa-power-mcp-server
|
|
4
|
-
**Version:** 0.
|
|
5
|
-
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.
|
|
4
|
+
**Version:** 0.4.0
|
|
5
|
+
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.18`
|
|
6
6
|
**Engines:** Bun ≥1.4.0, Node ≥24.0.0
|
|
7
|
-
**MCP SDK:** `@modelcontextprotocol/server` ^2.
|
|
7
|
+
**MCP SDK:** `@modelcontextprotocol/server` ^2.4.0
|
|
8
8
|
**Zod:** ^4.6.7
|
|
9
9
|
|
|
10
10
|
> **Read the framework docs first:** `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md` contains the full API reference — builders, Context, error codes, exports, patterns. This file covers server-specific conventions only.
|
|
@@ -52,16 +52,18 @@ Read the real contracts before extending them:
|
|
|
52
52
|
- `src/services/power/power-service.ts` owns fixed-origin requests, bounded pacing, cache and deadlines.
|
|
53
53
|
- `src/services/canvas/canvas-service.ts` owns explicit-token admission, provenance, staging and cleanup.
|
|
54
54
|
|
|
55
|
-
Tool files live in `src/mcp-server/tools/definitions/`. Nine tools are registered; eight are enabled by default. `NASA_POWER_DATAFRAME_DROP_ENABLED=true` exposes explicit table removal. No resources or prompts are registered.
|
|
55
|
+
Tool files live in `src/mcp-server/tools/definitions/`. Nine tools are registered; eight are enabled by default. `NASA_POWER_DATAFRAME_DROP_ENABLED=true` exposes explicit table removal. No resources or prompts are registered. `createApp({ skills: 'skills' })` serves the published `skills/nasa-power-guide/SKILL.md` as `skill://nasa-power-guide/SKILL.md`; when a tool's gates, units or identifiers change, update that skill and re-verify its claims against live behavior.
|
|
56
56
|
|
|
57
57
|
### Configuration and distribution
|
|
58
58
|
|
|
59
|
-
`src/config/server-config.ts` lazily parses the drop flag with `z.stringbool().default(false)` and exports fixed `POWER_LIMITS`. Never use `z.coerce.boolean()` for environment flags.
|
|
59
|
+
`src/config/server-config.ts` lazily parses the drop flag with `z.stringbool().default(false)`, the positive `NASA_POWER_MAX_CANVASES_PER_PROCESS` (default eight), and exports fixed `POWER_LIMITS`. Never use `z.coerce.boolean()` for environment flags.
|
|
60
60
|
|
|
61
|
-
`src/index.ts`
|
|
61
|
+
`src/index.ts` defaults DuckDB to 256 MiB engine memory, four canvases per tenant, a one-hour sliding TTL and a six-hour absolute cap while honoring validated operator overrides. Pass resolved core canvas limits to service admission and provenance retention. The service enforces the configured process cap, eight tables per canvas and a 30-minute table TTL. Engine memory is not total RSS or temporary-disk capacity.
|
|
62
62
|
|
|
63
63
|
`src/index.ts` also defaults `CANVAS_PROVIDER_TYPE` to `duckdb` once `parseConfig()` has loaded `.env`, so npm and Docker installs, which install the native dependency normally on supported platforms, stage by default; `none` disables staging. The portable MCPB fixes `CANVAS_PROVIDER_TYPE=none` because its bundle strips DuckDB's native bindings. Keep those option sets distinct.
|
|
64
64
|
|
|
65
|
+
`@duckdb/node-api` stays on 1.5.6: the framework's optional peer also admits 2.x, but its canvas SQL gate refuses `SHOW <table>` on DuckDB 2 with `plan_operator_not_allowed` (cyanheads/mcp-ts-core#800), a query 1.5.x answers with the column listing.
|
|
66
|
+
|
|
65
67
|
### Identity and lifecycle
|
|
66
68
|
|
|
67
69
|
`createApp()` sets both `name` and `title` to `nasa-power-mcp-server`. npm install surfaces use `@cyanheads/nasa-power-mcp-server`; registry identity is `io.github.cyanheads/nasa-power-mcp-server`. Derive descriptions from `package.json`; do not duplicate one into the entrypoint.
|
|
@@ -159,9 +161,18 @@ scripts/ # Build, validation and packaging
|
|
|
159
161
|
|
|
160
162
|
## Skills
|
|
161
163
|
|
|
162
|
-
|
|
164
|
+
Two skill trees live at the project root, written for different readers:
|
|
165
|
+
|
|
166
|
+
| Tree | For | Written by |
|
|
167
|
+
|:-----|:----|:-----------|
|
|
168
|
+
| `framework-skills/` | The agent developing this server — framework skills (`metadata.audience: external`) plus any development-time skills of the server's own | `init` and the `maintenance` sync (framework skills); you (your own) |
|
|
169
|
+
| `skills/` | The agents that install the server and call its tools — tool chains, identifier sources, gates | You, deliberately, with the `add-skill` skill. Absent by default; usually none is needed |
|
|
170
|
+
|
|
171
|
+
Development skills are modular instructions. Read them directly when a task matches — e.g., `framework-skills/add-tool/SKILL.md` when adding a tool. `bun run list-skills` prints the full registry. Their directory is deliberately not `skills/`: Claude Code and Codex auto-load a plugin's root `skills/`, so a server that ships `.claude-plugin/` or `.codex-plugin/` would hand them to every agent that installs it.
|
|
172
|
+
|
|
173
|
+
A published skill in root `skills/` reaches plugin installs and the `.mcpb` bundle as-is, ships in the npm package and the Docker image, and reaches MCP clients when the server opts in with `createApp({ skills: 'skills' })`. `lint:packaging` validates the tree.
|
|
163
174
|
|
|
164
|
-
**Agent skill directory:** Copy skills into the directory your agent discovers (Claude Code: `.claude/skills/`, others: equivalent). Skills then load as context without referencing `framework-skills/` paths. After framework updates, run the `maintenance` skill — Phase B re-syncs the agent directory.
|
|
175
|
+
**Agent skill directory:** Copy `framework-skills/` into the directory your agent discovers (Claude Code: `.claude/skills/`, others: equivalent). Skills then load as context without referencing `framework-skills/` paths. After framework updates, run the `maintenance` skill — Phase B re-syncs the agent directory.
|
|
165
176
|
|
|
166
177
|
Available skills:
|
|
167
178
|
|
|
@@ -173,6 +184,7 @@ Available skills:
|
|
|
173
184
|
| `add-app-tool` | Scaffold an MCP App tool + paired UI resource |
|
|
174
185
|
| `add-resource` | Scaffold a new resource definition |
|
|
175
186
|
| `add-prompt` | Scaffold a new prompt definition |
|
|
187
|
+
| `add-skill` | Author a skill the server publishes in root `skills/` for the agents that use it — when one earns its place, structure, validation, delivery |
|
|
176
188
|
| `add-service` | Scaffold a new service integration |
|
|
177
189
|
| `add-test` | Scaffold test file for a tool, resource, or service |
|
|
178
190
|
| `field-test` | Exercise tools/resources/prompts with real inputs, verify behavior, report issues |
|
|
@@ -220,7 +232,7 @@ When you complete a skill's checklist, check the boxes and add a completion time
|
|
|
220
232
|
| `bun run audit:fix` | `bun audit fix` — upgrade vulnerable packages to the lowest safe version within existing ranges (`--dry-run` previews, `--latest` rewrites ranges). First response when `devcheck` flags a transitive advisory; then `bun update <name>`, then `bun dedupe` |
|
|
221
233
|
| `bun run audit:refresh` | Delete `bun.lock` and reinstall. Last resort after `audit:fix`, `bun update <name>`, and `bun dedupe` — re-resolves every ranged dep (the framework pin included) and rewrites the lockfile as `lockfileVersion: 2` |
|
|
222
234
|
| `bun run lint:mcp` | Run the MCP definition linter standalone (rule catalog: `api-linter` skill) |
|
|
223
|
-
| `bun run lint:packaging` | Packaging surface checks — `server.json`/`manifest.json` env-var parity (run by devcheck) |
|
|
235
|
+
| `bun run lint:packaging` | Packaging surface checks — `server.json`/`manifest.json` env-var parity, `.mcpbignore` coverage, plugin manifests, the published `skills/` tree (run by devcheck) |
|
|
224
236
|
| `bun run list-skills` | Print the skill registry |
|
|
225
237
|
| `bun run tree` | Generate directory structure doc |
|
|
226
238
|
| `bun run format` | Auto-fix formatting (safe fixes only) |
|
|
@@ -242,7 +254,7 @@ When you complete a skill's checklist, check the boxes and add a completion time
|
|
|
242
254
|
|
|
243
255
|
## Bundling
|
|
244
256
|
|
|
245
|
-
`bun run bundle` builds the stdio-only portable MCPB for Claude Desktop. `scripts/clean-mcpb.ts` prunes development dependencies, dependency
|
|
257
|
+
`bun run bundle` builds the stdio-only portable MCPB for Claude Desktop. `mcpb pack` reads `.mcpbignore`, not `.gitignore`, so every root path the bundle must not ship needs a root-anchored line there (`/docs/`, never `docs/`, which also strips `node_modules/*/docs/`); `lint:packaging` names each missing or unanchored line. Root `skills/` ships on purpose. `scripts/clean-mcpb.ts` prunes development dependencies, a dependency package root's agent docs, platform-specific native bindings, node-gyp build output and the framework's build-only files. Its agent-doc selector is anchored to a package root so the MCP SDK's runtime `dist/ext/skills/` modules survive (cyanheads/mcp-ts-core#794); `tests/scripts/mcpb-agent-docs.test.ts` holds the cleaner and `lint:packaging` to the same selection. The manifest fixes `CANVAS_PROVIDER_TYPE=none`: inline observations work, oversized source requests fail with narrowing guidance, and dataframe tools report that the provider is unavailable. `@duckdb/node-api` is a direct dependency for npm and Docker installs on supported platforms; bundle pruning does not change that package contract.
|
|
246
258
|
|
|
247
259
|
**Adding an env var requires both files:** `server.json` (registry discovery, `environmentVariables[]`) and `manifest.json` (bundle install UX, `mcp_config.env` + `user_config`). `lint:packaging` (run by `devcheck`) verifies the env var names match, that every `user_config` option is wired into `mcp_config.env` as `"X": "${user_config.X}"` (the host substitutes nothing else — `"${X}"` reaches the server as that literal string), and that an optional string option carries `"default": ""`.
|
|
248
260
|
|
|
@@ -305,14 +317,17 @@ import { getMyService } from '@/services/my-domain/my-service.js';
|
|
|
305
317
|
- [ ] Handlers throw on failure — error factories or plain `Error`, no try/catch
|
|
306
318
|
- [ ] New codes and presets are checked against the selected community/resolution dictionary; source units, fill-as-`null`, `omittedParameters` and annual-period distinctions survive normalization
|
|
307
319
|
- [ ] Producing tools present through `CanvasService.present()`: oversized data stages completely or fails with `canvas_required` / `dataset_limit`, never a truncated source prefix
|
|
308
|
-
- [ ] Workload bounds live in `POWER_LIMITS`;
|
|
320
|
+
- [ ] Workload bounds live in `POWER_LIMITS`; configurable canvas defaults and process cap match across `src/index.ts`, `.env.example`, `server.json`, `manifest.json` and both plugin manifests
|
|
309
321
|
- [ ] `format()` renders all data the LLM needs — different clients forward different surfaces (Claude Code → `structuredContent`, Claude Desktop → `content[]`); both must carry the same data
|
|
310
322
|
- [ ] If wrapping external API: raw/domain/output schemas reviewed against real upstream sparsity/nullability before finalizing required vs optional fields
|
|
311
323
|
- [ ] If wrapping external API: normalization and `format()` preserve uncertainty; do not fabricate facts from missing upstream data
|
|
312
324
|
- [ ] If wrapping external API: tests include at least one sparse payload case with omitted upstream fields
|
|
313
325
|
- [ ] Registered in `createApp()` arrays (directly or via barrel exports)
|
|
314
326
|
- [ ] Tests use `createMockContext()` from `@cyanheads/mcp-ts-core/testing`
|
|
327
|
+
- [ ] `plugin.json` + `mcp.json` (Agent Plugins 1.0.0 — read by Codex, Cursor, GitHub Copilot, VS Code, Kiro) populated — `plugin.json` `name` = the unscoped repo name (lowercase `a-z`, `0-9`, `-`, `.` only); `version`, `description`, `author`, `homepage`, `repository`, `license`, `keywords` from `package.json`; no other top-level field, `extensions` included. `mcp.json` holds one `"type": "stdio"` entry keyed by the unscoped name, `npx -y <full package name>`, and the same fixed `env` as `.codex-plugin/mcp.json`. Neither file carries a user-supplied variable (no `""`, no `${…}` besides `${PLUGIN_ROOT}`/`${PLUGIN_DATA}`): keys reach Codex through `.codex-plugin/mcp.json` `env_vars`, which works only while `.codex-plugin/plugin.json` keeps `"mcpServers": "./.codex-plugin/mcp.json"`
|
|
315
328
|
- [ ] `.codex-plugin/plugin.json` populated — `name`, `version`, `description`, `repository`, `license` from `package.json`; `interface.displayName` = the unscoped repo name (never the npm scope — `lint:packaging` enforces this); `interface.shortDescription` from `package.json` description
|
|
316
329
|
- [ ] `.codex-plugin/mcp.json` updated — server name key is the unscoped repo name; every user-supplied variable (API key, contact email, instance URL) is listed in `env_vars` so Codex forwards it from the user's environment. Never write `"KEY": ""` into `env` — an empty value replaces the user's exported key and is read as unset
|
|
317
330
|
- [ ] `.claude-plugin/plugin.json` populated — `name`, `version`, `description`, `author`, `repository`, `license`, `keywords` from `package.json`; inline `mcpServers` entry keyed by the unscoped repo name. Every user-supplied variable is declared under `userConfig` (`type`, `title`, `description`; `sensitive: true` for keys and tokens; `required: true` or `default: ""`) and referenced from `env` as `"KEY": "${user_config.<option>}"` — mirror the `user_config` block in `manifest.json`. Never write `"KEY": ""` into `env`
|
|
331
|
+
- [ ] Any new root dev path has a root-anchored line in `.mcpbignore`; `bun run bundle` and `lint:packaging` pass
|
|
332
|
+
- [ ] If the server publishes a skill in root `skills/`: `lint:packaging` passes, and `field-test` verified every gate and identifier claim in it against live tool behavior
|
|
318
333
|
- [ ] `npm run devcheck` passes
|
package/Dockerfile
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
# output. A stage that compiles a native addon needs the target-arch toolchain
|
|
15
15
|
# and cannot cross-compile this way — drop the flag there.
|
|
16
16
|
# ==============================================================================
|
|
17
|
-
FROM --platform=$BUILDPLATFORM oven/bun:1.4.
|
|
17
|
+
FROM --platform=$BUILDPLATFORM oven/bun:1.4.4 AS build
|
|
18
18
|
|
|
19
19
|
WORKDIR /usr/src/app
|
|
20
20
|
|
|
@@ -29,6 +29,11 @@ RUN --mount=type=cache,target=/root/.bun/install/cache \
|
|
|
29
29
|
# Copy the rest of the source code
|
|
30
30
|
COPY . .
|
|
31
31
|
|
|
32
|
+
# The skills a server publishes (`createApp({ skills: 'skills' })`) are read at
|
|
33
|
+
# runtime from the application root. Created when the project has none, so the
|
|
34
|
+
# production stage's copy below holds with or without one.
|
|
35
|
+
RUN mkdir -p skills
|
|
36
|
+
|
|
32
37
|
# Build the application
|
|
33
38
|
RUN bun run build
|
|
34
39
|
|
|
@@ -46,7 +51,7 @@ RUN bun run build
|
|
|
46
51
|
# A clean image rather than `FROM build`: the build stage's node_modules holds
|
|
47
52
|
# devDependencies.
|
|
48
53
|
# ==============================================================================
|
|
49
|
-
FROM --platform=$BUILDPLATFORM oven/bun:1.4.
|
|
54
|
+
FROM --platform=$BUILDPLATFORM oven/bun:1.4.4 AS deps
|
|
50
55
|
|
|
51
56
|
WORKDIR /usr/src/app
|
|
52
57
|
|
|
@@ -114,7 +119,7 @@ RUN rm -rf node_modules/@socketsecurity/bun-security-scanner
|
|
|
114
119
|
# dependencies and build artifacts. Its only Bun invocations are HEALTHCHECK
|
|
115
120
|
# and CMD, which run on the real target at container start.
|
|
116
121
|
# ==============================================================================
|
|
117
|
-
FROM oven/bun:1.4.
|
|
122
|
+
FROM oven/bun:1.4.4-slim AS production
|
|
118
123
|
|
|
119
124
|
WORKDIR /usr/src/app
|
|
120
125
|
|
|
@@ -136,6 +141,7 @@ COPY --from=deps /usr/src/app/node_modules ./node_modules
|
|
|
136
141
|
|
|
137
142
|
# Copy the compiled application code from the build stage
|
|
138
143
|
COPY --from=build /usr/src/app/dist ./dist
|
|
144
|
+
COPY --from=build /usr/src/app/skills ./skills
|
|
139
145
|
|
|
140
146
|
# Mirror CLI (MirrorService adopters only — Tier 3, opt-in):
|
|
141
147
|
# Copy your mirror lifecycle scripts and emit a runtime tsconfig so Bun resolves
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
<div align="center">
|
|
9
9
|
|
|
10
|
-
[](./CHANGELOG.md) [](./LICENSE) [](https://github.com/users/cyanheads/packages/container/package/nasa-power-mcp-server) [](https://modelcontextprotocol.io/) [](https://www.npmjs.com/package/@cyanheads/nasa-power-mcp-server) [](https://www.typescriptlang.org/) [](https://bun.sh/)
|
|
11
11
|
|
|
12
12
|
</div>
|
|
13
13
|
|
|
@@ -19,6 +19,12 @@
|
|
|
19
19
|
|
|
20
20
|
</div>
|
|
21
21
|
|
|
22
|
+
<div align="center">
|
|
23
|
+
|
|
24
|
+
**Public Hosted Server:** [https://nasa-power.caseyjhand.com/mcp](https://nasa-power.caseyjhand.com/mcp)
|
|
25
|
+
|
|
26
|
+
</div>
|
|
27
|
+
|
|
22
28
|
---
|
|
23
29
|
|
|
24
30
|
## Overview
|
|
@@ -41,6 +47,14 @@
|
|
|
41
47
|
|
|
42
48
|
Eight tools are enabled by default; `NASA_POWER_DATAFRAME_DROP_ENABLED=true` enables the ninth.
|
|
43
49
|
|
|
50
|
+
### Skills
|
|
51
|
+
|
|
52
|
+
| Skill | Description |
|
|
53
|
+
|:---|:---|
|
|
54
|
+
| `nasa-power-guide` | Which tool answers a typical-month versus a dated question, grid-cell size, data freshness, rate versus total units, degree days, the one-data-call-at-a-time gate, and SQL over staged tables |
|
|
55
|
+
|
|
56
|
+
The skill ships in `skills/nasa-power-guide/SKILL.md`. Plugin hosts load it from the package, and MCP clients that support the Skills extension read it from the server as `skill://nasa-power-guide/SKILL.md`.
|
|
57
|
+
|
|
44
58
|
## Capability reference
|
|
45
59
|
|
|
46
60
|
### `nasa_power_get_timeseries` <sub>tool</sub>
|
|
@@ -54,14 +68,16 @@ Eight tools are enabled by default; `NASA_POWER_DATAFRAME_DROP_ENABLED=true` ena
|
|
|
54
68
|
### `nasa_power_get_climatology` <sub>tool</sub>
|
|
55
69
|
|
|
56
70
|
- Point coordinates with the same selection and corrections; optional `startYear` and `endYear` together, otherwise the source product range. No `temporalResolution` input.
|
|
57
|
-
-
|
|
71
|
+
- Small profiles remain inline; larger profiles return a bounded preview and complete `dataset` handle. Pass optional `canvas_id` to reuse an existing workspace. Without DuckDB, narrow oversized selections for inline output. `SI_EF_TILTED_SURFACE` and the distinct `SI_TILTED_AVG`, `SI_TILTED_MIN`, `SI_TILTED_MAX` groups list only their actually returned members, numeric angles and N/S orientation text included, in `expansions`. A group is omitted only when none of its members return.
|
|
58
72
|
|
|
59
73
|
---
|
|
60
74
|
|
|
61
75
|
### `nasa_power_get_region` <sub>tool</sub>
|
|
62
76
|
|
|
63
77
|
- One `parameter` over ordered `latitudeMin` / `latitudeMax` and `longitudeMin` / `longitudeMax`, each axis spanning 2–10 degrees (`invalid_region` otherwise); split antimeridian regions into separate calls. `temporalResolution` is `daily`, `monthly` or `climatology`; point corrections are unsupported.
|
|
78
|
+
- Daily regions require date bounds and monthly regions require year bounds. Regional climatology accepts no year fields and reports the source's precomputed period; use `nasa_power_get_climatology` for a custom point year window.
|
|
64
79
|
- Returns cell-tagged `rows`, `cellCount` and per-period `summaries` with equal-weight cell `min` / `mean` / `max`, not area-weighted. Optional `canvas_id` reuses a canvas for staging.
|
|
80
|
+
- Oversized summary envelopes return `summaryDataset` with all cross-cell summaries, exact `summaryCount` and a whole-record inline preview. Query the table in `summaryIndex` order; SQL `units: null` restores an omitted source unit. Observations and summaries register together and retain linked provenance.
|
|
65
81
|
|
|
66
82
|
---
|
|
67
83
|
|
|
@@ -117,6 +133,7 @@ POWER-specific:
|
|
|
117
133
|
- Historical gridded observations, rather than site measurements or forecasts. Meteorological coverage starts in 1981, solar in 1984 and hourly in 2001; source configuration and publication latency further constrain availability.
|
|
118
134
|
- One active upstream request, starts at least two seconds apart, bounded retries and a 55-second overall call deadline. NASA publishes no numeric request allowance. References cache for 24 hours and observations for 10 minutes.
|
|
119
135
|
- Source fill values become `null`; zero remains a measurement. Monthly annual keys and climatology `ANN` remain distinct from monthly observations. LST labels have no UTC offset.
|
|
136
|
+
- `T_ZONES` and `TM_ZONES` retain numeric climate-zone codes with `valueKind: categorical`, including in SQL column metadata. They have no arithmetic summaries or comparison sort metrics; explicit numeric sorting by either is rejected.
|
|
120
137
|
|
|
121
138
|
Agent-friendly output:
|
|
122
139
|
|
|
@@ -124,93 +141,36 @@ Agent-friendly output:
|
|
|
124
141
|
- Explicit gaps — `omittedParameters` distinguishes an absent series from fill values; arithmetic observation means and calendar-season buckets are not climate normals, annual yields or water balances.
|
|
125
142
|
- Complete datasets — inline outputs each fit 40,000 characters. Larger datasets stage all rows with a preview of at most 20 rows and a `dataset` handle; unsupported or oversized requests fail with narrowing guidance instead of returning a capped source prefix.
|
|
126
143
|
|
|
127
|
-
Staging requires DuckDB and supports at most 250,000 rows, 64 parameter columns and 32 MiB of serialized rows per dataset. Canvases are process-local capabilities: pass the returned token explicitly and route later calls to the same process. Tables expire after 30 minutes
|
|
144
|
+
Staging requires DuckDB and supports at most 250,000 rows, 64 parameter columns and 32 MiB of serialized rows per dataset. Canvases are process-local capabilities: pass the returned token explicitly and route later calls to the same process. Tables expire after 30 minutes with eight tables per canvas. Defaults are one idle hour and six absolute hours per canvas, four canvases per tenant, eight per process, and 256 MiB engine memory per canvas. Operators can size canvas capacity, memory and lifetime below; engine memory does not bound total RSS or temporary disk.
|
|
128
145
|
|
|
129
146
|
## Getting started
|
|
130
147
|
|
|
131
|
-
|
|
148
|
+
Connect to the hosted instance, no install:
|
|
132
149
|
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
"mcpServers": {
|
|
136
|
-
"nasa-power-mcp-server": {
|
|
137
|
-
"type": "stdio",
|
|
138
|
-
"command": "bunx",
|
|
139
|
-
"args": ["@cyanheads/nasa-power-mcp-server@latest"],
|
|
140
|
-
"env": { "MCP_TRANSPORT_TYPE": "stdio" }
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
150
|
+
```sh
|
|
151
|
+
claude mcp add --transport http nasa-power-mcp-server https://nasa-power.caseyjhand.com/mcp
|
|
144
152
|
```
|
|
145
153
|
|
|
146
|
-
Or
|
|
154
|
+
Or run it locally:
|
|
147
155
|
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
"mcpServers": {
|
|
151
|
-
"nasa-power-mcp-server": {
|
|
152
|
-
"type": "stdio",
|
|
153
|
-
"command": "npx",
|
|
154
|
-
"args": ["-y", "@cyanheads/nasa-power-mcp-server@latest"],
|
|
155
|
-
"env": { "MCP_TRANSPORT_TYPE": "stdio" }
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
156
|
+
```sh
|
|
157
|
+
claude mcp add nasa-power-mcp-server -- npx -y @cyanheads/nasa-power-mcp-server
|
|
159
158
|
```
|
|
160
159
|
|
|
161
|
-
|
|
160
|
+
For other clients, add this to the MCP config file:
|
|
162
161
|
|
|
163
162
|
```json
|
|
164
163
|
{
|
|
165
164
|
"mcpServers": {
|
|
166
165
|
"nasa-power-mcp-server": {
|
|
167
|
-
"
|
|
168
|
-
"
|
|
169
|
-
"args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/nasa-power-mcp-server:latest"]
|
|
166
|
+
"command": "npx",
|
|
167
|
+
"args": ["-y", "@cyanheads/nasa-power-mcp-server"]
|
|
170
168
|
}
|
|
171
169
|
}
|
|
172
170
|
}
|
|
173
171
|
```
|
|
174
172
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
```sh
|
|
178
|
-
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
|
|
179
|
-
# Server listens at http://127.0.0.1:3010/mcp
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
### Prerequisites
|
|
183
|
-
|
|
184
|
-
- [Bun v1.4.0](https://bun.sh/) or higher (or Node.js v24+).
|
|
185
|
-
- npm and Docker install native DuckDB dependencies normally on supported platforms, and staging and SQL are on by default. Set `CANVAS_PROVIDER_TYPE=none` to keep every result inline.
|
|
186
|
-
- The portable Claude Desktop MCPB bundle fixes `CANVAS_PROVIDER_TYPE=none` and supports inline results. Narrow an oversized request or use npm/Docker for analytics.
|
|
187
|
-
|
|
188
|
-
### Installation
|
|
189
|
-
|
|
190
|
-
1. **Clone the repository:**
|
|
191
|
-
|
|
192
|
-
```sh
|
|
193
|
-
git clone https://github.com/cyanheads/nasa-power-mcp-server.git
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
2. **Navigate into the directory:**
|
|
197
|
-
|
|
198
|
-
```sh
|
|
199
|
-
cd nasa-power-mcp-server
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
3. **Install dependencies:**
|
|
203
|
-
|
|
204
|
-
```sh
|
|
205
|
-
bun install
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
4. **Configure environment:**
|
|
209
|
-
|
|
210
|
-
```sh
|
|
211
|
-
cp .env.example .env
|
|
212
|
-
# edit .env to change transport, logging or canvas settings
|
|
213
|
-
```
|
|
173
|
+
npm and Docker installs stage large results in DuckDB for SQL by default; set `CANVAS_PROVIDER_TYPE=none` to keep every result inline. The Claude Desktop bundle is inline-only: narrow an oversized request, or use npm or Docker for analytics. No NASA account or API key is required. For Docker or a source build, see [Running the server](#running-the-server).
|
|
214
174
|
|
|
215
175
|
## Configuration
|
|
216
176
|
|
|
@@ -218,22 +178,33 @@ cp .env.example .env
|
|
|
218
178
|
|:---|:---|:---|
|
|
219
179
|
| `NASA_POWER_DATAFRAME_DROP_ENABLED` | Expose explicit staged-table removal. | `false` |
|
|
220
180
|
| `CANVAS_PROVIDER_TYPE` | `duckdb` stages large results for SQL on npm/Docker; `none` keeps results inline. MCPB fixes `none`. | `duckdb` |
|
|
221
|
-
| `CANVAS_DEFAULT_MEMORY_LIMIT_MB` |
|
|
222
|
-
| `CANVAS_MAX_CANVASES_PER_TENANT` |
|
|
223
|
-
| `
|
|
224
|
-
| `
|
|
181
|
+
| `CANVAS_DEFAULT_MEMORY_LIMIT_MB` | Per-canvas engine memory, integer ≥64 MiB; not total RSS or temporary disk. | `256` |
|
|
182
|
+
| `CANVAS_MAX_CANVASES_PER_TENANT` | Positive tenant canvas cap; auth-none callers share one tenant. | `4` |
|
|
183
|
+
| `NASA_POWER_MAX_CANVASES_PER_PROCESS` | Positive process canvas cap, including pending and failed cleanup reservations. | `8` |
|
|
184
|
+
| `CANVAS_TTL_MS` | Positive sliding canvas lifetime in milliseconds. | `3600000` |
|
|
185
|
+
| `CANVAS_ABSOLUTE_CAP_MS` | Absolute canvas lifetime in milliseconds, at least the sliding TTL. | `21600000` |
|
|
225
186
|
| `MCP_TRANSPORT_TYPE` | `stdio` or `http`. | `stdio` |
|
|
226
187
|
| `MCP_HTTP_HOST` / `MCP_HTTP_PORT` | HTTP bind address and port. | `127.0.0.1` / `3010` |
|
|
227
188
|
| `MCP_AUTH_MODE` | `none`, `jwt` or `oauth`. | `none` |
|
|
228
189
|
| `MCP_LOG_LEVEL` | Minimum log level. | `info` |
|
|
229
190
|
| `OTEL_ENABLED` | Enable [OpenTelemetry](https://github.com/cyanheads/mcp-ts-core/tree/main/docs/telemetry). | `false` |
|
|
230
191
|
|
|
231
|
-
|
|
192
|
+
Unset, blank and whole-value placeholder settings retain these defaults. Invalid sizing fails startup. Byte budgets, table limits and producer concurrency remain fixed independently of operator canvas sizing. See [`.env.example`](./.env.example) for optional transport, authentication, storage, logging and telemetry settings.
|
|
232
193
|
|
|
233
194
|
## Running the server
|
|
234
195
|
|
|
235
196
|
### Local development
|
|
236
197
|
|
|
198
|
+
Requires [Bun v1.4.0](https://bun.sh/) or higher (or Node.js v24+).
|
|
199
|
+
|
|
200
|
+
- **Clone and install:**
|
|
201
|
+
|
|
202
|
+
```sh
|
|
203
|
+
git clone https://github.com/cyanheads/nasa-power-mcp-server.git
|
|
204
|
+
cd nasa-power-mcp-server && bun install
|
|
205
|
+
cp .env.example .env # optional: transport, logging or canvas settings
|
|
206
|
+
```
|
|
207
|
+
|
|
237
208
|
- **Build and run the production version**:
|
|
238
209
|
|
|
239
210
|
```sh
|
|
@@ -255,17 +226,17 @@ DuckDB startup rejects changes to the four fixed canvas settings. See [`.env.exa
|
|
|
255
226
|
### Docker
|
|
256
227
|
|
|
257
228
|
```sh
|
|
258
|
-
docker
|
|
259
|
-
docker run --rm -p 127.0.0.1:3010:3010 nasa-power-mcp-server
|
|
229
|
+
docker run --rm -p 127.0.0.1:3010:3010 ghcr.io/cyanheads/nasa-power-mcp-server:latest
|
|
260
230
|
```
|
|
261
231
|
|
|
262
|
-
The image defaults to HTTP on port 3010 in stateless session mode and logs to `/var/log/nasa-power-mcp-server`. OpenTelemetry peer dependencies are installed by default
|
|
232
|
+
The image defaults to HTTP on port 3010 in stateless session mode and logs to `/var/log/nasa-power-mcp-server`. To run it over stdio from an MCP client, use `"command": "docker"` with `"args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/nasa-power-mcp-server:latest"]`. To build locally, `docker build -t nasa-power-mcp-server .`; OpenTelemetry peer dependencies are installed by default — build with `--build-arg OTEL_ENABLED=false` to omit them. For a client outside loopback, configure authentication and TLS at the deployment boundary.
|
|
263
233
|
|
|
264
234
|
## Project structure
|
|
265
235
|
|
|
266
236
|
| Path | Purpose |
|
|
267
237
|
|:---|:---|
|
|
268
|
-
| `src/index.ts` | Nine tool registrations, bounded canvas setup and service shutdown |
|
|
238
|
+
| `src/index.ts` | Nine tool registrations, the published skill tree, bounded canvas setup and service shutdown |
|
|
239
|
+
| `skills` | The `nasa-power-guide` agent skill, published to plugin hosts and served over MCP |
|
|
269
240
|
| `src/config` | Workload limits and server-specific environment parsing |
|
|
270
241
|
| `src/mcp-server/tools/definitions` | Tool contracts and comparison orchestration |
|
|
271
242
|
| `src/services/power` | Paced NASA client, normalization, presets and scientific summaries |
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Complete regional analysis and configurable canvases"
|
|
3
|
+
breaking: true
|
|
4
|
+
security: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 0.3.0 — 2026-10-24
|
|
8
|
+
|
|
9
|
+
## Added
|
|
10
|
+
|
|
11
|
+
- **Canvas sizing** honors validated memory, tenant capacity and lifetime overrides; `NASA_POWER_MAX_CANVASES_PER_PROCESS` controls process capacity with the existing default of eight ([#19](https://github.com/cyanheads/nasa-power-mcp-server/issues/19)).
|
|
12
|
+
- **Regional summary staging** returns complete observation and summary tables with `summaryDataset`, exact `summaryCount`, ordered `summaryIndex` retrieval and linked provenance; registration failures roll back the complete new batch ([#24](https://github.com/cyanheads/nasa-power-mcp-server/issues/24)).
|
|
13
|
+
- **Point climatology** accepts optional `canvas_id` for workspace reuse and stages oversized profiles completely with bounded previews ([#23](https://github.com/cyanheads/nasa-power-mcp-server/issues/23)).
|
|
14
|
+
|
|
15
|
+
## Changed
|
|
16
|
+
|
|
17
|
+
- Regional climatology no longer accepts startYear or endYear; omit both even when they match the source period (#20). Use point climatology for custom year windows.
|
|
18
|
+
- **SQL columns named `current_schema`** now require table qualification: use `c.current_schema` rather than `current_schema` when selecting that CTE column.
|
|
19
|
+
- **Development tooling** follows the adopted framework guidance and audit classification; Bun runtime and Docker images move from 1.4.3 to 1.4.4.
|
|
20
|
+
- **Hosted access** is documented at `https://nasa-power.caseyjhand.com/mcp` and advertised in registry metadata.
|
|
21
|
+
|
|
22
|
+
## Fixed
|
|
23
|
+
|
|
24
|
+
- **Climate-zone codes** `T_ZONES` and `TM_ZONES` retain numeric values with categorical metadata and no arithmetic summaries or numeric comparison sorting; shared source units remain present independently of numeric comparability ([#21](https://github.com/cyanheads/nasa-power-mcp-server/issues/21)).
|
|
25
|
+
- **Tilted-solar aliases** `SI_TILTED_AVG`, `SI_TILTED_MIN` and `SI_TILTED_MAX` report only their returned members in `expansions` and are omitted only when no member returns ([#22](https://github.com/cyanheads/nasa-power-mcp-server/issues/22)).
|
|
26
|
+
- **Environment initialization** loads `.env` before server-specific parsing; framework error text and link rendering preserve literal source values on both response surfaces.
|
|
27
|
+
|
|
28
|
+
## Dependencies
|
|
29
|
+
|
|
30
|
+
- `@cyanheads/mcp-ts-core` ^0.13.15 → ^0.13.16.
|
|
31
|
+
- `@duckdb/node-api` ^1.5.6-r.1 → ^1.5.6-r.2.
|
|
32
|
+
- `@biomejs/biome` 2.5.15 → 2.6.2.
|
|
33
|
+
- `ignore` ^7.0.12 → ^7.0.13.
|
|
34
|
+
- `tsc-alias` ^1.9.7 → ^1.9.8.
|
|
35
|
+
- Added test dependencies `markdown-it` ^15.0.3 and `@types/markdown-it` ^14.2.0.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Publishes the nasa-power-guide agent skill, served over MCP as skill://nasa-power-guide/SKILL.md, and moves to mcp-ts-core 0.13.18, which stops HTTP memory growth under Bun and keeps the framework build-only files out of the .mcpb bundle."
|
|
3
|
+
breaking: false
|
|
4
|
+
security: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 0.4.0 — 2026-10-28
|
|
8
|
+
|
|
9
|
+
## Added
|
|
10
|
+
|
|
11
|
+
- **`nasa-power-guide` agent skill** — `skills/nasa-power-guide/SKILL.md`, served over MCP as `skill://nasa-power-guide/SKILL.md` (plus the `skill://{+path}` template) through `createApp({ skills })` (mcp-ts-core 0.13.18). It covers which tool answers a typical-month versus a dated question, grid-cell size, data freshness, rate versus total units, degree days, the one-data-call-at-a-time gate, and SQL over staged tables. It ships in the npm package, the Docker image, and the `.mcpb` bundle.
|
|
12
|
+
- **Agent Plugins `plugin.json` and `mcp.json`** at the repo root (mcp-ts-core 0.13.18 template, [cyanheads/mcp-ts-core#426](https://github.com/cyanheads/mcp-ts-core/issues/426)) — the 1.0.0 manifest read by Codex, Cursor, GitHub Copilot, VS Code and Kiro, and a stdio `npx -y @cyanheads/nasa-power-mcp-server` entry with `MCP_TRANSPORT_TYPE=stdio`.
|
|
13
|
+
- **`add-skill` framework skill** for authoring published skills in root `skills/`.
|
|
14
|
+
|
|
15
|
+
## Changed
|
|
16
|
+
|
|
17
|
+
- **The `.mcpb` bundle** no longer carries the framework's build-only files (its `changelog/`, `config/`, `scripts/`, `templates/`, `CLAUDE.md`, `AGENTS.md`) (mcp-ts-core 0.13.18, [cyanheads/mcp-ts-core#791](https://github.com/cyanheads/mcp-ts-core/issues/791)). The bundle cleaner and `lint:packaging` select agent docs only at a dependency package's root, so the MCP SDK's runtime `dist/ext/skills/` modules stay in the bundle ([cyanheads/mcp-ts-core#794](https://github.com/cyanheads/mcp-ts-core/issues/794), ported locally with `tests/scripts/mcpb-agent-docs.test.ts`).
|
|
18
|
+
- **`.mcpbignore`** uses root-anchored entries and now also excludes `/changelog/`, `/.claude-plugin/`, `/.codex-plugin/`, `/plugin.json`, `/mcp.json`, `/CLAUDE.md`, `/AGENTS.md`, `/.dockerignore`, `/.gitattributes` and `/devcheck.config.json`; root `skills/` ships.
|
|
19
|
+
- **`package.json` `files`** gains `skills/`, and the **Dockerfile** copies `skills/` into the production image.
|
|
20
|
+
- **`lint:packaging`** also validates the root `plugin.json`/`mcp.json` pair and the published `skills/` tree; `check-skills-sync` identifies framework skills by frontmatter only.
|
|
21
|
+
- **README getting started** is restructured: a hosted-endpoint `claude mcp add` line, an `npx` install, one generic JSON config, and the Docker run command against the published image; the clone-and-install steps move under Local development. A Skills section lists `nasa-power-guide`.
|
|
22
|
+
- **Bug report form** replaces five separate fields with one Environment table.
|
|
23
|
+
- **`bunfig.toml`** `minimumReleaseAge` drops from 3 days to 1 day (`@cyanheads/mcp-ts-core` stays excluded).
|
|
24
|
+
- **Framework skills**: 17 updated to the mcp-ts-core 0.13.18 versions.
|
|
25
|
+
- **`tests/config/startup.test.ts`** links `skills/` into its scratch directory so the bundled entry finds it; `CLAUDE.md`, `AGENTS.md` and `docs/design.md` describe the published skill and the DuckDB 1.5.6 hold.
|
|
26
|
+
|
|
27
|
+
## Fixed
|
|
28
|
+
|
|
29
|
+
- **HTTP memory growth under Bun** — the HTTP transport no longer retains about 71 KiB per request through its shutdown signal, so sustained HTTP traffic no longer grows memory until the process runs out. 0.3.0 shipped on mcp-ts-core 0.13.16, and the Docker image runs under Bun (mcp-ts-core 0.13.17, [cyanheads/mcp-ts-core#786](https://github.com/cyanheads/mcp-ts-core/issues/786)).
|
|
30
|
+
|
|
31
|
+
## Dependencies
|
|
32
|
+
|
|
33
|
+
- `@cyanheads/mcp-ts-core` ^0.13.16 → ^0.13.18.
|
|
34
|
+
- `@biomejs/biome` 2.6.2 → 2.6.3.
|
|
35
|
+
- `ignore` ^7.0.13 → ^7.0.14.
|
|
36
|
+
- `tsc-alias` ^1.9.8 → ^1.9.9.
|
|
@@ -37,6 +37,7 @@ export declare const POWER_LIMITS: {
|
|
|
37
37
|
};
|
|
38
38
|
/** Server-specific environment configuration. */
|
|
39
39
|
export declare const ServerConfigSchema: z.ZodObject<{
|
|
40
|
+
maxCanvasesPerProcess: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
40
41
|
dataframeDropEnabled: z.ZodDefault<z.ZodCodec<z.ZodString, z.ZodBoolean>>;
|
|
41
42
|
}, z.core.$strip>;
|
|
42
43
|
/** Parsed configuration consumed by services. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-config.d.ts","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA,uGAAuG;AACvG,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAG3C,4EAA4E;AAC5E,eAAO,MAAM,YAAY;aACvB,UAAU,EAAE,IAAK;aACjB,UAAU,EAAE,EAAE;aACd,WAAW,EAAE,KAAM;aACnB,UAAU,EAAE,KAAM;aAClB,SAAS,EAAE,KAAM;aACjB,QAAQ,EAAE,CAAC;aACX,kBAAkB,EAAE,EAAE;aACtB,SAAS;aACT,mBAAmB;aACnB,IAAI,EAAE,MAAO;aACb,OAAO,EAAE,EAAE;aACX,QAAQ;aACR,gBAAgB,EAAE,KAAM;aACxB,UAAU;aACV,YAAY,EAAE,GAAG;aACjB,cAAc,EAAE,QAAU;aAC1B,SAAS,EAAE,MAAO;aAClB,mBAAmB;aACnB,oBAAoB;aACpB,mBAAmB;aACnB,oBAAoB;aACpB,SAAS,EAAE,CAAC;aACZ,eAAe,EAAE,CAAC;aAClB,iBAAiB,EAAE,CAAC;aACpB,kBAAkB,EAAE,CAAC;aACrB,UAAU,EAAE,OAAS;aACrB,WAAW,EAAE,OAAS;aACtB,mBAAmB,EAAE,QAAU;aAC/B,OAAO,EAAE,KAAM;aACf,aAAa,EAAE,KAAM;aACrB,SAAS,EAAE,IAAK;aAChB,OAAO,EAAE,CAAC;CACF,CAAC;AACX,iDAAiD;AACjD,eAAO,MAAM,kBAAkB
|
|
1
|
+
{"version":3,"file":"server-config.d.ts","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA,uGAAuG;AACvG,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAG3C,4EAA4E;AAC5E,eAAO,MAAM,YAAY;aACvB,UAAU,EAAE,IAAK;aACjB,UAAU,EAAE,EAAE;aACd,WAAW,EAAE,KAAM;aACnB,UAAU,EAAE,KAAM;aAClB,SAAS,EAAE,KAAM;aACjB,QAAQ,EAAE,CAAC;aACX,kBAAkB,EAAE,EAAE;aACtB,SAAS;aACT,mBAAmB;aACnB,IAAI,EAAE,MAAO;aACb,OAAO,EAAE,EAAE;aACX,QAAQ;aACR,gBAAgB,EAAE,KAAM;aACxB,UAAU;aACV,YAAY,EAAE,GAAG;aACjB,cAAc,EAAE,QAAU;aAC1B,SAAS,EAAE,MAAO;aAClB,mBAAmB;aACnB,oBAAoB;aACpB,mBAAmB;aACnB,oBAAoB;aACpB,SAAS,EAAE,CAAC;aACZ,eAAe,EAAE,CAAC;aAClB,iBAAiB,EAAE,CAAC;aACpB,kBAAkB,EAAE,CAAC;aACrB,UAAU,EAAE,OAAS;aACrB,WAAW,EAAE,OAAS;aACtB,mBAAmB,EAAE,QAAU;aAC/B,OAAO,EAAE,KAAM;aACf,aAAa,EAAE,KAAM;aACrB,SAAS,EAAE,IAAK;aAChB,OAAO,EAAE,CAAC;CACF,CAAC;AACX,iDAAiD;AACjD,eAAO,MAAM,kBAAkB;;;iBAY7B,CAAC;AACH,iDAAiD;AACjD,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,wEAAwE;AACxE,wBAAgB,eAAe,IAAI,YAAY,CAO9C"}
|