Bls Mcp Server

io.github.cyanheads由 GitHub 帳號 cyanheads 發布v0.1.9更新於 Oct 24, 2026

Fetch US Bureau of Labor Statistics data — CPI, unemployment, wages, JOLTS, and more via MCP.

已驗證STDIO僅桌面資料庫金融資料與分析

概覽

AI 產生的概覽

取得美國勞工統計局資料,例如 CPI、失業率、薪資與 JOLTS,可解析序列 ID 並對大型結果集執行 SQL 查詢。

可以做什麼
提供 BLS 勞動統計工具:bls_list_surveys 列出調查計畫,bls_search_series 透過離線 LABSTAT 目錄以自然語言解析晦澀的 SeriesID 且不消耗 API 配額,bls_get_series 依年份區間取得 1-50 個序列並可選計算期間變化,bls_get_latest 傳回每個序列的最新觀測值。啟用選用的 DuckDB DataCanvas 後,bls_dataframe_describe 與 bls_dataframe_query 提供結構描述探索與唯讀 SELECT 查詢,明確啟用時 bls_dataframe_drop 可刪除資料框架。
適用情境
適合助理需要權威美國勞動統計資料用於分析、報告或經濟問題,以及需要自然語言序列探索和對多序列結果執行 SQL 的情境。也適合否則會觸及 BLS API 配額上限的高頻工作負載。
執行需求
以 stdio 在本機執行,或作為 Streamable HTTP 伺服器執行;也有公開託管端點。需要 Bun v1.4.0+ 或 Node.js v24+,或 Docker。BLS_API_KEY 為選用:沒有金鑰每天 25 次請求,免費金鑰每天 500 次請求並支援計算與年度平均值。選用設定包括 MCP_AUTH_MODE、MCP_HTTP_HOST、MCP_HTTP_PORT、MCP_HTTP_ENDPOINT_PATH 與 MCP_LOG_LEVEL;DataCanvas 需要 CANVAS_PROVIDER_TYPE=duckdb。
安裝前請注意
BLS_API_KEY 是憑證,應透過環境變數提供,不要寫入設定檔。伺服器會查詢 BLS 公開端點並下載 LABSTAT 平面檔案,因此會使用網路存取與本機快取儲存。bls_dataframe_query 為唯讀,拒絕寫入與外部檔案讀取,但當 BLS_DATAFRAME_DROP_ENABLED=true 時 bls_dataframe_drop 會刪除已註冊的資料框架。LOG_TOOL_FAILURE_PAYLOADS 可記錄失敗呼叫的參數與結果,僅依鍵名遮蔽,自由文字中的密鑰仍可能保留。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Bls Mcp Server,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

@cyanheads/bls-labor-mcp-server

Fetch US Bureau of Labor Statistics data — CPI, unemployment, wages, JOLTS, and more via MCP. STDIO or Streamable HTTP.

6 Tools by default · 7 with opt-in drop

Public Hosted Server: https://bls-labor.caseyjhand.com/mcp


Overview

US labor statistics from the Bureau of Labor Statistics: jobs, unemployment, wages, and inflation. Find series in plain language instead of decoding SeriesIDs, pull full history or the latest value, and run SQL over large multi-series results.

Tools

ToolDescription
bls_list_surveysList BLS survey programs (CPI, CPS, CES, JOLTS, PPI, OEWS, …) with codes, descriptions, and calculation-support flags.
bls_search_seriesSearch the BLS series catalog by natural language, survey, area, or keywords to resolve cryptic SeriesIDs.
bls_get_seriesFetch time-series data for 1–50 BLS series by SeriesID, with optional year range and period-over-period calculations.
bls_get_latestReturn the single most recent observation for one or more BLS series.
bls_dataframe_describeList canvas dataframes registered by bls_get_series or bls_dataframe_query — provenance, TTL, row count, column schema. Unavailable when CANVAS_PROVIDER_TYPE=none.
bls_dataframe_queryRun a SELECT against canvas dataframes registered by bls_get_series or an earlier register_as. Supports JOINs, aggregates, window functions, CTEs. Unavailable when CANVAS_PROVIDER_TYPE=none.
bls_dataframe_dropDrop a canvas dataframe by name. Available when BLS_DATAFRAME_DROP_ENABLED=true, unless CANVAS_PROVIDER_TYPE=none; TTL handles cleanup by default.

Capability reference

bls_list_surveys tool

  • Optional category filters survey programs by subject; returns codes, names, and calculation-support flags (allowsNetChange, allowsPercentChange, hasAnnualAverages). Each row's searchCoverage (indexed, composed, or none) says whether bls_search_series reaches the survey, with seriesIndexed for indexed ones.
  • Backed by the BLS surveys API with 30-day process-local caching. Annual-average support is advisory; read bls_get_series's annualAverageRows for the rows actually returned.

