Query FDA data on drugs, food, devices, and recalls via openFDA. STDIO or Streamable HTTP.
Public Hosted Server: https://openfda.caseyjhand.com/mcp
Seven tools for querying FDA data across drugs, food, devices, and recalls:
| Tool | Description |
|---|---|
openfda_search_adverse_events |
Search adverse event reports across drugs, food, and devices |
openfda_search_recalls |
Search enforcement reports and recall actions across drugs, food, and devices |
openfda_count |
Aggregate and tally unique values for any field across any openFDA endpoint |
openfda_get_drug_label |
Look up FDA drug labeling (package inserts / SPL documents) |
openfda_search_drug_approvals |
Search the Drugs@FDA database for NDA/ANDA application approvals |
openfda_search_device_clearances |
Search FDA device premarket notifications — 510(k) clearances and PMA approvals |
openfda_lookup_ndc |
Look up drugs in the NDC (National Drug Code) Directory |
Search adverse event reports across drugs, food, and devices. Use to investigate safety signals, find reports for a specific product, or explore reactions by demographics.
- Category selection:
drug,food, ordevice— each returns different field schemas - Elasticsearch query syntax for filtering by product, reaction, seriousness, date range
- Pagination via
limit(up to 1000) andskip(up to 25000) - Formatted output includes report ID, seriousness, patient demographics, reactions, drugs with characterization/indication/route, and all remaining fields
Aggregate and tally unique values for any field across any openFDA endpoint. Returns ranked term-count pairs sorted by count descending.
- Works across all 19 openFDA endpoints (drugs, food, devices, animal/veterinary, other)
- Use
.exactsuffix on field names for whole-phrase counting - Optional
searchfilter to scope the aggregation - Returns up to 1000 terms per query
Search enforcement reports and recall actions across drugs, food, and devices.
- Supports
enforcement(all categories) andrecall(devices only) endpoints - Filter by classification (Class I/II/III), recalling firm, reason, status
- Formatted output includes recall number, classification, product description, reason, distribution pattern
Search FDA device premarket notifications — 510(k) clearances and PMA approvals.
- Two pathways:
510k(174K+ records, most common) andpma(higher-risk devices) - Filter by applicant, product code, advisory committee, device name
- Formatted output adapts to pathway: 510(k) shows K-number/clearance type, PMA shows supplement info
Look up FDA drug labeling (package inserts / SPL documents). Check indications, warnings, dosage, contraindications, active ingredients, or any structured label section.
- Search by brand name, generic name, manufacturer, or set ID
- Formatted output dynamically renders all label sections and openfda metadata present in the record
- Large sections are automatically truncated to keep output readable
- Default limit of 5 — labels are large documents
Search the Drugs@FDA database for drug application approvals (NDAs and ANDAs). Returns application details, sponsor info, and full submission history.
- Filter by brand name, sponsor, submission type, review priority
- Formatted output includes products with active ingredients, dosage forms, routes, and marketing status
- Full submission history with type, status, date, and review priority
- Pagination via
limit(up to 1000) andskip(up to 25000)
Look up drugs in the NDC (National Drug Code) Directory. Identify drug products by NDC code, find active ingredients, packaging details, or manufacturer info.
- Search by product NDC, brand name, generic name, manufacturer, or active ingredient
- Returns product details, active ingredients with strengths, and packaging information
- Sortable by listing expiration date or other fields
Built on @cyanheads/mcp-ts-core:
- Declarative tool definitions — single file per tool, framework handles registration and validation
- Unified error handling across all tools
- Pluggable auth (
none,jwt,oauth) - Swappable storage backends:
in-memory,filesystem,Supabase,Cloudflare KV/R2/D1 - Structured logging with optional OpenTelemetry tracing
- Runs locally (stdio/HTTP) or on Cloudflare Workers from the same codebase
openFDA-specific:
- Generic API client for all openFDA endpoints with retry (exponential backoff) and rate-limit awareness
- Automatic error normalization — 404 returns empty results, 429/5xx retries, 400 provides actionable messages
- Optional API key support — works without a key (1K requests/day), increases to 120K/day with a free key
A public instance is available at https://openfda.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"openfda": {
"type": "streamable-http",
"url": "https://openfda.caseyjhand.com/mcp"
}
}
}Add to your MCP client config:
{
"mcpServers": {
"openfda": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/openfda-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"OPENFDA_API_KEY": "your-key-here"
}
}
}
}Or with npx (no Bun required):
{
"mcpServers": {
"openfda": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/openfda-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"OPENFDA_API_KEY": "your-key-here"
}
}
}
}Or with Docker:
{
"mcpServers": {
"openfda": {
"type": "stdio",
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/openfda-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- Bun v1.2.0 or higher.
- Optional: openFDA API key for higher rate limits (120K requests/day vs 1K/day).
- Clone the repository:
git clone https://github.com/cyanheads/openfda-mcp-server.git- Navigate into the directory:
cd openfda-mcp-server- Install dependencies:
bun installAll configuration is validated at startup via Zod schemas in src/config/server-config.ts. Key environment variables:
| Variable | Description | Default |
|---|---|---|
MCP_TRANSPORT_TYPE |
Transport: stdio or http |
stdio |
MCP_HTTP_PORT |
HTTP server port | 3010 |
MCP_AUTH_MODE |
Authentication: none, jwt, or oauth |
none |
MCP_LOG_LEVEL |
Log level (debug, info, warning, error, etc.) |
info |
LOGS_DIR |
Directory for log files (Node.js only). | <project-root>/logs |
STORAGE_PROVIDER_TYPE |
Storage backend: in-memory, filesystem, supabase, cloudflare-kv/r2/d1 |
in-memory |
OPENFDA_API_KEY |
Free API key from open.fda.gov. Increases daily limit from 1K to 120K requests. | none |
OPENFDA_BASE_URL |
Base URL override for testing against a proxy or mock. | https://api.fda.gov |
OTEL_ENABLED |
Enable OpenTelemetry | false |
-
Build and run the production version:
# One-time build bun run rebuild # Run the built server bun run start:http # or bun run start:stdio
-
Dev mode with watch:
bun run dev:stdio # or dev:http -
Run checks and tests:
bun run devcheck # Lints, formats, type-checks, and more bun run test # Runs the test suite
| Directory | Purpose |
|---|---|
src/index.ts |
Entry point — createApp() with tool registration and service setup. |
src/config/ |
Server-specific env var parsing and validation with Zod. |
src/services/openfda/ |
openFDA API client with retry, rate-limit handling, and error normalization. |
src/mcp-server/tools/definitions/ |
Tool definitions (*.tool.ts). Seven openFDA tools. |
See CLAUDE.md for development guidelines and architectural rules. The short version:
- Handlers throw, framework catches — no
try/catchin tool logic - Use
ctx.logfor request-scoped logging - Register new tools in
src/mcp-server/tools/definitions/index.ts
Issues and pull requests are welcome. Run checks and tests before submitting:
bun run devcheck
bun run testThis project is licensed under the Apache 2.0 License. See the LICENSE file for details.