Skip to content

io.github.cyanheads/openfda-mcp-server

by cyanheads · remote · local (npm) · no sign-in to list tools · v0.8.1 · published by GitHub user cyanheads

Query FDA data on drugs, food, devices, and recalls via openFDA. STDIO or Streamable HTTP.

Changes · 1

14 tools: 1 change things and 13 only read.

Scanned Oct 21, 2026

1 check matched something in the tool definitions. No finding is not a safety guarantee. How the checks work.

claude mcp add --transport http openfda https://openfda.caseyjhand.com/mcp

Findings

Matches of fixed checks, with the text they matched.

1 warn
  • The server marks "openfda_dataframe_query" read-only (readOnlyHint: true), and its own name, description or input give the class "write".

    Matched text

    annotations: {"readOnlyHint":true,"idempotentHint":true,"openWorldHint":false}; The name "openfda_dataframe_query" says "query": a word for reading.

    What this check looks for

Tools

Open a tool for its reasons and full description. Descriptions are the publisher's own words, shown as they are.

14 tools

Changes things 1Claude Code: ask
  • openfda_dataframe_queryRun a read-only SQL SELECT against a DataCanvas table staged by an openFDA search tool (call one with stage=true; its response carries canvas_id + canvas_table).1 finding

    Why it is in this group

    • The name "openfda_dataframe_query" says "query": a word for reading.
    • The description's first verb is "run": a word for a change.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

    Findings

    • Warn

      The server marks "openfda_dataframe_query" read-only (readOnlyHint: true), and its own name, description or input give the class "write".

      Matched text

      annotations: {"readOnlyHint":true,"idempotentHint":true,"openWorldHint":false}; The name "openfda_dataframe_query" says "query": a word for reading.

      What this check looks for
    Description, as the server wrote it
    Run a read-only SQL SELECT against a DataCanvas table staged by an openFDA search tool (call one with stage=true; its response carries canvas_id + canvas_table). Enables GROUP BY, COUNT/SUM/AVG, time-series, and joins across the staged result set without re-paging the API. Call openfda_dataframe_describe first to get the exact table and column names. Results are capped at the canvas row limit — when truncated is true, page the rest with ORDER BY plus LIMIT/OFFSET. Scalar fields are stored as text (CAST for numeric math); nested objects/arrays are JSON columns — read them with DuckDB json functions, e.g. json_extract_string(openfda, '$.brand_name[0]'). Only SELECT is allowed — DDL, DML, COPY, and file-reading functions are blocked.

    Annotations the server declares

    • readOnlyHint: true
    • idempotentHint: true
    • openWorldHint: false