bls_search_series tool

  • Search by text or SeriesID, with optional survey, area, and seasonal_adjustment; blank filters are omitted. area takes a USPS or 2-digit FIPS state code; a 3-, 4-, 5-, or 7-digit CSA, CPI area, county or CBSA, or state + place code; otherwise a substring of area, title, or SeriesID (all-digit values outside those lengths add a notice). limit defaults to 10 and requests above 50 clamp to 50 with notice, with offset pagination. Exact SeriesIDs rank first, then series matching every query word, with any place the query names in full ahead of the rest; at equal score, current series rank first, then national ones, then the JOLTS aggregate.
  • Returns decoded SeriesIDs, titles, frequency, and independently optional startYear, endYear, and endPeriod coverage (for example, 1982–2005 Q04). Coverage describes the catalog snapshot, not continuous observations. Follow nextOffset while truncated is true; capped: true makes totalCount a lower bound, and paging stops at the FTS candidate pool.
  • Searches the offline LABSTAT index without using API quota; OE/OEWS is opt-in through BLS_CATALOG_INCLUDE_OES. Under survey: "OE" without those rows, it composes OEWS SeriesIDs from the OE code tables, up to 50 per search; each is marked composed: true and is unconfirmed until bls_get_series returns data for it. Unindexed surveys remain fetchable by SeriesID.

bls_get_series tool

  • Fetch up to 25 SeriesIDs without an API key or 50 with one per call, with a start_year/end_year window of up to 20 years, optional calculations, and annual_average. A start alone resolves the end to the current year capped at start + 19; an end alone is rejected. One batch consumes one API query; calculations depend on survey support (CPI/PPI return percent change only).
  • Returns local-catalog titles when available and optional BLS measure metadata, and observations with available; preserves the raw - missing-value sentinel, and keeps valid series in mixed batches. Enrichment reports the applied year window, calculations actually returned, annual-summary rows, and any upstream reductions or advisories.
  • SeriesIDs are trimmed, uppercased, and deduplicated before the cap; unprocessedSeriesIds lists the exact ordered remainder without automatic extra batches. Omitted year bounds use BLS's three-calendar-year default, subject to coverage.
  • Large results spill to dataset.name. With CANVAS_PROVIDER_TYPE=none, all fetched observations return inline.

bls_get_latest tool

  • Fetch the latest observation for up to 50 SeriesIDs (recommended ≤10). IDs are trimmed, uppercased, and deduplicated before the cap; unprocessedSeriesIds lists the exact ordered remainder. Each processed ID consumes one API query; use bls_get_series for a more efficient multi-series batch.
  • Returns successful results[] beside per-series failed[] entries. latestObservation.available distinguishes a published value from BLS's missing-value sentinel.

bls_dataframe_describe tool

  • Optional name describes one registered dataframe; omit it to list active dataframes for the tenant. Unavailable when CANVAS_PROVIDER_TYPE=none.
  • Returns source tool, query params, row count, TTL (created_at/expires_at, fixed at table creation), and column_schema; BLS columns are nullable. Registered-query types outside the canvas set (DECIMAL, HUGEINT, SMALLINT, lists) report as VARCHAR. Expired entries are removed when their canvas drop succeeds.

bls_dataframe_query tool

  • Run one SELECT against registered tables, with JOINs, aggregates, window functions, or CTEs. row_limit defaults to 1000; larger values clamp to 10000, and preview clamps to the applied row limit with requested/applied notices. Zero preview remains valid; writes, external-file reads, and system catalogs are denied.
  • Engine-setting functions (current_setting, current_schema, current_schemas, in_search_path) and query_table are denied. Unqualified current_schema keyword or column references are also denied; qualify a real column with its table alias (for example, t.current_schema). query() accepts one plain SQL string literal, checked recursively up to four levels; computed SQL strings are rejected. Reference staged tables directly for analysis.
  • Returns rows without consuming BLS API quota. Optional register_as stages the result with a fresh TTL for chained analysis. Unavailable when CANVAS_PROVIDER_TYPE=none.

bls_dataframe_drop tool

  • Required name identifies the dataframe to drop. Available only with BLS_DATAFRAME_DROP_ENABLED=true, and never with CANVAS_PROVIDER_TYPE=none; TTL handles cleanup by default.
  • Returns dropped: false for a missing table. A failed drop returns retryable canvas_drop_failed and leaves the dataframe registered.

Features

Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.

