Skip to main content
Glama
README.md
# warn-mcp — US layoff data (WARN Act) as an MCP server

**61,320 mass-layoff notices · 48 states · 1988 → today · rebuilt every morning ·
no API key · zero dependencies.**

Every US state publishes the layoff notices employers must file under the
[WARN Act](https://en.wikipedia.org/wiki/Worker_Adjustment_and_Retraining_Notification_Act_of_1988),
and every state publishes them differently — a web page here, a pile of PDFs
there, a search form somewhere else. [WARN Feed](https://approjects-warn-act-notices.static.hf.space/)
scrapes all 48 of them daily and normalizes them into one schema. This is that
dataset wired into the [Model Context Protocol](https://modelcontextprotocol.io),
so Claude, Cursor, Continue or your own agent can ask questions like:

> *"Has Starbucks filed any WARN notices this year, and in which states?"*
> *"What layoffs were announced in the last two weeks in Texas?"*
> *"Which state had the most workers affected in 2026?"*
> *"Did any agency quietly change or delete a notice this week?"*

## Install

Nothing to build and nothing to install into your Python environment — the
server is standard library only.

**Claude Desktop / Claude Code / anything that reads an `mcpServers` block:**

```json
{
  "mcpServers": {
    "warn": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/APVentureEngine/warn-mcp", "warn-mcp"]
    }
  }
}
```

Claude Code, one line:

```bash
claude mcp add warn -- uvx --from git+https://github.com/APVentureEngine/warn-mcp warn-mcp
```

No `uv`? Clone and run it with plain Python:

```bash
git clone https://github.com/APVentureEngine/warn-mcp && cd warn-mcp
python3 -m warn_mcp.server --selftest    # exercises every tool against live data
```

```json
{
  "mcpServers": {
    "warn": { "command": "python3", "args": ["-m", "warn_mcp.server"], "cwd": "/path/to/warn-mcp" }
  }
}
```

## Or run it over HTTP (Streamable HTTP transport)

The same six tools, same implementation, spoken over MCP's Streamable HTTP
transport instead of stdio — for clients that want a URL rather than a
subprocess, and for putting one shared instance behind your own team:

```bash
docker build -t warn-mcp . && docker run -p 8080:8080 warn-mcp
# -> http://localhost:8080/mcp   (and a short human page at http://localhost:8080/)
claude mcp add --transport http warn http://localhost:8080/mcp
```

No Docker? `python3 http/app.py` does the same thing — it is standard library
only, like everything else here. `PORT` selects the port, `/healthz` returns
`{"ok":true}`, and the server is stateless, so you can run as many replicas as
you like behind any load balancer.

It is deliberately keyless: the data underneath is public and read-only, the
server keeps no session state and stores nothing about callers. Do not bolt auth
onto a public deployment of it and then advertise it as this server.

## Tools

| Tool | What it answers |
|---|---|
| `search_layoff_notices` | Employer / state / date-range / minimum-headcount search across the whole archive. Returns matched notice count, total workers affected, and the newest matches. |
| `latest_layoff_notices` | The rolling ~14-day feed of newly published notices, newest first, optionally one state. |
| `employer_layoff_history` | One employer's whole WARN record back to 1988 — notices, workers affected, every state it filed in, first and latest activity. |
| `state_layoff_totals` | Monthly notice counts and workers affected: a national leaderboard by state, or one state's month-by-month series. |
| `agency_revisions` | What the agencies **changed**: a field-level diff of consecutive daily snapshots — corrected headcounts, moved dates, and notices the agency stopped publishing. |
| `dataset_status` | Last rebuild time, states flagged stale, license, and the raw endpoints — call it before quoting a number. |

Every answer carries `as_of` and `source`, because a layoff figure with no date
and no attribution is not worth repeating. Where the data is weaker than it
looks, the tool says so in a `caveat` field rather than letting the model round
it off: headcount is only counted where the agency published one, employer names
are normalized by an auditable rule table rather than a corporate-registry join,
and `row_absent` in the revision log means the agency stopped publishing a
notice — not that the layoff was cancelled.

## Why an MCP server and not just the CSV

The CSV is right there and it is free — [take it](https://github.com/APVentureEngine/warn-act-notices).
This exists for the case where a model needs one specific answer out of a 9 MB
file: the tools do the filtering and the arithmetic locally, so an agent spends a
few hundred tokens instead of a context window, and it gets the freshness stamp
with the answer.

`agency_revisions` is the part you cannot reconstruct from any single copy of
the data. A state agency editing its own WARN page leaves no changelog, so a
mirror taken today simply *is* today's truth. WARN Feed diffs yesterday's
snapshot against today's and keeps the field-level log — **616 logged agency
changes so far**, including notices that vanished from the official page
entirely.

## Caching and network

Tools read the free public WARN Feed endpoints over HTTPS and cache them on disk
(`~/.cache/warn-mcp`, override with `WARN_MCP_CACHE`) with ETag revalidation, so
ten tool calls in a row make at most one request per file per hour
(`WARN_MCP_TTL`, seconds). If the network is down and a cached copy exists, the
cached copy is served and its own `as_of` tells you how old it is.

There is no key, no signup, no rate limit and no telemetry — this server sends
nothing anywhere except plain GETs for public files.

## Data, license, attribution

Data is compiled from official state WARN publications and released under
**CC BY 4.0** — credit "WARN Feed" and link back. This server's code is MIT.
Not affiliated with any state agency or the US Department of Labor; state
agencies' own postings are the authority and are occasionally revised (see
`agency_revisions`).

- Dataset repo: <https://github.com/APVentureEngine/warn-act-notices>
- Raw HTTP API and per-state files: <https://approjects-warn-act-notices.static.hf.space/api.html>
- Hugging Face: <https://huggingface.co/datasets/APProjects/us-warn-act-layoffs-notices-daily>

## The one paid thing

Everything above is free and stays free. If you need to be *told* — your own
list of employers matched against every daily refresh and pushed to a private
alert page, a calendar feed, RSS, or a Slack / Discord / Teams webhook — that is
[WARN Watch, $49/year](https://approjects-warn-act-notices.static.hf.space/watch.html),
with a free 30-day trial and no card. It is the only thing here that costs money.

Bugs, a state we should cover, a tool you want:
[open an issue](https://github.com/APVentureEngine/warn-mcp/issues).

TDQS

A4/5.0

Scored across 6 tools

Disambiguation5/5

Each tool targets a distinct aspect of WARN data: dataset health, searching, recent feed, employer history, state stats, and revision diffs. No two tools overlap in purpose; even the search and latest feed are clearly differentiated by time scope.

Naming Consistency4/5

Names are all lowercase with underscores, which is consistent. However, the pattern mixes verb-led names (search_layoff_notices) with noun-led names (employer_layoff_history); while not chaotic, it's not a uniform verb_noun convention across the board.

Tool Count5/5

Six tools is well-scoped for a domain-specific WARN server. Each tool covers a natural query pattern (status, search, recent, employer, state, revisions) without unnecessary bloat or an anemic surface.

Completeness4/5

The set covers core workflows: searching, recent notices, employer lookups, state aggregation, and data quality checks. Minor gaps might include fetching a single notice by ID or filtering by industry, but the existing tools handle most real-world queries without dead ends.

Maintenance

ActivityMaintained
ResponsivenessNo issues