Releases: cyanheads/bls-labor-mcp-server
Release list
v0.4.6: mcp-ts-core ^0.10.9 maintenance
mcp-ts-core ^0.10.9 maintenance
Adopts @cyanheads/mcp-ts-core ^0.10.6 → ^0.10.9; framework changes most relevant to this server's DataCanvas and plugin surfaces.
Added:
- check-dependency-specifiers devcheck gate — rejects floating specifiers (latest, *, pre-release dist-tags) in package.json and bun.lock workspaces.
- Plugin-manifest validation in lint:packaging (devcheck.config.json packaging.pluginManifests), checking the .claude-plugin/.codex-plugin manifests for descriptions, unscoped display identity, and full-name install args.
Changed:
- bls_dataframe_query SQL gate now classifies a parseable-but-unpreparable SELECT (mistyped column, unknown function) as ValidationError reason=invalid_sql with the DuckDB binder detail, instead of the misleading non_select_statement.
- DuckdbProvider.describe() WHERE filters qualified with the table alias — fixes an ambiguous-column Binder Error on filtered bls_dataframe_describe.
- Filled the empty .codex-plugin/plugin.json longDescription with the server workflow summary.
- Re-synced eight bundled skills and the devcheck script set to ^0.10.9.
Dependency bumps:
- @cyanheads/mcp-ts-core ^0.10.6 → ^0.10.9
- @duckdb/node-api ^1.5.3-r.3 → ^1.5.4-r.1
- @types/node ^25.9.3 → ^26.0.0
154 tests pass; bun run devcheck clean.
v0.4.5: Server instructions, plugin identity, dep refresh
Server instructions, plugin identity, dep refresh
Adds a server-level instruction string to createApp() and finishes unscoping the plugin manifests' display identity to the bare repo name.
Added:
- createApp() instructions string — orients clients to the bls_* surface, the optional BLS_API_KEY quota tiers, SeriesID/survey conventions, and the list-surveys → search-series → get-series/get-latest workflow.
Changed:
- Plugin manifest display identity unscoped to bls-labor-mcp-server — .claude-plugin/plugin.json name + mcpServers key, .codex-plugin/plugin.json name, .codex-plugin/mcp.json server key drop the npm scope. Install args stay @cyanheads/bls-labor-mcp-server; the published package is unchanged.
Dependency bumps:
- better-sqlite3 ^12.10.0 → ^12.11.1
- @biomejs/biome ^2.4.16 → ^2.5.0
- vitest ^4.1.8 → ^4.1.9
154 tests pass; bun run devcheck clean.
v0.4.4: mcp-ts-core ^0.10.6 adoption, MCPB bundle hygiene
mcp-ts-core ^0.10.6 adoption, MCPB bundle hygiene
Adopts the @cyanheads/mcp-ts-core 0.10 framework APIs and tightens MCPB bundle packaging.
Dependency bumps:
@cyanheads/mcp-ts-core^0.9.21 → ^0.10.6@types/node^25.9.1 → ^25.9.3
Added:
scripts/clean-mcpb.ts— strips dependency-shipped agent-docs (skills/, .claude/, .agents/, SKILL.md) nested under node_modules/ from the packed bundle; wired into thebundlescript.lint-packagingchecks 5-9 — .mcpbignore content guards, post-bundle agent-doc assertion, and name/title/display_name identity enforcement.check-framework-antipatternsrule 4 — flags z.coerce.boolean() on env flags.- Dockerfile
HEALTHCHECK(bun fetch /healthz) and APP_VERSION image label.
Changed:
- Canvas SQL system-catalog denial delegated to the framework gate via
denySystemCatalogs: true;system_catalog_accessreason code preserved. bls_search_seriesenrichment usesctx.enrich.total()/ctx.enrich.truncated();totalFound→totalCount, adds truncated/shown/cap.- Boolean env flags use
z.stringbool()sofalse/0/no/offdisable correctly. createApp()name/title and .codex-plugin displayName set to the unscoped repo name.- .mcpbignore patterns anchored to root.
Removed:
sql-gate-extras.ts— superseded by the framework gate.
154 tests pass; bun run devcheck clean.
v0.4.3: Search output renames, get-latest double-list fix, capped flag
Search output renames, get-latest double-list fix, capped flag
BREAKING: bls_search_series output fields renamed and seasonal type changed. Consumers reading areaName, itemName, or treating seasonal as boolean must update.
Breaking:
- bls_search_series series[].areaName renamed to area (#41)
- bls_search_series series[].itemName renamed to item (#41)
- bls_search_series series[].seasonal changed from boolean to descriptive string ("Seasonally Adjusted" / "Not Seasonally Adjusted") (#41)
Fixed:
- bls_get_latest double-listed failed series — rejected and no-observation series now appear in failed[] only, not also as stubs in results[]; format footer N-of-M denominator corrected (#42)
- bls_dataframe_query cap notice named wrong parameter when preview was the binding cap (#42)
Added:
- bls_search_series enrichment capped: boolean — true when FTS candidate pool hit the ~1000-row cap; totalFound is then a lower bound (#40)
167 tests pass; bun run devcheck clean.
v0.4.2: bls_search_series headline series fix, concept/synonym resolution
bls_search_series headline series fix, concept/synonym resolution
bls_search_series now unions headline common series into the candidate
set before the relevance rescore (fixing #35 where CUUR0000SA0 was
dropped for 'CPI' queries), and adds concept/synonym resolution so
'inflation' → CU, 'jobs'/'payroll' → CE, 'PPI' → WP/PC, etc. (#36).
bls_get_series calculations wording corrected (#37).
Fixed:
- bls_search_series: headline common series (e.g. CUUR0000SA0) now
always unioned into candidates, independent of FTS5 cap (#35)
Added:
- CONCEPT_ALIASES map resolves economic vocabulary to BLS survey codes;
matching surveys get a relevance boost in the rescore (#36)
Changed:
- bls_get_series calculations description corrected: survey returns
whichever calculations it supports; CPI/PPI return percent change
only, with no error; only surveys supporting neither return an error (#37)
Internal:
- observations ingester/service: non-null assertions replaced with
for...of entries(), bracket-key access replaced with dot notation
162 tests pass; bun run devcheck clean.
v0.4.1: Catalog SQLite index, bls_search_series restored, OES gate
Catalog SQLite index, bls_search_series restored, OES gate
Moves the LABSTAT series catalog from in-memory parse to an on-disk SQLite FTS5 store (sqliteMirrorStore). Off-heap storage removes the multi-GB heap footprint; search narrows via FTS5 then applies the bespoke relevance rescore.
Restores bls_search_series (#34) — download.bls.gov (Akamai) was returning 403 for any User-Agent containing a URL. The default UA drops the embedded GitHub URL, keeping name + contact email only.
Changed:
- BlsCatalogService backed by sqliteMirrorStore FTS5 index, queried on demand (#33)
- BLS_CATALOG_CACHE_PATH renamed BLS_CATALOG_DB_PATH (default .cache/bls-catalog.db)
- User-Agent URL removed — cyanheads-bls-mcp/1.0 (casey@caseyjhand.com)
- Dockerfile: mkdir .cache/.mirror + chown bun for non-root container user
Fixed:
- bls_search_series returning 0 results — Akamai 403 on catalog download was silently emptying the index (#34)
Added:
- BLS_CATALOG_INCLUDE_OES gate (default false) — OES/OEWS (~6M series / ~1.2 GB) opt-in; stays fetchable by ID when off (#33)
157 tests pass; bun run devcheck clean.
v0.4.0: Observation mirror, catalog cache, request echoes
Observation mirror, catalog cache, request echoes
Adds three independently useful features: an opt-in LABSTAT observation mirror
backed by SQLite, a persistent catalog cache so the parsed flat-file survives
restarts, and request-parameter echoes in structuredContent on the three search/
fetch tools.
Added:
- LABSTAT observation mirror (#26) — framework defineMirror/sqliteMirrorStore, default OFF, event-loop-safe subprocess ingest, BLS_OBSERVATIONS_MIRROR_* config, out-of-band bootstrap
- Persistent catalog cache (#32) — BLS_CATALOG_CACHE_PATH / BLS_CATALOG_CACHE_TTL_HOURS; parsed catalog survives restarts
- Request-parameter echoes (#29, #30) — structuredContent.request on bls_search_series, bls_list_surveys, bls_get_series
Changed:
- Catalog cold fetch bounded-concurrency, gentler on download.bls.gov (#32)
Dependency bumps:
- better-sqlite3 ^12.10.0 (new — Node SQLite driver for the observation mirror)
158 tests pass; bun run devcheck clean.
v0.3.1: result ordering fix, error contracts
result ordering fix, error contracts
bls_get_latest results[] now mirrors series_ids[] request order — results[i]
corresponds to series_ids[i] even when that series failed. Removes the
series_not_found errors[] entry (not-found series are failed[] partial results,
not tool-level throws). Enriches failed[].error descriptions with common values.
bls_list_surveys gains a typed errors[] contract — service_unavailable and
serialization_failure — with matching data.reason on the wire, so agents can
distinguish API outages from empty category results.
Fixed:
- bls_get_latest: results array ordering (#25)
- bls_get_latest: series_not_found contract mismatch (#28)
Changed:
- bls_list_surveys: added errors[] for service_unavailable and serialization_failure (#27)
- bls_get_latest: failed[].error and failed[] descriptions clarify partial-failure semantics
130 tests pass; bun run devcheck clean.
v0.3.0: configurable BLS User-Agent; mcp-ts-core ^0.9.21
configurable BLS User-Agent; mcp-ts-core ^0.9.21
All HTTP requests to the BLS API and LABSTAT flat-file server now carry a configurable User-Agent header that satisfies BLS data-access policy by default, overridable via BLS_USER_AGENT.
Added:
- BLS_USER_AGENT env var — User-Agent sent on all outbound HTTP requests; default satisfies BLS data-access policy (descriptive UA + contact)
Changed:
- @cyanheads/mcp-ts-core ^0.9.16 → ^0.9.21 (HTTP transport log context fix; fetchWithTimeout strips query-string secrets; withRetry fail-fast on non-retryable errors)
- scripts/devcheck.ts: Open-Indexed Interfaces and Skill Versions checks added
- scripts/check-skill-versions.ts (new): skill version policy enforcement
- scripts/release-github.ts (new): GitHub Release with correct title format
- Skills synced: api-mirror and orchestrations added; 8 skills updated from upstream
- README client-config server key normalized to bls-labor-mcp-server
Dependencies:
- @duckdb/node-api ^1.5.3-r.2 → ^1.5.3-r.3
- vitest ^4.1.7 → ^4.1.8
127 tests pass; bun run devcheck clean.
v0.2.3: enrichment adoption — search/series/dataframe tools
enrichment adoption — search/series/dataframe tools
query echoes, result totals, and empty-result guidance now surface in a typed enrichment block reaching both structuredContent JSON and content[] markdown trailer.
Changed:
- bls_search_series: total+catalogSize moved to enrichment block; total renamed totalFound; notice for empty-result guidance
- bls_get_series: enrichment.totalObservations + notice when canvas spill occurs
- bls_get_latest: enrichment.notice when series fail (directs to bls_search_series)
- bls_dataframe_query: enrichment.notice when row_limit caps query results
Dependency bumps:
@cyanheads/mcp-ts-core^0.9.13 → ^0.9.16
42 tests pass; bun run devcheck clean.