warn-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@warn-mcpHas Starbucks filed any WARN notices this year, and in which states?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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, and every state publishes them differently — a web page here, a pile of PDFs there, a search form somewhere else. WARN Feed scrapes all 48 of them daily and normalizes them into one schema. This is that dataset wired into the Model Context Protocol, 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:
{
"mcpServers": {
"warn": {
"command": "uvx",
"args": ["--from", "git+https://github.com/APVentureEngine/warn-mcp", "warn-mcp"]
}
}
}Claude Code, one line:
claude mcp add warn -- uvx --from git+https://github.com/APVentureEngine/warn-mcp warn-mcpNo uv? Clone and run it with plain Python:
git clone https://github.com/APVentureEngine/warn-mcp && cd warn-mcp
python3 -m warn_mcp.server --selftest # exercises every tool against live data{
"mcpServers": {
"warn": { "command": "python3", "args": ["-m", "warn_mcp.server"], "cwd": "/path/to/warn-mcp" }
}
}Related MCP server: treasury-fiscaldata-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:
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/mcpNo 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 |
| Employer / state / date-range / minimum-headcount search across the whole archive. Returns matched notice count, total workers affected, and the newest matches. |
| The rolling ~14-day feed of newly published notices, newest first, optionally one state. |
| One employer's whole WARN record back to 1988 — notices, workers affected, every state it filed in, first and latest activity. |
| Monthly notice counts and workers affected: a national leaderboard by state, or one state's month-by-month series. |
| What the agencies changed: a field-level diff of consecutive daily snapshots — corrected headcounts, moved dates, and notices the agency stopped publishing. |
| 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. 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, 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.
Available Tools
6 toolsagency_revisionsB
What the state agencies quietly CHANGED: a field-level diff of consecutive daily snapshots — corrected headcounts, moved dates, and notices the agency stopped publishing altogether. This history does not exist in any single-snapshot copy of the data.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max changes returned, 1-200 (default 25). | |
| since | No | Earliest observed_date, YYYY-MM-DD. | |
| state | No | Two-letter state code. | |
| company | No | Substring of the employer name. | |
| change_type | No | e.g. 'row_absent', 'field_changed', 'row_new'. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. It reveals that the tool computes diffs between consecutive daily snapshots and includes removed notices, which is useful, but it does not disclose output structure, pagination, ordering, default behavior, or any access/safety characteristics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is one vivid, front-loaded sentence that conveys the core concept efficiently. The word 'quietly' is stylistic filler, but the overall structure is compact and the key differentiator is placed at the end for impact.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, no annotations, and five optional parameters, the description should explain more about result shape, defaults, and how parameters combine. It explains the conceptual value of the tool but leaves an agent without enough operational detail to know what a typical response looks like or how to constrain a query effectively.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all five parameters. The description adds no parameter-level meaning beyond the schema, so the baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool as a field-level diff of consecutive daily snapshots for state agency data, with concrete examples of change types. It also distinguishes itself from any single-snapshot tool by stating that this history 'does not exist in any single-snapshot copy of the data,' which separates it from sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use this tool: when you need revision history across daily snapshots rather than current snapshot data. However, it does not explicitly name sibling tools, state when not to use it, or provide decision criteria for choosing between this and alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
dataset_statusA
Freshness and coverage of the dataset itself: when it was last rebuilt, which states are flagged stale, the license, and the raw endpoints. Call this before quoting a number so you can attribute it correctly.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must disclose behavioral traits. It lists the content (freshness, stale states, license, raw endpoints) but does not explicitly state whether this is a read-only, non-mutating operation, nor does it mention any costs, latency, or side effects. While 'status' implies safety, the description carries only partial burden—it lacks explicit reassurance or caveats. With no annotations, a 3 is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences with no fluff. The first sentence front-loads the core content, naming the specific data points. The second adds a practical usage hint. Every word earns its place, and the description is appropriately sized for a simple status tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This tool has no output schema, so the description must explain what is returned. It lists the key categories: rebuilt time, stale states, license, and raw endpoints. It also gives a usage scenario ('before quoting a number') to help the agent understand when it adds value. For a zero-parameter metadata tool, this is complete—nothing an agent needs to know to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has zero parameters, so the description is the sole source of semantic meaning. It clearly explains that the tool provides dataset-level metadata rather than taking inputs, and it lists the categories of information returned. This fully compensates for the empty schema, matching the baseline of 4 for a no-parameter tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool provides 'Freshness and coverage of the dataset itself' and enumerates specific aspects (last rebuilt, stale states, license, raw endpoints). This is a specific noun phrase that distinguishes it from sibling tools like search_layoff_notices or state_layoff_totals, which operate on record-level data. No ambiguity about what the tool returns.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when-to-use context: 'Call this before quoting a number so you can attribute it correctly.' This tells the agent the appropriate timing for invocation. It does not mention alternatives or exclusions, but for a metadata tool that is mainly a pre-call context check, this is sufficient. Siblings are clearly about data retrieval, so no conflict.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
employer_layoff_historyA
Every WARN notice one employer has filed, in any covered state, back to 1988: notice count, total workers affected, states, first and latest activity, plus the individual notices for the best-matching employer.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max individual notices returned, 1-200 (default 25). | |
| company | Yes | Employer name or a substring of it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It discloses the time range (back to 1988), geographic scope (any covered state), fuzzy matching ('best-matching employer'), and the return structure (summary plus individual notices). This is substantial behavioral disclosure, though it omits details like pagination or error handling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, information-dense sentence that front-loads the core purpose and lists key output elements. While it's a bit run-on, it has no fluff and every phrase adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter read tool, the description provides a thorough overview of what the tool returns, including summary and detail. The limit parameter is covered in the schema, and the output format is sufficiently described. Nothing critical is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both parameters are documented. The description adds the 'best-matching' nuance for the company parameter, which goes beyond the schema's substring description. This is a helpful semantic addition.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool as retrieving WARN notice history for a single employer, including summary statistics and individual notices. It distinguishes itself from sibling tools by focusing on employer-level data rather than general notice searches or state totals.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies use when you need a specific employer's layoff history, but it doesn't explicitly mention when not to use it or name alternative tools. However, the context is clear enough that an agent can infer its purpose without confusion.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
latest_layoff_noticesA
The rolling feed of newly published WARN notices (the last ~14 days as the agencies posted them), newest first, optionally one state. Use this for 'what layoffs were announced recently'.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max notices returned, 1-200 (default 25). | |
| state | No | Two-letter state code to filter to. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. It does reveal non-obvious behavior: notices from the last ~14 days as agencies posted them, newest-first ordering, and optional single-state filtering. It does not address edge cases like invalid state codes or pagination, but for a read-only feed the core behavior is clearly disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences with the core concept front-loaded and the use case stated directly. There is no filler, and it does not redundantly restate what the schema already covers.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple feed tool with two optional parameters, the description plus schema covers what an agent needs to invoke it correctly. There is no output schema, but the return shape is implied by 'WARN notices' and the feed framing; a pointer to search_layoff_notices for older data would make it slightly more complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents both limit and state parameter meanings. The description adds only that the state filter is optional and that the feed is time-bound, which is useful but not a substantial extension beyond the schema. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a concrete resource ('rolling feed of newly published WARN notices') and a precise use case ('what layoffs were announced recently'), with temporal scope and ordering. It does not explicitly name sibling search_layoff_notices, so sibling differentiation is implicit rather than stated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit when-to-use guidance: 'Use this for "what layoffs were announced recently".' It also clarifies the time window and optional state filter. However, it does not state when not to use this tool or point to alternatives such as search_layoff_notices for historical queries.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_layoff_noticesA
Search US WARN Act mass-layoff notices across 48 states, 1988 to today, by employer name, state, date range and minimum headcount. Returns matched notice count, total workers affected, and the newest matching notices. Pass a state to make the search much faster.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max notices returned, 1-200 (default 25). | |
| since | No | Earliest notice_date, YYYY-MM-DD. | |
| state | No | Two-letter state code, e.g. 'CA'. | |
| until | No | Latest notice_date, YYYY-MM-DD. | |
| company | No | Case-insensitive substring of the employer name, e.g. 'united airlines'. | |
| min_employees | No | Only notices affecting at least this many workers. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full disclosure burden and does disclose the return shape ('matched notice count, total workers affected, and the newest matching notices') and a performance behavior. It does not mention sorting or pagination details, but for a read-only search tool these gaps are minor.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with no filler. The scope and filter dimensions are front-loaded, the return summary is compact, and the state performance tip is placed last without bloating the description.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so explaining the return values is necessary and the description does so. It provides scope, filter dimensions, result summary, and a performance caveat. It is slightly incomplete in that it does not describe the ordering of 'newest matching notices' or how results behave when no filters are supplied, but overall it is sufficient for an agent to invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds value by grouping parameters into search dimensions ('employer name, state, date range and minimum headcount') and by adding a performance-relevant semantic for `state` that the schema does not convey. This lifts it above the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Search'), resource ('US WARN Act mass-layoff notices'), and scope ('48 states, 1988 to today'), with filter dimensions. It is clear, but it does not explicitly distinguish itself from siblings like latest_layoff_notices or state_layoff_totals, so sibling differentiation is only implicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a concrete usage tip ('Pass a state to make the search much faster'), but it never says when to prefer this tool over its siblings or when to avoid it. The intended context is implied rather than explicitly stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
state_layoff_totalsA
Monthly WARN notice counts and workers affected. With no state, returns a national leaderboard by state; with a state, the month-by-month series for it. Optionally restrict to one year.
| Name | Required | Description | Default |
|---|---|---|---|
| year | No | Four-digit year, e.g. '2026'. | |
| state | No | Two-letter state code. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses the key behavioral branching — output shape changes based on whether state is present — and notes the optional year restriction. It does not mention update cadence or empty-result behavior, but for a read-style aggregation tool these are minor gaps.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three compact sentences, each carrying substantive information with no filler. The most important behavioral distinction is front-loaded and the optional parameter is stated last with minimal wording.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with two optional parameters, no output schema, and no annotations, the description is complete enough to invoke correctly: it states what is returned, how the two modes differ, and how the year parameter applies. No critical operational detail is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds meaningful semantics beyond the schema by explaining that state is the mode-switching parameter (absent = national leaderboard; present = per-state series) and that year is an optional restriction. This is useful behavioral context the schema alone does not provide.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific resource (state-level WARN layoff totals) and concrete behavior: monthly counts and workers affected, with a national leaderboard when no state is given and a monthly series when a state is given. This clearly distinguishes it from sibling tools like search_layoff_notices and latest_layoff_notices, which deal with individual notices rather than monthly aggregates.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context for the main usage decision: omit state for a national leaderboard, supply state for that state's month-by-month series, and optionally restrict to one year. It does not explicitly name sibling alternatives or exclusion conditions, but the conditional behavior is enough to guide correct use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
6 tool updates
v0.1.0- First observed
agency_revisions - First observed
dataset_status - First observed
employer_layoff_history - First observed
latest_layoff_notices - First observed
search_layoff_notices - First observed
state_layoff_totals
TDQS
Scored across 6 tools
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.
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.
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.
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
Related MCP Connectors
Search 5,950 US WARN Act layoff notices by state, employer, and date (CA, TX, NY, IL, NC).
WARN Act layoff filings and Forward Deployed Engineering rules. Agent pays per query, no account.
WARN layoffs, H-1B/LCA visas, SEC 8-K, bankruptcies, DOL claims & JOLTS for all 50 US states.
Related MCP Servers
- AlicenseAqualityCmaintenanceEnables users to query U.S. labor statistics, including employment, CPI, and wages, directly from the Bureau of Labor Statistics Public Data API. It provides tools to retrieve real-time economic time series data, browse popular series, and access survey metadata through natural language.61MIT
- AlicenseNot gradedqualityDmaintenanceEnables querying U.S. Treasury fiscal data including debt, interest rates, auctions, and more via natural language, with no API key required.MIT
- AlicenseNot gradedqualityFmaintenanceProvides access to US Treasury Fiscal Data via a free, no-auth public API. Enables querying government financial data through natural language.2 npmMIT
- AlicenseNot gradedqualityBmaintenanceProvides access to SEC EDGAR data through natural language, including company filings, financial statements, and company info, without requiring an API key.MIT