Only reads 13Claude Code: allow
  • openfda_count_valuesAggregate and tally unique values for any field across any openFDA endpoint.No findings

    Why it is in this group

    • The name "openfda_count_values" says "count": a word for reading.
    Description, as the server wrote it
    Aggregate and tally unique values for any field across any openFDA endpoint. Returns ranked term-count pairs sorted by count descending. Pair with openfda_search_adverse_events, openfda_search_drug_approvals, openfda_search_device_clearances, openfda_search_recalls, openfda_get_drug_label, or openfda_lookup_ndc when sample records help interpret the aggregates.

    Annotations the server declares

    • readOnlyHint: true
  • openfda_dataframe_describeList the tables and column schemas on a DataCanvas staged by an openFDA search tool.No findings

    Why it is in this group

    • The name "openfda_dataframe_describe" says "describe": a word for reading.
    Description, as the server wrote it
    List the tables and column schemas on a DataCanvas staged by an openFDA search tool. Call before openfda_dataframe_query to discover the exact table name, column names, and DuckDB types needed for valid SQL. row_count is the full staged result set, not the inline preview count. Columns typed JSON hold nested openFDA objects/arrays — query them with DuckDB json functions.

    Annotations the server declares

    • readOnlyHint: true
    • idempotentHint: true
    • openWorldHint: false
  • openfda_describe_fieldsReturn the searchable field paths for an openFDA endpoint, grouped by category with type and description.No findings

    Why it is in this group

    • The name "openfda_describe_fields" says "describe": a word for reading.
    Description, as the server wrote it
    Return the searchable field paths for an openFDA endpoint, grouped by category with type and description. Use before constructing a search query to find the correct dotted field path — field names differ per endpoint and are not discoverable from the tool schema alone.

    Annotations the server declares

    • readOnlyHint: true
  • openfda_drug_profileResolve one drug name to its FDA identity, then fan out in parallel across the bounded per-drug openFDA endpoints and merge into one profile: identity, label highlights, adverse-ev…No findings

    Why it is in this group

    • The description's first verb is "resolve": a word for reading.
    Description, as the server wrote it
    Resolve one drug name to its FDA identity, then fan out in parallel across the bounded per-drug openFDA endpoints and merge into one profile: identity, label highlights, adverse-event summary, recall history, Drugs@FDA approval, and shortage status. Replaces chaining openfda_get_drug_label, openfda_search_adverse_events, openfda_search_recalls, openfda_search_drug_approvals, and openfda_search_drug_shortages — and reconciles the identifier drift between endpoints that makes that chaining error-prone. Each section is best-effort: a miss returns null rather than failing the call. For deep dives into any one area, use the dedicated tool.

    Annotations the server declares

    • readOnlyHint: true
  • openfda_get_drug_labelLook up FDA drug labeling (package inserts / SPL documents).No findings

    Why it is in this group

    • The name "openfda_get_drug_label" says "get": a word for reading.
    Description, as the server wrote it
    Look up FDA drug labeling (package inserts / SPL documents). Check indications, warnings, dosage, contraindications, active ingredients, or any structured label section. A label runs to tens of thousands of tokens, so a page that exceeds the inline budget returns the list of available sections instead; re-call with sections to pull the ones you need.

    Annotations the server declares

    • readOnlyHint: true
  • openfda_lookup_ndcLook up drugs in the NDC (National Drug Code) Directory.No findings

    Why it is in this group

    • The name "openfda_lookup_ndc" says "lookup": a word for reading.
    Description, as the server wrote it
    Look up drugs in the NDC (National Drug Code) Directory. Identify drug products by NDC code, find active ingredients, packaging details, or manufacturer info. Pair with openfda_get_drug_label using the returned brand_name or set_id to read the package insert. With stage=true, call openfda_dataframe_describe for the staged columns, then openfda_dataframe_query for SQL.

    Annotations the server declares

    • readOnlyHint: true
  • openfda_search_adverse_eventsSearch adverse event reports across drugs, food, and devices.No findings

    Why it is in this group

    • The name "openfda_search_adverse_events" says "search": a word for reading.
    Description, as the server wrote it
    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. With stage=true, call openfda_dataframe_describe for the staged columns, then openfda_dataframe_query for SQL.

    Annotations the server declares

    • readOnlyHint: true
  • openfda_search_animal_eventsSearch adverse event reports for veterinary drugs and devices submitted to the FDA Center for Veterinary Medicine.No findings

    Why it is in this group

    • The name "openfda_search_animal_events" says "search": a word for reading.
    Description, as the server wrote it
    Search adverse event reports for veterinary drugs and devices submitted to the FDA Center for Veterinary Medicine. Records include animal species, breed, age, weight, drug name and route, adverse reactions (using VeDDRA terminology), and outcome. Use to investigate safety signals for veterinary products, find reports by animal species or drug, or explore reaction patterns. Brand and manufacturer names are masked as "MSK" on every record (the FDA null flavor for withheld data), so find a product by active ingredient on drug.active_ingredients.name, unsuffixed. An ingredient search spans every product containing it and cannot attribute reports to one brand; drug.manufacturer.registration_number (the full value, e.g. "USA-USFDACVM-N141426") narrows it to one approval. With stage=true, call openfda_dataframe_describe for the staged columns, then openfda_dataframe_query for SQL.

    Annotations the server declares

    • readOnlyHint: true
  • openfda_search_device_clearancesSearch FDA device premarket notifications — 510(k) clearances and PMA approvals.No findings

    Why it is in this group

    • The name "openfda_search_device_clearances" says "search": a word for reading.
    Description, as the server wrote it
    Search FDA device premarket notifications — 510(k) clearances and PMA approvals. With stage=true, call openfda_dataframe_describe for the staged columns, then openfda_dataframe_query for SQL.

    Annotations the server declares

    • readOnlyHint: true
  • openfda_search_drug_approvalsSearch the Drugs@FDA database for drug application approvals (NDAs and ANDAs).No findings

    Why it is in this group

    • The name "openfda_search_drug_approvals" says "search": a word for reading.
    Description, as the server wrote it
    Search the Drugs@FDA database for drug application approvals (NDAs and ANDAs). Returns application details, sponsor info, and full submission history. Pair with openfda_get_drug_label to read the approved label, or openfda_count_values to aggregate by sponsor_name, product_type, or route. With stage=true, call openfda_dataframe_describe for the staged columns, then openfda_dataframe_query for SQL.

    Annotations the server declares

    • readOnlyHint: true
  • openfda_search_drug_shortagesSearch FDA drug shortage records.No findings

    Why it is in this group

    • The name "openfda_search_drug_shortages" says "search": a word for reading.
    Description, as the server wrote it
    Search FDA drug shortage records. Returns per-product shortage status, availability, therapeutic category, dosage form, manufacturer, and dates. Use to check whether a drug is currently in shortage, find all oncology drugs with supply issues, or retrieve the openfda block (brand_name, product_ndc, rxcui) to chain into openfda_get_drug_label or openfda_lookup_ndc. With stage=true, call openfda_dataframe_describe for the staged columns, then openfda_dataframe_query for SQL.

    Annotations the server declares

    • readOnlyHint: true
  • openfda_search_recallsSearch enforcement reports and recall actions across drugs, food, and devices.No findings

    Why it is in this group

    • The name "openfda_search_recalls" says "search": a word for reading.
    Description, as the server wrote it
    Search enforcement reports and recall actions across drugs, food, and devices. With stage=true, call openfda_dataframe_describe for the staged columns, then openfda_dataframe_query for SQL.

    Annotations the server declares

    • readOnlyHint: true
  • openfda_search_tobacco_reportsSearch problem reports submitted to the FDA for tobacco products, including e-cigarettes, vaping products, cigarettes, and smokeless tobacco.No findings

    Why it is in this group

    • The name "openfda_search_tobacco_reports" says "search": a word for reading.
    Description, as the server wrote it
    Search problem reports submitted to the FDA for tobacco products, including e-cigarettes, vaping products, cigarettes, and smokeless tobacco. Reports capture product type, reported health problems (e.g. seizure, chest pain), product problems (e.g. exploding battery), whether a non-user was affected, and submission date. Use to investigate safety signals, find reports by product type, or analyze health effects. With stage=true, call openfda_dataframe_describe for the staged columns, then openfda_dataframe_query for SQL.

    Annotations the server declares

    • readOnlyHint: true

