mcpField
C
cpsc-recalls-mcp-server

cpsc-recalls-mcp-server

Remote
github.com/cyanheadsLegal & Government1Updated today
Repository

About cpsc-recalls-mcp-server

An MCP server for finding and retrieving US CPSC consumer product recall records. It supports filtered searches, complete recall details, and recent-recall feeds, with scope notes identifying recalls handled by other agencies.

Key features

  1. 01Search recalls by product, brand, hazard, and dates
  2. 02Retrieve full records by recall number
  3. 03List recent recalls within a date window
  4. 04Expose hazards, remedies, products, and provenance

Use cases

  1. 01Check whether a product or brand has been recalled
  2. 02Review hazards and remedy instructions for a known recall
  3. 03Monitor recent CPSC recalls for a date range

MCP support

Exposes three recall-search and retrieval tools to MCP clients. Supports STDIO and Streamable HTTP transports.

Configuration

Remote servers need no local install. Pick your client, then copy the config or install in one click.

Endpointhttps://cpsc-recalls.caseyjhand.com/mcp
Copy install command
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

Run commands in a terminal; paste JSON into the client’s MCP config and restart. Servers that need sign-in will prompt on first connect.

Packages
npm@cyanheads/cpsc-recalls-mcp-server0.3.0

Tools

3
ParameterTypeRequiredDescription
limitintegerNoMaximum number of recalls to return on this page. Defaults to 20. A page returns fewer when it reaches the 64,000-byte response size budget; has_more then says more remain.
offsetintegerNoSkip this many matching records before returning results. To page through total_found, raise offset by the number of recalls the previous page returned — limit, unless that page reached the response size budget. An offset at or past total_found returns an empty result set rather than an error.
remedystringNoKeyword search within the free-text remedy instructions, e.g. "repair", "refund", "firmware update"; matches instructions containing every word, in any order. This searches the remedy text, not the remedy_options categories — "repair" matches records whose remedy_options list only "Refund" but whose instructions describe a free repair kit. Combines with the other filters using AND; use hazard_search instead to match remedy text as one of several fields.
date_endanyNoInclude only recalls on or before this date. ISO 8601 format: "YYYY-MM-DD". Must be a real calendar date, and on or after date_start.
importerstringNoImporter company name. Matches recalls whose importer names contain every word, in any order. Use when searching for recalls by the company that brought the product into the US.
retailerstringNoRetailer name, e.g. "Walmart", "Target", "Amazon". Matches recalls whose retailer text (store name, dates sold, and price) contains every word, in any order.
date_startanyNoInclude only recalls on or after this date. ISO 8601 format: "YYYY-MM-DD". Must be a real calendar date — "2026-02-31" and "2026-99-99" are rejected.
distributorstringNoDistributor company name, e.g. "Walmart", "Costco". Matches recalls whose distributor names contain every word, in any order — a role distinct from retailer and importer, and listed on far fewer recalls.
updated_endanyNoInclude only recalls last published by CPSC on or before this date. ISO 8601 format: "YYYY-MM-DD". Must be a real calendar date, and on or after updated_start.
manufacturerstringNoManufacturer name, e.g. "Samsung", "LEGO". Matches recalls whose manufacturer names contain every word, in any order. Many recalls name the importer, retailer, or distributor rather than the manufacturer — try those filters when this finds nothing.
product_namestringNoProduct name to search for, e.g. "crib", "space heater", "bicycle". Matches recalls whose product names contain every word, in any order — partial words work.
title_searchstringNoKeyword search within the recall title, e.g. "chandelier", "space heater", "Graco crib". Matches titles containing every word, in any order. CPSC titles name the brand, the product, and the hazard, which makes this the highest-signal single filter for most searches.
hazard_searchstringNoHazard or safety-concept keyword, e.g. "fire", "choking", "burn", "tip-over dresser". Matches when every word appears in the hazard descriptions, product names, or remedy instructions — each word in any of the three, in any order, case-insensitive. The filter to use for hazard types; combine it with another filter to narrow a broad hazard.
updated_startanyNoInclude only recalls last published by CPSC on or after this date. ISO 8601 format: "YYYY-MM-DD". A separate axis from date_start: a 2003 recall re-published in 2025 matches updated_start "2025-01-01". Use to answer "what has CPSC updated recently". Must be a real calendar date.
description_searchstringNoKeyword search within the recall description only — not the title, hazard text, or remedy instructions; matches descriptions containing every word, in any order. Use for product details not captured in product_name — model numbers, colors, sale channels. For hazard concepts, prefer hazard_search; for the recall headline, prefer title_search.

Details

From the project README

@cyanheads/cpsc-recalls-mcp-server

Search and retrieve US consumer product recalls from the CPSC (Consumer Product Safety Commission) via MCP. STDIO or Streamable HTTP.

