openfda_device_searcher
Query the FDA's MAUDE database to identify medical device issues, including malfunctions, patient injuries, and genomic/diagnostic device problems. Filter by device type, manufacturer, or problem description to uncover adverse event reports.
Instructions
Search FDA device adverse event reports (MAUDE) for medical device issues.
⚠️ PREREQUISITE: Use the 'think' tool FIRST to plan your research strategy!
Searches FDA's device adverse event database for:
- Device malfunctions and failures
- Patient injuries related to devices
- Genomic test and diagnostic device issues
By default, filters to genomic/diagnostic devices relevant to precision medicine.
Set genomics_only=False to search all medical devices.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| api_key | No | Optional OpenFDA API key (overrides OPENFDA_API_KEY env var) | |
| device | No | Device name to search for | |
| genomics_only | No | Filter to genomic/diagnostic devices only | |
| limit | No | Maximum number of results | |
| manufacturer | No | Manufacturer name | |
| page | No | Page number (1-based) | |
| problem | No | Device problem description | |
| product_code | No | FDA product code |
Implementation Reference
- src/biomcp/individual_tools.py:1457-1519 (handler)MCP tool handler function 'openfda_device_searcher'. Defines the tool schema with Pydantic annotations, registers via @mcp_app.tool(), and delegates execution to the core search_device_events helper.@track_performance("biomcp.openfda_device_searcher") async def openfda_device_searcher( device: Annotated[ str | None, Field(description="Device name to search for"), ] = None, manufacturer: Annotated[ str | None, Field(description="Manufacturer name"), ] = None, problem: Annotated[ str | None, Field(description="Device problem description"), ] = None, product_code: Annotated[ str | None, Field(description="FDA product code"), ] = None, genomics_only: Annotated[ bool, Field(description="Filter to genomic/diagnostic devices only"), ] = True, limit: Annotated[ int, Field(description="Maximum number of results", ge=1, le=100), ] = 25, page: Annotated[ int, Field(description="Page number (1-based)", ge=1), ] = 1, api_key: Annotated[ str | None, Field( description="Optional OpenFDA API key (overrides OPENFDA_API_KEY env var)" ), ] = None, ) -> str: """Search FDA device adverse event reports (MAUDE) for medical device issues. ⚠️ PREREQUISITE: Use the 'think' tool FIRST to plan your research strategy! Searches FDA's device adverse event database for: - Device malfunctions and failures - Patient injuries related to devices - Genomic test and diagnostic device issues By default, filters to genomic/diagnostic devices relevant to precision medicine. Set genomics_only=False to search all medical devices. """ from biomcp.openfda import search_device_events skip = (page - 1) * limit return await search_device_events( device=device, manufacturer=manufacturer, problem=problem, product_code=product_code, genomics_only=genomics_only, limit=limit, skip=skip, api_key=api_key, )
- Core helper function implementing the OpenFDA MAUDE device events search. Builds complex search queries, handles API requests, analyzes common problems, formats summaries and sample reports with genomics filtering.async def search_device_events( device: str | None = None, manufacturer: str | None = None, problem: str | None = None, product_code: str | None = None, genomics_only: bool = True, limit: int = OPENFDA_DEFAULT_LIMIT, skip: int = 0, api_key: str | None = None, ) -> str: """ Search FDA device adverse event reports (MAUDE). Args: device: Device name to search for manufacturer: Manufacturer name problem: Device problem description product_code: FDA product code genomics_only: Filter to genomic/diagnostic devices only limit: Maximum number of results skip: Number of results to skip api_key: Optional OpenFDA API key (overrides OPENFDA_API_KEY env var) Returns: Formatted string with device event information """ if not device and not manufacturer and not product_code and not problem: return ( "⚠️ Please specify a device name, manufacturer, or problem to search.\n\n" "Examples:\n" "- Search by device: --device 'FoundationOne'\n" "- Search by manufacturer: --manufacturer 'Illumina'\n" "- Search by problem: --problem 'false positive'" ) # Build and execute search search_query = _build_device_search_query( device, manufacturer, problem, product_code, genomics_only ) params = { "search": search_query, "limit": min(limit, OPENFDA_MAX_LIMIT), "skip": skip, } response, error = await make_openfda_request( OPENFDA_DEVICE_EVENTS_URL, params, "openfda_device_events", api_key ) if error: return f"⚠️ Error searching device events: {error}" if not response or not response.get("results"): return _format_no_results(device, manufacturer, problem, genomics_only) results = response["results"] total = ( response.get("meta", {}).get("results", {}).get("total", len(results)) ) # Build output output = ["## FDA Device Adverse Event Reports\n"] output.extend( _format_search_summary( device, manufacturer, problem, genomics_only, total ) ) # Analyze and format problems all_problems, all_device_names, _ = analyze_device_problems(results) output.extend(format_top_problems(all_problems, results)) # Show device distribution if searching by problem if problem: output.extend(format_device_distribution(all_device_names, results)) # Display sample reports output.append( f"### Sample Reports (showing {min(len(results), 3)} of {total}):\n" ) for i, result in enumerate(results[:3], 1): output.extend(format_device_report_summary(result, i)) # Add tips if genomics_only: output.append( "\n💡 **Note**: Results filtered to genomic/diagnostic devices. " "Use --no-genomics-only to search all medical devices." ) output.append(f"\n{OPENFDA_DISCLAIMER}") return "\n".join(output)
- src/biomcp/openfda/__init__.py:16-46 (registration)Exposes the search_device_events helper function for import in the MCP tool handler.from .device_events import ( search_device_events, get_device_event, ) from .drug_approvals import ( search_drug_approvals, get_drug_approval, ) from .drug_recalls import ( search_drug_recalls, get_drug_recall, ) from .drug_shortages import ( search_drug_shortages, get_drug_shortage, ) __all__ = [ "get_adverse_event", "get_device_event", "get_drug_approval", "get_drug_label", "get_drug_recall", "get_drug_shortage", "search_adverse_events", "search_device_events", "search_drug_approvals", "search_drug_labels", "search_drug_recalls", "search_drug_shortages", ]
- Helper function that constructs sophisticated OpenFDA search queries with exact matches, wildcards, multi-word handling, and genomic product code filtering.def _build_device_search_query( device: str | None, manufacturer: str | None, problem: str | None, product_code: str | None, genomics_only: bool, ) -> str: """Build the search query for device events.""" search_parts = [] if device: # Build flexible search queries device_queries = [] # First try exact match device_queries.extend([ f'device.brand_name:"{device}"', f'device.generic_name:"{device}"', f'device.openfda.device_name:"{device}"', ]) # For multi-word terms, also search for key words with wildcards # This helps match "FoundationOne CDx" to "F1CDX" or similar variations words = device.split() # If it's a multi-word query, add wildcard searches for significant words for word in words: # Skip common words and very short ones if len(word) > 3 and word.lower() not in [ "test", "system", "device", ]: # Use prefix wildcard for better performance device_queries.append(f"device.brand_name:{word}*") device_queries.append(f"device.generic_name:{word}*") # Also try searching by removing spaces (e.g., "Foundation One" -> "FoundationOne") if len(words) > 1: combined = "".join(words) device_queries.append(f'device.brand_name:"{combined}"') device_queries.append(f'device.generic_name:"{combined}"') search_parts.append(f"({' OR '.join(device_queries)})") if manufacturer: # Search manufacturer field with both exact and wildcard matching mfr_queries = [ f'device.manufacturer_d_name:"{manufacturer}"', f"device.manufacturer_d_name:*{manufacturer}*", ] search_parts.append(f"({' OR '.join(mfr_queries)})") if problem: search_parts.append(f'device.device_problem_text:"{problem}"') if product_code: search_parts.append(f'device.openfda.product_code:"{product_code}"') elif ( genomics_only and not device ): # Only apply genomics filter if no specific device is named # Filter to genomic device product codes code_parts = [ f'device.openfda.product_code:"{code}"' for code in GENOMIC_DEVICE_PRODUCT_CODES ] if code_parts: search_parts.append(f"({' OR '.join(code_parts)})") return " AND ".join(search_parts)