This is not a safety rating, and no finding is not a safety guarantee. The groups and findings come from fixed checks of the tool definitions the server returned on the date shown, not from its code or what it does when called. How the checks work.

Install

Pinned to version 0.8.1. Values in angle brackets are yours to fill in.

claude mcp add --transport http openfda https://openfda.caseyjhand.com/mcp

Run in a terminal.

Claude Code permissions

Allow the reads, ask before a change, deny the deletes. Paste into .claude/settings.json.

.claude/settings.json
{
  "permissions": {
    "allow": [
      "mcp__openfda__openfda_search_adverse_events",
      "mcp__openfda__openfda_search_animal_events",
      "mcp__openfda__openfda_search_drug_shortages",
      "mcp__openfda__openfda_search_recalls",
      "mcp__openfda__openfda_search_tobacco_reports",
      "mcp__openfda__openfda_count_values",
      "mcp__openfda__openfda_describe_fields",
      "mcp__openfda__openfda_get_drug_label",
      "mcp__openfda__openfda_search_drug_approvals",
      "mcp__openfda__openfda_search_device_clearances",
      "mcp__openfda__openfda_lookup_ndc",
      "mcp__openfda__openfda_drug_profile",
      "mcp__openfda__openfda_dataframe_describe"
    ],
    "ask": [
      "mcp__openfda__openfda_dataframe_query"
    ],
    "deny": []
  }
}

Tools that only read are allowed, tools that change things ask first, tools that delete or cancel are denied. It assumes the server is installed as openfda. Review it before you use it.