3 Tools

Version License Docker MCP SDK npm TypeScript Bun

Install in Claude Desktop Install in Cursor Install in VS Code

Framework


Overview

Consumer product recalls from the CPSC saferproducts.gov database — toys, electronics, furniture, appliances, children's products, tools, and clothing. Search recalls by product, brand, retailer, or hazard, fetch full detail for a specific recall number, or pull a recent-recalls feed for a date window.

Tools
ToolDescription
cpsc_search_recallsSearch consumer product recalls by title, product name, brand, retailer, importer, distributor, hazard, remedy, or description keyword, with optional date filtering and offset paging
cpsc_get_recallFull detail for a single recall by recall number — hazards, remedy, products, injuries, images, and the official CPSC page
cpsc_get_recentFetch the most recent recalls ordered newest-first, scoped to a configurable date window

CPSC jurisdiction is consumer products only — food/drugs (FDA), motor vehicles/tires (NHTSA), boats (USCG), pesticides (EPA), and firearms (ATF) are not in this database; every response carries a jurisdiction note.

Capability reference

cpsc_search_recalls tool
  • At least one criterion, combined with AND: nine text filters of up to 500 characters each (title_search, usually the highest-signal, plus product_name, manufacturer, retailer, importer, distributor, description_search, remedy, hazard_search) and two date axes (date_start/date_end for the issue date, updated_start/updated_end for the last CPSC publish date); limit (1–200, default 20) and offset page through total_found
  • Returns hazards, remedy options and instructions, products, UPCs, company names by role, images, cpsc_url, and per-recall data_quality_notes; zero matches is an empty success whose effectiveQuery echoes the criteria and whose notice names the criterion to relax. Failures: missing_criteria, invalid_date_range, upstream_rejected (not retryable), upstream_error (retryable)
  • has_more is the paging signal; a page cut short by the 64,000-byte response budget carries a notice with the offset to continue from

cpsc_get_recall tool
  • One recall_number: 5 digits for 2002–present records ("25043"), or 5 digits plus a letter a–d for 1998–2001 records ("99003a")
  • Returns the complete record — nullable description (where model numbers usually live), hazards, remedy options and instructions, every product variant, UPCs, injury narrative, company names by role, country of manufacture, images, coordinated-agency recall URLs, and data_quality_notes
  • Failures: not_found (resolve a number through cpsc_search_recalls or cpsc_get_recent), upstream_rejected (not retryable), upstream_error (retryable)

cpsc_get_recent tool
  • days look-back window (1–365, default 30) anchored to today; limit (1–100, default 20) and offset page through total_found, since narrowing days drops the oldest recalls rather than paging. Older recalls are reachable through cpsc_search_recalls date bounds
  • Returns a lightweight record per recall — number, date, title, hazards, remedy types, product names, cpsc_url, data_quality_notes — for cpsc_get_recall to expand; has_more is the paging signal, and an empty window, an offset past the end, or a budget-cut page carries a notice. Failures: upstream_rejected (not retryable), upstream_error (retryable)

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.

CPSC-specific:

  • Full client for the CPSC saferproducts.gov public recalls API — search, single-recall detail, and a recent-recalls feed
  • Every-word matching on all nine text filters — each word in any order, case-insensitive, against the plain text the results show — applied over the complete result set before paging so total_found and has_more stay accurate; hazard_search (alias hazard) covers hazard text, product names, and remedy instructions
  • Handles both modern 5-digit recall numbers and historical 1998–2001 records with letter suffixes
  • Jurisdiction boundary documented in every response — flags food, vehicle, and drug recalls as out of scope before an agent misattributes them

Agent-friendly output:

  • Provenance on every response — source_note, cpsc_url, and (CPSC source text) blockquote labels distinguish relayed CPSC narrative from the server's own guidance
  • Plain text on both surfaces — the HTML markup and character codes CPSC stores in some records (&amp;, <br>, stray table tags) are converted to plain text before matching and output, and content[] escapes Markdown so model and serial numbers such as 1HFVE05**K4000003 keep every character; recall pages and coordinated recalls render as links, and product images render inline with their captions; HTTP(S) addresses preserve CPSC’s URL values on both surfaces, while other schemes remain visible as text
  • Pagination discriminators — total_found, offset, has_more, and truncated on every search/recent response so agents can tell when results are clipped and page with offset; each surface of a page stays within a 64,000-byte budget, and a notice gives the next offset when the budget ends a page early
  • data_quality_notes on every response — gaps observed in the upstream record (missing hazard text, no product entries), derived from which fields CPSC left blank rather than any judgment call
  • Jurisdiction note (cpsc_jurisdiction) on every response — lets agents route callers to the correct agency (FDA, NHTSA, USCG, EPA, ATF) when a product is out of scope