BLS-specific:

  • BLS API v2 client with retry/backoff and daily quota tracking
  • Offline series catalog search against LABSTAT flat files, indexed as an on-disk SQLite/FTS5 store — zero API quota for discovery; the OES/OEWS wage survey (~6M series) is opt-in via BLS_CATALOG_INCLUDE_OES
  • Typed error contracts for BLS-specific failure modes — quota exhaustion, locked database, calculations not supported
  • Period-over-period net/percent-change calculations via BLS's own server-side flag, consistent with BLS's published numbers
  • DataCanvas spillover (DuckDB, on by default) for large multi-series result sets — schema discovery and SQL access without re-querying the API

Agent-friendly output:

  • Provenance — canvas-spilled results carry a dataset.name handle plus row count and expiry; bls_search_series echoes effectiveQuery, catalogSize, and whether the FTS candidate pool was capped
  • Graceful partial failure — bls_get_latest returns per-item failed[] (seriesId + error) alongside successful results[] instead of failing the whole batch; bls_get_series keeps valid series when another SeriesID in the same batch is invalid or empty
  • Discriminated outputs — every observation carries an available boolean for BLS's - missing-value sentinel, so callers branch on a typed field instead of parsing raw values
  • Actionable notices — enrichment.notice explains empty results, canvas spillover, and unavailable data with concrete next steps (e.g. using bls_search_series to verify a SeriesID)

Getting started

Public Hosted Instance

A public instance is available at https://bls-labor.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:

json
{  "mcpServers": {    "bls-labor-mcp-server": {      "type": "streamable-http",      "url": "https://bls-labor.caseyjhand.com/mcp"    }  }}

Self-Hosted / Local

Add the following to your MCP client configuration file. A free BLS API key unlocks 500 queries/day — register at bls.gov/developers. The server works without a key at 25 req/day.

json
{  "mcpServers": {    "bls-labor-mcp-server": {      "type": "stdio",      "command": "bunx",      "args": ["@cyanheads/bls-labor-mcp-server@latest"],      "env": {        "MCP_TRANSPORT_TYPE": "stdio",        "MCP_LOG_LEVEL": "info",        "BLS_API_KEY": "your-key-here"      }    }  }}

Or with npx (no Bun required):

json
{  "mcpServers": {    "bls-labor-mcp-server": {      "type": "stdio",      "command": "npx",      "args": ["-y", "@cyanheads/bls-labor-mcp-server@latest"],      "env": {        "MCP_TRANSPORT_TYPE": "stdio",        "MCP_LOG_LEVEL": "info",        "BLS_API_KEY": "your-key-here"      }    }  }}

Or with Docker:

