cpsc-recalls-mcp-server

v0.2.2 pre-1.0

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

cpsc-recalls.caseyjhand.com/mcp
claude mcp add --transport http cpsc-recalls-mcp-server https://cpsc-recalls.caseyjhand.com/mcp
codex mcp add cpsc-recalls-mcp-server --url https://cpsc-recalls.caseyjhand.com/mcp
{
  "mcpServers": {
    "cpsc-recalls-mcp-server": {
      "url": "https://cpsc-recalls.caseyjhand.com/mcp"
    }
  }
}
gemini mcp add --transport http cpsc-recalls-mcp-server https://cpsc-recalls.caseyjhand.com/mcp
{
  "mcpServers": {
    "cpsc-recalls-mcp-server": {
      "command": "bunx",
      "args": [
        "mcp-remote",
        "https://cpsc-recalls.caseyjhand.com/mcp"
      ]
    }
  }
}
{
  "mcpServers": {
    "cpsc-recalls-mcp-server": {
      "type": "http",
      "url": "https://cpsc-recalls.caseyjhand.com/mcp"
    }
  }
}
curl -X POST https://cpsc-recalls.caseyjhand.com/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"1.0.0"}}}'

Tools

3

cpsc_search_recalls

Search consumer product recalls from the CPSC (Consumer Product Safety Commission) — toys, electronics, furniture, appliances, children's products, tools, and clothing. Give at least one text filter or date bound; to browse the latest recalls without one, use cpsc_get_recent. Filters combine with AND, and a text filter matches records whose field contains every one of its words, in any order and case-insensitively. Start with title_search when you have a product in hand — CPSC titles carry the brand, product, and hazard phrasing. For hazard types ("fire", "choking", "burn"), use hazard_search, which matches hazard descriptions, product names, and remedy instructions. When manufacturer finds nothing, try importer, retailer, or distributor: many recalls name one of those as the responsible company. Page past limit with offset — total_found counts every match and has_more says whether more remain; a page returns fewer than limit recalls when it reaches the 64,000-byte response size budget. Pass a recall_number to cpsc_get_recall for the full record, including the complete description, all images, and incident reports. CPSC jurisdiction: consumer products only — food/drugs (FDA), motor vehicles/tires (NHTSA), boats (USCG), pesticides (EPA), and firearms (ATF) are covered by other agencies.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "cpsc_search_recalls",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "product_name": {
      "description": "Product name to search for, e.g. \"crib\", \"space heater\", \"bicycle\". Matches recalls whose product names contain every word, in any order — partial words work.",
      "type": "string",
      "maxLength": 500
    },
    "manufacturer": {
      "description": "Manufacturer 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.",
      "type": "string",
      "maxLength": 500
    },
    "retailer": {
      "description": "Retailer name, e.g. \"Walmart\", \"Target\", \"Amazon\". Matches recalls whose retailer text (store name, dates sold, and price) contains every word, in any order.",
      "type": "string",
      "maxLength": 500
    },
    "importer": {
      "description": "Importer 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.",
      "type": "string",
      "maxLength": 500
    },
    "distributor": {
      "description": "Distributor 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.",
      "type": "string",
      "maxLength": 500
    },
    "title_search": {
      "description": "Keyword 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.",
      "type": "string",
      "maxLength": 500
    },
    "description_search": {
      "description": "Keyword 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.",
      "type": "string",
      "maxLength": 500
    },
    "remedy": {
      "description": "Keyword 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.",
      "type": "string",
      "maxLength": 500
    },
    "hazard_search": {
      "description": "Hazard 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.",
      "type": "string",
      "maxLength": 500
    },
    "date_start": {
      "description": "Include 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.",
      "anyOf": [
        {
          "type": "string",
          "const": ""
        },
        {
          "type": "string",
          "format": "date",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
          "description": "ISO 8601 date: \"YYYY-MM-DD\"."
        }
      ]
    },
    "date_end": {
      "description": "Include 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.",
      "anyOf": [
        {
          "type": "string",
          "const": ""
        },
        {
          "type": "string",
          "format": "date",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
          "description": "ISO 8601 date: \"YYYY-MM-DD\"."
        }
      ]
    },
    "updated_start": {
      "description": "Include 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.",
      "anyOf": [
        {
          "type": "string",
          "const": ""
        },
        {
          "type": "string",
          "format": "date",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
          "description": "ISO 8601 date: \"YYYY-MM-DD\"."
        }
      ]
    },
    "updated_end": {
      "description": "Include 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.",
      "anyOf": [
        {
          "type": "string",
          "const": ""
        },
        {
          "type": "string",
          "format": "date",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
          "description": "ISO 8601 date: \"YYYY-MM-DD\"."
        }
      ]
    },
    "limit": {
      "default": 20,
      "description": "Maximum 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.",
      "type": "integer",
      "minimum": 1,
      "maximum": 200
    },
    "offset": {
      "default": 0,
      "description": "Skip 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.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    }
  },
  "required": [
    "limit",
    "offset"
  ],
  "additionalProperties": false
}
view source ↗

cpsc_get_recall

Fetch the full record for one CPSC recall by recall number: hazard description, remedy instructions, every product variant, UPCs, incident and injury reports, images, and the official CPSC recall page URL. Get a recall number from cpsc_search_recalls or cpsc_get_recent. CPSC jurisdiction: consumer products only — food/drugs (FDA), motor vehicles/tires (NHTSA), boats (USCG), pesticides (EPA), and firearms (ATF) are covered by other agencies.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "cpsc_get_recall",
    "arguments": {
      "recall_number": "<recall_number>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "recall_number": {
      "type": "string",
      "pattern": "^\\d{5}([a-d])?$",
      "description": "CPSC recall number: 5 digits for 2002–present records, e.g. \"25043\", or 5 digits plus a letter a–d for 1998–2001 records, e.g. \"99003a\". Get one from cpsc_search_recalls or cpsc_get_recent results."
    }
  },
  "required": [
    "recall_number"
  ],
  "additionalProperties": false
}
view source ↗

cpsc_get_recent

Fetch the most recent CPSC consumer product recalls, newest-first, from a window of the last N days (default 30, up to 365). Use for "what's been recalled lately?" or a product safety feed; to find recalls by product, brand, hazard, or an older date range, use cpsc_search_recalls. Page past limit with offset: narrowing days cannot page, because the window is anchored to today and shrinking it drops the oldest recalls rather than advancing past the newest. A page returns fewer than limit recalls when it reaches the 64,000-byte response size budget; has_more and the notice give the offset to continue from. Pass a recall_number to cpsc_get_recall for the full record. CPSC jurisdiction: consumer products only — food/drugs (FDA), motor vehicles/tires (NHTSA), boats (USCG), pesticides (EPA), and firearms (ATF) are covered by other agencies.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "cpsc_get_recent",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "days": {
      "default": 30,
      "description": "Look back this many days from today. Defaults to 30. Use 7 for a weekly digest, 90 for a quarterly review.",
      "type": "integer",
      "minimum": 1,
      "maximum": 365
    },
    "limit": {
      "default": 20,
      "description": "Maximum number of recalls to return. Defaults to 20. A page returns fewer when it reaches the 64,000-byte response size budget.",
      "type": "integer",
      "minimum": 1,
      "maximum": 100
    },
    "offset": {
      "default": 0,
      "description": "Skip this many recalls in the window 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.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    }
  },
  "required": [
    "days",
    "limit",
    "offset"
  ],
  "additionalProperties": false
}
view source ↗