Getting started

Public Hosted Instance

A public instance is available at https://cpsc-recalls.caseyjhand.com/mcp — no installation required. It serves Streamable HTTP; each client takes its own configuration shape.

For Claude Code:

claude mcp add --transport http cpsc-recalls-mcp-server https://cpsc-recalls.caseyjhand.com/mcp

For Cline (cline_mcp_settings.json):

{
  "mcpServers": {
    "cpsc-recalls-mcp-server": {
      "type": "streamableHttp",
      "url": "https://cpsc-recalls.caseyjhand.com/mcp"
    }
  }
}

For Cursor (mcp.json):

{
  "mcpServers": {
    "cpsc-recalls-mcp-server": {
      "url": "https://cpsc-recalls.caseyjhand.com/mcp"
    }
  }
}

Claude Desktop adds remote servers under Settings → Connectors.

Self-Hosted / Local

Add the following to your MCP client configuration file.

{
  "mcpServers": {
    "cpsc-recalls-mcp-server": {
      "type": "stdio",
      "command": "bunx",
      "args": ["@cyanheads/cpsc-recalls-mcp-server@latest"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info"
      }
    }
  }
}

Or with npx (no Bun required):

{
  "mcpServers": {
    "cpsc-recalls-mcp-server": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@cyanheads/cpsc-recalls-mcp-server@latest"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info"
      }
    }
  }
}

Or with Docker:

{
  "mcpServers": {
    "cpsc-recalls-mcp-server": {
      "type": "stdio",
      "command": "docker",
      "args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/cpsc-recalls-mcp-server:latest"]
    }
  }
}

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

MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcp
Prerequisites
  • Bun v1.4.0 or higher (or Node.js v24+).
  • No API key required — the CPSC public recalls API is freely accessible.
Installation
  1. Clone the repository:
git clone https://github.com/cyanheads/cpsc-recalls-mcp-server.git
  1. Navigate into the directory:
cd cpsc-recalls-mcp-server
  1. Install dependencies:
bun install
  1. Configure environment:
cp .env.example .env
# edit .env if needed — no required API keys

Configuration

All configuration is validated at startup via Zod schemas. Key environment variables:

VariableDescriptionDefault
MCP_TRANSPORT_TYPETransport: stdio or httpstdio
MCP_HTTP_PORTHTTP server port3010
MCP_HTTP_HOSTHTTP server host127.0.0.1
MCP_HTTP_ENDPOINT_PATHHTTP endpoint path/mcp
MCP_PUBLIC_URLPublic origin for TLS-terminating reverse-proxy deployments—
MCP_SESSION_MODESession handling: auto, stateful, or stateless. The server declares stateless in src/index.ts; setting this overrides it.stateless
MCP_AUTH_MODEAuthentication: none, jwt, or oauthnone
MCP_LOG_LEVELLog level (debug, info, warning, error)info
LOGS_DIRDirectory for log files (Node.js only)<project-root>/logs
LOG_TOOL_FAILURE_PAYLOADSLog each failed tool call's arguments and result, redacted by key name and capped at LOG_TOOL_FAILURE_PAYLOAD_MAX_BYTES (default 16384). A secret inside a free-form value is not redacted.false
STORAGE_PROVIDER_TYPEStorage backend: in-memory, filesystem, supabase, cloudflare-kv/r2/d1in-memory
OTEL_ENABLEDEnable OpenTelemetryfalse

No server-specific API keys are required. See .env.example for the full list of optional overrides.

Running the server

Local development
  • Build and run the production version:

    # One-time build
    bun run rebuild
    
    # Run the built server
    bun run start:stdio
    # or
    bun run start:http
    
  • Run checks and tests:

    bun run devcheck  # Lint, format, typecheck, security
    bun run test      # Vitest test suite
    
Docker
docker build -t cpsc-recalls-mcp-server .
docker run --rm -p 3010:3010 cpsc-recalls-mcp-server

The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/cpsc-recalls-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 inits the CPSC service
src/mcp-server/toolsTool definitions (definitions/*.tool.ts) — search, get-recall, get-recent — plus response-budget.ts, the page size budget the two list tools share, and markdown-escape.ts, the escaping applied to CPSC text in content[]
src/services/cpsc-recallCPSC recall service — API client, types, and normalize-text.ts, which converts CPSC's HTML markup and character codes to plain text

Development guide

See CLAUDE.md / AGENTS.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
  • Register new tools in the createApp() arrays in src/index.ts
  • Wrap external 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:

bun run devcheck
bun run test

License

Apache-2.0 — see LICENSE for details.

Comments

Markdown supported

New to MCP?

From what the protocol is to installing your first server, these answers cover most first questions.

An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.