json
{  "mcpServers": {    "bls-labor-mcp-server": {      "type": "stdio",      "command": "docker",      "args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "-e", "BLS_API_KEY=your-key-here", "ghcr.io/cyanheads/bls-labor-mcp-server:latest"]    }  }}

For Streamable HTTP, set the transport and start the server:

sh
MCP_TRANSPORT_TYPE=http MCP_SESSION_MODE=stateless MCP_HTTP_PORT=3010 BLS_API_KEY=... bun run start:http# Server listens at http://localhost:3010/mcp

Prerequisites

  • Bun v1.4.0 or higher (or Node.js v24+).
  • A free BLS API v2 key — register at bls.gov/developers. Grants 500 queries/day; the server also works without a key at 25 req/day.

Installation

  1. Clone the repository:
sh
git clone https://github.com/cyanheads/bls-labor-mcp-server.git
  1. Navigate into the directory:
sh
cd bls-labor-mcp-server
  1. Install dependencies:
sh
bun install
  1. Configure environment:
sh
cp .env.example .env# edit .env and set BLS_API_KEY

Configuration

All configuration is validated at startup via Zod schemas in src/config/server-config.ts.

VariableDescriptionDefault
BLS_API_KEYBLS v2 API key. Optional — 25 req/day without, 500 req/day with. Register free at bls.gov/developers.—
BLS_BASE_URLBLS API v2 base URL.https://api.bls.gov/publicAPI/v2
BLS_CATALOG_BASE_URLLABSTAT flat-file base URL. Override to point at a local mirror.https://download.bls.gov/pub/time.series
BLS_CATALOG_DB_PATHOn-disk SQLite catalog index — queried on demand and persisted across restarts. Empty uses an in-memory DB (re-harvested each boot). Mount a volume here in containers..cache/bls-catalog.db
BLS_CATALOG_CACHE_TTL_HOURSPer-survey catalog freshness window in hours — a survey re-harvests once its last success is older, and a failed survey's retry backoff is capped at this many hourly checks. Checked at startup and hourly while running.168 (7 days)
BLS_CATALOG_INCLUDE_OESInclude the OES/OEWS wage survey (~6M series / ~1.26 GB; Bun-only; multi-minute first harvest). Off by default — OES series stay fetchable by ID, and search composes them from the small OE code tables.false
BLS_OBSERVATIONS_MIRROR_ENABLEDServe observations from a local SQLite mirror instead of the live API (requires a one-time bootstrap — see below).false
BLS_DATASET_TTL_SECONDSPer-dataframe TTL for canvas-registered tables, in seconds.86400 (24 h)
BLS_DATAFRAME_DROP_ENABLEDExpose bls_dataframe_drop. TTL handles cleanup by default.false
CANVAS_PROVIDER_TYPEDataCanvas provider for tabular spillover of large result sets and the dataframe tools. Set to none to disable them. The Claude Desktop bundle ships without DuckDB and pins none.duckdb
MCP_TRANSPORT_TYPETransport: stdio or http.stdio
MCP_HTTP_PORTHTTP server port.3010
MCP_SESSION_MODESession mode. This server uses stateless; valid schema values are auto, stateful, and stateless. Schema-default auto resolves to stateful.stateless
MCP_AUTH_MODEAuth mode: none, jwt, or oauth.none
MCP_LOG_LEVELLog level (RFC 5424).info
LOGS_DIRDirectory for log files (Node.js only).<project-root>/logs
OTEL_ENABLEDEnable OpenTelemetry instrumentation.false
OTEL_EXPORTER_OTLP_ENDPOINTBase OTLP URL for traces and metrics; signal-specific endpoints override it.—
OTEL_EXPORTER_OTLP_LOGS_ENDPOINTOpt-in OTLP log endpoint. The base URL never enables log export.—
LOG_TOOL_FAILURE_PAYLOADSLog failed-call arguments and results, redacted by key name; secrets in free-form values remain.false
LOG_TOOL_FAILURE_PAYLOAD_MAX_BYTESUTF-8 byte cap per logged failure payload.16384

See .env.example for the full list of optional overrides.

Observation mirror (optional)

For high-volume workloads, an opt-in local mirror serves bls_get_series / bls_get_latest from an embedded SQLite store of the LABSTAT files instead of the BLS API, removing the 500/day quota cap; requests fall back to the live API until it is built. Enable it with BLS_OBSERVATIONS_MIRROR_ENABLED=true, then run the one-time bootstrap: node dist/services/bls-observations/subprocess.js --init. Settings, survey coverage, harvest checkpoint and exit codes, fallback and calculation behavior, and upgrade notes are in docs/observation-mirror.md.

Running the server

Local development

  • Build and run:

    sh
    # One-time buildbun run rebuild
    # Run the built serverbun run start:stdio# orbun run start:http
  • Run checks and tests:

    sh
    bun run devcheck   # Lint, format, typecheck, securitybun run test       # Vitest test suitebun run lint:mcp   # Validate MCP definitions against spec

Docker

sh
docker build -t bls-labor-mcp-server .docker run --rm -e BLS_API_KEY=your-key -e MCP_TRANSPORT_TYPE=http -p 3010:3010 bls-labor-mcp-server

The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/bls-labor-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.

Project structure

DirectoryPurpose
src/index.tscreateApp() entry point — registers tools and initializes services.
src/configServer-specific environment variable parsing and validation with Zod.
src/mcp-server/toolsTool definitions (*.tool.ts).
src/services/bls-apiBLS API v2 service — batch fetch, latest-value GET, surveys metadata.
src/services/bls-catalogLABSTAT flat-file catalog — offline series index and search.
src/services/bls-observationsOptional LABSTAT observation mirror — embedded SQLite store, ingester, and refresh subprocess.
src/services/bls-periodsPeriod-code semantics shared by the API and mirror paths: annual-average codes (M13/Q05/S03) and the live API's period names.
src/services/canvas-bridgeDataCanvas bridge — dataframe registration, SQL gate, lifecycle management.
docs/design.mdFull tool surface specification, service architecture, and error contracts.
docs/observation-mirror.mdObservation mirror setup, coverage, and upgrade notes.
tests/Unit and integration tests mirroring src/.

Development guide

See CLAUDE.md for development guidelines and architectural rules. The short version:

  • Handlers throw, framework catches — no try/catch in tool logic
  • Use ctx.log for request-scoped logging, ctx.state for tenant-scoped storage
  • bls_search_series is the anchor tool — design workflows to call it before the API tools
  • Wrap BLS API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields

Contributing

Issues are welcome. Run checks and tests before submitting:

sh
bun run devcheckbun run test

License

Apache-2.0 — see LICENSE for details.

來源:README.md,提交 caef232

工具

0
SourceWeft 尚未在沙箱中啟動過該軟體包,因此其工具未知。

版本歷史

1
  1. v0.1.9最新Sep 16, 2026

評分

已滿足適用檢查項的 40%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分

    請在儲存庫或註冊中心條目中宣告授權條款。