fda_recalls_recent
Obtain FDA medical device recalls, filtered by class (1 most serious, 3 least). Supports openFDA wildcard queries for partial matches.
Instructions
Recent FDA medical device recalls via openFDA. Optionally filter by class (1=most serious, 3=least). Note: openFDA query syntax uses token-exact matching on string fields — for partial matches use wildcards (e.g. product_description:mammog*).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | ||
| days | No | ||
| class_level | No | ||
| max_results | No | ||
| response_format | No | markdown |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- trends_mcp.py:1270-1310 (handler)The async function that executes the fda_recalls_recent tool logic. It queries the openFDA recall API, supports filtering by days, class_level, and query. Returns formatted markdown results.
async def fda_recalls_recent( query: str | None = None, days: int = 90, class_level: str | None = None, max_results: int = 20, response_format: ResponseFormat = ResponseFormat.MARKDOWN, ) -> str: try: args = FDARecallInput( query=query, days=days, class_level=class_level, max_results=max_results, response_format=response_format, ) end = _utc_now().strftime("%Y%m%d") start = (_utc_now() - timedelta(days=args.days)).strftime("%Y%m%d") parts = [f"event_date_initiated:[{start}+TO+{end}]"] if args.query: parts.append(args.query) if args.class_level: roman = _RECALL_CLASS_TO_ROMAN.get(args.class_level, args.class_level) parts.append(f"classification:Class+{roman}") search = _build_openfda_search(parts) api_key = os.environ.get("OPENFDA_API_KEY") url = f"{OPENFDA_RECALL}?search={search}&limit={args.max_results}&sort=event_date_initiated:desc" if api_key: url += f"&api_key={api_key}" data = await _http_get_json(url, ttl=TTL_STATIC) items = data.get("results", []) if isinstance(data, dict) else [] cls_tag = f" · Class {args.class_level}" if args.class_level else "" header = f"FDA Recalls — 최근 {args.days}일{cls_tag} ({len(items)}건)" return _format(items, args.response_format, render_md=lambda x: _render_recall_md(x, header)) except httpx.HTTPStatusError as e: if e.response.status_code == 404: cls_tag = f" · Class {args.class_level}" if args.class_level else "" header = f"FDA Recalls — 최근 {args.days}일{cls_tag} (0건)" return _format([], args.response_format, render_md=lambda x: _render_recall_md(x, header)) return _handle_error(e, "fda_recalls_recent") except Exception as e: return _handle_error(e, "fda_recalls_recent") - trends_mcp.py:1142-1149 (schema)Pydantic model FDARecallInput — validates input parameters for fda_recalls_recent: query (optional), days (1-365), class_level (Arabic 1-3 or Roman I-III), max_results (1-100), response_format.
class FDARecallInput(BaseModel): model_config = ConfigDict(str_strip_whitespace=True, extra="forbid") query: str | None = Field(None, max_length=300) days: int = Field(90, ge=1, le=365) # Accept Arabic ("1","2","3") or Roman ("I","II","III") — normalized internally. class_level: str | None = Field(None, pattern=r"^(?:[123]|I{1,3})$") max_results: int = Field(20, ge=1, le=100) response_format: ResponseFormat = ResponseFormat.MARKDOWN - trends_mcp.py:1254-1269 (registration)The @_maybe_tool decorator registers fda_recalls_recent with FastMCP under the 'fda_recalls' source gating. It is only registered if 'fda_recalls' is in TRENDS_ENABLED_SOURCES.
@_maybe_tool( source="fda_recalls", name="fda_recalls_recent", description=( "Recent FDA medical device recalls via openFDA. Optionally filter by class " "(1=most serious, 3=least). Note: openFDA query syntax uses token-exact " "matching on string fields — for partial matches use wildcards " "(e.g. `product_description:mammog*`)." ), annotations={ "readOnlyHint": True, "destructiveHint": False, "openWorldHint": True, "idempotentHint": True, }, ) - trends_mcp.py:1248-1251 (helper)Lookup dict normalizing class_level input (Arabic '1','2','3' or Roman 'I','II','III') to Roman numeral for querying the openFDA recall API.
_RECALL_CLASS_TO_ROMAN: dict[str, str] = { "1": "I", "2": "II", "3": "III", "I": "I", "II": "II", "III": "III", } - trends_mcp.py:1169-1181 (helper)Renders the FDA recall results as markdown. Shows product description, recall number, classification, date, company, status, and reason for recall.
def _render_recall_md(items: list[dict[str, Any]], header: str) -> str: if not items: return f"# {header}\n\n_결과 없음_" lines = [f"# {header}", f"_총 {len(items)}건_", ""] for i, r in enumerate(items, 1): lines.append( f"## {i}. {_trim(r.get('product_description'), 120)}\n" f"- 회수번호 `{r.get('recall_number', '?')}` · {r.get('classification', '?')} · " f"{r.get('event_date_initiated', '?')}\n" f"- 회사: {r.get('recalling_firm', '?')} · 상태: {r.get('recall_status', '?')}\n" f"- 사유: {_trim(r.get('reason_for_recall'), 400)}\n" ) return "\n".join(lines)