Skip to content

noaa climate mcp server changelog

io.github.cyanheads/noaa-climate-mcp-server

10 changes recorded. MCP Harbor re-reads this listing from the official registry every six hours and asks the live server what it exposes, and keeps what changed between one look and the next.

  • Tools +1
    • + noaa_climate_get_normals

  • server.json 1 field changed
    version
    0.8.0 0.9.0

  • AGENTS.md +12 −6

    https://raw.githubusercontent.com/cyanheads/noaa-climate-mcp-server/HEAD/AGENTS.md

    − **Version:** 0.7.1− **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.15`− **MCP SDK:** `@modelcontextprotocol/server` ^2.3.1− NOAA Climate Data Online (CDO) API v2 — historical weather data — plus two separate NCEI bulk-CSV corpora: the Storm Events Database and Billion-Dollar Weather and Climate Disasters. 10 tools, 2 resources:− | `bun run lint:packaging` | Packaging surface checks — `server.json`/`manifest.json` env-var parity (run by devcheck) |− `npm run bundle` produces a `.mcpb` extension bundle for one-click install in Claude Desktop. The pack step is followed by `scripts/clean-mcpb.ts`, which prunes dev dependencies (`mcpb clean`) and strips two classes of `node_modules/**` content that root-anchored `.mcpbignore` patterns cannot reach: dependency-shipped agent docs (`framework-skills/`, `skills/`, `.claude/`, `.agents/`, `SKILL.md`) and platform-specific native bindings, which would otherwise lock the bundle to the platform it was + **Version:** 0.8.0+ **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.18`+ **MCP SDK:** `@modelcontextprotocol/server` ^2.4.0+ NOAA Climate Data Online (CDO) API v2 — historical weather data — plus two separate NCEI bulk-CSV corpora: the Storm Events Database and Billion-Dollar Weather and Climate Disasters. 10 tools, 2 data resources, and 1 published agent skill:+ CDO station inputs share `stationIdFilter` / `stationIdArrayFilter` and `normalizeStationId` in `shared/validation.ts`: trim, uppercase, and prefix bare 11-character GHCN aliases; generic IDs remain opaque. Successful tools compose normalization notices; the station resource keeps its existing result shape. `/data` alone checks the actual encoded query against 4000 characters before retry/fetch. Fetch-data keeps raw CDO types distinct from its output: documented PRECIP_HLY/HPCP and PRECIP_15/QPC+ `skills/noaa-climate-guide/SKILL.md` is the published caller guide for climate comparisons, coverage, observation quality, and storm-to-station investigation. `src/index.ts` serves it through the MCP Skills extension and a skill resource alongside the two data resources. Plugin, npm, Docker, and MCPB delivery preserve the root `skills/` tree.+ | `add-skill` | Author and publish agent-facing skills from root `skills/`, served over MCP |+ | `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) |+ `npm run bundle` produces a `.mcpb` extension bundle for one-click install in Claude Desktop. `mcpb pack` reads `.mcpbignore`, not `.gitignore`, so every root path the bundle must not ship — source, tests, docs, caches, logs, agent docs, plugin manifests, gitignored local files — 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. The pack step is followed by+ - [ ] `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 `.code+ - [ ] Any new root dev path has a root-anchored line in `.mcpbignore`; `bun run bundle` and `lint:packaging` pass+ - [ ] 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

  • Resources +1
    • + noaa-climate-guide
  • server.json 1 field changed
    version
    0.7.1 0.8.0

  • AGENTS.md +6 −6

    https://raw.githubusercontent.com/cyanheads/noaa-climate-mcp-server/HEAD/AGENTS.md

    − **Version:** 0.6.5− **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.14`− **MCP SDK:** `@modelcontextprotocol/server` ^2.0.0− **Zod:** ^4.6.5− - `noaa_climate_get_billion_dollar_disasters` — query NCEI Billion-Dollar Weather and Climate Disasters, per disaster or per year− **Every release goes through a release PR, straight-through** — `git-wrapup`'s "Release PR mode", mode `straight-through`. One run: `git-wrapup` lands the commit stack on `release/<version>`, pushes it, and opens the PR (title = the release commit subject, body = the release digest: theme line, `## Changes`, `## Gates`, changelog link last); `release-and-publish` then fast-forwards `main` locally with `git merge --ff-only`, creates the tag on `main`'s tip, pushes `main` and the tag, deletes the + **Version:** 0.7.1+ **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.15`+ **MCP SDK:** `@modelcontextprotocol/server` ^2.3.1+ **Zod:** ^4.6.7+ - `noaa_climate_get_billion_dollar_disasters` — query NCEI’s retired 1980–2024 Billion-Dollar Weather and Climate Disasters archive, per disaster or per year. Every successful response carries a retirement notice composed with paging guidance. CPI adjustments stay as archived, without current-price rebasing or an inferred base year; `coveredYears` stays row-derived. State shape is advertised as `^\s*[A-Za-z]{2}\s*$`; well-formed unavailable codes remain `unknown_state`.+ **Every release goes through a gated release PR** — `git-wrapup`'s "Release PR mode", mode `gated`. Three separate runs, never one: `git-wrapup` lands the commit stack on `release/<version>`, pushes it, and opens the PR (title = the release commit subject, body = the release digest: theme line, `## Changes`, `## Gates`, changelog link last); `release-pr-review` reviews and fixes on that branch (each fix an ordinary commit on top of the stack, pushed plainly — nothing already pushed is ever rewri
  • server.json 2 fields changed
    env_vars
    NOAA_CDO_TOKEN, MCP_LOG_LEVEL NOAA_CLAMP_LIMITS, NOAA_CDO_TOKEN, MCP_LOG_LEVEL
    version
    0.7.0 0.7.1

  • server.json 1 field changed
    version
    0.6.5 0.7.0

  • AGENTS.md +19 −18

    https://raw.githubusercontent.com/cyanheads/noaa-climate-mcp-server/HEAD/AGENTS.md

    − **Version:** 0.6.4− **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.6`− | `ctx.fail` / `ctx.recoveryFor` | Emit a declared tool/resource failure and carry its canonical recovery hint. |− | `ctx.requestId` / `ctx.tenantId` / `ctx.auth` | Propagated by passing the complete `ctx` as `parentContext` when a service creates an operation context. |− **Recommended: typed error contract.** Declare `errors: [{ reason, code, when, recovery, retryable?, severity?, thrownBy? }]` on `tool()` / `resource()` to receive `ctx.fail(reason, …)` typed against the reason union. TypeScript catches typos at compile time, `data.reason` is auto-populated for observability, linter enforces conformance against the handler body. `recovery` is required (≥ 5 words, lint-validated) — the single source of truth for the agent's next move. Pass `ctx.recoveryFor('reaso−   if (!item) throw ctx.fail('no_match', `No item ${input.id}`, ctx.recoveryFor('no_match'));− throw new McpError(JsonRpcErrorCode.DatabaseError, 'Connection failed', { pool: 'primary' });− | `git-wrapup` | Land working-tree changes as a versioned commit stack on a `release/<version>` branch — version bump, changelog, verify, PR |− | `release-pr-review` | Review pass on an open release PR — simplifier + correctness review, fixes as ordinary commits on top of the stack, PR body kept in sync |− | `release-and-publish` | Fast-forward `main`, tag, push + npm + MCP Registry + GH Release + Docker. Picks up from `git-wrapup` |− | `api-context` | Context interface, dual-sink logger, state, requestInput/inputs, enrichment |− | `bun run audit:refresh` | Delete `bun.lock`, reinstall, and re-run `bun audit`. Last resort after `audit:fix`, `bun update <name>`, and `bun dedupe` — it re-resolves every ranged dep (the framework pin included) and rewrites the lockfile as `lockfileVersion: 2` |− **CI is one file.** `.github/workflows/codeql.yml` is the only GitHub Actions workflow: CodeQL is GitHub-owned end to end, and the file runs only while the repo's CodeQL *default setup* is turned off. Verification — `devcheck`, tests, the release gates — runs locally; don't add a workflow that re-runs it.− **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.− **Every release goes through a release PR, straight-through** — `git-wrapup`'s "Release PR mode", mode `straight-through`. One run: `git-wrapup` lands the commit stack on `release/<version>`, pushes it, and opens the PR (title = the release commit subject, body = the changelog entry plus a gates section); `release-and-publish` then fast-forwards `main` locally with `git merge --ff-only`, creates the tag on `main`'s tip, pushes `main` and the tag, deletes the branch, and publishes. A caller's bri− - [ ] `.codex-plugin/plugin.json` populated — `name`, `version`, `description`, `repository`, `license` from `package.json`; `interface.displayName` = package name; `interface.shortDescription` from `package.json` description− - [ ] `.codex-plugin/mcp.json` updated — server name key matches `package.json` name; env vars added for any required API keys− - [ ] `.claude-plugin/plugin.json` populated — `name`, `version`, `description`, `repository`, `license` from `package.json`; inline `mcpServers` entry with server name key, env vars for any required API keys+ **Version:** 0.6.5+ **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.14`+ - **Cut noise.** Add only what earns its place: no speculative generality, no guards for states the framework already prevents (Zod-validated params, classified errors), no abstraction until a third caller proves it, no option nothing sets.+ | `ctx.fail` | Emit a declared tool/resource failure; the framework fills the entry's recovery hint on the wire. `ctx.recoveryFor(reason)` reads a declared hint, for forwarding one reason's hint onto another. |+ | `ctx.requestId` / `ctx.tenantId` / `ctx.auth` | Propagated by passing the complete `ctx` as `parentContext` when a service creates an operation context. `ctx.requestId` is the ID every log record of the call carries and its error envelope returns as `data.requestId`. |+ **Recommended: typed error contract.** Declare `errors: [{ reason, code, when, recovery, retryable?, severity?, thrownBy? }]` on `tool()` / `resource()` to receive `ctx.fail(reason, …)` typed against the reason union. TypeScript catches typos at compile time, `data.reason` is auto-populated for observability, linter enforces conformance against the handler body. `recovery` is required (≥ 5 words, lint-validated) — the single source of truth for the agent's next move. The framework puts it on the+   if (!item) throw ctx.fail('no_match', `No item ${input.id}`);+ throw new McpError(JsonRpcErrorCode.InitializationFailed, 'Connection failed', { pool: 'primary' });+ | `git-wrapup` | Land working-tree changes as a commit stack — version bump, changelog, verify, commit by concern, release commit on top. No tag, no push to main; opens the release PR when the project declares release PR mode |+ | `release-pr-review` | Review pass on an open release PR — simplifier + correctness review, fixes as ordinary commits on top of the stack, PR body kept in sync. Release PR mode only |+ | `release-and-publish` | Fast-forward merge (release PR mode) + tag + push + npm + MCP Registry + GH Release + Docker. Picks up from `git-wrapup` |+ | `api-context` | Context interface, RequestContext, logger, state, multi-round-trip input |+ | `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` |+ **CI is one file.** `.github/workflows/codeql.yml` (scaffolded) is the only GitHub Actions workflow: CodeQL is GitHub-owned end to end, and the file runs only while the repo's CodeQL *default setup* is turned off. Verification — `devcheck`, tests, the release gates — runs locally; don't add a workflow that re-runs it.+ **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": ""`.+ **Every release goes through a release PR, straight-through** — `git-wrapup`'s "Release PR mode", mode `straight-through`. One run: `git-wrapup` lands the commit stack on `release/<version>`, pushes it, and opens the PR (title = the release commit subject, body = the release digest: theme line, `## Changes`, `## Gates`, changelog link last); `release-and-publish` then fast-forwards `main` locally with `git merge --ff-only`, creates the tag on `main`'s tip, pushes `main` and the tag, deletes the + - [ ] `.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+ - [ ] `.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+ - [ ] `.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 wri

  • server.json 1 field changed
    version
    0.6.4 0.6.5