@pipeworx/us-econ-calendar
Connect: https://gateway.pipeworx.io/us-econ-calendar/mcp · Install: one-click buttons
Tools: 3
US macro-economic release SCHEDULE — when CPI, PPI, the Employment Situation
(jobs report), JOLTS, FOMC meetings, weekly DOL jobless-claims reports and
Treasury auctions happen, in Eastern Time. This pack answers when, never
what the number was — for the released values, use bls or fred.
Tools
econ_calendar_upcoming({hours?, days?, types?})— every tracked release falling in the next N hours/days, sorted by datetime.econ_calendar_next({release, from?})— the next occurrence of one release type (cpi,ppi,employment_situation,jolts,fomc,claims,treasury_auction).econ_calendar_recent({days?})— releases in the last N days (“what came out this week”).
Auth
Keyless. No platform key, no BYO key.
Data sources
- https://www.bls.gov/schedule/news_release/cpi.htm,
ppi.htm,empsit.htm,jolts.htm— BLS’s own annual release calendars, published roughly 12-13 months ahead. - https://www.federalreserve.gov/monetarypolicy/fomccalendars.htm — the
FOMC meeting calendar, via the already-live
fed-commspack’sfomc_calendartool (compound call — this pack does not re-scrape it). - DOL weekly Unemployment Insurance claims: fixed Thursday 08:30 ET cadence (https://oui.doleta.gov/unemploy/claims.asp, https://www.dol.gov/), computed rather than fetched, with a hardcoded override for the one known 2026 holiday shift (Thanksgiving week: Thu 2026-11-26 → Wed 2026-11-25).
- https://www.treasurydirect.gov/TA_WS/securities/upcoming — Treasury’s own live, keyless JSON auction calendar. Fetched live on every call.
Important gotcha: bls.gov refuses the clients we SERVE from — but not Node
www.bls.gov sits behind Akamai bot-management. What it refuses is the client
FINGERPRINT, not our address and not our user-agent. Measured 2026-09-13 from
one laptop on one residential IP, within the same minute:
| Client | Result |
|---|---|
curl, plain UA | 403 Access Denied (AkamaiGHost) |
curl, full Chrome header set (UA, sec-ch-ua-*, all four Sec-Fetch-*) | 403 |
curl https://www.bls.gov/robots.txt | 403 |
a deployed Cloudflare Worker fetch() (measured in #1914) | 403 |
node fetch() (undici) with the same Chrome headers | 200, 55,572 bytes, the real schedule table |
Headers and IP were held constant across the curl and Node rows, so the difference is the TLS/HTTP stack. Two consequences, and they point opposite ways:
- At runtime the pack still cannot fetch bls.gov. The Worker is one of the
refused clients, so the CPI / PPI / Employment-Situation / JOLTS tables in
src/index.tsremain a checked-in copy with a coverage horizon. Nothing about the sections below changes. - At refresh time we can.
scripts/refresh-econ-calendar.mjsruns on a dev machine, reads all four schedule pages with Node’sfetch, and rewrites the tables. The annual refresh is a command, not a browser-and-retype chore.
Re-measure rather than trust this table; bot rules move. node scripts/refresh-econ-calendar.mjs --check is the probe — it exits non-zero on
drift and prints the HTTP status when bls.gov refuses it.
(Separately: data.bls.gov’s general pages are blocked too, while its
/timeseries/<series> data-table path is not — but that path carries series
data, never schedule information.)
Coverage is reported on every response — and it expires
The BLS legs are DATA WITH AN EXPIRY DATE, so every response carries a
schedule_coverage array saying, per release, how far this pack reaches and on
what basis:
cpi/ppi/employment_situation/jolts—basis: "published calendar": BLS issues these dates about a year ahead, so they have a horizon. Carriescovered_through(the last date this pack answers for) andsource_vintage(when the dates were last brought current).fomc/treasury_auction—basis: "live upstream". No expiry.claims—basis: "computed cadence". Answers for any future date; only the federal-holiday overrides are hardcoded, and they currently cover 2026.
When a query reaches past covered_through:
econ_calendar_upcoming/_recentadd acoverage_warningarray naming the release, the cutoff and the fact that our data ran out — so an emptyeventslist is never read as “nothing is scheduled”.econ_calendar_nextreturnsfound: falsewithreason: "schedule_coverage_exhausted",covered_through, and a hint that says in words that BLS has very likely published past that date and we have not refreshed.
pnpm check:econ-calendar-coverage is the other half: a CI gate (and pre-push
gate) that warns from 120 days of coverage out and fails the build at 60, so
the refresh below gets done while there is still slack. Do not silence it —
extend the data.
Refreshing the BLS schedule (annual, and someone has to do it)
BLS publishes the following year’s calendar once a year, so this recurs. It is one command.
1. Preferred: scripts/refresh-econ-calendar.mjs. It fetches all four
schedule pages from bls.gov with Node’s fetch (which Akamai lets through —
see the table above), parses the Reference Month / Release Date / Release Time
rows, and diffs them against the tables in src/index.ts:
node scripts/refresh-econ-calendar.mjs # fetch + diff, exit 1 on drift
node scripts/refresh-econ-calendar.mjs --write # rewrite the tables + bump SCHEDULE_VINTAGE
node scripts/check-econ-calendar-coverage.mjs # confirm the 60-day gate is green
Commit the pack change and the bumped vintage together. Verified 2026-09-13:
--check returned 52 rows across the four releases and matched the checked-in
tables exactly, which is also an independent re-verification that what we ship
is what BLS published.
It refuses rather than returns empty — a block page, renamed table headers, or
a table that parses to zero rows all throw. --selftest proves those three
directions plus a real parse, with no network.
2. Fallback: FRED’s release-date API. If Akamai’s rules move and Node stops
clearing them, the St. Louis Fed mirrors each BLS release’s scheduled future
dates, keyless-to-us through our own fred pack:
scripts/pwcall.sh call fred_release_dates '{"release_id":10,"limit":24,"include_release_dates_with_no_data":true}'
Release ids: CPI 10 · PPI 46 · Employment Situation 50 · JOLTS 192. Verified 2026-09-13 — all four returned exactly the dates in our tables, through the same mid-December cutoff, which is BLS’s own published horizon. FRED does NOT give you two things the tables need: the release time (stable: 08:30 ET for CPI, PPI and the Employment Situation, 10:00 ET for JOLTS) and the reference period (CPI/PPI/empsit describe the prior month; JOLTS lags two).
Does the egress relay clear bls.gov? The question is moot — do not wire it.
The relay (supabase/functions/egress-proxy, the non-CF hop this pack already
uses for its TreasuryDirect leg) exists for upstreams that block Cloudflare
egress addresses. bls.gov is not that class: the block follows the client
fingerprint, not the IP, which is why curl is refused from a residential
address and Node is served from the same one. It was never probed through the
relay and now does not need to be — the refresh runs on a dev machine where
plain Node already works, and allow-listing a host to route a build-time chore
through a production relay buys nothing. If someone ever wants the pack to
fetch bls.gov at runtime, that is a different question and the relay is an
untested guess at it; the honest starting point is that Deno’s stack has not
been measured against Akamai here.
Who does it: whoever the 60-day gate stops. It fails on push with the
release name, the cutoff and this procedure, so the person holding a commit is
the person who fixes it. --write bumps SCHEDULE_VINTAGE for you — the gate
reads the tables, not that string, so a stale vintage is the one lie it cannot
catch.
Treasury and the Fed calendar have no such problem — both are fetched live
(Treasury directly; FOMC via fed-comms) and need no manual refresh.
Tools
- econ_calendar_upcoming — Upcoming US macro release SCHEDULE — which of CPI, PPI, the Employment Situation (jobs report), JOLTS, an FOMC meeting/rate decision, the weekly DOL jobless-claims report, and Treasury auctions fall i
- econ_calendar_next — When the NEXT occurrence of a specific US macro release is — next CPI, next PPI, next jobs report, next JOLTS, next FOMC meeting, next weekly jobless-claims report, or next Treasury auction — with its
- econ_calendar_recent — What US macro releases happened in the last N days — ‘what was released this week’, ‘has CPI come out yet this month’. Lists CPI/PPI/Employment Situation/JOLTS/FOMC/claims/Treasury-auction events whos
Tools
econ_calendar_next— When the NEXT occurrence of a specific US macro release is — next CPI, next PPI, next jobs report, next JOLTS, next FOMC meeting, next weekly jobless-claims report, or next Treasury auction — with itsecon_calendar_recent— What US macro releases happened in the last N days — 'what was released this week', 'has CPI come out yet this month'. Lists CPI/PPI/Employment Situation/JOLTS/FOMC/claims/Treasury-auction events whosecon_calendar_upcoming— Upcoming US macro release SCHEDULE — which of CPI, PPI, the Employment Situation (jobs report), JOLTS, an FOMC meeting/rate decision, the weekly DOL jobless-claims report, and Treasury auctions fall i